blob: db9c679b7673ccc7b6fa30179ddb2e72fcd9f4aa [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;
1136 }
1137 }
1138
Jack Carter9e65aa32013-03-22 00:05:30 +00001139 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001140 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001141 else
1142 Instructions.push_back(Inst);
1143
1144 return false;
1145}
1146
Jack Carter30a59822012-10-04 04:03:53 +00001147bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1148
Jack Carterd0bd6422013-04-18 00:41:53 +00001149 switch (Inst.getOpcode()) {
1150 case Mips::LoadImm32Reg:
1151 case Mips::LoadAddr32Imm:
1152 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001153 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001154 return true;
1155 default:
1156 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001157 }
1158}
Jack Carter92995f12012-10-06 00:53:28 +00001159
Matheus Almeida3813d572014-06-19 14:39:14 +00001160bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001161 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001162 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001163 default:
1164 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001165 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001166 case Mips::LoadImm32Reg:
1167 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001168 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001169 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001170 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001171 return true;
1172 }
1173 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001174 case Mips::LoadAddr32Imm:
1175 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1176 case Mips::LoadAddr32Reg:
1177 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1178 }
Jack Carter30a59822012-10-04 04:03:53 +00001179}
Jack Carter92995f12012-10-06 00:53:28 +00001180
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001181namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001182template <bool PerformShift>
1183void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001184 SmallVectorImpl<MCInst> &Instructions) {
1185 MCInst tmpInst;
1186 if (PerformShift) {
1187 tmpInst.setOpcode(Mips::DSLL);
1188 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1189 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1190 tmpInst.addOperand(MCOperand::CreateImm(16));
1191 tmpInst.setLoc(IDLoc);
1192 Instructions.push_back(tmpInst);
1193 tmpInst.clear();
1194 }
1195 tmpInst.setOpcode(Mips::ORi);
1196 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1197 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001198 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001199 tmpInst.setLoc(IDLoc);
1200 Instructions.push_back(tmpInst);
1201}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001202
1203template <int Shift, bool PerformShift>
1204void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1205 SmallVectorImpl<MCInst> &Instructions) {
1206 createShiftOr<PerformShift>(
1207 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1208 IDLoc, Instructions);
1209}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001210}
1211
Matheus Almeida3813d572014-06-19 14:39:14 +00001212bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001213 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001214 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001215 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001216 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001217 const MCOperand &RegOp = Inst.getOperand(0);
1218 assert(RegOp.isReg() && "expected register operand kind");
1219
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001220 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001221 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001222 // FIXME: gas has a special case for values that are 000...1111, which
1223 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001224 if (0 <= ImmValue && ImmValue <= 65535) {
1225 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001226 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001227 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001228 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001229 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001230 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001231 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001232 } else if (ImmValue < 0 && ImmValue >= -32768) {
1233 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001234 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001235 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001236 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001237 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001238 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001239 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001240 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1241 // For any value of j that is representable as a 32-bit integer, create
1242 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001243 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001244 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001245 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001246 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1247 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001248 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001249 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1250 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001251 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001252 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001253 return true;
1254 }
1255
1256 // <------- lo32 ------>
1257 // <------- hi32 ------>
1258 // <- hi16 -> <- lo16 ->
1259 // _________________________________
1260 // | | | |
1261 // | 16-bytes | 16-bytes | 16-bytes |
1262 // |__________|__________|__________|
1263 //
1264 // For any value of j that is representable as a 48-bit integer, create
1265 // a sequence of:
1266 // li d,j => lui d,hi16(j)
1267 // ori d,d,hi16(lo32(j))
1268 // dsll d,d,16
1269 // ori d,d,lo16(lo32(j))
1270 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001271 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001272 tmpInst.addOperand(
1273 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001274 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001275 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1276 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1277 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001278 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001279 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001280 return true;
1281 }
1282
1283 // <------- hi32 ------> <------- lo32 ------>
1284 // <- hi16 -> <- lo16 ->
1285 // ___________________________________________
1286 // | | | | |
1287 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1288 // |__________|__________|__________|__________|
1289 //
1290 // For any value of j that isn't representable as a 48-bit integer.
1291 // li d,j => lui d,hi16(j)
1292 // ori d,d,lo16(hi32(j))
1293 // dsll d,d,16
1294 // ori d,d,hi16(lo32(j))
1295 // dsll d,d,16
1296 // ori d,d,lo16(lo32(j))
1297 tmpInst.setOpcode(Mips::LUi);
1298 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1299 tmpInst.addOperand(
1300 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1301 Instructions.push_back(tmpInst);
1302 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1303 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1304 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001305 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001306 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001307}
Jack Carter92995f12012-10-06 00:53:28 +00001308
Matheus Almeida3813d572014-06-19 14:39:14 +00001309bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001310MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1311 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001312 MCInst tmpInst;
1313 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001314 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1315 "expected immediate operand kind");
1316 if (!ImmOp.isImm()) {
1317 expandLoadAddressSym(Inst, IDLoc, Instructions);
1318 return false;
1319 }
Jack Carter543fdf82012-10-09 23:29:45 +00001320 const MCOperand &SrcRegOp = Inst.getOperand(1);
1321 assert(SrcRegOp.isReg() && "expected register operand kind");
1322 const MCOperand &DstRegOp = Inst.getOperand(0);
1323 assert(DstRegOp.isReg() && "expected register operand kind");
1324 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001325 if (-32768 <= ImmValue && ImmValue <= 65535) {
1326 // For -32768 <= j <= 65535.
1327 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001328 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001329 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1330 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1331 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1332 Instructions.push_back(tmpInst);
1333 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001334 // For any other value of j that is representable as a 32-bit integer.
1335 // la d,j(s) => lui d,hi16(j)
1336 // ori d,d,lo16(j)
1337 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001338 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001339 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1340 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1341 Instructions.push_back(tmpInst);
1342 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001343 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001344 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1345 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1346 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1347 Instructions.push_back(tmpInst);
1348 tmpInst.clear();
1349 tmpInst.setOpcode(Mips::ADDu);
1350 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1351 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1352 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1353 Instructions.push_back(tmpInst);
1354 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001355 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001356}
1357
Matheus Almeida3813d572014-06-19 14:39:14 +00001358bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001359MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1360 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001361 MCInst tmpInst;
1362 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001363 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1364 "expected immediate operand kind");
1365 if (!ImmOp.isImm()) {
1366 expandLoadAddressSym(Inst, IDLoc, Instructions);
1367 return false;
1368 }
Jack Carter543fdf82012-10-09 23:29:45 +00001369 const MCOperand &RegOp = Inst.getOperand(0);
1370 assert(RegOp.isReg() && "expected register operand kind");
1371 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001372 if (-32768 <= ImmValue && ImmValue <= 65535) {
1373 // For -32768 <= j <= 65535.
1374 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001375 tmpInst.setOpcode(Mips::ADDiu);
1376 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001377 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001378 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1379 Instructions.push_back(tmpInst);
1380 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001381 // For any other value of j that is representable as a 32-bit integer.
1382 // la d,j => lui d,hi16(j)
1383 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001384 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001385 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1386 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1387 Instructions.push_back(tmpInst);
1388 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001389 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001390 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1391 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1392 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1393 Instructions.push_back(tmpInst);
1394 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001395 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001396}
1397
Toma Tabacu0d64b202014-08-14 10:29:17 +00001398void
1399MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1400 SmallVectorImpl<MCInst> &Instructions) {
1401 // FIXME: If we do have a valid at register to use, we should generate a
1402 // slightly shorter sequence here.
1403 MCInst tmpInst;
1404 int ExprOperandNo = 1;
1405 // Sometimes the assembly parser will get the immediate expression as
1406 // a $zero + an immediate.
1407 if (Inst.getNumOperands() == 3) {
1408 assert(Inst.getOperand(1).getReg() ==
1409 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1410 ExprOperandNo = 2;
1411 }
1412 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1413 assert(SymOp.isExpr() && "expected symbol operand kind");
1414 const MCOperand &RegOp = Inst.getOperand(0);
1415 unsigned RegNo = RegOp.getReg();
1416 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1417 const MCSymbolRefExpr *HiExpr =
1418 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1419 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1420 const MCSymbolRefExpr *LoExpr =
1421 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1422 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1423 if (isGP64bit()) {
1424 // If it's a 64-bit architecture, expand to:
1425 // la d,sym => lui d,highest(sym)
1426 // ori d,d,higher(sym)
1427 // dsll d,d,16
1428 // ori d,d,hi16(sym)
1429 // dsll d,d,16
1430 // ori d,d,lo16(sym)
1431 const MCSymbolRefExpr *HighestExpr =
1432 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1433 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1434 const MCSymbolRefExpr *HigherExpr =
1435 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1436 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1437
1438 tmpInst.setOpcode(Mips::LUi);
1439 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1440 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1441 Instructions.push_back(tmpInst);
1442
1443 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1444 Instructions);
1445 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1446 Instructions);
1447 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1448 Instructions);
1449 } else {
1450 // Otherwise, expand to:
1451 // la d,sym => lui d,hi16(sym)
1452 // ori d,d,lo16(sym)
1453 tmpInst.setOpcode(Mips::LUi);
1454 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1455 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1456 Instructions.push_back(tmpInst);
1457
1458 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1459 Instructions);
1460 }
1461}
1462
Jack Carter9e65aa32013-03-22 00:05:30 +00001463void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001464 SmallVectorImpl<MCInst> &Instructions,
1465 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001466 const MCSymbolRefExpr *SR;
1467 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001468 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001469 const MCExpr *ExprOffset;
1470 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001471 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001472 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1473 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001474 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001475 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1476 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001477 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001478 if (isImmOpnd) {
1479 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1480 ImmOffset = Inst.getOperand(2).getImm();
1481 LoOffset = ImmOffset & 0x0000ffff;
1482 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001483 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001484 if (LoOffset & 0x8000)
1485 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001486 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001487 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001488 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001489 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001490 // These are some of the types of expansions we perform here:
1491 // 1) lw $8, sym => lui $8, %hi(sym)
1492 // lw $8, %lo(sym)($8)
1493 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1494 // add $8, $8, $9
1495 // lw $8, %lo(offset)($9)
1496 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1497 // add $at, $at, $8
1498 // lw $8, %lo(offset)($at)
1499 // 4) sw $8, sym => lui $at, %hi(sym)
1500 // sw $8, %lo(sym)($at)
1501 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1502 // add $at, $at, $8
1503 // sw $8, %lo(offset)($at)
1504 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1505 // ldc1 $f0, %lo(sym)($at)
1506 //
1507 // For load instructions we can use the destination register as a temporary
1508 // if base and dst are different (examples 1 and 2) and if the base register
1509 // is general purpose otherwise we must use $at (example 6) and error if it's
1510 // not available. For stores we must use $at (examples 4 and 5) because we
1511 // must not clobber the source register setting up the offset.
1512 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1513 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1514 unsigned RegClassIDOp0 =
1515 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1516 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1517 (RegClassIDOp0 == Mips::GPR64RegClassID);
1518 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001519 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001520 else {
1521 int AT = getATReg(IDLoc);
1522 // At this point we need AT to perform the expansions and we exit if it is
1523 // not available.
1524 if (!AT)
1525 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001526 TmpRegNum = getReg(
1527 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001528 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001529
Jack Carter9e65aa32013-03-22 00:05:30 +00001530 TempInst.setOpcode(Mips::LUi);
1531 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1532 if (isImmOpnd)
1533 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1534 else {
1535 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001536 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001537 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1538 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1539 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001540 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001541 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001542 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001543 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001544 }
1545 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001546 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001547 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001548 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001549 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001550 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001551 TempInst.setOpcode(Mips::ADDu);
1552 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1553 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1554 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1555 Instructions.push_back(TempInst);
1556 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001557 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001558 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001559 TempInst.setOpcode(Inst.getOpcode());
1560 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1561 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1562 if (isImmOpnd)
1563 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1564 else {
1565 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001566 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1567 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1568 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001569 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001570 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001571 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001572 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001573 }
1574 }
1575 Instructions.push_back(TempInst);
1576 TempInst.clear();
1577}
1578
Matheus Almeida595fcab2014-06-11 15:05:56 +00001579unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1580 // As described by the Mips32r2 spec, the registers Rd and Rs for
1581 // jalr.hb must be different.
1582 unsigned Opcode = Inst.getOpcode();
1583
1584 if (Opcode == Mips::JALR_HB &&
1585 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1586 return Match_RequiresDifferentSrcAndDst;
1587
1588 return Match_Success;
1589}
1590
David Blaikie960ea3f2014-06-08 16:18:35 +00001591bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1592 OperandVector &Operands,
1593 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001594 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001595 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001596
Jack Carterb4dbc172012-09-05 23:34:03 +00001597 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001598 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001599 unsigned MatchResult =
1600 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001601
1602 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 default:
1604 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001605 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001606 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001607 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001608 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001609 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001610 return false;
1611 }
1612 case Match_MissingFeature:
1613 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1614 return true;
1615 case Match_InvalidOperand: {
1616 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001617 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001618 if (ErrorInfo >= Operands.size())
1619 return Error(IDLoc, "too few operands for instruction");
1620
David Blaikie960ea3f2014-06-08 16:18:35 +00001621 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 if (ErrorLoc == SMLoc())
1623 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001624 }
1625
1626 return Error(ErrorLoc, "invalid operand for instruction");
1627 }
1628 case Match_MnemonicFail:
1629 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001630 case Match_RequiresDifferentSrcAndDst:
1631 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001632 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001633 return true;
1634}
1635
Toma Tabacu13964452014-09-04 13:23:44 +00001636void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001637 if ((RegIndex != 0) &&
1638 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001639 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001640 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001641 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001642 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001643 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001644 }
1645}
1646
Daniel Sandersef638fe2014-10-03 15:37:37 +00001647void
1648MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1649 SMRange Range, bool ShowColors) {
1650 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001651 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001652 ShowColors);
1653}
1654
Jack Carter1ac53222013-02-20 23:11:17 +00001655int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001656 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001657
Vladimir Medic4c299852013-11-06 11:27:05 +00001658 CC = StringSwitch<unsigned>(Name)
1659 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001660 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001661 .Case("a0", 4)
1662 .Case("a1", 5)
1663 .Case("a2", 6)
1664 .Case("a3", 7)
1665 .Case("v0", 2)
1666 .Case("v1", 3)
1667 .Case("s0", 16)
1668 .Case("s1", 17)
1669 .Case("s2", 18)
1670 .Case("s3", 19)
1671 .Case("s4", 20)
1672 .Case("s5", 21)
1673 .Case("s6", 22)
1674 .Case("s7", 23)
1675 .Case("k0", 26)
1676 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001677 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001678 .Case("sp", 29)
1679 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001680 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001681 .Case("ra", 31)
1682 .Case("t0", 8)
1683 .Case("t1", 9)
1684 .Case("t2", 10)
1685 .Case("t3", 11)
1686 .Case("t4", 12)
1687 .Case("t5", 13)
1688 .Case("t6", 14)
1689 .Case("t7", 15)
1690 .Case("t8", 24)
1691 .Case("t9", 25)
1692 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001693
Toma Tabacufda445c2014-09-15 15:33:01 +00001694 if (!(isABI_N32() || isABI_N64()))
1695 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001696
Daniel Sandersef638fe2014-10-03 15:37:37 +00001697 if (12 <= CC && CC <= 15) {
1698 // Name is one of t4-t7
1699 AsmToken RegTok = getLexer().peekTok();
1700 SMRange RegRange = RegTok.getLocRange();
1701
1702 StringRef FixedName = StringSwitch<StringRef>(Name)
1703 .Case("t4", "t0")
1704 .Case("t5", "t1")
1705 .Case("t6", "t2")
1706 .Case("t7", "t3")
1707 .Default("");
1708 assert(FixedName != "" && "Register name is not one of t4-t7.");
1709
1710 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1711 "Did you mean $" + FixedName + "?", RegRange);
1712 }
1713
Toma Tabacufda445c2014-09-15 15:33:01 +00001714 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1715 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1716 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1717 if (8 <= CC && CC <= 11)
1718 CC += 4;
1719
1720 if (CC == -1)
1721 CC = StringSwitch<unsigned>(Name)
1722 .Case("a4", 8)
1723 .Case("a5", 9)
1724 .Case("a6", 10)
1725 .Case("a7", 11)
1726 .Case("kt0", 26)
1727 .Case("kt1", 27)
1728 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001729
1730 return CC;
1731}
Jack Carterd0bd6422013-04-18 00:41:53 +00001732
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001733int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001734
Jack Cartera63b16a2012-09-07 00:23:42 +00001735 if (Name[0] == 'f') {
1736 StringRef NumString = Name.substr(1);
1737 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001738 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001739 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001740 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001741 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001742 return IntVal;
1743 }
1744 return -1;
1745}
Jack Cartera63b16a2012-09-07 00:23:42 +00001746
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001747int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1748
1749 if (Name.startswith("fcc")) {
1750 StringRef NumString = Name.substr(3);
1751 unsigned IntVal;
1752 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001753 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001754 if (IntVal > 7) // There are only 8 fcc registers.
1755 return -1;
1756 return IntVal;
1757 }
1758 return -1;
1759}
1760
1761int MipsAsmParser::matchACRegisterName(StringRef Name) {
1762
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001763 if (Name.startswith("ac")) {
1764 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001765 unsigned IntVal;
1766 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001767 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001768 if (IntVal > 3) // There are only 3 acc registers.
1769 return -1;
1770 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001771 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001772 return -1;
1773}
Jack Carterd0bd6422013-04-18 00:41:53 +00001774
Jack Carter5dc8ac92013-09-25 23:50:44 +00001775int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1776 unsigned IntVal;
1777
1778 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1779 return -1;
1780
1781 if (IntVal > 31)
1782 return -1;
1783
1784 return IntVal;
1785}
1786
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001787int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1788 int CC;
1789
1790 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001791 .Case("msair", 0)
1792 .Case("msacsr", 1)
1793 .Case("msaaccess", 2)
1794 .Case("msasave", 3)
1795 .Case("msamodify", 4)
1796 .Case("msarequest", 5)
1797 .Case("msamap", 6)
1798 .Case("msaunmap", 7)
1799 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001800
1801 return CC;
1802}
1803
Jack Carter0b744b32012-10-04 02:29:46 +00001804bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1805 if (Reg > 31)
1806 return false;
1807
Toma Tabacu3c24b042014-09-05 15:43:21 +00001808 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001809 return true;
1810}
1811
Matheus Almeida7de68e72014-06-18 14:46:05 +00001812int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001813 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001814 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001815 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00001816 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001817 return AT;
1818}
Jack Carter0b744b32012-10-04 02:29:46 +00001819
Jack Carterd0bd6422013-04-18 00:41:53 +00001820unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001821 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001822}
1823
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001824unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001825 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001826 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001827}
1828
Jack Carter873c7242013-01-12 01:03:14 +00001829int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001830 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001831 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001832 return -1;
1833
Jack Carter873c7242013-01-12 01:03:14 +00001834 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001835}
1836
Toma Tabacu13964452014-09-04 13:23:44 +00001837bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1838 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001839
Jack Carter30a59822012-10-04 04:03:53 +00001840 // Check if the current operand has a custom associated parser, if so, try to
1841 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001842 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1843 if (ResTy == MatchOperand_Success)
1844 return false;
1845 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1846 // there was a match, but an error occurred, in which case, just return that
1847 // the operand parsing failed.
1848 if (ResTy == MatchOperand_ParseFail)
1849 return true;
1850
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001851 DEBUG(dbgs() << ".. Generic Parser\n");
1852
Jack Carterb4dbc172012-09-05 23:34:03 +00001853 switch (getLexer().getKind()) {
1854 default:
1855 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1856 return true;
1857 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001858 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001859 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001860
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001861 // Almost all registers have been parsed by custom parsers. There is only
1862 // one exception to this. $zero (and it's alias $0) will reach this point
1863 // for div, divu, and similar instructions because it is not an operand
1864 // to the instruction definition but an explicit register. Special case
1865 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001866 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001867 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001868
Jack Carterd0bd6422013-04-18 00:41:53 +00001869 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001870 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001871 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001872 return true;
1873
Jack Carter873c7242013-01-12 01:03:14 +00001874 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001875 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001876 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001877 const MCExpr *Res =
1878 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001879
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001880 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001881 return false;
1882 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001883 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001884 case AsmToken::LParen:
1885 case AsmToken::Minus:
1886 case AsmToken::Plus:
1887 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001888 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001889 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001890 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001891 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001892 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001893 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001894 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001895 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001896 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001897 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001898 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001899 return true;
1900
Jack Carter873c7242013-01-12 01:03:14 +00001901 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1902
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001903 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001904 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001905 } // case AsmToken::Percent
1906 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001907 return true;
1908}
1909
Vladimir Medic4c299852013-11-06 11:27:05 +00001910const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001911 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001912 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001913 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001914 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001915 // It's a constant, evaluate reloc value.
1916 int16_t Val;
1917 switch (getVariantKind(RelocStr)) {
1918 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1919 // Get the 1st 16-bits.
1920 Val = MCE->getValue() & 0xffff;
1921 break;
1922 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1923 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1924 // 16 bits being negative.
1925 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1926 break;
1927 case MCSymbolRefExpr::VK_Mips_HIGHER:
1928 // Get the 3rd 16-bits.
1929 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1930 break;
1931 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1932 // Get the 4th 16-bits.
1933 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1934 break;
1935 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00001936 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001937 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001938 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001939 }
1940
Jack Carterb5cf5902013-04-17 00:18:04 +00001941 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001942 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001943 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001944 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001945 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001946 return Res;
1947 }
1948
1949 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001950 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1951
Sasa Stankovic06c47802014-04-03 10:37:45 +00001952 // Try to create target expression.
1953 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1954 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001955
Jack Carterd0bd6422013-04-18 00:41:53 +00001956 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1957 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001958 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1959 return Res;
1960 }
1961
1962 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001963 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1964 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1965 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001966 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001967 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001968 return Expr;
1969}
1970
1971bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1972
1973 switch (Expr->getKind()) {
1974 case MCExpr::Constant:
1975 return true;
1976 case MCExpr::SymbolRef:
1977 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1978 case MCExpr::Binary:
1979 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1980 if (!isEvaluated(BE->getLHS()))
1981 return false;
1982 return isEvaluated(BE->getRHS());
1983 }
1984 case MCExpr::Unary:
1985 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001986 case MCExpr::Target:
1987 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001988 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001989 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001990}
Jack Carterd0bd6422013-04-18 00:41:53 +00001991
Jack Carterb5cf5902013-04-17 00:18:04 +00001992bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001993 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001994 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001995 if (Tok.isNot(AsmToken::Identifier))
1996 return true;
1997
1998 std::string Str = Tok.getIdentifier().str();
1999
Jack Carterd0bd6422013-04-18 00:41:53 +00002000 Parser.Lex(); // Eat the identifier.
2001 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002002 const MCExpr *IdVal;
2003 SMLoc EndLoc;
2004
2005 if (getLexer().getKind() == AsmToken::LParen) {
2006 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002007 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002008 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002009 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002010 const AsmToken &nextTok = Parser.getTok();
2011 if (nextTok.isNot(AsmToken::Identifier))
2012 return true;
2013 Str += "(%";
2014 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002015 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002016 if (getLexer().getKind() != AsmToken::LParen)
2017 return true;
2018 } else
2019 break;
2020 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002021 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002022 return true;
2023
2024 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002025 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002026
2027 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002028 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002029
Jack Carterd0bd6422013-04-18 00:41:53 +00002030 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002031 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002032}
2033
Jack Carterb4dbc172012-09-05 23:34:03 +00002034bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2035 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002036 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002037 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002038 if (ResTy == MatchOperand_Success) {
2039 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002040 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002041 StartLoc = Operand.getStartLoc();
2042 EndLoc = Operand.getEndLoc();
2043
2044 // AFAIK, we only support numeric registers and named GPR's in CFI
2045 // directives.
2046 // Don't worry about eating tokens before failing. Using an unrecognised
2047 // register is a parse error.
2048 if (Operand.isGPRAsmReg()) {
2049 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002050 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002051 }
2052
2053 return (RegNo == (unsigned)-1);
2054 }
2055
2056 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002057 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002058}
2059
Jack Carterb5cf5902013-04-17 00:18:04 +00002060bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00002061 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002062 bool Result = true;
2063
2064 while (getLexer().getKind() == AsmToken::LParen)
2065 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002066
Jack Carterd0bd6422013-04-18 00:41:53 +00002067 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002068 default:
2069 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002070 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002071 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002072 case AsmToken::Integer:
2073 case AsmToken::Minus:
2074 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002075 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002076 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002077 else
2078 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002079 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002080 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002081 break;
Jack Carter873c7242013-01-12 01:03:14 +00002082 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002083 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002084 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002085 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002086}
2087
David Blaikie960ea3f2014-06-08 16:18:35 +00002088MipsAsmParser::OperandMatchResultTy
2089MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002090 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002091 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002092 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002093 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002094 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002095 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002096 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002097
Jack Carterb5cf5902013-04-17 00:18:04 +00002098 if (getLexer().getKind() == AsmToken::LParen) {
2099 Parser.Lex();
2100 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002101 }
2102
Jack Carterb5cf5902013-04-17 00:18:04 +00002103 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002105 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002106
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002108 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002109 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2110 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002111 SMLoc E =
2112 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002113 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002114 return MatchOperand_Success;
2115 }
2116 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002117 SMLoc E =
2118 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002119
Jack Carterd0bd6422013-04-18 00:41:53 +00002120 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002121 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002122 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002123 S, E, *this);
2124 Operands.push_back(
2125 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002126 return MatchOperand_Success;
2127 }
2128 Error(Parser.getTok().getLoc(), "'(' expected");
2129 return MatchOperand_ParseFail;
2130 }
2131
Jack Carterd0bd6422013-04-18 00:41:53 +00002132 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002133 }
2134
Toma Tabacu13964452014-09-04 13:23:44 +00002135 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002136 if (Res != MatchOperand_Success)
2137 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002138
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002139 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002140 Error(Parser.getTok().getLoc(), "')' expected");
2141 return MatchOperand_ParseFail;
2142 }
2143
Jack Carter873c7242013-01-12 01:03:14 +00002144 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2145
Jack Carterd0bd6422013-04-18 00:41:53 +00002146 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002147
Craig Topper062a2ba2014-04-25 05:30:21 +00002148 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002149 IdVal = MCConstantExpr::Create(0, getContext());
2150
Jack Carterd0bd6422013-04-18 00:41:53 +00002151 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002152 std::unique_ptr<MipsOperand> op(
2153 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002154 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002155 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002156 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002157 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002158 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2159 int64_t Imm;
2160 if (IdVal->EvaluateAsAbsolute(Imm))
2161 IdVal = MCConstantExpr::Create(Imm, getContext());
2162 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2163 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2164 getContext());
2165 }
2166
David Blaikie960ea3f2014-06-08 16:18:35 +00002167 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002168 return MatchOperand_Success;
2169}
2170
David Blaikie960ea3f2014-06-08 16:18:35 +00002171bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002172
Jack Carterd76b2372013-03-21 21:44:16 +00002173 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2174 if (Sym) {
2175 SMLoc S = Parser.getTok().getLoc();
2176 const MCExpr *Expr;
2177 if (Sym->isVariable())
2178 Expr = Sym->getVariableValue();
2179 else
2180 return false;
2181 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002182 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002183 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002184 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002185 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002186 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002187 if (ResTy == MatchOperand_Success) {
2188 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002189 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002190 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002191 llvm_unreachable("Should never ParseFail");
2192 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002193 }
2194 } else if (Expr->getKind() == MCExpr::Constant) {
2195 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002196 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002197 Operands.push_back(
2198 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002199 return true;
2200 }
2201 }
2202 return false;
2203}
Jack Carterd0bd6422013-04-18 00:41:53 +00002204
Jack Carter873c7242013-01-12 01:03:14 +00002205MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002206MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002207 StringRef Identifier,
2208 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002209 int Index = matchCPURegisterName(Identifier);
2210 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002211 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002212 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2213 return MatchOperand_Success;
2214 }
2215
2216 Index = matchFPURegisterName(Identifier);
2217 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002218 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002219 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2220 return MatchOperand_Success;
2221 }
2222
2223 Index = matchFCCRegisterName(Identifier);
2224 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002225 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002226 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2227 return MatchOperand_Success;
2228 }
2229
2230 Index = matchACRegisterName(Identifier);
2231 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002232 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002233 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2234 return MatchOperand_Success;
2235 }
2236
2237 Index = matchMSA128RegisterName(Identifier);
2238 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002239 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002240 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2241 return MatchOperand_Success;
2242 }
2243
2244 Index = matchMSA128CtrlRegisterName(Identifier);
2245 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002246 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002247 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2248 return MatchOperand_Success;
2249 }
2250
2251 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002252}
2253
2254MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002255MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002256 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002257
2258 if (Token.is(AsmToken::Identifier)) {
2259 DEBUG(dbgs() << ".. identifier\n");
2260 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002261 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002262 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002263 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002264 } else if (Token.is(AsmToken::Integer)) {
2265 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002266 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002267 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2268 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002269 return MatchOperand_Success;
2270 }
2271
2272 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2273
2274 return MatchOperand_NoMatch;
2275}
2276
David Blaikie960ea3f2014-06-08 16:18:35 +00002277MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002278MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
2279 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002280
2281 auto Token = Parser.getTok();
2282
2283 SMLoc S = Token.getLoc();
2284
2285 if (Token.isNot(AsmToken::Dollar)) {
2286 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2287 if (Token.is(AsmToken::Identifier)) {
2288 if (searchSymbolAlias(Operands))
2289 return MatchOperand_Success;
2290 }
2291 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2292 return MatchOperand_NoMatch;
2293 }
2294 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002295
Toma Tabacu13964452014-09-04 13:23:44 +00002296 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002297 if (ResTy == MatchOperand_Success) {
2298 Parser.Lex(); // $
2299 Parser.Lex(); // identifier
2300 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002301 return ResTy;
2302}
2303
2304MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002305MipsAsmParser::parseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002306 switch (getLexer().getKind()) {
2307 default:
2308 return MatchOperand_NoMatch;
2309 case AsmToken::LParen:
2310 case AsmToken::Minus:
2311 case AsmToken::Plus:
2312 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002313 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002314 case AsmToken::String:
2315 break;
2316 }
2317
2318 const MCExpr *IdVal;
2319 SMLoc S = Parser.getTok().getLoc();
2320 if (getParser().parseExpression(IdVal))
2321 return MatchOperand_ParseFail;
2322
2323 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2324 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2325 return MatchOperand_Success;
2326}
2327
David Blaikie960ea3f2014-06-08 16:18:35 +00002328MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002329MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
2330 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002331
2332 SMLoc S = getLexer().getLoc();
2333
2334 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002335 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002336 if (ResTy != MatchOperand_NoMatch)
2337 return ResTy;
2338
Daniel Sanders315386c2014-04-01 10:40:14 +00002339 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002340 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002341 if (ResTy != MatchOperand_NoMatch)
2342 return ResTy;
2343
Daniel Sandersffd84362014-04-01 10:41:48 +00002344 const MCExpr *Expr = nullptr;
2345 if (Parser.parseExpression(Expr)) {
2346 // We have no way of knowing if a symbol was consumed so we must ParseFail
2347 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002348 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002349 Operands.push_back(
2350 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002351 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002352}
2353
Vladimir Medic2b953d02013-10-01 09:48:56 +00002354MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002355MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002356 const MCExpr *IdVal;
2357 // If the first token is '$' we may have register operand.
2358 if (Parser.getTok().is(AsmToken::Dollar))
2359 return MatchOperand_NoMatch;
2360 SMLoc S = Parser.getTok().getLoc();
2361 if (getParser().parseExpression(IdVal))
2362 return MatchOperand_ParseFail;
2363 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002364 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002365 int64_t Val = MCE->getValue();
2366 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2367 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002368 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002369 return MatchOperand_Success;
2370}
2371
Matheus Almeida779c5932013-11-18 12:32:49 +00002372MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002373MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002374 switch (getLexer().getKind()) {
2375 default:
2376 return MatchOperand_NoMatch;
2377 case AsmToken::LParen:
2378 case AsmToken::Plus:
2379 case AsmToken::Minus:
2380 case AsmToken::Integer:
2381 break;
2382 }
2383
2384 const MCExpr *Expr;
2385 SMLoc S = Parser.getTok().getLoc();
2386
2387 if (getParser().parseExpression(Expr))
2388 return MatchOperand_ParseFail;
2389
2390 int64_t Val;
2391 if (!Expr->EvaluateAsAbsolute(Val)) {
2392 Error(S, "expected immediate value");
2393 return MatchOperand_ParseFail;
2394 }
2395
2396 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2397 // and because the CPU always adds one to the immediate field, the allowed
2398 // range becomes 1..4. We'll only check the range here and will deal
2399 // with the addition/subtraction when actually decoding/encoding
2400 // the instruction.
2401 if (Val < 1 || Val > 4) {
2402 Error(S, "immediate not in range (1..4)");
2403 return MatchOperand_ParseFail;
2404 }
2405
Jack Carter3b2c96e2014-01-22 23:31:38 +00002406 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002407 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002408 return MatchOperand_Success;
2409}
2410
Jack Carterdc1e35d2012-09-06 20:00:02 +00002411MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2412
Vladimir Medic4c299852013-11-06 11:27:05 +00002413 MCSymbolRefExpr::VariantKind VK =
2414 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2415 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2416 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2417 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2418 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2419 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2420 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2421 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2422 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2423 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2424 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2425 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2426 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2427 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2428 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2429 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2430 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2431 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002432 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2433 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2434 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2435 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2436 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2437 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002438 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2439 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002440 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002441
Matheus Almeida2852af82014-04-22 10:15:54 +00002442 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002443
Jack Carterdc1e35d2012-09-06 20:00:02 +00002444 return VK;
2445}
Jack Cartera63b16a2012-09-07 00:23:42 +00002446
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002447/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2448/// either this.
2449/// ::= '(', register, ')'
2450/// handle it before we iterate so we don't get tripped up by the lack of
2451/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002452bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002453 if (getLexer().is(AsmToken::LParen)) {
2454 Operands.push_back(
2455 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2456 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002457 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002458 SMLoc Loc = getLexer().getLoc();
2459 Parser.eatToEndOfStatement();
2460 return Error(Loc, "unexpected token in argument list");
2461 }
2462 if (Parser.getTok().isNot(AsmToken::RParen)) {
2463 SMLoc Loc = getLexer().getLoc();
2464 Parser.eatToEndOfStatement();
2465 return Error(Loc, "unexpected token, expected ')'");
2466 }
2467 Operands.push_back(
2468 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2469 Parser.Lex();
2470 }
2471 return false;
2472}
2473
2474/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2475/// either one of these.
2476/// ::= '[', register, ']'
2477/// ::= '[', integer, ']'
2478/// handle it before we iterate so we don't get tripped up by the lack of
2479/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002480bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002481 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002482 if (getLexer().is(AsmToken::LBrac)) {
2483 Operands.push_back(
2484 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2485 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002486 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002487 SMLoc Loc = getLexer().getLoc();
2488 Parser.eatToEndOfStatement();
2489 return Error(Loc, "unexpected token in argument list");
2490 }
2491 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2492 SMLoc Loc = getLexer().getLoc();
2493 Parser.eatToEndOfStatement();
2494 return Error(Loc, "unexpected token, expected ']'");
2495 }
2496 Operands.push_back(
2497 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2498 Parser.Lex();
2499 }
2500 return false;
2501}
2502
David Blaikie960ea3f2014-06-08 16:18:35 +00002503bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2504 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002505 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002506
2507 // We have reached first instruction, module directive are now forbidden.
2508 getTargetStreamer().forbidModuleDirective();
2509
Vladimir Medic74593e62013-07-17 15:00:42 +00002510 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002511 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002512 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002513 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002514 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002515 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002516 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002517
2518 // Read the remaining operands.
2519 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2520 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002521 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002522 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002523 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002524 return Error(Loc, "unexpected token in argument list");
2525 }
Toma Tabacu13964452014-09-04 13:23:44 +00002526 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002527 return true;
2528 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002529
Jack Carterd0bd6422013-04-18 00:41:53 +00002530 while (getLexer().is(AsmToken::Comma)) {
2531 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002532 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002533 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002534 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002535 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002536 return Error(Loc, "unexpected token in argument list");
2537 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002538 // Parse bracket and parenthesis suffixes before we iterate
2539 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002540 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002541 return true;
2542 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002543 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002544 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002545 }
2546 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002547 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2548 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002549 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002550 return Error(Loc, "unexpected token in argument list");
2551 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002552 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002553 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002554}
2555
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002556bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002557 SMLoc Loc = getLexer().getLoc();
2558 Parser.eatToEndOfStatement();
2559 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002560}
2561
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002562bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002563 return Error(Loc, ErrorMsg);
2564}
2565
Jack Carter0b744b32012-10-04 02:29:46 +00002566bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 // Line should look like: ".set noat".
2568 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002569 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002570 // eat noat
2571 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002572 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002573 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002574 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002575 return false;
2576 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002577 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002578 return false;
2579}
Jack Carterd0bd6422013-04-18 00:41:53 +00002580
Jack Carter0b744b32012-10-04 02:29:46 +00002581bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002582 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002583 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002584 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002585 getParser().Lex();
2586 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002587 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002588 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002589 return false;
2590 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002591 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002592 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002593 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002594 return false;
2595 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002596 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002597 const AsmToken &Reg = Parser.getTok();
2598 if (Reg.is(AsmToken::Identifier)) {
2599 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2600 } else if (Reg.is(AsmToken::Integer)) {
2601 AtRegNo = Reg.getIntVal();
2602 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002603 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002604 return false;
2605 }
Jack Carter1ac53222013-02-20 23:11:17 +00002606
Daniel Sanders71a89d922014-03-25 13:01:06 +00002607 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002608 reportParseError("unexpected token in statement");
2609 return false;
2610 }
2611
Toma Tabacu9db22db2014-09-09 10:15:38 +00002612 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002613 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002614 return false;
2615 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002616 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002617
2618 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002619 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002620 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002621 }
2622 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002623 return false;
2624 } else {
2625 reportParseError("unexpected token in statement");
2626 return false;
2627 }
2628}
2629
2630bool MipsAsmParser::parseSetReorderDirective() {
2631 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002632 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002633 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002634 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002635 return false;
2636 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002637 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002638 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002639 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002640 return false;
2641}
2642
2643bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002644 Parser.Lex();
2645 // If this is not the end of the statement, report an error.
2646 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002647 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002648 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002649 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002650 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002651 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002652 Parser.Lex(); // Consume the EndOfStatement.
2653 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002654}
2655
2656bool MipsAsmParser::parseSetMacroDirective() {
2657 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002658 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002659 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002660 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002661 return false;
2662 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002663 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002664 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002665 return false;
2666}
2667
2668bool MipsAsmParser::parseSetNoMacroDirective() {
2669 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002670 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002671 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002672 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002673 return false;
2674 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002675 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002676 reportParseError("`noreorder' must be set before `nomacro'");
2677 return false;
2678 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002679 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002680 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002681 return false;
2682}
Jack Carterd76b2372013-03-21 21:44:16 +00002683
Daniel Sanders44934432014-08-07 12:03:36 +00002684bool MipsAsmParser::parseSetMsaDirective() {
2685 Parser.Lex();
2686
2687 // If this is not the end of the statement, report an error.
2688 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002689 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002690
2691 setFeatureBits(Mips::FeatureMSA, "msa");
2692 getTargetStreamer().emitDirectiveSetMsa();
2693 return false;
2694}
2695
2696bool MipsAsmParser::parseSetNoMsaDirective() {
2697 Parser.Lex();
2698
2699 // If this is not the end of the statement, report an error.
2700 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002701 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002702
2703 clearFeatureBits(Mips::FeatureMSA, "msa");
2704 getTargetStreamer().emitDirectiveSetNoMsa();
2705 return false;
2706}
2707
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002708bool MipsAsmParser::parseSetNoDspDirective() {
2709 Parser.Lex(); // Eat "nodsp".
2710
2711 // If this is not the end of the statement, report an error.
2712 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2713 reportParseError("unexpected token, expected end of statement");
2714 return false;
2715 }
2716
2717 clearFeatureBits(Mips::FeatureDSP, "dsp");
2718 getTargetStreamer().emitDirectiveSetNoDsp();
2719 return false;
2720}
2721
Jack Carter39536722014-01-22 23:08:42 +00002722bool MipsAsmParser::parseSetNoMips16Directive() {
2723 Parser.Lex();
2724 // If this is not the end of the statement, report an error.
2725 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002726 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00002727 return false;
2728 }
2729 // For now do nothing.
2730 Parser.Lex(); // Consume the EndOfStatement.
2731 return false;
2732}
2733
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002734bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002735 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002736 // Line can be: .set fp=32
2737 // .set fp=xx
2738 // .set fp=64
2739 Parser.Lex(); // Eat fp token
2740 AsmToken Tok = Parser.getTok();
2741 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002742 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002743 return false;
2744 }
2745 Parser.Lex(); // Eat '=' token.
2746 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002747
2748 if (!parseFpABIValue(FpAbiVal, ".set"))
2749 return false;
2750
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002751 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002752 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002753 return false;
2754 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002755 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002756 Parser.Lex(); // Consume the EndOfStatement.
2757 return false;
2758}
2759
Toma Tabacu9db22db2014-09-09 10:15:38 +00002760bool MipsAsmParser::parseSetPopDirective() {
2761 SMLoc Loc = getLexer().getLoc();
2762
2763 Parser.Lex();
2764 if (getLexer().isNot(AsmToken::EndOfStatement))
2765 return reportParseError("unexpected token, expected end of statement");
2766
2767 // Always keep an element on the options "stack" to prevent the user
2768 // from changing the initial options. This is how we remember them.
2769 if (AssemblerOptions.size() == 2)
2770 return reportParseError(Loc, ".set pop with no .set push");
2771
2772 AssemblerOptions.pop_back();
2773 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2774
2775 getTargetStreamer().emitDirectiveSetPop();
2776 return false;
2777}
2778
2779bool MipsAsmParser::parseSetPushDirective() {
2780 Parser.Lex();
2781 if (getLexer().isNot(AsmToken::EndOfStatement))
2782 return reportParseError("unexpected token, expected end of statement");
2783
2784 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00002785 AssemblerOptions.push_back(
2786 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00002787
2788 getTargetStreamer().emitDirectiveSetPush();
2789 return false;
2790}
2791
Jack Carterd76b2372013-03-21 21:44:16 +00002792bool MipsAsmParser::parseSetAssignment() {
2793 StringRef Name;
2794 const MCExpr *Value;
2795
2796 if (Parser.parseIdentifier(Name))
2797 reportParseError("expected identifier after .set");
2798
2799 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00002800 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00002801 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002802
Jack Carter3b2c96e2014-01-22 23:31:38 +00002803 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002804 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002805
Jack Carterd0bd6422013-04-18 00:41:53 +00002806 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002807 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002808 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002809 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002810 Sym = getContext().GetOrCreateSymbol(Name);
2811 Sym->setVariableValue(Value);
2812
2813 return false;
2814}
Jack Carterd0bd6422013-04-18 00:41:53 +00002815
Toma Tabacu26647792014-09-09 12:52:14 +00002816bool MipsAsmParser::parseSetMips0Directive() {
2817 Parser.Lex();
2818 if (getLexer().isNot(AsmToken::EndOfStatement))
2819 return reportParseError("unexpected token, expected end of statement");
2820
2821 // Reset assembler options to their initial values.
2822 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
2823 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
2824
2825 getTargetStreamer().emitDirectiveSetMips0();
2826 return false;
2827}
2828
Toma Tabacu85618b32014-08-19 14:22:52 +00002829bool MipsAsmParser::parseSetArchDirective() {
2830 Parser.Lex();
2831 if (getLexer().isNot(AsmToken::Equal))
2832 return reportParseError("unexpected token, expected equals sign");
2833
2834 Parser.Lex();
2835 StringRef Arch;
2836 if (Parser.parseIdentifier(Arch))
2837 return reportParseError("expected arch identifier");
2838
2839 StringRef ArchFeatureName =
2840 StringSwitch<StringRef>(Arch)
2841 .Case("mips1", "mips1")
2842 .Case("mips2", "mips2")
2843 .Case("mips3", "mips3")
2844 .Case("mips4", "mips4")
2845 .Case("mips5", "mips5")
2846 .Case("mips32", "mips32")
2847 .Case("mips32r2", "mips32r2")
2848 .Case("mips32r6", "mips32r6")
2849 .Case("mips64", "mips64")
2850 .Case("mips64r2", "mips64r2")
2851 .Case("mips64r6", "mips64r6")
2852 .Case("cnmips", "cnmips")
2853 .Case("r4000", "mips3") // This is an implementation of Mips3.
2854 .Default("");
2855
2856 if (ArchFeatureName.empty())
2857 return reportParseError("unsupported architecture");
2858
2859 selectArch(ArchFeatureName);
2860 getTargetStreamer().emitDirectiveSetArch(Arch);
2861 return false;
2862}
2863
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002864bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2865 Parser.Lex();
2866 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002867 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002868
Matheus Almeida2852af82014-04-22 10:15:54 +00002869 switch (Feature) {
2870 default:
2871 llvm_unreachable("Unimplemented feature");
2872 case Mips::FeatureDSP:
2873 setFeatureBits(Mips::FeatureDSP, "dsp");
2874 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002875 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002876 case Mips::FeatureMicroMips:
2877 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002878 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002879 case Mips::FeatureMips16:
2880 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002881 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002882 case Mips::FeatureMips1:
2883 selectArch("mips1");
2884 getTargetStreamer().emitDirectiveSetMips1();
2885 break;
2886 case Mips::FeatureMips2:
2887 selectArch("mips2");
2888 getTargetStreamer().emitDirectiveSetMips2();
2889 break;
2890 case Mips::FeatureMips3:
2891 selectArch("mips3");
2892 getTargetStreamer().emitDirectiveSetMips3();
2893 break;
2894 case Mips::FeatureMips4:
2895 selectArch("mips4");
2896 getTargetStreamer().emitDirectiveSetMips4();
2897 break;
2898 case Mips::FeatureMips5:
2899 selectArch("mips5");
2900 getTargetStreamer().emitDirectiveSetMips5();
2901 break;
2902 case Mips::FeatureMips32:
2903 selectArch("mips32");
2904 getTargetStreamer().emitDirectiveSetMips32();
2905 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002906 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002907 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002908 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002909 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002910 case Mips::FeatureMips32r6:
2911 selectArch("mips32r6");
2912 getTargetStreamer().emitDirectiveSetMips32R6();
2913 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002914 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002915 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002916 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002917 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002918 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002919 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002920 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002921 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002922 case Mips::FeatureMips64r6:
2923 selectArch("mips64r6");
2924 getTargetStreamer().emitDirectiveSetMips64R6();
2925 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002926 }
2927 return false;
2928}
2929
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002930bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2931 if (getLexer().isNot(AsmToken::Comma)) {
2932 SMLoc Loc = getLexer().getLoc();
2933 Parser.eatToEndOfStatement();
2934 return Error(Loc, ErrorStr);
2935 }
2936
Matheus Almeida2852af82014-04-22 10:15:54 +00002937 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002938 return true;
2939}
2940
Toma Tabacuc4c202a2014-10-01 14:53:19 +00002941bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002942 if (AssemblerOptions.back()->isReorder())
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002943 Warning(Loc, ".cpload in reorder section");
2944
2945 // FIXME: Warn if cpload is used in Mips16 mode.
2946
David Blaikie960ea3f2014-06-08 16:18:35 +00002947 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00002948 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002949 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2950 reportParseError("expected register containing function address");
2951 return false;
2952 }
2953
David Blaikie960ea3f2014-06-08 16:18:35 +00002954 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2955 if (!RegOpnd.isGPRAsmReg()) {
2956 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002957 return false;
2958 }
2959
Toma Tabacuc4c202a2014-10-01 14:53:19 +00002960 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002961 return false;
2962}
2963
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002964bool MipsAsmParser::parseDirectiveCPSetup() {
2965 unsigned FuncReg;
2966 unsigned Save;
2967 bool SaveIsReg = true;
2968
Matheus Almeida7e815762014-06-18 13:08:59 +00002969 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00002970 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002971 if (ResTy == MatchOperand_NoMatch) {
2972 reportParseError("expected register containing function address");
2973 Parser.eatToEndOfStatement();
2974 return false;
2975 }
2976
2977 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2978 if (!FuncRegOpnd.isGPRAsmReg()) {
2979 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2980 Parser.eatToEndOfStatement();
2981 return false;
2982 }
2983
2984 FuncReg = FuncRegOpnd.getGPR32Reg();
2985 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002986
Toma Tabacu65f10572014-09-16 15:00:52 +00002987 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002988 return true;
2989
Toma Tabacu13964452014-09-04 13:23:44 +00002990 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002991 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002992 const AsmToken &Tok = Parser.getTok();
2993 if (Tok.is(AsmToken::Integer)) {
2994 Save = Tok.getIntVal();
2995 SaveIsReg = false;
2996 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002997 } else {
2998 reportParseError("expected save register or stack offset");
2999 Parser.eatToEndOfStatement();
3000 return false;
3001 }
3002 } else {
3003 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3004 if (!SaveOpnd.isGPRAsmReg()) {
3005 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3006 Parser.eatToEndOfStatement();
3007 return false;
3008 }
3009 Save = SaveOpnd.getGPR32Reg();
3010 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003011
Toma Tabacu65f10572014-09-16 15:00:52 +00003012 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003013 return true;
3014
3015 StringRef Name;
3016 if (Parser.parseIdentifier(Name))
3017 reportParseError("expected identifier");
3018 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003019
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003020 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003021 return false;
3022}
3023
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003024bool MipsAsmParser::parseDirectiveNaN() {
3025 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3026 const AsmToken &Tok = Parser.getTok();
3027
3028 if (Tok.getString() == "2008") {
3029 Parser.Lex();
3030 getTargetStreamer().emitDirectiveNaN2008();
3031 return false;
3032 } else if (Tok.getString() == "legacy") {
3033 Parser.Lex();
3034 getTargetStreamer().emitDirectiveNaNLegacy();
3035 return false;
3036 }
3037 }
3038 // If we don't recognize the option passed to the .nan
3039 // directive (e.g. no option or unknown option), emit an error.
3040 reportParseError("invalid option in .nan directive");
3041 return false;
3042}
3043
Jack Carter0b744b32012-10-04 02:29:46 +00003044bool MipsAsmParser::parseDirectiveSet() {
3045
Jack Carterd0bd6422013-04-18 00:41:53 +00003046 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003047 const AsmToken &Tok = Parser.getTok();
3048
3049 if (Tok.getString() == "noat") {
3050 return parseSetNoAtDirective();
3051 } else if (Tok.getString() == "at") {
3052 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003053 } else if (Tok.getString() == "arch") {
3054 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003055 } else if (Tok.getString() == "fp") {
3056 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003057 } else if (Tok.getString() == "pop") {
3058 return parseSetPopDirective();
3059 } else if (Tok.getString() == "push") {
3060 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003061 } else if (Tok.getString() == "reorder") {
3062 return parseSetReorderDirective();
3063 } else if (Tok.getString() == "noreorder") {
3064 return parseSetNoReorderDirective();
3065 } else if (Tok.getString() == "macro") {
3066 return parseSetMacroDirective();
3067 } else if (Tok.getString() == "nomacro") {
3068 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003069 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003070 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00003071 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003072 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003073 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003074 getTargetStreamer().emitDirectiveSetNoMicroMips();
3075 Parser.eatToEndOfStatement();
3076 return false;
3077 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003078 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003079 } else if (Tok.getString() == "mips0") {
3080 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003081 } else if (Tok.getString() == "mips1") {
3082 return parseSetFeature(Mips::FeatureMips1);
3083 } else if (Tok.getString() == "mips2") {
3084 return parseSetFeature(Mips::FeatureMips2);
3085 } else if (Tok.getString() == "mips3") {
3086 return parseSetFeature(Mips::FeatureMips3);
3087 } else if (Tok.getString() == "mips4") {
3088 return parseSetFeature(Mips::FeatureMips4);
3089 } else if (Tok.getString() == "mips5") {
3090 return parseSetFeature(Mips::FeatureMips5);
3091 } else if (Tok.getString() == "mips32") {
3092 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003093 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003094 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003095 } else if (Tok.getString() == "mips32r6") {
3096 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003097 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003098 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003099 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003100 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003101 } else if (Tok.getString() == "mips64r6") {
3102 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003103 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003104 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003105 } else if (Tok.getString() == "nodsp") {
3106 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003107 } else if (Tok.getString() == "msa") {
3108 return parseSetMsaDirective();
3109 } else if (Tok.getString() == "nomsa") {
3110 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003111 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003112 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003113 parseSetAssignment();
3114 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003115 }
Jack Carter07c818d2013-01-25 01:31:34 +00003116
Jack Carter0b744b32012-10-04 02:29:46 +00003117 return true;
3118}
3119
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003120/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003121/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003122bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00003123 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3124 for (;;) {
3125 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003126 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003127 return true;
3128
3129 getParser().getStreamer().EmitValue(Value, Size);
3130
3131 if (getLexer().is(AsmToken::EndOfStatement))
3132 break;
3133
Jack Carter07c818d2013-01-25 01:31:34 +00003134 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003135 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003136 Parser.Lex();
3137 }
3138 }
3139
3140 Parser.Lex();
3141 return false;
3142}
3143
Vladimir Medic4c299852013-11-06 11:27:05 +00003144/// parseDirectiveGpWord
3145/// ::= .gpword local_sym
3146bool MipsAsmParser::parseDirectiveGpWord() {
3147 const MCExpr *Value;
3148 // EmitGPRel32Value requires an expression, so we are using base class
3149 // method to evaluate the expression.
3150 if (getParser().parseExpression(Value))
3151 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003152 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003153
Vladimir Medice10c1122013-11-13 13:18:04 +00003154 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003155 return Error(getLexer().getLoc(),
3156 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003157 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003158 return false;
3159}
3160
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003161/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003162/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003163bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00003164 const MCExpr *Value;
3165 // EmitGPRel64Value requires an expression, so we are using base class
3166 // method to evaluate the expression.
3167 if (getParser().parseExpression(Value))
3168 return true;
3169 getParser().getStreamer().EmitGPRel64Value(Value);
3170
3171 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003172 return Error(getLexer().getLoc(),
3173 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003174 Parser.Lex(); // Eat EndOfStatement token.
3175 return false;
3176}
3177
Jack Carter0cd3c192014-01-06 23:27:31 +00003178bool MipsAsmParser::parseDirectiveOption() {
3179 // Get the option token.
3180 AsmToken Tok = Parser.getTok();
3181 // At the moment only identifiers are supported.
3182 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003183 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003184 Parser.eatToEndOfStatement();
3185 return false;
3186 }
3187
3188 StringRef Option = Tok.getIdentifier();
3189
3190 if (Option == "pic0") {
3191 getTargetStreamer().emitDirectiveOptionPic0();
3192 Parser.Lex();
3193 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3194 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003195 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003196 Parser.eatToEndOfStatement();
3197 }
3198 return false;
3199 }
3200
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003201 if (Option == "pic2") {
3202 getTargetStreamer().emitDirectiveOptionPic2();
3203 Parser.Lex();
3204 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3205 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003206 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003207 Parser.eatToEndOfStatement();
3208 }
3209 return false;
3210 }
3211
Jack Carter0cd3c192014-01-06 23:27:31 +00003212 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003213 Warning(Parser.getTok().getLoc(),
3214 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003215 Parser.eatToEndOfStatement();
3216 return false;
3217}
3218
Daniel Sanders7e527422014-07-10 13:38:23 +00003219/// parseDirectiveModule
3220/// ::= .module oddspreg
3221/// ::= .module nooddspreg
3222/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003223bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003224 MCAsmLexer &Lexer = getLexer();
3225 SMLoc L = Lexer.getLoc();
3226
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003227 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003228 // TODO : get a better message.
3229 reportParseError(".module directive must appear before any code");
3230 return false;
3231 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003232
3233 if (Lexer.is(AsmToken::Identifier)) {
3234 StringRef Option = Parser.getTok().getString();
3235 Parser.Lex();
3236
3237 if (Option == "oddspreg") {
3238 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3239 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3240
3241 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003242 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003243 return false;
3244 }
3245
3246 return false;
3247 } else if (Option == "nooddspreg") {
3248 if (!isABI_O32()) {
3249 Error(L, "'.module nooddspreg' requires the O32 ABI");
3250 return false;
3251 }
3252
3253 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3254 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3255
3256 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003257 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003258 return false;
3259 }
3260
3261 return false;
3262 } else if (Option == "fp") {
3263 return parseDirectiveModuleFP();
3264 }
3265
3266 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003267 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003268
3269 return false;
3270}
3271
3272/// parseDirectiveModuleFP
3273/// ::= =32
3274/// ::= =xx
3275/// ::= =64
3276bool MipsAsmParser::parseDirectiveModuleFP() {
3277 MCAsmLexer &Lexer = getLexer();
3278
3279 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003280 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003281 return false;
3282 }
3283 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003284
Daniel Sanders7e527422014-07-10 13:38:23 +00003285 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003286 if (!parseFpABIValue(FpABI, ".module"))
3287 return false;
3288
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003289 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003290 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003291 return false;
3292 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003293
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003294 // Emit appropriate flags.
3295 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003296 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003297 return false;
3298}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003299
Daniel Sanders7e527422014-07-10 13:38:23 +00003300bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003301 StringRef Directive) {
3302 MCAsmLexer &Lexer = getLexer();
3303
3304 if (Lexer.is(AsmToken::Identifier)) {
3305 StringRef Value = Parser.getTok().getString();
3306 Parser.Lex();
3307
3308 if (Value != "xx") {
3309 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3310 return false;
3311 }
3312
3313 if (!isABI_O32()) {
3314 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3315 return false;
3316 }
3317
Daniel Sanders7e527422014-07-10 13:38:23 +00003318 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003319 return true;
3320 }
3321
3322 if (Lexer.is(AsmToken::Integer)) {
3323 unsigned Value = Parser.getTok().getIntVal();
3324 Parser.Lex();
3325
3326 if (Value != 32 && Value != 64) {
3327 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3328 return false;
3329 }
3330
3331 if (Value == 32) {
3332 if (!isABI_O32()) {
3333 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3334 return false;
3335 }
3336
Daniel Sanders7e527422014-07-10 13:38:23 +00003337 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3338 } else
3339 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003340
Daniel Sanders7e527422014-07-10 13:38:23 +00003341 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003342 }
3343
3344 return false;
3345}
3346
Jack Carter0b744b32012-10-04 02:29:46 +00003347bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003348 StringRef IDVal = DirectiveID.getString();
3349
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003350 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003351 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003352 if (IDVal == ".dword") {
3353 parseDataDirective(8, DirectiveID.getLoc());
3354 return false;
3355 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003356 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003357 StringRef SymbolName;
3358
3359 if (Parser.parseIdentifier(SymbolName)) {
3360 reportParseError("expected identifier after .ent");
3361 return false;
3362 }
3363
3364 // There's an undocumented extension that allows an integer to
3365 // follow the name of the procedure which AFAICS is ignored by GAS.
3366 // Example: .ent foo,2
3367 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3368 if (getLexer().isNot(AsmToken::Comma)) {
3369 // Even though we accept this undocumented extension for compatibility
3370 // reasons, the additional integer argument does not actually change
3371 // the behaviour of the '.ent' directive, so we would like to discourage
3372 // its use. We do this by not referring to the extended version in
3373 // error messages which are not directly related to its use.
3374 reportParseError("unexpected token, expected end of statement");
3375 return false;
3376 }
3377 Parser.Lex(); // Eat the comma.
3378 const MCExpr *DummyNumber;
3379 int64_t DummyNumberVal;
3380 // If the user was explicitly trying to use the extended version,
3381 // we still give helpful extension-related error messages.
3382 if (Parser.parseExpression(DummyNumber)) {
3383 reportParseError("expected number after comma");
3384 return false;
3385 }
3386 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3387 reportParseError("expected an absolute expression after comma");
3388 return false;
3389 }
3390 }
3391
3392 // If this is not the end of the statement, report an error.
3393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3394 reportParseError("unexpected token, expected end of statement");
3395 return false;
3396 }
3397
3398 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3399
3400 getTargetStreamer().emitDirectiveEnt(*Sym);
3401 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003402 return false;
3403 }
3404
Jack Carter07c818d2013-01-25 01:31:34 +00003405 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003406 StringRef SymbolName;
3407
3408 if (Parser.parseIdentifier(SymbolName)) {
3409 reportParseError("expected identifier after .end");
3410 return false;
3411 }
3412
3413 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3414 reportParseError("unexpected token, expected end of statement");
3415 return false;
3416 }
3417
3418 if (CurrentFn == nullptr) {
3419 reportParseError(".end used without .ent");
3420 return false;
3421 }
3422
3423 if ((SymbolName != CurrentFn->getName())) {
3424 reportParseError(".end symbol does not match .ent symbol");
3425 return false;
3426 }
3427
3428 getTargetStreamer().emitDirectiveEnd(SymbolName);
3429 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003430 return false;
3431 }
3432
Jack Carter07c818d2013-01-25 01:31:34 +00003433 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003434 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3435 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003436 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003437 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3438 reportParseError("expected stack register");
3439 return false;
3440 }
3441
3442 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3443 if (!StackRegOpnd.isGPRAsmReg()) {
3444 reportParseError(StackRegOpnd.getStartLoc(),
3445 "expected general purpose register");
3446 return false;
3447 }
3448 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3449
3450 if (Parser.getTok().is(AsmToken::Comma))
3451 Parser.Lex();
3452 else {
3453 reportParseError("unexpected token, expected comma");
3454 return false;
3455 }
3456
3457 // Parse the frame size.
3458 const MCExpr *FrameSize;
3459 int64_t FrameSizeVal;
3460
3461 if (Parser.parseExpression(FrameSize)) {
3462 reportParseError("expected frame size value");
3463 return false;
3464 }
3465
3466 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3467 reportParseError("frame size not an absolute expression");
3468 return false;
3469 }
3470
3471 if (Parser.getTok().is(AsmToken::Comma))
3472 Parser.Lex();
3473 else {
3474 reportParseError("unexpected token, expected comma");
3475 return false;
3476 }
3477
3478 // Parse the return register.
3479 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003480 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003481 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3482 reportParseError("expected return register");
3483 return false;
3484 }
3485
3486 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3487 if (!ReturnRegOpnd.isGPRAsmReg()) {
3488 reportParseError(ReturnRegOpnd.getStartLoc(),
3489 "expected general purpose register");
3490 return false;
3491 }
3492
3493 // If this is not the end of the statement, report an error.
3494 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3495 reportParseError("unexpected token, expected end of statement");
3496 return false;
3497 }
3498
3499 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3500 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003501 return false;
3502 }
3503
Jack Carter07c818d2013-01-25 01:31:34 +00003504 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003505 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003506 }
3507
Daniel Sandersd97a6342014-08-13 10:07:34 +00003508 if (IDVal == ".mask" || IDVal == ".fmask") {
3509 // .mask bitmask, frame_offset
3510 // bitmask: One bit for each register used.
3511 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3512 // first register is expected to be saved.
3513 // Examples:
3514 // .mask 0x80000000, -4
3515 // .fmask 0x80000000, -4
3516 //
Jack Carterbe332172012-09-07 00:48:02 +00003517
Daniel Sandersd97a6342014-08-13 10:07:34 +00003518 // Parse the bitmask
3519 const MCExpr *BitMask;
3520 int64_t BitMaskVal;
3521
3522 if (Parser.parseExpression(BitMask)) {
3523 reportParseError("expected bitmask value");
3524 return false;
3525 }
3526
3527 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3528 reportParseError("bitmask not an absolute expression");
3529 return false;
3530 }
3531
3532 if (Parser.getTok().is(AsmToken::Comma))
3533 Parser.Lex();
3534 else {
3535 reportParseError("unexpected token, expected comma");
3536 return false;
3537 }
3538
3539 // Parse the frame_offset
3540 const MCExpr *FrameOffset;
3541 int64_t FrameOffsetVal;
3542
3543 if (Parser.parseExpression(FrameOffset)) {
3544 reportParseError("expected frame offset value");
3545 return false;
3546 }
3547
3548 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3549 reportParseError("frame offset not an absolute expression");
3550 return false;
3551 }
3552
3553 // If this is not the end of the statement, report an error.
3554 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3555 reportParseError("unexpected token, expected end of statement");
3556 return false;
3557 }
3558
3559 if (IDVal == ".mask")
3560 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3561 else
3562 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003563 return false;
3564 }
3565
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003566 if (IDVal == ".nan")
3567 return parseDirectiveNaN();
3568
Jack Carter07c818d2013-01-25 01:31:34 +00003569 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003570 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003571 return false;
3572 }
3573
Rafael Espindolab59fb732014-03-28 18:50:26 +00003574 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003575 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003576 return false;
3577 }
3578
Jack Carter07c818d2013-01-25 01:31:34 +00003579 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003580 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003581 return false;
3582 }
3583
Jack Carter0cd3c192014-01-06 23:27:31 +00003584 if (IDVal == ".option")
3585 return parseDirectiveOption();
3586
3587 if (IDVal == ".abicalls") {
3588 getTargetStreamer().emitDirectiveAbiCalls();
3589 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003590 Error(Parser.getTok().getLoc(),
3591 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003592 // Clear line
3593 Parser.eatToEndOfStatement();
3594 }
3595 return false;
3596 }
3597
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003598 if (IDVal == ".cpsetup")
3599 return parseDirectiveCPSetup();
3600
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003601 if (IDVal == ".module")
3602 return parseDirectiveModule();
3603
Rafael Espindola870c4e92012-01-11 03:56:41 +00003604 return true;
3605}
3606
Rafael Espindola870c4e92012-01-11 03:56:41 +00003607extern "C" void LLVMInitializeMipsAsmParser() {
3608 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3609 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3610 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3611 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3612}
Jack Carterb4dbc172012-09-05 23:34:03 +00003613
3614#define GET_REGISTER_MATCHER
3615#define GET_MATCHER_IMPLEMENTATION
3616#include "MipsGenAsmMatcher.inc"