blob: 21d2876fdd0b78fef94fbe56204638b775987927 [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
1120 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001121 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001122 else
1123 Instructions.push_back(Inst);
1124
1125 return false;
1126}
1127
Jack Carter30a59822012-10-04 04:03:53 +00001128bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1129
Jack Carterd0bd6422013-04-18 00:41:53 +00001130 switch (Inst.getOpcode()) {
1131 case Mips::LoadImm32Reg:
1132 case Mips::LoadAddr32Imm:
1133 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001134 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001135 return true;
1136 default:
1137 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001138 }
1139}
Jack Carter92995f12012-10-06 00:53:28 +00001140
Matheus Almeida3813d572014-06-19 14:39:14 +00001141bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001142 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001143 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001144 default:
1145 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001146 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001147 case Mips::LoadImm32Reg:
1148 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001149 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001150 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001151 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001152 return true;
1153 }
1154 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001155 case Mips::LoadAddr32Imm:
1156 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1157 case Mips::LoadAddr32Reg:
1158 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1159 }
Jack Carter30a59822012-10-04 04:03:53 +00001160}
Jack Carter92995f12012-10-06 00:53:28 +00001161
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001162namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001163template <bool PerformShift>
1164void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001165 SmallVectorImpl<MCInst> &Instructions) {
1166 MCInst tmpInst;
1167 if (PerformShift) {
1168 tmpInst.setOpcode(Mips::DSLL);
1169 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1170 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1171 tmpInst.addOperand(MCOperand::CreateImm(16));
1172 tmpInst.setLoc(IDLoc);
1173 Instructions.push_back(tmpInst);
1174 tmpInst.clear();
1175 }
1176 tmpInst.setOpcode(Mips::ORi);
1177 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1178 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001179 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001180 tmpInst.setLoc(IDLoc);
1181 Instructions.push_back(tmpInst);
1182}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001183
1184template <int Shift, bool PerformShift>
1185void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1186 SmallVectorImpl<MCInst> &Instructions) {
1187 createShiftOr<PerformShift>(
1188 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1189 IDLoc, Instructions);
1190}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001191}
1192
Matheus Almeida3813d572014-06-19 14:39:14 +00001193bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001194 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001195 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001196 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001197 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001198 const MCOperand &RegOp = Inst.getOperand(0);
1199 assert(RegOp.isReg() && "expected register operand kind");
1200
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001201 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001202 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001203 // FIXME: gas has a special case for values that are 000...1111, which
1204 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001205 if (0 <= ImmValue && ImmValue <= 65535) {
1206 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001207 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001208 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001209 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001210 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001211 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001212 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001213 } else if (ImmValue < 0 && ImmValue >= -32768) {
1214 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001215 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001216 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001217 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001218 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001219 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001220 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001221 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1222 // For any value of j that is representable as a 32-bit integer, create
1223 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001224 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001225 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001226 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001227 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1228 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001229 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001230 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1231 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001232 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001233 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001234 return true;
1235 }
1236
1237 // <------- lo32 ------>
1238 // <------- hi32 ------>
1239 // <- hi16 -> <- lo16 ->
1240 // _________________________________
1241 // | | | |
1242 // | 16-bytes | 16-bytes | 16-bytes |
1243 // |__________|__________|__________|
1244 //
1245 // For any value of j that is representable as a 48-bit integer, create
1246 // a sequence of:
1247 // li d,j => lui d,hi16(j)
1248 // ori d,d,hi16(lo32(j))
1249 // dsll d,d,16
1250 // ori d,d,lo16(lo32(j))
1251 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001252 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001253 tmpInst.addOperand(
1254 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001255 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001256 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1257 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1258 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001259 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001260 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001261 return true;
1262 }
1263
1264 // <------- hi32 ------> <------- lo32 ------>
1265 // <- hi16 -> <- lo16 ->
1266 // ___________________________________________
1267 // | | | | |
1268 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1269 // |__________|__________|__________|__________|
1270 //
1271 // For any value of j that isn't representable as a 48-bit integer.
1272 // li d,j => lui d,hi16(j)
1273 // ori d,d,lo16(hi32(j))
1274 // dsll d,d,16
1275 // ori d,d,hi16(lo32(j))
1276 // dsll d,d,16
1277 // ori d,d,lo16(lo32(j))
1278 tmpInst.setOpcode(Mips::LUi);
1279 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1280 tmpInst.addOperand(
1281 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1282 Instructions.push_back(tmpInst);
1283 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1284 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1285 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001286 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001287 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001288}
Jack Carter92995f12012-10-06 00:53:28 +00001289
Matheus Almeida3813d572014-06-19 14:39:14 +00001290bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001291MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1292 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001293 MCInst tmpInst;
1294 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001295 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1296 "expected immediate operand kind");
1297 if (!ImmOp.isImm()) {
1298 expandLoadAddressSym(Inst, IDLoc, Instructions);
1299 return false;
1300 }
Jack Carter543fdf82012-10-09 23:29:45 +00001301 const MCOperand &SrcRegOp = Inst.getOperand(1);
1302 assert(SrcRegOp.isReg() && "expected register operand kind");
1303 const MCOperand &DstRegOp = Inst.getOperand(0);
1304 assert(DstRegOp.isReg() && "expected register operand kind");
1305 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001306 if (-32768 <= ImmValue && ImmValue <= 65535) {
1307 // For -32768 <= j <= 65535.
1308 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001309 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001310 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1311 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1312 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1313 Instructions.push_back(tmpInst);
1314 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001315 // For any other value of j that is representable as a 32-bit integer.
1316 // la d,j(s) => lui d,hi16(j)
1317 // ori d,d,lo16(j)
1318 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001319 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001320 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1321 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1322 Instructions.push_back(tmpInst);
1323 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001324 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001325 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1326 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1327 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1328 Instructions.push_back(tmpInst);
1329 tmpInst.clear();
1330 tmpInst.setOpcode(Mips::ADDu);
1331 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1332 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1333 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1334 Instructions.push_back(tmpInst);
1335 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001336 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001337}
1338
Matheus Almeida3813d572014-06-19 14:39:14 +00001339bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001340MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1341 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001342 MCInst tmpInst;
1343 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001344 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1345 "expected immediate operand kind");
1346 if (!ImmOp.isImm()) {
1347 expandLoadAddressSym(Inst, IDLoc, Instructions);
1348 return false;
1349 }
Jack Carter543fdf82012-10-09 23:29:45 +00001350 const MCOperand &RegOp = Inst.getOperand(0);
1351 assert(RegOp.isReg() && "expected register operand kind");
1352 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001353 if (-32768 <= ImmValue && ImmValue <= 65535) {
1354 // For -32768 <= j <= 65535.
1355 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001356 tmpInst.setOpcode(Mips::ADDiu);
1357 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001358 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001359 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1360 Instructions.push_back(tmpInst);
1361 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001362 // For any other value of j that is representable as a 32-bit integer.
1363 // la d,j => lui d,hi16(j)
1364 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001365 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001366 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1367 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1368 Instructions.push_back(tmpInst);
1369 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001370 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001371 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1372 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1373 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1374 Instructions.push_back(tmpInst);
1375 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001376 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001377}
1378
Toma Tabacu0d64b202014-08-14 10:29:17 +00001379void
1380MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1381 SmallVectorImpl<MCInst> &Instructions) {
1382 // FIXME: If we do have a valid at register to use, we should generate a
1383 // slightly shorter sequence here.
1384 MCInst tmpInst;
1385 int ExprOperandNo = 1;
1386 // Sometimes the assembly parser will get the immediate expression as
1387 // a $zero + an immediate.
1388 if (Inst.getNumOperands() == 3) {
1389 assert(Inst.getOperand(1).getReg() ==
1390 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1391 ExprOperandNo = 2;
1392 }
1393 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1394 assert(SymOp.isExpr() && "expected symbol operand kind");
1395 const MCOperand &RegOp = Inst.getOperand(0);
1396 unsigned RegNo = RegOp.getReg();
1397 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1398 const MCSymbolRefExpr *HiExpr =
1399 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1400 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1401 const MCSymbolRefExpr *LoExpr =
1402 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1403 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1404 if (isGP64bit()) {
1405 // If it's a 64-bit architecture, expand to:
1406 // la d,sym => lui d,highest(sym)
1407 // ori d,d,higher(sym)
1408 // dsll d,d,16
1409 // ori d,d,hi16(sym)
1410 // dsll d,d,16
1411 // ori d,d,lo16(sym)
1412 const MCSymbolRefExpr *HighestExpr =
1413 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1414 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1415 const MCSymbolRefExpr *HigherExpr =
1416 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1417 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1418
1419 tmpInst.setOpcode(Mips::LUi);
1420 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1421 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1422 Instructions.push_back(tmpInst);
1423
1424 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1425 Instructions);
1426 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1427 Instructions);
1428 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1429 Instructions);
1430 } else {
1431 // Otherwise, expand to:
1432 // la d,sym => lui d,hi16(sym)
1433 // ori d,d,lo16(sym)
1434 tmpInst.setOpcode(Mips::LUi);
1435 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1436 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1437 Instructions.push_back(tmpInst);
1438
1439 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1440 Instructions);
1441 }
1442}
1443
Jack Carter9e65aa32013-03-22 00:05:30 +00001444void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001445 SmallVectorImpl<MCInst> &Instructions,
1446 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001447 const MCSymbolRefExpr *SR;
1448 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001449 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001450 const MCExpr *ExprOffset;
1451 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001452 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001453 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1454 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001455 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001456 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1457 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001458 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001459 if (isImmOpnd) {
1460 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1461 ImmOffset = Inst.getOperand(2).getImm();
1462 LoOffset = ImmOffset & 0x0000ffff;
1463 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001464 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001465 if (LoOffset & 0x8000)
1466 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001467 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001468 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001469 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001470 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001471 // These are some of the types of expansions we perform here:
1472 // 1) lw $8, sym => lui $8, %hi(sym)
1473 // lw $8, %lo(sym)($8)
1474 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1475 // add $8, $8, $9
1476 // lw $8, %lo(offset)($9)
1477 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1478 // add $at, $at, $8
1479 // lw $8, %lo(offset)($at)
1480 // 4) sw $8, sym => lui $at, %hi(sym)
1481 // sw $8, %lo(sym)($at)
1482 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1483 // add $at, $at, $8
1484 // sw $8, %lo(offset)($at)
1485 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1486 // ldc1 $f0, %lo(sym)($at)
1487 //
1488 // For load instructions we can use the destination register as a temporary
1489 // if base and dst are different (examples 1 and 2) and if the base register
1490 // is general purpose otherwise we must use $at (example 6) and error if it's
1491 // not available. For stores we must use $at (examples 4 and 5) because we
1492 // must not clobber the source register setting up the offset.
1493 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1494 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1495 unsigned RegClassIDOp0 =
1496 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1497 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1498 (RegClassIDOp0 == Mips::GPR64RegClassID);
1499 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001500 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001501 else {
1502 int AT = getATReg(IDLoc);
1503 // At this point we need AT to perform the expansions and we exit if it is
1504 // not available.
1505 if (!AT)
1506 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001507 TmpRegNum = getReg(
1508 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001509 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001510
Jack Carter9e65aa32013-03-22 00:05:30 +00001511 TempInst.setOpcode(Mips::LUi);
1512 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1513 if (isImmOpnd)
1514 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1515 else {
1516 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001517 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001518 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1519 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1520 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001521 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001522 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001523 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001524 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001525 }
1526 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001527 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001528 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001529 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001530 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001531 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001532 TempInst.setOpcode(Mips::ADDu);
1533 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1534 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1535 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1536 Instructions.push_back(TempInst);
1537 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001538 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001539 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001540 TempInst.setOpcode(Inst.getOpcode());
1541 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1542 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1543 if (isImmOpnd)
1544 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1545 else {
1546 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001547 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1548 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1549 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001550 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001551 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001552 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001553 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001554 }
1555 }
1556 Instructions.push_back(TempInst);
1557 TempInst.clear();
1558}
1559
Matheus Almeida595fcab2014-06-11 15:05:56 +00001560unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1561 // As described by the Mips32r2 spec, the registers Rd and Rs for
1562 // jalr.hb must be different.
1563 unsigned Opcode = Inst.getOpcode();
1564
1565 if (Opcode == Mips::JALR_HB &&
1566 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1567 return Match_RequiresDifferentSrcAndDst;
1568
1569 return Match_Success;
1570}
1571
David Blaikie960ea3f2014-06-08 16:18:35 +00001572bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1573 OperandVector &Operands,
1574 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001575 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001576 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001577
Jack Carterb4dbc172012-09-05 23:34:03 +00001578 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001579 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001580 unsigned MatchResult =
1581 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001582
1583 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001584 default:
1585 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001586 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001587 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001588 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001589 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001590 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001591 return false;
1592 }
1593 case Match_MissingFeature:
1594 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1595 return true;
1596 case Match_InvalidOperand: {
1597 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001598 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001599 if (ErrorInfo >= Operands.size())
1600 return Error(IDLoc, "too few operands for instruction");
1601
David Blaikie960ea3f2014-06-08 16:18:35 +00001602 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 if (ErrorLoc == SMLoc())
1604 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001605 }
1606
1607 return Error(ErrorLoc, "invalid operand for instruction");
1608 }
1609 case Match_MnemonicFail:
1610 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001611 case Match_RequiresDifferentSrcAndDst:
1612 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001613 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001614 return true;
1615}
1616
Toma Tabacu13964452014-09-04 13:23:44 +00001617void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001618 if ((RegIndex != 0) &&
1619 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001620 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001621 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001622 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001623 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001624 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001625 }
1626}
1627
Daniel Sandersef638fe2014-10-03 15:37:37 +00001628void
1629MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1630 SMRange Range, bool ShowColors) {
1631 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001632 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001633 ShowColors);
1634}
1635
Jack Carter1ac53222013-02-20 23:11:17 +00001636int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001637 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001638
Vladimir Medic4c299852013-11-06 11:27:05 +00001639 CC = StringSwitch<unsigned>(Name)
1640 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001641 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001642 .Case("a0", 4)
1643 .Case("a1", 5)
1644 .Case("a2", 6)
1645 .Case("a3", 7)
1646 .Case("v0", 2)
1647 .Case("v1", 3)
1648 .Case("s0", 16)
1649 .Case("s1", 17)
1650 .Case("s2", 18)
1651 .Case("s3", 19)
1652 .Case("s4", 20)
1653 .Case("s5", 21)
1654 .Case("s6", 22)
1655 .Case("s7", 23)
1656 .Case("k0", 26)
1657 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001658 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001659 .Case("sp", 29)
1660 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001661 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001662 .Case("ra", 31)
1663 .Case("t0", 8)
1664 .Case("t1", 9)
1665 .Case("t2", 10)
1666 .Case("t3", 11)
1667 .Case("t4", 12)
1668 .Case("t5", 13)
1669 .Case("t6", 14)
1670 .Case("t7", 15)
1671 .Case("t8", 24)
1672 .Case("t9", 25)
1673 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001674
Toma Tabacufda445c2014-09-15 15:33:01 +00001675 if (!(isABI_N32() || isABI_N64()))
1676 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001677
Daniel Sandersef638fe2014-10-03 15:37:37 +00001678 if (12 <= CC && CC <= 15) {
1679 // Name is one of t4-t7
1680 AsmToken RegTok = getLexer().peekTok();
1681 SMRange RegRange = RegTok.getLocRange();
1682
1683 StringRef FixedName = StringSwitch<StringRef>(Name)
1684 .Case("t4", "t0")
1685 .Case("t5", "t1")
1686 .Case("t6", "t2")
1687 .Case("t7", "t3")
1688 .Default("");
1689 assert(FixedName != "" && "Register name is not one of t4-t7.");
1690
1691 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1692 "Did you mean $" + FixedName + "?", RegRange);
1693 }
1694
Toma Tabacufda445c2014-09-15 15:33:01 +00001695 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1696 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1697 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1698 if (8 <= CC && CC <= 11)
1699 CC += 4;
1700
1701 if (CC == -1)
1702 CC = StringSwitch<unsigned>(Name)
1703 .Case("a4", 8)
1704 .Case("a5", 9)
1705 .Case("a6", 10)
1706 .Case("a7", 11)
1707 .Case("kt0", 26)
1708 .Case("kt1", 27)
1709 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001710
1711 return CC;
1712}
Jack Carterd0bd6422013-04-18 00:41:53 +00001713
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001714int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001715
Jack Cartera63b16a2012-09-07 00:23:42 +00001716 if (Name[0] == 'f') {
1717 StringRef NumString = Name.substr(1);
1718 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001720 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001721 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001722 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001723 return IntVal;
1724 }
1725 return -1;
1726}
Jack Cartera63b16a2012-09-07 00:23:42 +00001727
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001728int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1729
1730 if (Name.startswith("fcc")) {
1731 StringRef NumString = Name.substr(3);
1732 unsigned IntVal;
1733 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001734 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001735 if (IntVal > 7) // There are only 8 fcc registers.
1736 return -1;
1737 return IntVal;
1738 }
1739 return -1;
1740}
1741
1742int MipsAsmParser::matchACRegisterName(StringRef Name) {
1743
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001744 if (Name.startswith("ac")) {
1745 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001746 unsigned IntVal;
1747 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001748 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001749 if (IntVal > 3) // There are only 3 acc registers.
1750 return -1;
1751 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001752 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001753 return -1;
1754}
Jack Carterd0bd6422013-04-18 00:41:53 +00001755
Jack Carter5dc8ac92013-09-25 23:50:44 +00001756int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1757 unsigned IntVal;
1758
1759 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1760 return -1;
1761
1762 if (IntVal > 31)
1763 return -1;
1764
1765 return IntVal;
1766}
1767
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001768int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1769 int CC;
1770
1771 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001772 .Case("msair", 0)
1773 .Case("msacsr", 1)
1774 .Case("msaaccess", 2)
1775 .Case("msasave", 3)
1776 .Case("msamodify", 4)
1777 .Case("msarequest", 5)
1778 .Case("msamap", 6)
1779 .Case("msaunmap", 7)
1780 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001781
1782 return CC;
1783}
1784
Jack Carter0b744b32012-10-04 02:29:46 +00001785bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1786 if (Reg > 31)
1787 return false;
1788
Toma Tabacu3c24b042014-09-05 15:43:21 +00001789 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001790 return true;
1791}
1792
Matheus Almeida7de68e72014-06-18 14:46:05 +00001793int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001794 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001795 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001796 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00001797 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001798 return AT;
1799}
Jack Carter0b744b32012-10-04 02:29:46 +00001800
Jack Carterd0bd6422013-04-18 00:41:53 +00001801unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001802 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001803}
1804
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001805unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001806 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001807 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001808}
1809
Jack Carter873c7242013-01-12 01:03:14 +00001810int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001811 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001812 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001813 return -1;
1814
Jack Carter873c7242013-01-12 01:03:14 +00001815 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001816}
1817
Toma Tabacu13964452014-09-04 13:23:44 +00001818bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1819 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001820
Jack Carter30a59822012-10-04 04:03:53 +00001821 // Check if the current operand has a custom associated parser, if so, try to
1822 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001823 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1824 if (ResTy == MatchOperand_Success)
1825 return false;
1826 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1827 // there was a match, but an error occurred, in which case, just return that
1828 // the operand parsing failed.
1829 if (ResTy == MatchOperand_ParseFail)
1830 return true;
1831
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001832 DEBUG(dbgs() << ".. Generic Parser\n");
1833
Jack Carterb4dbc172012-09-05 23:34:03 +00001834 switch (getLexer().getKind()) {
1835 default:
1836 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1837 return true;
1838 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001839 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001840 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001841
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001842 // Almost all registers have been parsed by custom parsers. There is only
1843 // one exception to this. $zero (and it's alias $0) will reach this point
1844 // for div, divu, and similar instructions because it is not an operand
1845 // to the instruction definition but an explicit register. Special case
1846 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001847 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001848 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001849
Jack Carterd0bd6422013-04-18 00:41:53 +00001850 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001851 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001852 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001853 return true;
1854
Jack Carter873c7242013-01-12 01:03:14 +00001855 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001856 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001857 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001858 const MCExpr *Res =
1859 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001860
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001861 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001862 return false;
1863 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001864 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001865 case AsmToken::LParen:
1866 case AsmToken::Minus:
1867 case AsmToken::Plus:
1868 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001869 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001870 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001871 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001872 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001873 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001874 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001875 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001876 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001877 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001878 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001879 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001880 return true;
1881
Jack Carter873c7242013-01-12 01:03:14 +00001882 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1883
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001884 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001885 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001886 } // case AsmToken::Percent
1887 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001888 return true;
1889}
1890
Vladimir Medic4c299852013-11-06 11:27:05 +00001891const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001892 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001893 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001894 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001895 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001896 // It's a constant, evaluate reloc value.
1897 int16_t Val;
1898 switch (getVariantKind(RelocStr)) {
1899 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1900 // Get the 1st 16-bits.
1901 Val = MCE->getValue() & 0xffff;
1902 break;
1903 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1904 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1905 // 16 bits being negative.
1906 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1907 break;
1908 case MCSymbolRefExpr::VK_Mips_HIGHER:
1909 // Get the 3rd 16-bits.
1910 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1911 break;
1912 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1913 // Get the 4th 16-bits.
1914 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1915 break;
1916 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00001917 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001918 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001919 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001920 }
1921
Jack Carterb5cf5902013-04-17 00:18:04 +00001922 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001923 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001924 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001925 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001926 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001927 return Res;
1928 }
1929
1930 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001931 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1932
Sasa Stankovic06c47802014-04-03 10:37:45 +00001933 // Try to create target expression.
1934 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1935 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001936
Jack Carterd0bd6422013-04-18 00:41:53 +00001937 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1938 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001939 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1940 return Res;
1941 }
1942
1943 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001944 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1945 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1946 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001947 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001948 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001949 return Expr;
1950}
1951
1952bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1953
1954 switch (Expr->getKind()) {
1955 case MCExpr::Constant:
1956 return true;
1957 case MCExpr::SymbolRef:
1958 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1959 case MCExpr::Binary:
1960 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1961 if (!isEvaluated(BE->getLHS()))
1962 return false;
1963 return isEvaluated(BE->getRHS());
1964 }
1965 case MCExpr::Unary:
1966 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001967 case MCExpr::Target:
1968 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001969 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001970 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001971}
Jack Carterd0bd6422013-04-18 00:41:53 +00001972
Jack Carterb5cf5902013-04-17 00:18:04 +00001973bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001974 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001975 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001976 if (Tok.isNot(AsmToken::Identifier))
1977 return true;
1978
1979 std::string Str = Tok.getIdentifier().str();
1980
Jack Carterd0bd6422013-04-18 00:41:53 +00001981 Parser.Lex(); // Eat the identifier.
1982 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001983 const MCExpr *IdVal;
1984 SMLoc EndLoc;
1985
1986 if (getLexer().getKind() == AsmToken::LParen) {
1987 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001988 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001989 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001990 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001991 const AsmToken &nextTok = Parser.getTok();
1992 if (nextTok.isNot(AsmToken::Identifier))
1993 return true;
1994 Str += "(%";
1995 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001996 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001997 if (getLexer().getKind() != AsmToken::LParen)
1998 return true;
1999 } else
2000 break;
2001 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002002 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002003 return true;
2004
2005 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002006 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002007
2008 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002009 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002010
Jack Carterd0bd6422013-04-18 00:41:53 +00002011 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002012 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002013}
2014
Jack Carterb4dbc172012-09-05 23:34:03 +00002015bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2016 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002017 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002018 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002019 if (ResTy == MatchOperand_Success) {
2020 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002021 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002022 StartLoc = Operand.getStartLoc();
2023 EndLoc = Operand.getEndLoc();
2024
2025 // AFAIK, we only support numeric registers and named GPR's in CFI
2026 // directives.
2027 // Don't worry about eating tokens before failing. Using an unrecognised
2028 // register is a parse error.
2029 if (Operand.isGPRAsmReg()) {
2030 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002031 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002032 }
2033
2034 return (RegNo == (unsigned)-1);
2035 }
2036
2037 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002038 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002039}
2040
Jack Carterb5cf5902013-04-17 00:18:04 +00002041bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00002042 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002043 bool Result = true;
2044
2045 while (getLexer().getKind() == AsmToken::LParen)
2046 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002047
Jack Carterd0bd6422013-04-18 00:41:53 +00002048 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002049 default:
2050 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002051 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002052 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002053 case AsmToken::Integer:
2054 case AsmToken::Minus:
2055 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002056 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002057 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002058 else
2059 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002060 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002061 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002062 break;
Jack Carter873c7242013-01-12 01:03:14 +00002063 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002064 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002065 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002066 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002067}
2068
David Blaikie960ea3f2014-06-08 16:18:35 +00002069MipsAsmParser::OperandMatchResultTy
2070MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002071 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002072 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002073 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002074 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002075 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002076 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002077 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002078
Jack Carterb5cf5902013-04-17 00:18:04 +00002079 if (getLexer().getKind() == AsmToken::LParen) {
2080 Parser.Lex();
2081 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002082 }
2083
Jack Carterb5cf5902013-04-17 00:18:04 +00002084 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002085 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002086 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002087
Jack Carterd0bd6422013-04-18 00:41:53 +00002088 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002089 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002090 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2091 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002092 SMLoc E =
2093 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002094 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002095 return MatchOperand_Success;
2096 }
2097 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002098 SMLoc E =
2099 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002100
Jack Carterd0bd6422013-04-18 00:41:53 +00002101 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002102 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002103 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002104 S, E, *this);
2105 Operands.push_back(
2106 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002107 return MatchOperand_Success;
2108 }
2109 Error(Parser.getTok().getLoc(), "'(' expected");
2110 return MatchOperand_ParseFail;
2111 }
2112
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002114 }
2115
Toma Tabacu13964452014-09-04 13:23:44 +00002116 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002117 if (Res != MatchOperand_Success)
2118 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002119
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002120 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002121 Error(Parser.getTok().getLoc(), "')' expected");
2122 return MatchOperand_ParseFail;
2123 }
2124
Jack Carter873c7242013-01-12 01:03:14 +00002125 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2126
Jack Carterd0bd6422013-04-18 00:41:53 +00002127 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002128
Craig Topper062a2ba2014-04-25 05:30:21 +00002129 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002130 IdVal = MCConstantExpr::Create(0, getContext());
2131
Jack Carterd0bd6422013-04-18 00:41:53 +00002132 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002133 std::unique_ptr<MipsOperand> op(
2134 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002135 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002136 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002137 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002138 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002139 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2140 int64_t Imm;
2141 if (IdVal->EvaluateAsAbsolute(Imm))
2142 IdVal = MCConstantExpr::Create(Imm, getContext());
2143 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2144 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2145 getContext());
2146 }
2147
David Blaikie960ea3f2014-06-08 16:18:35 +00002148 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002149 return MatchOperand_Success;
2150}
2151
David Blaikie960ea3f2014-06-08 16:18:35 +00002152bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002153
Jack Carterd76b2372013-03-21 21:44:16 +00002154 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2155 if (Sym) {
2156 SMLoc S = Parser.getTok().getLoc();
2157 const MCExpr *Expr;
2158 if (Sym->isVariable())
2159 Expr = Sym->getVariableValue();
2160 else
2161 return false;
2162 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002163 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002164 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002165 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002166 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002167 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002168 if (ResTy == MatchOperand_Success) {
2169 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002170 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002171 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002172 llvm_unreachable("Should never ParseFail");
2173 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002174 }
2175 } else if (Expr->getKind() == MCExpr::Constant) {
2176 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002177 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002178 Operands.push_back(
2179 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002180 return true;
2181 }
2182 }
2183 return false;
2184}
Jack Carterd0bd6422013-04-18 00:41:53 +00002185
Jack Carter873c7242013-01-12 01:03:14 +00002186MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002187MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002188 StringRef Identifier,
2189 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002190 int Index = matchCPURegisterName(Identifier);
2191 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002192 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002193 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2194 return MatchOperand_Success;
2195 }
2196
2197 Index = matchFPURegisterName(Identifier);
2198 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002199 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002200 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2201 return MatchOperand_Success;
2202 }
2203
2204 Index = matchFCCRegisterName(Identifier);
2205 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002206 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002207 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2208 return MatchOperand_Success;
2209 }
2210
2211 Index = matchACRegisterName(Identifier);
2212 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002213 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002214 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2215 return MatchOperand_Success;
2216 }
2217
2218 Index = matchMSA128RegisterName(Identifier);
2219 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002220 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002221 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2222 return MatchOperand_Success;
2223 }
2224
2225 Index = matchMSA128CtrlRegisterName(Identifier);
2226 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002227 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002228 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2229 return MatchOperand_Success;
2230 }
2231
2232 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002233}
2234
2235MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002236MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002237 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002238
2239 if (Token.is(AsmToken::Identifier)) {
2240 DEBUG(dbgs() << ".. identifier\n");
2241 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002242 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002243 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002244 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002245 } else if (Token.is(AsmToken::Integer)) {
2246 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002247 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002248 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2249 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002250 return MatchOperand_Success;
2251 }
2252
2253 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2254
2255 return MatchOperand_NoMatch;
2256}
2257
David Blaikie960ea3f2014-06-08 16:18:35 +00002258MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002259MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
2260 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002261
2262 auto Token = Parser.getTok();
2263
2264 SMLoc S = Token.getLoc();
2265
2266 if (Token.isNot(AsmToken::Dollar)) {
2267 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2268 if (Token.is(AsmToken::Identifier)) {
2269 if (searchSymbolAlias(Operands))
2270 return MatchOperand_Success;
2271 }
2272 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2273 return MatchOperand_NoMatch;
2274 }
2275 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002276
Toma Tabacu13964452014-09-04 13:23:44 +00002277 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002278 if (ResTy == MatchOperand_Success) {
2279 Parser.Lex(); // $
2280 Parser.Lex(); // identifier
2281 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002282 return ResTy;
2283}
2284
2285MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002286MipsAsmParser::parseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002287 switch (getLexer().getKind()) {
2288 default:
2289 return MatchOperand_NoMatch;
2290 case AsmToken::LParen:
2291 case AsmToken::Minus:
2292 case AsmToken::Plus:
2293 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002294 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002295 case AsmToken::String:
2296 break;
2297 }
2298
2299 const MCExpr *IdVal;
2300 SMLoc S = Parser.getTok().getLoc();
2301 if (getParser().parseExpression(IdVal))
2302 return MatchOperand_ParseFail;
2303
2304 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2305 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2306 return MatchOperand_Success;
2307}
2308
David Blaikie960ea3f2014-06-08 16:18:35 +00002309MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002310MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
2311 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002312
2313 SMLoc S = getLexer().getLoc();
2314
2315 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002316 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002317 if (ResTy != MatchOperand_NoMatch)
2318 return ResTy;
2319
Daniel Sanders315386c2014-04-01 10:40:14 +00002320 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002321 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002322 if (ResTy != MatchOperand_NoMatch)
2323 return ResTy;
2324
Daniel Sandersffd84362014-04-01 10:41:48 +00002325 const MCExpr *Expr = nullptr;
2326 if (Parser.parseExpression(Expr)) {
2327 // We have no way of knowing if a symbol was consumed so we must ParseFail
2328 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002329 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002330 Operands.push_back(
2331 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002332 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002333}
2334
Vladimir Medic2b953d02013-10-01 09:48:56 +00002335MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002336MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002337 const MCExpr *IdVal;
2338 // If the first token is '$' we may have register operand.
2339 if (Parser.getTok().is(AsmToken::Dollar))
2340 return MatchOperand_NoMatch;
2341 SMLoc S = Parser.getTok().getLoc();
2342 if (getParser().parseExpression(IdVal))
2343 return MatchOperand_ParseFail;
2344 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002345 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002346 int64_t Val = MCE->getValue();
2347 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2348 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002349 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002350 return MatchOperand_Success;
2351}
2352
Matheus Almeida779c5932013-11-18 12:32:49 +00002353MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002354MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002355 switch (getLexer().getKind()) {
2356 default:
2357 return MatchOperand_NoMatch;
2358 case AsmToken::LParen:
2359 case AsmToken::Plus:
2360 case AsmToken::Minus:
2361 case AsmToken::Integer:
2362 break;
2363 }
2364
2365 const MCExpr *Expr;
2366 SMLoc S = Parser.getTok().getLoc();
2367
2368 if (getParser().parseExpression(Expr))
2369 return MatchOperand_ParseFail;
2370
2371 int64_t Val;
2372 if (!Expr->EvaluateAsAbsolute(Val)) {
2373 Error(S, "expected immediate value");
2374 return MatchOperand_ParseFail;
2375 }
2376
2377 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2378 // and because the CPU always adds one to the immediate field, the allowed
2379 // range becomes 1..4. We'll only check the range here and will deal
2380 // with the addition/subtraction when actually decoding/encoding
2381 // the instruction.
2382 if (Val < 1 || Val > 4) {
2383 Error(S, "immediate not in range (1..4)");
2384 return MatchOperand_ParseFail;
2385 }
2386
Jack Carter3b2c96e2014-01-22 23:31:38 +00002387 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002388 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002389 return MatchOperand_Success;
2390}
2391
Jack Carterdc1e35d2012-09-06 20:00:02 +00002392MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2393
Vladimir Medic4c299852013-11-06 11:27:05 +00002394 MCSymbolRefExpr::VariantKind VK =
2395 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2396 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2397 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2398 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2399 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2400 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2401 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2402 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2403 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2404 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2405 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2406 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2407 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2408 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2409 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2410 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2411 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2412 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002413 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2414 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2415 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2416 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2417 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2418 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002419 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2420 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002421 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002422
Matheus Almeida2852af82014-04-22 10:15:54 +00002423 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002424
Jack Carterdc1e35d2012-09-06 20:00:02 +00002425 return VK;
2426}
Jack Cartera63b16a2012-09-07 00:23:42 +00002427
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002428/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2429/// either this.
2430/// ::= '(', register, ')'
2431/// handle it before we iterate so we don't get tripped up by the lack of
2432/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002433bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002434 if (getLexer().is(AsmToken::LParen)) {
2435 Operands.push_back(
2436 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2437 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002438 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002439 SMLoc Loc = getLexer().getLoc();
2440 Parser.eatToEndOfStatement();
2441 return Error(Loc, "unexpected token in argument list");
2442 }
2443 if (Parser.getTok().isNot(AsmToken::RParen)) {
2444 SMLoc Loc = getLexer().getLoc();
2445 Parser.eatToEndOfStatement();
2446 return Error(Loc, "unexpected token, expected ')'");
2447 }
2448 Operands.push_back(
2449 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2450 Parser.Lex();
2451 }
2452 return false;
2453}
2454
2455/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2456/// either one of these.
2457/// ::= '[', register, ']'
2458/// ::= '[', integer, ']'
2459/// handle it before we iterate so we don't get tripped up by the lack of
2460/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002461bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002462 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002463 if (getLexer().is(AsmToken::LBrac)) {
2464 Operands.push_back(
2465 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2466 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002467 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002468 SMLoc Loc = getLexer().getLoc();
2469 Parser.eatToEndOfStatement();
2470 return Error(Loc, "unexpected token in argument list");
2471 }
2472 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2473 SMLoc Loc = getLexer().getLoc();
2474 Parser.eatToEndOfStatement();
2475 return Error(Loc, "unexpected token, expected ']'");
2476 }
2477 Operands.push_back(
2478 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2479 Parser.Lex();
2480 }
2481 return false;
2482}
2483
David Blaikie960ea3f2014-06-08 16:18:35 +00002484bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2485 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002486 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002487
2488 // We have reached first instruction, module directive are now forbidden.
2489 getTargetStreamer().forbidModuleDirective();
2490
Vladimir Medic74593e62013-07-17 15:00:42 +00002491 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002492 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002493 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002494 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002495 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002496 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002497 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002498
2499 // Read the remaining operands.
2500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2501 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002502 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002503 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002504 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002505 return Error(Loc, "unexpected token in argument list");
2506 }
Toma Tabacu13964452014-09-04 13:23:44 +00002507 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002508 return true;
2509 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002510
Jack Carterd0bd6422013-04-18 00:41:53 +00002511 while (getLexer().is(AsmToken::Comma)) {
2512 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002513 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002514 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002515 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002516 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002517 return Error(Loc, "unexpected token in argument list");
2518 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002519 // Parse bracket and parenthesis suffixes before we iterate
2520 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002521 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002522 return true;
2523 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002524 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002525 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002526 }
2527 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002528 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2529 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002530 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002531 return Error(Loc, "unexpected token in argument list");
2532 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002533 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002534 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002535}
2536
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002537bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002538 SMLoc Loc = getLexer().getLoc();
2539 Parser.eatToEndOfStatement();
2540 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002541}
2542
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002543bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002544 return Error(Loc, ErrorMsg);
2545}
2546
Jack Carter0b744b32012-10-04 02:29:46 +00002547bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002548 // Line should look like: ".set noat".
2549 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002550 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002551 // eat noat
2552 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002553 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002554 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002555 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002556 return false;
2557 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002558 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002559 return false;
2560}
Jack Carterd0bd6422013-04-18 00:41:53 +00002561
Jack Carter0b744b32012-10-04 02:29:46 +00002562bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002563 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002564 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002565 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002566 getParser().Lex();
2567 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002568 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002569 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002570 return false;
2571 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002572 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002573 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002574 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002575 return false;
2576 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002577 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002578 const AsmToken &Reg = Parser.getTok();
2579 if (Reg.is(AsmToken::Identifier)) {
2580 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2581 } else if (Reg.is(AsmToken::Integer)) {
2582 AtRegNo = Reg.getIntVal();
2583 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002584 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002585 return false;
2586 }
Jack Carter1ac53222013-02-20 23:11:17 +00002587
Daniel Sanders71a89d922014-03-25 13:01:06 +00002588 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002589 reportParseError("unexpected token in statement");
2590 return false;
2591 }
2592
Toma Tabacu9db22db2014-09-09 10:15:38 +00002593 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002594 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002595 return false;
2596 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002597 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002598
2599 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002600 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002601 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002602 }
2603 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002604 return false;
2605 } else {
2606 reportParseError("unexpected token in statement");
2607 return false;
2608 }
2609}
2610
2611bool MipsAsmParser::parseSetReorderDirective() {
2612 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002613 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002614 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002615 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002616 return false;
2617 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002618 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002619 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002620 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002621 return false;
2622}
2623
2624bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002625 Parser.Lex();
2626 // If this is not the end of the statement, report an error.
2627 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002628 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002629 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002630 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002631 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002632 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002633 Parser.Lex(); // Consume the EndOfStatement.
2634 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002635}
2636
2637bool MipsAsmParser::parseSetMacroDirective() {
2638 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002639 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002640 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002641 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002642 return false;
2643 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002644 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002645 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002646 return false;
2647}
2648
2649bool MipsAsmParser::parseSetNoMacroDirective() {
2650 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002651 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002652 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002653 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002654 return false;
2655 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002656 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002657 reportParseError("`noreorder' must be set before `nomacro'");
2658 return false;
2659 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002660 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002661 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002662 return false;
2663}
Jack Carterd76b2372013-03-21 21:44:16 +00002664
Daniel Sanders44934432014-08-07 12:03:36 +00002665bool MipsAsmParser::parseSetMsaDirective() {
2666 Parser.Lex();
2667
2668 // If this is not the end of the statement, report an error.
2669 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002670 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002671
2672 setFeatureBits(Mips::FeatureMSA, "msa");
2673 getTargetStreamer().emitDirectiveSetMsa();
2674 return false;
2675}
2676
2677bool MipsAsmParser::parseSetNoMsaDirective() {
2678 Parser.Lex();
2679
2680 // If this is not the end of the statement, report an error.
2681 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002682 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002683
2684 clearFeatureBits(Mips::FeatureMSA, "msa");
2685 getTargetStreamer().emitDirectiveSetNoMsa();
2686 return false;
2687}
2688
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002689bool MipsAsmParser::parseSetNoDspDirective() {
2690 Parser.Lex(); // Eat "nodsp".
2691
2692 // If this is not the end of the statement, report an error.
2693 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2694 reportParseError("unexpected token, expected end of statement");
2695 return false;
2696 }
2697
2698 clearFeatureBits(Mips::FeatureDSP, "dsp");
2699 getTargetStreamer().emitDirectiveSetNoDsp();
2700 return false;
2701}
2702
Jack Carter39536722014-01-22 23:08:42 +00002703bool MipsAsmParser::parseSetNoMips16Directive() {
2704 Parser.Lex();
2705 // If this is not the end of the statement, report an error.
2706 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002707 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00002708 return false;
2709 }
2710 // For now do nothing.
2711 Parser.Lex(); // Consume the EndOfStatement.
2712 return false;
2713}
2714
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002715bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002716 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002717 // Line can be: .set fp=32
2718 // .set fp=xx
2719 // .set fp=64
2720 Parser.Lex(); // Eat fp token
2721 AsmToken Tok = Parser.getTok();
2722 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002723 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002724 return false;
2725 }
2726 Parser.Lex(); // Eat '=' token.
2727 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002728
2729 if (!parseFpABIValue(FpAbiVal, ".set"))
2730 return false;
2731
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002732 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002733 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002734 return false;
2735 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002736 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002737 Parser.Lex(); // Consume the EndOfStatement.
2738 return false;
2739}
2740
Toma Tabacu9db22db2014-09-09 10:15:38 +00002741bool MipsAsmParser::parseSetPopDirective() {
2742 SMLoc Loc = getLexer().getLoc();
2743
2744 Parser.Lex();
2745 if (getLexer().isNot(AsmToken::EndOfStatement))
2746 return reportParseError("unexpected token, expected end of statement");
2747
2748 // Always keep an element on the options "stack" to prevent the user
2749 // from changing the initial options. This is how we remember them.
2750 if (AssemblerOptions.size() == 2)
2751 return reportParseError(Loc, ".set pop with no .set push");
2752
2753 AssemblerOptions.pop_back();
2754 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2755
2756 getTargetStreamer().emitDirectiveSetPop();
2757 return false;
2758}
2759
2760bool MipsAsmParser::parseSetPushDirective() {
2761 Parser.Lex();
2762 if (getLexer().isNot(AsmToken::EndOfStatement))
2763 return reportParseError("unexpected token, expected end of statement");
2764
2765 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00002766 AssemblerOptions.push_back(
2767 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00002768
2769 getTargetStreamer().emitDirectiveSetPush();
2770 return false;
2771}
2772
Jack Carterd76b2372013-03-21 21:44:16 +00002773bool MipsAsmParser::parseSetAssignment() {
2774 StringRef Name;
2775 const MCExpr *Value;
2776
2777 if (Parser.parseIdentifier(Name))
2778 reportParseError("expected identifier after .set");
2779
2780 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00002781 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00002782 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002783
Jack Carter3b2c96e2014-01-22 23:31:38 +00002784 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002785 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002786
Jack Carterd0bd6422013-04-18 00:41:53 +00002787 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002788 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002789 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002790 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002791 Sym = getContext().GetOrCreateSymbol(Name);
2792 Sym->setVariableValue(Value);
2793
2794 return false;
2795}
Jack Carterd0bd6422013-04-18 00:41:53 +00002796
Toma Tabacu26647792014-09-09 12:52:14 +00002797bool MipsAsmParser::parseSetMips0Directive() {
2798 Parser.Lex();
2799 if (getLexer().isNot(AsmToken::EndOfStatement))
2800 return reportParseError("unexpected token, expected end of statement");
2801
2802 // Reset assembler options to their initial values.
2803 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
2804 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
2805
2806 getTargetStreamer().emitDirectiveSetMips0();
2807 return false;
2808}
2809
Toma Tabacu85618b32014-08-19 14:22:52 +00002810bool MipsAsmParser::parseSetArchDirective() {
2811 Parser.Lex();
2812 if (getLexer().isNot(AsmToken::Equal))
2813 return reportParseError("unexpected token, expected equals sign");
2814
2815 Parser.Lex();
2816 StringRef Arch;
2817 if (Parser.parseIdentifier(Arch))
2818 return reportParseError("expected arch identifier");
2819
2820 StringRef ArchFeatureName =
2821 StringSwitch<StringRef>(Arch)
2822 .Case("mips1", "mips1")
2823 .Case("mips2", "mips2")
2824 .Case("mips3", "mips3")
2825 .Case("mips4", "mips4")
2826 .Case("mips5", "mips5")
2827 .Case("mips32", "mips32")
2828 .Case("mips32r2", "mips32r2")
2829 .Case("mips32r6", "mips32r6")
2830 .Case("mips64", "mips64")
2831 .Case("mips64r2", "mips64r2")
2832 .Case("mips64r6", "mips64r6")
2833 .Case("cnmips", "cnmips")
2834 .Case("r4000", "mips3") // This is an implementation of Mips3.
2835 .Default("");
2836
2837 if (ArchFeatureName.empty())
2838 return reportParseError("unsupported architecture");
2839
2840 selectArch(ArchFeatureName);
2841 getTargetStreamer().emitDirectiveSetArch(Arch);
2842 return false;
2843}
2844
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002845bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2846 Parser.Lex();
2847 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002848 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002849
Matheus Almeida2852af82014-04-22 10:15:54 +00002850 switch (Feature) {
2851 default:
2852 llvm_unreachable("Unimplemented feature");
2853 case Mips::FeatureDSP:
2854 setFeatureBits(Mips::FeatureDSP, "dsp");
2855 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002856 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002857 case Mips::FeatureMicroMips:
2858 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002859 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002860 case Mips::FeatureMips16:
2861 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002862 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002863 case Mips::FeatureMips1:
2864 selectArch("mips1");
2865 getTargetStreamer().emitDirectiveSetMips1();
2866 break;
2867 case Mips::FeatureMips2:
2868 selectArch("mips2");
2869 getTargetStreamer().emitDirectiveSetMips2();
2870 break;
2871 case Mips::FeatureMips3:
2872 selectArch("mips3");
2873 getTargetStreamer().emitDirectiveSetMips3();
2874 break;
2875 case Mips::FeatureMips4:
2876 selectArch("mips4");
2877 getTargetStreamer().emitDirectiveSetMips4();
2878 break;
2879 case Mips::FeatureMips5:
2880 selectArch("mips5");
2881 getTargetStreamer().emitDirectiveSetMips5();
2882 break;
2883 case Mips::FeatureMips32:
2884 selectArch("mips32");
2885 getTargetStreamer().emitDirectiveSetMips32();
2886 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002887 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002888 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002889 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002890 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002891 case Mips::FeatureMips32r6:
2892 selectArch("mips32r6");
2893 getTargetStreamer().emitDirectiveSetMips32R6();
2894 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002895 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002896 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002897 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002898 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002899 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002900 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002901 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002902 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002903 case Mips::FeatureMips64r6:
2904 selectArch("mips64r6");
2905 getTargetStreamer().emitDirectiveSetMips64R6();
2906 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002907 }
2908 return false;
2909}
2910
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002911bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2912 if (getLexer().isNot(AsmToken::Comma)) {
2913 SMLoc Loc = getLexer().getLoc();
2914 Parser.eatToEndOfStatement();
2915 return Error(Loc, ErrorStr);
2916 }
2917
Matheus Almeida2852af82014-04-22 10:15:54 +00002918 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002919 return true;
2920}
2921
Toma Tabacuc4c202a2014-10-01 14:53:19 +00002922bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002923 if (AssemblerOptions.back()->isReorder())
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002924 Warning(Loc, ".cpload in reorder section");
2925
2926 // FIXME: Warn if cpload is used in Mips16 mode.
2927
David Blaikie960ea3f2014-06-08 16:18:35 +00002928 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00002929 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002930 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2931 reportParseError("expected register containing function address");
2932 return false;
2933 }
2934
David Blaikie960ea3f2014-06-08 16:18:35 +00002935 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2936 if (!RegOpnd.isGPRAsmReg()) {
2937 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002938 return false;
2939 }
2940
Toma Tabacuc4c202a2014-10-01 14:53:19 +00002941 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002942 return false;
2943}
2944
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002945bool MipsAsmParser::parseDirectiveCPSetup() {
2946 unsigned FuncReg;
2947 unsigned Save;
2948 bool SaveIsReg = true;
2949
Matheus Almeida7e815762014-06-18 13:08:59 +00002950 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00002951 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002952 if (ResTy == MatchOperand_NoMatch) {
2953 reportParseError("expected register containing function address");
2954 Parser.eatToEndOfStatement();
2955 return false;
2956 }
2957
2958 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2959 if (!FuncRegOpnd.isGPRAsmReg()) {
2960 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2961 Parser.eatToEndOfStatement();
2962 return false;
2963 }
2964
2965 FuncReg = FuncRegOpnd.getGPR32Reg();
2966 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002967
Toma Tabacu65f10572014-09-16 15:00:52 +00002968 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002969 return true;
2970
Toma Tabacu13964452014-09-04 13:23:44 +00002971 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002972 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002973 const AsmToken &Tok = Parser.getTok();
2974 if (Tok.is(AsmToken::Integer)) {
2975 Save = Tok.getIntVal();
2976 SaveIsReg = false;
2977 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002978 } else {
2979 reportParseError("expected save register or stack offset");
2980 Parser.eatToEndOfStatement();
2981 return false;
2982 }
2983 } else {
2984 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2985 if (!SaveOpnd.isGPRAsmReg()) {
2986 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2987 Parser.eatToEndOfStatement();
2988 return false;
2989 }
2990 Save = SaveOpnd.getGPR32Reg();
2991 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002992
Toma Tabacu65f10572014-09-16 15:00:52 +00002993 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002994 return true;
2995
2996 StringRef Name;
2997 if (Parser.parseIdentifier(Name))
2998 reportParseError("expected identifier");
2999 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003000
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003001 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003002 return false;
3003}
3004
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003005bool MipsAsmParser::parseDirectiveNaN() {
3006 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3007 const AsmToken &Tok = Parser.getTok();
3008
3009 if (Tok.getString() == "2008") {
3010 Parser.Lex();
3011 getTargetStreamer().emitDirectiveNaN2008();
3012 return false;
3013 } else if (Tok.getString() == "legacy") {
3014 Parser.Lex();
3015 getTargetStreamer().emitDirectiveNaNLegacy();
3016 return false;
3017 }
3018 }
3019 // If we don't recognize the option passed to the .nan
3020 // directive (e.g. no option or unknown option), emit an error.
3021 reportParseError("invalid option in .nan directive");
3022 return false;
3023}
3024
Jack Carter0b744b32012-10-04 02:29:46 +00003025bool MipsAsmParser::parseDirectiveSet() {
3026
Jack Carterd0bd6422013-04-18 00:41:53 +00003027 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003028 const AsmToken &Tok = Parser.getTok();
3029
3030 if (Tok.getString() == "noat") {
3031 return parseSetNoAtDirective();
3032 } else if (Tok.getString() == "at") {
3033 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003034 } else if (Tok.getString() == "arch") {
3035 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003036 } else if (Tok.getString() == "fp") {
3037 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003038 } else if (Tok.getString() == "pop") {
3039 return parseSetPopDirective();
3040 } else if (Tok.getString() == "push") {
3041 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003042 } else if (Tok.getString() == "reorder") {
3043 return parseSetReorderDirective();
3044 } else if (Tok.getString() == "noreorder") {
3045 return parseSetNoReorderDirective();
3046 } else if (Tok.getString() == "macro") {
3047 return parseSetMacroDirective();
3048 } else if (Tok.getString() == "nomacro") {
3049 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003050 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003051 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00003052 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003053 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003054 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003055 getTargetStreamer().emitDirectiveSetNoMicroMips();
3056 Parser.eatToEndOfStatement();
3057 return false;
3058 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003059 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003060 } else if (Tok.getString() == "mips0") {
3061 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003062 } else if (Tok.getString() == "mips1") {
3063 return parseSetFeature(Mips::FeatureMips1);
3064 } else if (Tok.getString() == "mips2") {
3065 return parseSetFeature(Mips::FeatureMips2);
3066 } else if (Tok.getString() == "mips3") {
3067 return parseSetFeature(Mips::FeatureMips3);
3068 } else if (Tok.getString() == "mips4") {
3069 return parseSetFeature(Mips::FeatureMips4);
3070 } else if (Tok.getString() == "mips5") {
3071 return parseSetFeature(Mips::FeatureMips5);
3072 } else if (Tok.getString() == "mips32") {
3073 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003074 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003075 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003076 } else if (Tok.getString() == "mips32r6") {
3077 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003078 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003079 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003080 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003081 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003082 } else if (Tok.getString() == "mips64r6") {
3083 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003084 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003085 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003086 } else if (Tok.getString() == "nodsp") {
3087 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003088 } else if (Tok.getString() == "msa") {
3089 return parseSetMsaDirective();
3090 } else if (Tok.getString() == "nomsa") {
3091 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003092 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003093 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003094 parseSetAssignment();
3095 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003096 }
Jack Carter07c818d2013-01-25 01:31:34 +00003097
Jack Carter0b744b32012-10-04 02:29:46 +00003098 return true;
3099}
3100
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003101/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003102/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003103bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00003104 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3105 for (;;) {
3106 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003107 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003108 return true;
3109
3110 getParser().getStreamer().EmitValue(Value, Size);
3111
3112 if (getLexer().is(AsmToken::EndOfStatement))
3113 break;
3114
Jack Carter07c818d2013-01-25 01:31:34 +00003115 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003116 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003117 Parser.Lex();
3118 }
3119 }
3120
3121 Parser.Lex();
3122 return false;
3123}
3124
Vladimir Medic4c299852013-11-06 11:27:05 +00003125/// parseDirectiveGpWord
3126/// ::= .gpword local_sym
3127bool MipsAsmParser::parseDirectiveGpWord() {
3128 const MCExpr *Value;
3129 // EmitGPRel32Value requires an expression, so we are using base class
3130 // method to evaluate the expression.
3131 if (getParser().parseExpression(Value))
3132 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003133 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003134
Vladimir Medice10c1122013-11-13 13:18:04 +00003135 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003136 return Error(getLexer().getLoc(),
3137 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003138 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003139 return false;
3140}
3141
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003142/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003143/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003144bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00003145 const MCExpr *Value;
3146 // EmitGPRel64Value requires an expression, so we are using base class
3147 // method to evaluate the expression.
3148 if (getParser().parseExpression(Value))
3149 return true;
3150 getParser().getStreamer().EmitGPRel64Value(Value);
3151
3152 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003153 return Error(getLexer().getLoc(),
3154 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003155 Parser.Lex(); // Eat EndOfStatement token.
3156 return false;
3157}
3158
Jack Carter0cd3c192014-01-06 23:27:31 +00003159bool MipsAsmParser::parseDirectiveOption() {
3160 // Get the option token.
3161 AsmToken Tok = Parser.getTok();
3162 // At the moment only identifiers are supported.
3163 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003164 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003165 Parser.eatToEndOfStatement();
3166 return false;
3167 }
3168
3169 StringRef Option = Tok.getIdentifier();
3170
3171 if (Option == "pic0") {
3172 getTargetStreamer().emitDirectiveOptionPic0();
3173 Parser.Lex();
3174 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3175 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003176 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003177 Parser.eatToEndOfStatement();
3178 }
3179 return false;
3180 }
3181
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003182 if (Option == "pic2") {
3183 getTargetStreamer().emitDirectiveOptionPic2();
3184 Parser.Lex();
3185 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3186 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003187 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003188 Parser.eatToEndOfStatement();
3189 }
3190 return false;
3191 }
3192
Jack Carter0cd3c192014-01-06 23:27:31 +00003193 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003194 Warning(Parser.getTok().getLoc(),
3195 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003196 Parser.eatToEndOfStatement();
3197 return false;
3198}
3199
Daniel Sanders7e527422014-07-10 13:38:23 +00003200/// parseDirectiveModule
3201/// ::= .module oddspreg
3202/// ::= .module nooddspreg
3203/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003204bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003205 MCAsmLexer &Lexer = getLexer();
3206 SMLoc L = Lexer.getLoc();
3207
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003208 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003209 // TODO : get a better message.
3210 reportParseError(".module directive must appear before any code");
3211 return false;
3212 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003213
3214 if (Lexer.is(AsmToken::Identifier)) {
3215 StringRef Option = Parser.getTok().getString();
3216 Parser.Lex();
3217
3218 if (Option == "oddspreg") {
3219 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3220 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3221
3222 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003223 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003224 return false;
3225 }
3226
3227 return false;
3228 } else if (Option == "nooddspreg") {
3229 if (!isABI_O32()) {
3230 Error(L, "'.module nooddspreg' requires the O32 ABI");
3231 return false;
3232 }
3233
3234 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3235 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3236
3237 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003238 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003239 return false;
3240 }
3241
3242 return false;
3243 } else if (Option == "fp") {
3244 return parseDirectiveModuleFP();
3245 }
3246
3247 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003248 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003249
3250 return false;
3251}
3252
3253/// parseDirectiveModuleFP
3254/// ::= =32
3255/// ::= =xx
3256/// ::= =64
3257bool MipsAsmParser::parseDirectiveModuleFP() {
3258 MCAsmLexer &Lexer = getLexer();
3259
3260 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003261 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003262 return false;
3263 }
3264 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003265
Daniel Sanders7e527422014-07-10 13:38:23 +00003266 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003267 if (!parseFpABIValue(FpABI, ".module"))
3268 return false;
3269
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003270 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003271 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003272 return false;
3273 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003274
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003275 // Emit appropriate flags.
3276 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003277 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003278 return false;
3279}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003280
Daniel Sanders7e527422014-07-10 13:38:23 +00003281bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003282 StringRef Directive) {
3283 MCAsmLexer &Lexer = getLexer();
3284
3285 if (Lexer.is(AsmToken::Identifier)) {
3286 StringRef Value = Parser.getTok().getString();
3287 Parser.Lex();
3288
3289 if (Value != "xx") {
3290 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3291 return false;
3292 }
3293
3294 if (!isABI_O32()) {
3295 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3296 return false;
3297 }
3298
Daniel Sanders7e527422014-07-10 13:38:23 +00003299 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003300 return true;
3301 }
3302
3303 if (Lexer.is(AsmToken::Integer)) {
3304 unsigned Value = Parser.getTok().getIntVal();
3305 Parser.Lex();
3306
3307 if (Value != 32 && Value != 64) {
3308 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3309 return false;
3310 }
3311
3312 if (Value == 32) {
3313 if (!isABI_O32()) {
3314 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3315 return false;
3316 }
3317
Daniel Sanders7e527422014-07-10 13:38:23 +00003318 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3319 } else
3320 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003321
Daniel Sanders7e527422014-07-10 13:38:23 +00003322 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003323 }
3324
3325 return false;
3326}
3327
Jack Carter0b744b32012-10-04 02:29:46 +00003328bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003329 StringRef IDVal = DirectiveID.getString();
3330
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003331 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003332 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003333 if (IDVal == ".dword") {
3334 parseDataDirective(8, DirectiveID.getLoc());
3335 return false;
3336 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003337 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003338 StringRef SymbolName;
3339
3340 if (Parser.parseIdentifier(SymbolName)) {
3341 reportParseError("expected identifier after .ent");
3342 return false;
3343 }
3344
3345 // There's an undocumented extension that allows an integer to
3346 // follow the name of the procedure which AFAICS is ignored by GAS.
3347 // Example: .ent foo,2
3348 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3349 if (getLexer().isNot(AsmToken::Comma)) {
3350 // Even though we accept this undocumented extension for compatibility
3351 // reasons, the additional integer argument does not actually change
3352 // the behaviour of the '.ent' directive, so we would like to discourage
3353 // its use. We do this by not referring to the extended version in
3354 // error messages which are not directly related to its use.
3355 reportParseError("unexpected token, expected end of statement");
3356 return false;
3357 }
3358 Parser.Lex(); // Eat the comma.
3359 const MCExpr *DummyNumber;
3360 int64_t DummyNumberVal;
3361 // If the user was explicitly trying to use the extended version,
3362 // we still give helpful extension-related error messages.
3363 if (Parser.parseExpression(DummyNumber)) {
3364 reportParseError("expected number after comma");
3365 return false;
3366 }
3367 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3368 reportParseError("expected an absolute expression after comma");
3369 return false;
3370 }
3371 }
3372
3373 // If this is not the end of the statement, report an error.
3374 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3375 reportParseError("unexpected token, expected end of statement");
3376 return false;
3377 }
3378
3379 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3380
3381 getTargetStreamer().emitDirectiveEnt(*Sym);
3382 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003383 return false;
3384 }
3385
Jack Carter07c818d2013-01-25 01:31:34 +00003386 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003387 StringRef SymbolName;
3388
3389 if (Parser.parseIdentifier(SymbolName)) {
3390 reportParseError("expected identifier after .end");
3391 return false;
3392 }
3393
3394 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3395 reportParseError("unexpected token, expected end of statement");
3396 return false;
3397 }
3398
3399 if (CurrentFn == nullptr) {
3400 reportParseError(".end used without .ent");
3401 return false;
3402 }
3403
3404 if ((SymbolName != CurrentFn->getName())) {
3405 reportParseError(".end symbol does not match .ent symbol");
3406 return false;
3407 }
3408
3409 getTargetStreamer().emitDirectiveEnd(SymbolName);
3410 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003411 return false;
3412 }
3413
Jack Carter07c818d2013-01-25 01:31:34 +00003414 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003415 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3416 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003417 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003418 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3419 reportParseError("expected stack register");
3420 return false;
3421 }
3422
3423 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3424 if (!StackRegOpnd.isGPRAsmReg()) {
3425 reportParseError(StackRegOpnd.getStartLoc(),
3426 "expected general purpose register");
3427 return false;
3428 }
3429 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3430
3431 if (Parser.getTok().is(AsmToken::Comma))
3432 Parser.Lex();
3433 else {
3434 reportParseError("unexpected token, expected comma");
3435 return false;
3436 }
3437
3438 // Parse the frame size.
3439 const MCExpr *FrameSize;
3440 int64_t FrameSizeVal;
3441
3442 if (Parser.parseExpression(FrameSize)) {
3443 reportParseError("expected frame size value");
3444 return false;
3445 }
3446
3447 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3448 reportParseError("frame size not an absolute expression");
3449 return false;
3450 }
3451
3452 if (Parser.getTok().is(AsmToken::Comma))
3453 Parser.Lex();
3454 else {
3455 reportParseError("unexpected token, expected comma");
3456 return false;
3457 }
3458
3459 // Parse the return register.
3460 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003461 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003462 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3463 reportParseError("expected return register");
3464 return false;
3465 }
3466
3467 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3468 if (!ReturnRegOpnd.isGPRAsmReg()) {
3469 reportParseError(ReturnRegOpnd.getStartLoc(),
3470 "expected general purpose register");
3471 return false;
3472 }
3473
3474 // If this is not the end of the statement, report an error.
3475 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3476 reportParseError("unexpected token, expected end of statement");
3477 return false;
3478 }
3479
3480 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3481 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003482 return false;
3483 }
3484
Jack Carter07c818d2013-01-25 01:31:34 +00003485 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003486 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003487 }
3488
Daniel Sandersd97a6342014-08-13 10:07:34 +00003489 if (IDVal == ".mask" || IDVal == ".fmask") {
3490 // .mask bitmask, frame_offset
3491 // bitmask: One bit for each register used.
3492 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3493 // first register is expected to be saved.
3494 // Examples:
3495 // .mask 0x80000000, -4
3496 // .fmask 0x80000000, -4
3497 //
Jack Carterbe332172012-09-07 00:48:02 +00003498
Daniel Sandersd97a6342014-08-13 10:07:34 +00003499 // Parse the bitmask
3500 const MCExpr *BitMask;
3501 int64_t BitMaskVal;
3502
3503 if (Parser.parseExpression(BitMask)) {
3504 reportParseError("expected bitmask value");
3505 return false;
3506 }
3507
3508 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3509 reportParseError("bitmask not an absolute expression");
3510 return false;
3511 }
3512
3513 if (Parser.getTok().is(AsmToken::Comma))
3514 Parser.Lex();
3515 else {
3516 reportParseError("unexpected token, expected comma");
3517 return false;
3518 }
3519
3520 // Parse the frame_offset
3521 const MCExpr *FrameOffset;
3522 int64_t FrameOffsetVal;
3523
3524 if (Parser.parseExpression(FrameOffset)) {
3525 reportParseError("expected frame offset value");
3526 return false;
3527 }
3528
3529 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3530 reportParseError("frame offset not an absolute expression");
3531 return false;
3532 }
3533
3534 // If this is not the end of the statement, report an error.
3535 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3536 reportParseError("unexpected token, expected end of statement");
3537 return false;
3538 }
3539
3540 if (IDVal == ".mask")
3541 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3542 else
3543 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003544 return false;
3545 }
3546
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003547 if (IDVal == ".nan")
3548 return parseDirectiveNaN();
3549
Jack Carter07c818d2013-01-25 01:31:34 +00003550 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003551 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003552 return false;
3553 }
3554
Rafael Espindolab59fb732014-03-28 18:50:26 +00003555 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003556 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003557 return false;
3558 }
3559
Jack Carter07c818d2013-01-25 01:31:34 +00003560 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003561 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003562 return false;
3563 }
3564
Jack Carter0cd3c192014-01-06 23:27:31 +00003565 if (IDVal == ".option")
3566 return parseDirectiveOption();
3567
3568 if (IDVal == ".abicalls") {
3569 getTargetStreamer().emitDirectiveAbiCalls();
3570 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003571 Error(Parser.getTok().getLoc(),
3572 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003573 // Clear line
3574 Parser.eatToEndOfStatement();
3575 }
3576 return false;
3577 }
3578
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003579 if (IDVal == ".cpsetup")
3580 return parseDirectiveCPSetup();
3581
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003582 if (IDVal == ".module")
3583 return parseDirectiveModule();
3584
Rafael Espindola870c4e92012-01-11 03:56:41 +00003585 return true;
3586}
3587
Rafael Espindola870c4e92012-01-11 03:56:41 +00003588extern "C" void LLVMInitializeMipsAsmParser() {
3589 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3590 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3591 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3592 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3593}
Jack Carterb4dbc172012-09-05 23:34:03 +00003594
3595#define GET_REGISTER_MATCHER
3596#define GET_MATCHER_IMPLEMENTATION
3597#include "MipsGenAsmMatcher.inc"