blob: 4f7b8c4231d832ec1a3a8dc28ca2bbea191d6d2b [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"
Toma Tabacu9db22db2014-09-09 10:15:38 +000030#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000031
32using namespace llvm;
33
Chandler Carruthe96dd892014-04-21 22:55:11 +000034#define DEBUG_TYPE "mips-asm-parser"
35
Joey Gouly0e76fa72013-09-12 10:28:05 +000036namespace llvm {
37class MCInstrInfo;
38}
39
Rafael Espindola870c4e92012-01-11 03:56:41 +000040namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000041class MipsAssemblerOptions {
42public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000043 MipsAssemblerOptions(uint64_t Features_) :
44 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000045
Toma Tabacu9db22db2014-09-09 10:15:38 +000046 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
47 ATReg = Opts->getATRegNum();
48 Reorder = Opts->isReorder();
49 Macro = Opts->isMacro();
50 Features = Opts->getFeatures();
51 }
52
53 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000054 bool setATReg(unsigned Reg);
55
Toma Tabacu9db22db2014-09-09 10:15:38 +000056 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000057 void setReorder() { Reorder = true; }
58 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000059
Toma Tabacu9db22db2014-09-09 10:15:38 +000060 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000061 void setMacro() { Macro = true; }
62 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000063
Toma Tabacu9db22db2014-09-09 10:15:38 +000064 uint64_t getFeatures() const { return Features; }
65 void setFeatures(uint64_t Features_) { Features = Features_; }
66
Daniel Sandersf0df2212014-08-04 12:20:00 +000067 // Set of features that are either architecture features or referenced
68 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
69 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
70 // The reason we need this mask is explained in the selectArch function.
71 // FIXME: Ideally we would like TableGen to generate this information.
72 static const uint64_t AllArchRelatedMask =
73 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
74 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
75 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
76 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
77 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
78 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
79 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
80
Jack Carter0b744b32012-10-04 02:29:46 +000081private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000082 unsigned ATReg;
83 bool Reorder;
84 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000085 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000086};
87}
88
89namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000090class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000091 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000092 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000093 return static_cast<MipsTargetStreamer &>(TS);
94 }
95
Jack Carterb4dbc172012-09-05 23:34:03 +000096 MCSubtargetInfo &STI;
97 MCAsmParser &Parser;
Toma Tabacu9db22db2014-09-09 10:15:38 +000098 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +000099 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
100 // nullptr, which indicates that no function is currently
101 // selected. This usually happens after an '.end func'
102 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000103
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000104#define GET_ASSEMBLER_HEADER
105#include "MipsGenAsmMatcher.inc"
106
Matheus Almeida595fcab2014-06-11 15:05:56 +0000107 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
108
Chad Rosier49963552012-10-13 00:26:04 +0000109 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000110 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000111 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000112 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000113
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000114 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000115 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000116
Toma Tabacu13964452014-09-04 13:23:44 +0000117 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000118
Toma Tabacu13964452014-09-04 13:23:44 +0000119 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000120
David Blaikie960ea3f2014-06-08 16:18:35 +0000121 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
122 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000123
Craig Topper56c590a2014-04-29 07:58:02 +0000124 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000125
David Blaikie960ea3f2014-06-08 16:18:35 +0000126 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000127
128 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000129 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000131
Jack Carter873c7242013-01-12 01:03:14 +0000132 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000133 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000134
Toma Tabacu13964452014-09-04 13:23:44 +0000135 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000136
Toma Tabacu13964452014-09-04 13:23:44 +0000137 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000140
David Blaikie960ea3f2014-06-08 16:18:35 +0000141 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 bool searchSymbolAlias(OperandVector &Operands);
146
Toma Tabacu13964452014-09-04 13:23:44 +0000147 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000148
Jack Carter30a59822012-10-04 04:03:53 +0000149 bool needsExpansion(MCInst &Inst);
150
Matheus Almeida3813d572014-06-19 14:39:14 +0000151 // Expands assembly pseudo instructions.
152 // Returns false on success, true otherwise.
153 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000154 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000155
156 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000157 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000158
159 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000160 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000161
162 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000163 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000164
Toma Tabacu0d64b202014-08-14 10:29:17 +0000165 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
166 SmallVectorImpl<MCInst> &Instructions);
167
Jack Carter9e65aa32013-03-22 00:05:30 +0000168 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000169 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
170 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000171 bool reportParseError(Twine ErrorMsg);
172 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000173
Jack Carterb5cf5902013-04-17 00:18:04 +0000174 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000175 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000176
Vladimir Medic4c299852013-11-06 11:27:05 +0000177 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000178
179 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000180 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000181 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000182 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000183 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000184 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000185 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000186 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000187 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000188
189 bool parseSetAtDirective();
190 bool parseSetNoAtDirective();
191 bool parseSetMacroDirective();
192 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000193 bool parseSetMsaDirective();
194 bool parseSetNoMsaDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000195 bool parseSetReorderDirective();
196 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000197 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000198 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000199 bool parseSetPopDirective();
200 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000201
Jack Carterd76b2372013-03-21 21:44:16 +0000202 bool parseSetAssignment();
203
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000204 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000205 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000206 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000207 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000208 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000209 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
210 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000211
Jack Carterdc1e35d2012-09-06 20:00:02 +0000212 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000213
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000214 bool eatComma(StringRef ErrorStr);
215
Jack Carter1ac53222013-02-20 23:11:17 +0000216 int matchCPURegisterName(StringRef Symbol);
217
Jack Carter873c7242013-01-12 01:03:14 +0000218 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000219
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000220 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000221
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000222 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000223
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000224 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000225
Jack Carter5dc8ac92013-09-25 23:50:44 +0000226 int matchMSA128RegisterName(StringRef Name);
227
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000228 int matchMSA128CtrlRegisterName(StringRef Name);
229
Jack Carterd0bd6422013-04-18 00:41:53 +0000230 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000231
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000232 unsigned getGPR(int RegNo);
233
Matheus Almeida7de68e72014-06-18 14:46:05 +0000234 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000235
236 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000237 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000238
239 // Helper function that checks if the value of a vector index is within the
240 // boundaries of accepted values for each RegisterKind
241 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
242 bool validateMSAIndex(int Val, int RegKind);
243
Daniel Sandersf0df2212014-08-04 12:20:00 +0000244 // Selects a new architecture by updating the FeatureBits with the necessary
245 // info including implied dependencies.
246 // Internally, it clears all the feature bits related to *any* architecture
247 // and selects the new one using the ToggleFeature functionality of the
248 // MCSubtargetInfo object that handles implied dependencies. The reason we
249 // clear all the arch related bits manually is because ToggleFeature only
250 // clears the features that imply the feature being cleared and not the
251 // features implied by the feature being cleared. This is easier to see
252 // with an example:
253 // --------------------------------------------------
254 // | Feature | Implies |
255 // | -------------------------------------------------|
256 // | FeatureMips1 | None |
257 // | FeatureMips2 | FeatureMips1 |
258 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
259 // | FeatureMips4 | FeatureMips3 |
260 // | ... | |
261 // --------------------------------------------------
262 //
263 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
264 // FeatureMipsGP64 | FeatureMips1)
265 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
266 void selectArch(StringRef ArchFeature) {
267 uint64_t FeatureBits = STI.getFeatureBits();
268 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
269 STI.setFeatureBits(FeatureBits);
270 setAvailableFeatures(
271 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000272 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000273 }
274
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000275 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000276 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000277 setAvailableFeatures(
278 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000279 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000280 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000281 }
282
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000283 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000284 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000285 setAvailableFeatures(
286 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000287 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000288 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000289 }
290
Rafael Espindola870c4e92012-01-11 03:56:41 +0000291public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000292 enum MipsMatchResultTy {
293 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
294#define GET_OPERAND_DIAGNOSTIC_TYPES
295#include "MipsGenAsmMatcher.inc"
296#undef GET_OPERAND_DIAGNOSTIC_TYPES
297
298 };
299
Joey Gouly0e76fa72013-09-12 10:28:05 +0000300 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000301 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000302 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000303 // Initialize the set of available features.
304 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000305
306 // Remember the initial assembler options. The user can not modify these.
307 MipsAssemblerOptions *TmpAOPtr =
308 new MipsAssemblerOptions(getAvailableFeatures());
309 AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
310
311 // Create an assembler options environment for the user to modify.
312 TmpAOPtr = new MipsAssemblerOptions(getAvailableFeatures());
313 AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
314 TmpAOPtr = nullptr;
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000315
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000316 getTargetStreamer().updateABIInfo(*this);
317
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000318 // Assert exactly one ABI was chosen.
319 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
320 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
321 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
322 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000323
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000324 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000325 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000326
327 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000328 }
329
Jack Carterb4dbc172012-09-05 23:34:03 +0000330 MCAsmParser &getParser() const { return Parser; }
331 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000332
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000333 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
334 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
335
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000336 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
337 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
338 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
339 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
340 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000341 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000342
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000343 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000344 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
345 }
346
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000347 bool inMicroMipsMode() const {
348 return STI.getFeatureBits() & Mips::FeatureMicroMips;
349 }
350 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
351 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
352 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
353 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
354 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
355 bool hasMips32() const {
356 return (STI.getFeatureBits() & Mips::FeatureMips32);
357 }
358 bool hasMips64() const {
359 return (STI.getFeatureBits() & Mips::FeatureMips64);
360 }
361 bool hasMips32r2() const {
362 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
363 }
364 bool hasMips64r2() const {
365 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
366 }
367 bool hasMips32r6() const {
368 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
369 }
370 bool hasMips64r6() const {
371 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
372 }
373 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
374 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
375 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
376
377 bool inMips16Mode() const {
378 return STI.getFeatureBits() & Mips::FeatureMips16;
379 }
380 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000381 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000382
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000383 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000384 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000385};
386}
387
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000388namespace {
389
390/// MipsOperand - Instances of this class represent a parsed Mips machine
391/// instruction.
392class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000393public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000394 /// Broad categories of register classes
395 /// The exact class is finalized by the render method.
396 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000397 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000398 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000399 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000400 RegKind_FCC = 4, /// FCC
401 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
402 RegKind_MSACtrl = 16, /// MSA control registers
403 RegKind_COP2 = 32, /// COP2
404 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
405 /// context).
406 RegKind_CCR = 128, /// CCR
407 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000408 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000409
410 /// Potentially any (e.g. $1)
411 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
412 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000413 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000414 };
415
416private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000417 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000418 k_Immediate, /// An immediate (possibly involving symbol references)
419 k_Memory, /// Base + Offset Memory Address
420 k_PhysRegister, /// A physical register from the Mips namespace
421 k_RegisterIndex, /// A register index in one or more RegKind.
422 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000423 } Kind;
424
David Blaikie960ea3f2014-06-08 16:18:35 +0000425public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000426 MipsOperand(KindTy K, MipsAsmParser &Parser)
427 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
428
David Blaikie960ea3f2014-06-08 16:18:35 +0000429private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000430 /// For diagnostics, and checking the assembler temporary
431 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000432
Eric Christopher8996c5d2013-03-15 00:42:55 +0000433 struct Token {
434 const char *Data;
435 unsigned Length;
436 };
437
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000438 struct PhysRegOp {
439 unsigned Num; /// Register Number
440 };
441
442 struct RegIdxOp {
443 unsigned Index; /// Index into the register class
444 RegKind Kind; /// Bitfield of the kinds it could possibly be
445 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000446 };
447
448 struct ImmOp {
449 const MCExpr *Val;
450 };
451
452 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000453 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000454 const MCExpr *Off;
455 };
456
Jack Carterb4dbc172012-09-05 23:34:03 +0000457 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000458 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000459 struct PhysRegOp PhysReg;
460 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000461 struct ImmOp Imm;
462 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000463 };
464
465 SMLoc StartLoc, EndLoc;
466
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000467 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000468 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
469 const MCRegisterInfo *RegInfo,
470 SMLoc S, SMLoc E,
471 MipsAsmParser &Parser) {
472 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000473 Op->RegIdx.Index = Index;
474 Op->RegIdx.RegInfo = RegInfo;
475 Op->RegIdx.Kind = RegKind;
476 Op->StartLoc = S;
477 Op->EndLoc = E;
478 return Op;
479 }
480
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000481public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000482 /// Coerce the register to GPR32 and return the real register for the current
483 /// target.
484 unsigned getGPR32Reg() const {
485 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000486 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000487 unsigned ClassID = Mips::GPR32RegClassID;
488 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000489 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000490
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000491 /// Coerce the register to GPR64 and return the real register for the current
492 /// target.
493 unsigned getGPR64Reg() const {
494 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
495 unsigned ClassID = Mips::GPR64RegClassID;
496 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000497 }
498
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000499private:
500 /// Coerce the register to AFGR64 and return the real register for the current
501 /// target.
502 unsigned getAFGR64Reg() const {
503 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
504 if (RegIdx.Index % 2 != 0)
505 AsmParser.Warning(StartLoc, "Float register should be even.");
506 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
507 .getRegister(RegIdx.Index / 2);
508 }
509
510 /// Coerce the register to FGR64 and return the real register for the current
511 /// target.
512 unsigned getFGR64Reg() const {
513 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
514 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
515 .getRegister(RegIdx.Index);
516 }
517
518 /// Coerce the register to FGR32 and return the real register for the current
519 /// target.
520 unsigned getFGR32Reg() const {
521 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
522 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
523 .getRegister(RegIdx.Index);
524 }
525
526 /// Coerce the register to FGRH32 and return the real register for the current
527 /// target.
528 unsigned getFGRH32Reg() const {
529 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
530 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
531 .getRegister(RegIdx.Index);
532 }
533
534 /// Coerce the register to FCC and return the real register for the current
535 /// target.
536 unsigned getFCCReg() const {
537 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
538 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
539 .getRegister(RegIdx.Index);
540 }
541
542 /// Coerce the register to MSA128 and return the real register for the current
543 /// target.
544 unsigned getMSA128Reg() const {
545 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
546 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
547 // identical
548 unsigned ClassID = Mips::MSA128BRegClassID;
549 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
550 }
551
552 /// Coerce the register to MSACtrl and return the real register for the
553 /// current target.
554 unsigned getMSACtrlReg() const {
555 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
556 unsigned ClassID = Mips::MSACtrlRegClassID;
557 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
558 }
559
560 /// Coerce the register to COP2 and return the real register for the
561 /// current target.
562 unsigned getCOP2Reg() const {
563 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
564 unsigned ClassID = Mips::COP2RegClassID;
565 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
566 }
567
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000568 /// Coerce the register to COP3 and return the real register for the
569 /// current target.
570 unsigned getCOP3Reg() const {
571 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
572 unsigned ClassID = Mips::COP3RegClassID;
573 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
574 }
575
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 /// Coerce the register to ACC64DSP and return the real register for the
577 /// current target.
578 unsigned getACC64DSPReg() const {
579 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
580 unsigned ClassID = Mips::ACC64DSPRegClassID;
581 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
582 }
583
584 /// Coerce the register to HI32DSP and return the real register for the
585 /// current target.
586 unsigned getHI32DSPReg() const {
587 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
588 unsigned ClassID = Mips::HI32DSPRegClassID;
589 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
590 }
591
592 /// Coerce the register to LO32DSP and return the real register for the
593 /// current target.
594 unsigned getLO32DSPReg() const {
595 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
596 unsigned ClassID = Mips::LO32DSPRegClassID;
597 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
598 }
599
600 /// Coerce the register to CCR and return the real register for the
601 /// current target.
602 unsigned getCCRReg() const {
603 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
604 unsigned ClassID = Mips::CCRRegClassID;
605 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
606 }
607
608 /// Coerce the register to HWRegs and return the real register for the
609 /// current target.
610 unsigned getHWRegsReg() const {
611 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
612 unsigned ClassID = Mips::HWRegsRegClassID;
613 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
614 }
615
616public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000617 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000618 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000619 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000620 Inst.addOperand(MCOperand::CreateImm(0));
621 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
622 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
623 else
624 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000625 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000626
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000627 void addRegOperands(MCInst &Inst, unsigned N) const {
628 llvm_unreachable("Use a custom parser instead");
629 }
630
Daniel Sanders21bce302014-04-01 12:35:23 +0000631 /// Render the operand to an MCInst as a GPR32
632 /// Asserts if the wrong number of operands are requested, or the operand
633 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
635 assert(N == 1 && "Invalid number of operands!");
636 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
637 }
638
Daniel Sanders21bce302014-04-01 12:35:23 +0000639 /// Render the operand to an MCInst as a GPR64
640 /// Asserts if the wrong number of operands are requested, or the operand
641 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000642 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
643 assert(N == 1 && "Invalid number of operands!");
644 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
645 }
646
647 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
648 assert(N == 1 && "Invalid number of operands!");
649 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
650 }
651
652 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
653 assert(N == 1 && "Invalid number of operands!");
654 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
655 }
656
657 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
658 assert(N == 1 && "Invalid number of operands!");
659 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000660 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000661 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000662 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
663 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 }
665
666 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
667 assert(N == 1 && "Invalid number of operands!");
668 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
669 }
670
671 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
672 assert(N == 1 && "Invalid number of operands!");
673 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
674 }
675
676 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
677 assert(N == 1 && "Invalid number of operands!");
678 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
679 }
680
681 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
682 assert(N == 1 && "Invalid number of operands!");
683 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
684 }
685
686 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
687 assert(N == 1 && "Invalid number of operands!");
688 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
689 }
690
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000691 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
692 assert(N == 1 && "Invalid number of operands!");
693 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
694 }
695
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000696 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
697 assert(N == 1 && "Invalid number of operands!");
698 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
699 }
700
701 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
702 assert(N == 1 && "Invalid number of operands!");
703 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
704 }
705
706 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
707 assert(N == 1 && "Invalid number of operands!");
708 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
709 }
710
711 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
712 assert(N == 1 && "Invalid number of operands!");
713 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
714 }
715
716 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
717 assert(N == 1 && "Invalid number of operands!");
718 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
719 }
720
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000721 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000722 assert(N == 1 && "Invalid number of operands!");
723 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000724 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000725 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000726
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000727 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000728 assert(N == 2 && "Invalid number of operands!");
729
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000730 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000731
732 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000733 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000734 }
735
Craig Topper56c590a2014-04-29 07:58:02 +0000736 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000737 // As a special case until we sort out the definition of div/divu, pretend
738 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
739 if (isGPRAsmReg() && RegIdx.Index == 0)
740 return true;
741
742 return Kind == k_PhysRegister;
743 }
744 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000745 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000746 bool isConstantImm() const {
747 return isImm() && dyn_cast<MCConstantExpr>(getImm());
748 }
Craig Topper56c590a2014-04-29 07:58:02 +0000749 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 // Note: It's not possible to pretend that other operand kinds are tokens.
751 // The matcher emitter checks tokens first.
752 return Kind == k_Token;
753 }
Craig Topper56c590a2014-04-29 07:58:02 +0000754 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000755 bool isConstantMemOff() const {
756 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
757 }
758 template <unsigned Bits> bool isMemWithSimmOffset() const {
759 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
760 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000761 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000762 bool isLSAImm() const {
763 if (!isConstantImm())
764 return false;
765 int64_t Val = getConstantImm();
766 return 1 <= Val && Val <= 4;
767 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000768
769 StringRef getToken() const {
770 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000771 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000772 }
773
Craig Topper56c590a2014-04-29 07:58:02 +0000774 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 // As a special case until we sort out the definition of div/divu, pretend
776 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
777 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
778 RegIdx.Kind & RegKind_GPR)
779 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000780
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 assert(Kind == k_PhysRegister && "Invalid access!");
782 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000783 }
784
Jack Carterb4dbc172012-09-05 23:34:03 +0000785 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000786 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000787 return Imm.Val;
788 }
789
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000790 int64_t getConstantImm() const {
791 const MCExpr *Val = getImm();
792 return static_cast<const MCConstantExpr *>(Val)->getValue();
793 }
794
795 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000796 assert((Kind == k_Memory) && "Invalid access!");
797 return Mem.Base;
798 }
799
800 const MCExpr *getMemOff() const {
801 assert((Kind == k_Memory) && "Invalid access!");
802 return Mem.Off;
803 }
804
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000805 int64_t getConstantMemOff() const {
806 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
807 }
808
David Blaikie960ea3f2014-06-08 16:18:35 +0000809 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
810 MipsAsmParser &Parser) {
811 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000812 Op->Tok.Data = Str.data();
813 Op->Tok.Length = Str.size();
814 Op->StartLoc = S;
815 Op->EndLoc = S;
816 return Op;
817 }
818
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 /// Create a numeric register (e.g. $1). The exact register remains
820 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000821 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000822 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000823 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000824 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000826 }
827
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 /// Create a register that is definitely a GPR.
829 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000830 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000831 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000832 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000834 }
835
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 /// Create a register that is definitely a FGR.
837 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000838 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000839 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000840 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000841 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
842 }
843
844 /// Create a register that is definitely an FCC.
845 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000846 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000847 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000848 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000849 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
850 }
851
852 /// Create a register that is definitely an ACC.
853 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000854 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000855 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000856 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000857 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
858 }
859
860 /// Create a register that is definitely an MSA128.
861 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000862 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000863 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000864 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
866 }
867
868 /// Create a register that is definitely an MSACtrl.
869 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000870 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000871 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000872 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
874 }
875
David Blaikie960ea3f2014-06-08 16:18:35 +0000876 static std::unique_ptr<MipsOperand>
877 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
878 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000879 Op->Imm.Val = Val;
880 Op->StartLoc = S;
881 Op->EndLoc = E;
882 return Op;
883 }
884
David Blaikie960ea3f2014-06-08 16:18:35 +0000885 static std::unique_ptr<MipsOperand>
886 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
887 SMLoc E, MipsAsmParser &Parser) {
888 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
889 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000890 Op->Mem.Off = Off;
891 Op->StartLoc = S;
892 Op->EndLoc = E;
893 return Op;
894 }
895
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000896 bool isGPRAsmReg() const {
897 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000898 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000899 bool isFGRAsmReg() const {
900 // AFGR64 is $0-$15 but we handle this in getAFGR64()
901 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000902 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000903 bool isHWRegsAsmReg() const {
904 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000905 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000906 bool isCCRAsmReg() const {
907 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000908 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000909 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000910 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
911 return false;
912 if (!AsmParser.hasEightFccRegisters())
913 return RegIdx.Index == 0;
914 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000915 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000916 bool isACCAsmReg() const {
917 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000918 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000919 bool isCOP2AsmReg() const {
920 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000921 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000922 bool isCOP3AsmReg() const {
923 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
924 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000925 bool isMSA128AsmReg() const {
926 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000927 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000928 bool isMSACtrlAsmReg() const {
929 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000930 }
931
Jack Carterb4dbc172012-09-05 23:34:03 +0000932 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000933 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000934 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000935 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000936
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000937 virtual ~MipsOperand() {
938 switch (Kind) {
939 case k_Immediate:
940 break;
941 case k_Memory:
942 delete Mem.Base;
943 break;
944 case k_PhysRegister:
945 case k_RegisterIndex:
946 case k_Token:
947 break;
948 }
949 }
950
Craig Topper56c590a2014-04-29 07:58:02 +0000951 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000952 switch (Kind) {
953 case k_Immediate:
954 OS << "Imm<";
955 Imm.Val->print(OS);
956 OS << ">";
957 break;
958 case k_Memory:
959 OS << "Mem<";
960 Mem.Base->print(OS);
961 OS << ", ";
962 Mem.Off->print(OS);
963 OS << ">";
964 break;
965 case k_PhysRegister:
966 OS << "PhysReg<" << PhysReg.Num << ">";
967 break;
968 case k_RegisterIndex:
969 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
970 break;
971 case k_Token:
972 OS << Tok.Data;
973 break;
974 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000975 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000976}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000977} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000978
Jack Carter9e65aa32013-03-22 00:05:30 +0000979namespace llvm {
980extern const MCInstrDesc MipsInsts[];
981}
982static const MCInstrDesc &getInstDesc(unsigned Opcode) {
983 return MipsInsts[Opcode];
984}
985
986bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000987 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000988 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000989
Jack Carter9e65aa32013-03-22 00:05:30 +0000990 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000991
992 if (MCID.isBranch() || MCID.isCall()) {
993 const unsigned Opcode = Inst.getOpcode();
994 MCOperand Offset;
995
996 switch (Opcode) {
997 default:
998 break;
999 case Mips::BEQ:
1000 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001001 case Mips::BEQ_MM:
1002 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001003 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001004 Offset = Inst.getOperand(2);
1005 if (!Offset.isImm())
1006 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001007 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001008 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001009 if (OffsetToAlignment(Offset.getImm(),
1010 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001011 return Error(IDLoc, "branch to misaligned address");
1012 break;
1013 case Mips::BGEZ:
1014 case Mips::BGTZ:
1015 case Mips::BLEZ:
1016 case Mips::BLTZ:
1017 case Mips::BGEZAL:
1018 case Mips::BLTZAL:
1019 case Mips::BC1F:
1020 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 case Mips::BGEZ_MM:
1022 case Mips::BGTZ_MM:
1023 case Mips::BLEZ_MM:
1024 case Mips::BLTZ_MM:
1025 case Mips::BGEZAL_MM:
1026 case Mips::BLTZAL_MM:
1027 case Mips::BC1F_MM:
1028 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001029 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001030 Offset = Inst.getOperand(1);
1031 if (!Offset.isImm())
1032 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001033 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001034 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001035 if (OffsetToAlignment(Offset.getImm(),
1036 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001037 return Error(IDLoc, "branch to misaligned address");
1038 break;
1039 }
1040 }
1041
Daniel Sandersa84989a2014-06-16 13:25:35 +00001042 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1043 // We still accept it but it is a normal nop.
1044 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1045 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1046 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1047 "nop instruction");
1048 }
1049
Toma Tabacu9db22db2014-09-09 10:15:38 +00001050 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001051 // If this instruction has a delay slot and .set reorder is active,
1052 // emit a NOP after it.
1053 Instructions.push_back(Inst);
1054 MCInst NopInst;
1055 NopInst.setOpcode(Mips::SLL);
1056 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1057 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1058 NopInst.addOperand(MCOperand::CreateImm(0));
1059 Instructions.push_back(NopInst);
1060 return false;
1061 }
1062
Jack Carter9e65aa32013-03-22 00:05:30 +00001063 if (MCID.mayLoad() || MCID.mayStore()) {
1064 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001065 // reference or immediate we may have to expand instructions.
1066 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001067 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001068 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1069 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001070 MCOperand &Op = Inst.getOperand(i);
1071 if (Op.isImm()) {
1072 int MemOffset = Op.getImm();
1073 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001074 // Offset can't exceed 16bit value.
1075 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001076 return false;
1077 }
1078 } else if (Op.isExpr()) {
1079 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001080 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001081 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001082 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001083 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001084 // Expand symbol.
1085 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001086 return false;
1087 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001088 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001089 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001090 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001091 }
1092 }
1093 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001094 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001095 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001096
1097 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001098 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001099 else
1100 Instructions.push_back(Inst);
1101
1102 return false;
1103}
1104
Jack Carter30a59822012-10-04 04:03:53 +00001105bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1106
Jack Carterd0bd6422013-04-18 00:41:53 +00001107 switch (Inst.getOpcode()) {
1108 case Mips::LoadImm32Reg:
1109 case Mips::LoadAddr32Imm:
1110 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001111 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001112 return true;
1113 default:
1114 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001115 }
1116}
Jack Carter92995f12012-10-06 00:53:28 +00001117
Matheus Almeida3813d572014-06-19 14:39:14 +00001118bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001119 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001120 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001121 default:
1122 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001123 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001124 case Mips::LoadImm32Reg:
1125 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001126 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001127 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001128 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1129 return true;
1130 }
1131 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001132 case Mips::LoadAddr32Imm:
1133 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1134 case Mips::LoadAddr32Reg:
1135 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1136 }
Jack Carter30a59822012-10-04 04:03:53 +00001137}
Jack Carter92995f12012-10-06 00:53:28 +00001138
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001139namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001140template <bool PerformShift>
1141void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001142 SmallVectorImpl<MCInst> &Instructions) {
1143 MCInst tmpInst;
1144 if (PerformShift) {
1145 tmpInst.setOpcode(Mips::DSLL);
1146 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1147 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1148 tmpInst.addOperand(MCOperand::CreateImm(16));
1149 tmpInst.setLoc(IDLoc);
1150 Instructions.push_back(tmpInst);
1151 tmpInst.clear();
1152 }
1153 tmpInst.setOpcode(Mips::ORi);
1154 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1155 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001156 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001157 tmpInst.setLoc(IDLoc);
1158 Instructions.push_back(tmpInst);
1159}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001160
1161template <int Shift, bool PerformShift>
1162void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1163 SmallVectorImpl<MCInst> &Instructions) {
1164 createShiftOr<PerformShift>(
1165 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1166 IDLoc, Instructions);
1167}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001168}
1169
Matheus Almeida3813d572014-06-19 14:39:14 +00001170bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001171 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001172 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001173 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001174 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001175 const MCOperand &RegOp = Inst.getOperand(0);
1176 assert(RegOp.isReg() && "expected register operand kind");
1177
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001178 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001179 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001180 // FIXME: gas has a special case for values that are 000...1111, which
1181 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001182 if (0 <= ImmValue && ImmValue <= 65535) {
1183 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001184 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001185 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001186 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001187 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001188 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001189 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001190 } else if (ImmValue < 0 && ImmValue >= -32768) {
1191 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001192 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001193 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001194 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001195 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001196 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001197 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001198 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1199 // For any value of j that is representable as a 32-bit integer, create
1200 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001201 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001202 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001203 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001204 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1205 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001206 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001207 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1208 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001209 if (!isGP64bit()) {
1210 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001211 return true;
1212 }
1213
1214 // <------- lo32 ------>
1215 // <------- hi32 ------>
1216 // <- hi16 -> <- lo16 ->
1217 // _________________________________
1218 // | | | |
1219 // | 16-bytes | 16-bytes | 16-bytes |
1220 // |__________|__________|__________|
1221 //
1222 // For any value of j that is representable as a 48-bit integer, create
1223 // a sequence of:
1224 // li d,j => lui d,hi16(j)
1225 // ori d,d,hi16(lo32(j))
1226 // dsll d,d,16
1227 // ori d,d,lo16(lo32(j))
1228 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001229 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001230 tmpInst.addOperand(
1231 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001232 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001233 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1234 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1235 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001236 if (!isGP64bit()) {
1237 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001238 return true;
1239 }
1240
1241 // <------- hi32 ------> <------- lo32 ------>
1242 // <- hi16 -> <- lo16 ->
1243 // ___________________________________________
1244 // | | | | |
1245 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1246 // |__________|__________|__________|__________|
1247 //
1248 // For any value of j that isn't representable as a 48-bit integer.
1249 // li d,j => lui d,hi16(j)
1250 // ori d,d,lo16(hi32(j))
1251 // dsll d,d,16
1252 // ori d,d,hi16(lo32(j))
1253 // dsll d,d,16
1254 // ori d,d,lo16(lo32(j))
1255 tmpInst.setOpcode(Mips::LUi);
1256 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1257 tmpInst.addOperand(
1258 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1259 Instructions.push_back(tmpInst);
1260 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1261 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1262 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001263 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001264 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001265}
Jack Carter92995f12012-10-06 00:53:28 +00001266
Matheus Almeida3813d572014-06-19 14:39:14 +00001267bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001268MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1269 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001270 MCInst tmpInst;
1271 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001272 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1273 "expected immediate operand kind");
1274 if (!ImmOp.isImm()) {
1275 expandLoadAddressSym(Inst, IDLoc, Instructions);
1276 return false;
1277 }
Jack Carter543fdf82012-10-09 23:29:45 +00001278 const MCOperand &SrcRegOp = Inst.getOperand(1);
1279 assert(SrcRegOp.isReg() && "expected register operand kind");
1280 const MCOperand &DstRegOp = Inst.getOperand(0);
1281 assert(DstRegOp.isReg() && "expected register operand kind");
1282 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001283 if (-32768 <= ImmValue && ImmValue <= 65535) {
1284 // For -32768 <= j <= 65535.
1285 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001286 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001287 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1288 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1289 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1290 Instructions.push_back(tmpInst);
1291 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001292 // For any other value of j that is representable as a 32-bit integer.
1293 // la d,j(s) => lui d,hi16(j)
1294 // ori d,d,lo16(j)
1295 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001296 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001297 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1298 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1299 Instructions.push_back(tmpInst);
1300 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001301 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001302 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1303 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1304 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1305 Instructions.push_back(tmpInst);
1306 tmpInst.clear();
1307 tmpInst.setOpcode(Mips::ADDu);
1308 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1309 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1310 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1311 Instructions.push_back(tmpInst);
1312 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001313 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001314}
1315
Matheus Almeida3813d572014-06-19 14:39:14 +00001316bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001317MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1318 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001319 MCInst tmpInst;
1320 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001321 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1322 "expected immediate operand kind");
1323 if (!ImmOp.isImm()) {
1324 expandLoadAddressSym(Inst, IDLoc, Instructions);
1325 return false;
1326 }
Jack Carter543fdf82012-10-09 23:29:45 +00001327 const MCOperand &RegOp = Inst.getOperand(0);
1328 assert(RegOp.isReg() && "expected register operand kind");
1329 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001330 if (-32768 <= ImmValue && ImmValue <= 65535) {
1331 // For -32768 <= j <= 65535.
1332 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001333 tmpInst.setOpcode(Mips::ADDiu);
1334 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001335 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001336 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1337 Instructions.push_back(tmpInst);
1338 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001339 // For any other value of j that is representable as a 32-bit integer.
1340 // la d,j => lui d,hi16(j)
1341 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001342 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001343 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1344 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1345 Instructions.push_back(tmpInst);
1346 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001347 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001348 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1349 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1350 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1351 Instructions.push_back(tmpInst);
1352 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001353 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001354}
1355
Toma Tabacu0d64b202014-08-14 10:29:17 +00001356void
1357MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1358 SmallVectorImpl<MCInst> &Instructions) {
1359 // FIXME: If we do have a valid at register to use, we should generate a
1360 // slightly shorter sequence here.
1361 MCInst tmpInst;
1362 int ExprOperandNo = 1;
1363 // Sometimes the assembly parser will get the immediate expression as
1364 // a $zero + an immediate.
1365 if (Inst.getNumOperands() == 3) {
1366 assert(Inst.getOperand(1).getReg() ==
1367 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1368 ExprOperandNo = 2;
1369 }
1370 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1371 assert(SymOp.isExpr() && "expected symbol operand kind");
1372 const MCOperand &RegOp = Inst.getOperand(0);
1373 unsigned RegNo = RegOp.getReg();
1374 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1375 const MCSymbolRefExpr *HiExpr =
1376 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1377 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1378 const MCSymbolRefExpr *LoExpr =
1379 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1380 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1381 if (isGP64bit()) {
1382 // If it's a 64-bit architecture, expand to:
1383 // la d,sym => lui d,highest(sym)
1384 // ori d,d,higher(sym)
1385 // dsll d,d,16
1386 // ori d,d,hi16(sym)
1387 // dsll d,d,16
1388 // ori d,d,lo16(sym)
1389 const MCSymbolRefExpr *HighestExpr =
1390 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1391 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1392 const MCSymbolRefExpr *HigherExpr =
1393 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1394 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1395
1396 tmpInst.setOpcode(Mips::LUi);
1397 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1398 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1399 Instructions.push_back(tmpInst);
1400
1401 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1402 Instructions);
1403 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1404 Instructions);
1405 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1406 Instructions);
1407 } else {
1408 // Otherwise, expand to:
1409 // la d,sym => lui d,hi16(sym)
1410 // ori d,d,lo16(sym)
1411 tmpInst.setOpcode(Mips::LUi);
1412 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1413 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1414 Instructions.push_back(tmpInst);
1415
1416 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1417 Instructions);
1418 }
1419}
1420
Jack Carter9e65aa32013-03-22 00:05:30 +00001421void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001422 SmallVectorImpl<MCInst> &Instructions,
1423 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001424 const MCSymbolRefExpr *SR;
1425 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001426 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001427 const MCExpr *ExprOffset;
1428 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001429 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001430 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1431 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001432 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001433 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1434 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001435 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001436 if (isImmOpnd) {
1437 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1438 ImmOffset = Inst.getOperand(2).getImm();
1439 LoOffset = ImmOffset & 0x0000ffff;
1440 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001441 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001442 if (LoOffset & 0x8000)
1443 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001444 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001445 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001446 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001447 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001448 // These are some of the types of expansions we perform here:
1449 // 1) lw $8, sym => lui $8, %hi(sym)
1450 // lw $8, %lo(sym)($8)
1451 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1452 // add $8, $8, $9
1453 // lw $8, %lo(offset)($9)
1454 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1455 // add $at, $at, $8
1456 // lw $8, %lo(offset)($at)
1457 // 4) sw $8, sym => lui $at, %hi(sym)
1458 // sw $8, %lo(sym)($at)
1459 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1460 // add $at, $at, $8
1461 // sw $8, %lo(offset)($at)
1462 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1463 // ldc1 $f0, %lo(sym)($at)
1464 //
1465 // For load instructions we can use the destination register as a temporary
1466 // if base and dst are different (examples 1 and 2) and if the base register
1467 // is general purpose otherwise we must use $at (example 6) and error if it's
1468 // not available. For stores we must use $at (examples 4 and 5) because we
1469 // must not clobber the source register setting up the offset.
1470 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1471 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1472 unsigned RegClassIDOp0 =
1473 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1474 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1475 (RegClassIDOp0 == Mips::GPR64RegClassID);
1476 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001477 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001478 else {
1479 int AT = getATReg(IDLoc);
1480 // At this point we need AT to perform the expansions and we exit if it is
1481 // not available.
1482 if (!AT)
1483 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001484 TmpRegNum = getReg(
1485 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001486 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001487
Jack Carter9e65aa32013-03-22 00:05:30 +00001488 TempInst.setOpcode(Mips::LUi);
1489 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1490 if (isImmOpnd)
1491 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1492 else {
1493 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001494 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001495 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1496 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1497 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001498 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001499 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001500 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001501 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001502 }
1503 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001504 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001505 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001506 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001507 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001508 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001509 TempInst.setOpcode(Mips::ADDu);
1510 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1511 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1512 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1513 Instructions.push_back(TempInst);
1514 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001515 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001516 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001517 TempInst.setOpcode(Inst.getOpcode());
1518 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1519 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1520 if (isImmOpnd)
1521 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1522 else {
1523 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001524 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1525 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1526 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001527 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001528 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001529 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001530 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001531 }
1532 }
1533 Instructions.push_back(TempInst);
1534 TempInst.clear();
1535}
1536
Matheus Almeida595fcab2014-06-11 15:05:56 +00001537unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1538 // As described by the Mips32r2 spec, the registers Rd and Rs for
1539 // jalr.hb must be different.
1540 unsigned Opcode = Inst.getOpcode();
1541
1542 if (Opcode == Mips::JALR_HB &&
1543 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1544 return Match_RequiresDifferentSrcAndDst;
1545
1546 return Match_Success;
1547}
1548
David Blaikie960ea3f2014-06-08 16:18:35 +00001549bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1550 OperandVector &Operands,
1551 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001552 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001553 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001554
Jack Carterb4dbc172012-09-05 23:34:03 +00001555 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001556 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001557 unsigned MatchResult =
1558 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001559
1560 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001561 default:
1562 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001563 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001564 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001565 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001566 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001567 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001568 return false;
1569 }
1570 case Match_MissingFeature:
1571 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1572 return true;
1573 case Match_InvalidOperand: {
1574 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001575 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001576 if (ErrorInfo >= Operands.size())
1577 return Error(IDLoc, "too few operands for instruction");
1578
David Blaikie960ea3f2014-06-08 16:18:35 +00001579 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001580 if (ErrorLoc == SMLoc())
1581 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001582 }
1583
1584 return Error(ErrorLoc, "invalid operand for instruction");
1585 }
1586 case Match_MnemonicFail:
1587 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001588 case Match_RequiresDifferentSrcAndDst:
1589 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001590 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001591 return true;
1592}
1593
Toma Tabacu13964452014-09-04 13:23:44 +00001594void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001595 if ((RegIndex != 0) &&
1596 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001597 if (RegIndex == 1)
1598 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001599 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001600 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1601 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001602 }
1603}
1604
Jack Carter1ac53222013-02-20 23:11:17 +00001605int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001606 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001607
Vladimir Medic4c299852013-11-06 11:27:05 +00001608 CC = StringSwitch<unsigned>(Name)
1609 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001610 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001611 .Case("a0", 4)
1612 .Case("a1", 5)
1613 .Case("a2", 6)
1614 .Case("a3", 7)
1615 .Case("v0", 2)
1616 .Case("v1", 3)
1617 .Case("s0", 16)
1618 .Case("s1", 17)
1619 .Case("s2", 18)
1620 .Case("s3", 19)
1621 .Case("s4", 20)
1622 .Case("s5", 21)
1623 .Case("s6", 22)
1624 .Case("s7", 23)
1625 .Case("k0", 26)
1626 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001627 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001628 .Case("sp", 29)
1629 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001630 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001631 .Case("ra", 31)
1632 .Case("t0", 8)
1633 .Case("t1", 9)
1634 .Case("t2", 10)
1635 .Case("t3", 11)
1636 .Case("t4", 12)
1637 .Case("t5", 13)
1638 .Case("t6", 14)
1639 .Case("t7", 15)
1640 .Case("t8", 24)
1641 .Case("t9", 25)
1642 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001643
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001644 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001645 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1646 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1647 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1648 if (8 <= CC && CC <= 11)
1649 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001650
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001651 if (CC == -1)
1652 CC = StringSwitch<unsigned>(Name)
1653 .Case("a4", 8)
1654 .Case("a5", 9)
1655 .Case("a6", 10)
1656 .Case("a7", 11)
1657 .Case("kt0", 26)
1658 .Case("kt1", 27)
1659 .Default(-1);
1660 }
Jack Carter1ac53222013-02-20 23:11:17 +00001661
1662 return CC;
1663}
Jack Carterd0bd6422013-04-18 00:41:53 +00001664
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001665int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001666
Jack Cartera63b16a2012-09-07 00:23:42 +00001667 if (Name[0] == 'f') {
1668 StringRef NumString = Name.substr(1);
1669 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001670 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001671 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001672 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001673 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001674 return IntVal;
1675 }
1676 return -1;
1677}
Jack Cartera63b16a2012-09-07 00:23:42 +00001678
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001679int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1680
1681 if (Name.startswith("fcc")) {
1682 StringRef NumString = Name.substr(3);
1683 unsigned IntVal;
1684 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001685 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001686 if (IntVal > 7) // There are only 8 fcc registers.
1687 return -1;
1688 return IntVal;
1689 }
1690 return -1;
1691}
1692
1693int MipsAsmParser::matchACRegisterName(StringRef Name) {
1694
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001695 if (Name.startswith("ac")) {
1696 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001697 unsigned IntVal;
1698 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001699 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001700 if (IntVal > 3) // There are only 3 acc registers.
1701 return -1;
1702 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001703 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001704 return -1;
1705}
Jack Carterd0bd6422013-04-18 00:41:53 +00001706
Jack Carter5dc8ac92013-09-25 23:50:44 +00001707int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1708 unsigned IntVal;
1709
1710 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1711 return -1;
1712
1713 if (IntVal > 31)
1714 return -1;
1715
1716 return IntVal;
1717}
1718
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001719int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1720 int CC;
1721
1722 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001723 .Case("msair", 0)
1724 .Case("msacsr", 1)
1725 .Case("msaaccess", 2)
1726 .Case("msasave", 3)
1727 .Case("msamodify", 4)
1728 .Case("msarequest", 5)
1729 .Case("msamap", 6)
1730 .Case("msaunmap", 7)
1731 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001732
1733 return CC;
1734}
1735
Jack Carter0b744b32012-10-04 02:29:46 +00001736bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1737 if (Reg > 31)
1738 return false;
1739
Toma Tabacu3c24b042014-09-05 15:43:21 +00001740 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001741 return true;
1742}
1743
Matheus Almeida7de68e72014-06-18 14:46:05 +00001744int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001745 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001746 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001747 reportParseError(Loc,
1748 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001749 return AT;
1750}
Jack Carter0b744b32012-10-04 02:29:46 +00001751
Jack Carterd0bd6422013-04-18 00:41:53 +00001752unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001753 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001754}
1755
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001756unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001757 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001758 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001759}
1760
Jack Carter873c7242013-01-12 01:03:14 +00001761int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001762 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001763 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001764 return -1;
1765
Jack Carter873c7242013-01-12 01:03:14 +00001766 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001767}
1768
Toma Tabacu13964452014-09-04 13:23:44 +00001769bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1770 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001771
Jack Carter30a59822012-10-04 04:03:53 +00001772 // Check if the current operand has a custom associated parser, if so, try to
1773 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001774 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1775 if (ResTy == MatchOperand_Success)
1776 return false;
1777 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1778 // there was a match, but an error occurred, in which case, just return that
1779 // the operand parsing failed.
1780 if (ResTy == MatchOperand_ParseFail)
1781 return true;
1782
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001783 DEBUG(dbgs() << ".. Generic Parser\n");
1784
Jack Carterb4dbc172012-09-05 23:34:03 +00001785 switch (getLexer().getKind()) {
1786 default:
1787 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1788 return true;
1789 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001790 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001791 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001792
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001793 // Almost all registers have been parsed by custom parsers. There is only
1794 // one exception to this. $zero (and it's alias $0) will reach this point
1795 // for div, divu, and similar instructions because it is not an operand
1796 // to the instruction definition but an explicit register. Special case
1797 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001798 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001799 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001800
Jack Carterd0bd6422013-04-18 00:41:53 +00001801 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001802 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001803 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001804 return true;
1805
Jack Carter873c7242013-01-12 01:03:14 +00001806 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001807 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001808 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001809 const MCExpr *Res =
1810 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001811
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001812 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001813 return false;
1814 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001815 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001816 case AsmToken::LParen:
1817 case AsmToken::Minus:
1818 case AsmToken::Plus:
1819 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001820 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001821 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001822 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001823 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001824 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001825 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001826 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001827 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001828 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001829 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001830 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001831 return true;
1832
Jack Carter873c7242013-01-12 01:03:14 +00001833 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1834
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001835 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001836 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001837 } // case AsmToken::Percent
1838 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001839 return true;
1840}
1841
Vladimir Medic4c299852013-11-06 11:27:05 +00001842const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001843 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001844 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001845 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001846 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001847 // It's a constant, evaluate reloc value.
1848 int16_t Val;
1849 switch (getVariantKind(RelocStr)) {
1850 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1851 // Get the 1st 16-bits.
1852 Val = MCE->getValue() & 0xffff;
1853 break;
1854 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1855 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1856 // 16 bits being negative.
1857 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1858 break;
1859 case MCSymbolRefExpr::VK_Mips_HIGHER:
1860 // Get the 3rd 16-bits.
1861 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1862 break;
1863 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1864 // Get the 4th 16-bits.
1865 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1866 break;
1867 default:
1868 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001869 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001870 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001871 }
1872
Jack Carterb5cf5902013-04-17 00:18:04 +00001873 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001874 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001875 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001876 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001877 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001878 return Res;
1879 }
1880
1881 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001882 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1883
Sasa Stankovic06c47802014-04-03 10:37:45 +00001884 // Try to create target expression.
1885 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1886 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001887
Jack Carterd0bd6422013-04-18 00:41:53 +00001888 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1889 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001890 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1891 return Res;
1892 }
1893
1894 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001895 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1896 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1897 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001898 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001899 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001900 return Expr;
1901}
1902
1903bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1904
1905 switch (Expr->getKind()) {
1906 case MCExpr::Constant:
1907 return true;
1908 case MCExpr::SymbolRef:
1909 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1910 case MCExpr::Binary:
1911 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1912 if (!isEvaluated(BE->getLHS()))
1913 return false;
1914 return isEvaluated(BE->getRHS());
1915 }
1916 case MCExpr::Unary:
1917 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001918 case MCExpr::Target:
1919 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001920 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001921 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001922}
Jack Carterd0bd6422013-04-18 00:41:53 +00001923
Jack Carterb5cf5902013-04-17 00:18:04 +00001924bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001925 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001926 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001927 if (Tok.isNot(AsmToken::Identifier))
1928 return true;
1929
1930 std::string Str = Tok.getIdentifier().str();
1931
Jack Carterd0bd6422013-04-18 00:41:53 +00001932 Parser.Lex(); // Eat the identifier.
1933 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001934 const MCExpr *IdVal;
1935 SMLoc EndLoc;
1936
1937 if (getLexer().getKind() == AsmToken::LParen) {
1938 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001939 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001940 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001941 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001942 const AsmToken &nextTok = Parser.getTok();
1943 if (nextTok.isNot(AsmToken::Identifier))
1944 return true;
1945 Str += "(%";
1946 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001947 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001948 if (getLexer().getKind() != AsmToken::LParen)
1949 return true;
1950 } else
1951 break;
1952 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001953 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001954 return true;
1955
1956 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001957 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001958
1959 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001960 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001961
Jack Carterd0bd6422013-04-18 00:41:53 +00001962 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001963 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001964}
1965
Jack Carterb4dbc172012-09-05 23:34:03 +00001966bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1967 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001968 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00001969 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001970 if (ResTy == MatchOperand_Success) {
1971 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001972 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001973 StartLoc = Operand.getStartLoc();
1974 EndLoc = Operand.getEndLoc();
1975
1976 // AFAIK, we only support numeric registers and named GPR's in CFI
1977 // directives.
1978 // Don't worry about eating tokens before failing. Using an unrecognised
1979 // register is a parse error.
1980 if (Operand.isGPRAsmReg()) {
1981 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001982 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001983 }
1984
1985 return (RegNo == (unsigned)-1);
1986 }
1987
1988 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001989 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001990}
1991
Jack Carterb5cf5902013-04-17 00:18:04 +00001992bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001993 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001994 bool Result = true;
1995
1996 while (getLexer().getKind() == AsmToken::LParen)
1997 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001998
Jack Carterd0bd6422013-04-18 00:41:53 +00001999 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002000 default:
2001 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002002 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002003 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002004 case AsmToken::Integer:
2005 case AsmToken::Minus:
2006 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002007 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002008 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002009 else
2010 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002011 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002012 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002013 break;
Jack Carter873c7242013-01-12 01:03:14 +00002014 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002015 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002016 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002017 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002018}
2019
David Blaikie960ea3f2014-06-08 16:18:35 +00002020MipsAsmParser::OperandMatchResultTy
2021MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002022 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002023 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002024 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002025 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002026 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002027 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002028 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002029
Jack Carterb5cf5902013-04-17 00:18:04 +00002030 if (getLexer().getKind() == AsmToken::LParen) {
2031 Parser.Lex();
2032 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002033 }
2034
Jack Carterb5cf5902013-04-17 00:18:04 +00002035 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002036 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002037 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002038
Jack Carterd0bd6422013-04-18 00:41:53 +00002039 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002040 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002041 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2042 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002043 SMLoc E =
2044 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002045 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002046 return MatchOperand_Success;
2047 }
2048 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002049 SMLoc E =
2050 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002051
Jack Carterd0bd6422013-04-18 00:41:53 +00002052 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002053 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002054 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002055 S, E, *this);
2056 Operands.push_back(
2057 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002058 return MatchOperand_Success;
2059 }
2060 Error(Parser.getTok().getLoc(), "'(' expected");
2061 return MatchOperand_ParseFail;
2062 }
2063
Jack Carterd0bd6422013-04-18 00:41:53 +00002064 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002065 }
2066
Toma Tabacu13964452014-09-04 13:23:44 +00002067 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002068 if (Res != MatchOperand_Success)
2069 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002070
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002071 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002072 Error(Parser.getTok().getLoc(), "')' expected");
2073 return MatchOperand_ParseFail;
2074 }
2075
Jack Carter873c7242013-01-12 01:03:14 +00002076 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2077
Jack Carterd0bd6422013-04-18 00:41:53 +00002078 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002079
Craig Topper062a2ba2014-04-25 05:30:21 +00002080 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002081 IdVal = MCConstantExpr::Create(0, getContext());
2082
Jack Carterd0bd6422013-04-18 00:41:53 +00002083 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002084 std::unique_ptr<MipsOperand> op(
2085 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002086 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002087 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002088 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002089 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002090 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2091 int64_t Imm;
2092 if (IdVal->EvaluateAsAbsolute(Imm))
2093 IdVal = MCConstantExpr::Create(Imm, getContext());
2094 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2095 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2096 getContext());
2097 }
2098
David Blaikie960ea3f2014-06-08 16:18:35 +00002099 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002100 return MatchOperand_Success;
2101}
2102
David Blaikie960ea3f2014-06-08 16:18:35 +00002103bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002104
Jack Carterd76b2372013-03-21 21:44:16 +00002105 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2106 if (Sym) {
2107 SMLoc S = Parser.getTok().getLoc();
2108 const MCExpr *Expr;
2109 if (Sym->isVariable())
2110 Expr = Sym->getVariableValue();
2111 else
2112 return false;
2113 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002114 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002115 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002116 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002117 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002118 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002119 if (ResTy == MatchOperand_Success) {
2120 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002121 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002122 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002123 llvm_unreachable("Should never ParseFail");
2124 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002125 }
2126 } else if (Expr->getKind() == MCExpr::Constant) {
2127 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002128 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002129 Operands.push_back(
2130 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002131 return true;
2132 }
2133 }
2134 return false;
2135}
Jack Carterd0bd6422013-04-18 00:41:53 +00002136
Jack Carter873c7242013-01-12 01:03:14 +00002137MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002138MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002139 StringRef Identifier,
2140 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002141 int Index = matchCPURegisterName(Identifier);
2142 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002143 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002144 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2145 return MatchOperand_Success;
2146 }
2147
2148 Index = matchFPURegisterName(Identifier);
2149 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002150 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002151 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2152 return MatchOperand_Success;
2153 }
2154
2155 Index = matchFCCRegisterName(Identifier);
2156 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002157 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002158 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2159 return MatchOperand_Success;
2160 }
2161
2162 Index = matchACRegisterName(Identifier);
2163 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002164 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002165 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2166 return MatchOperand_Success;
2167 }
2168
2169 Index = matchMSA128RegisterName(Identifier);
2170 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002171 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002172 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2173 return MatchOperand_Success;
2174 }
2175
2176 Index = matchMSA128CtrlRegisterName(Identifier);
2177 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002178 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002179 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2180 return MatchOperand_Success;
2181 }
2182
2183 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002184}
2185
2186MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002187MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002188 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002189
2190 if (Token.is(AsmToken::Identifier)) {
2191 DEBUG(dbgs() << ".. identifier\n");
2192 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002193 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002194 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002195 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002196 } else if (Token.is(AsmToken::Integer)) {
2197 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002198 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002199 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2200 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002201 return MatchOperand_Success;
2202 }
2203
2204 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2205
2206 return MatchOperand_NoMatch;
2207}
2208
David Blaikie960ea3f2014-06-08 16:18:35 +00002209MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002210MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
2211 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002212
2213 auto Token = Parser.getTok();
2214
2215 SMLoc S = Token.getLoc();
2216
2217 if (Token.isNot(AsmToken::Dollar)) {
2218 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2219 if (Token.is(AsmToken::Identifier)) {
2220 if (searchSymbolAlias(Operands))
2221 return MatchOperand_Success;
2222 }
2223 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2224 return MatchOperand_NoMatch;
2225 }
2226 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002227
Toma Tabacu13964452014-09-04 13:23:44 +00002228 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002229 if (ResTy == MatchOperand_Success) {
2230 Parser.Lex(); // $
2231 Parser.Lex(); // identifier
2232 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002233 return ResTy;
2234}
2235
2236MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002237MipsAsmParser::parseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002238 switch (getLexer().getKind()) {
2239 default:
2240 return MatchOperand_NoMatch;
2241 case AsmToken::LParen:
2242 case AsmToken::Minus:
2243 case AsmToken::Plus:
2244 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002245 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002246 case AsmToken::String:
2247 break;
2248 }
2249
2250 const MCExpr *IdVal;
2251 SMLoc S = Parser.getTok().getLoc();
2252 if (getParser().parseExpression(IdVal))
2253 return MatchOperand_ParseFail;
2254
2255 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2256 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2257 return MatchOperand_Success;
2258}
2259
David Blaikie960ea3f2014-06-08 16:18:35 +00002260MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002261MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
2262 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002263
2264 SMLoc S = getLexer().getLoc();
2265
2266 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002267 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002268 if (ResTy != MatchOperand_NoMatch)
2269 return ResTy;
2270
Daniel Sanders315386c2014-04-01 10:40:14 +00002271 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002272 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002273 if (ResTy != MatchOperand_NoMatch)
2274 return ResTy;
2275
Daniel Sandersffd84362014-04-01 10:41:48 +00002276 const MCExpr *Expr = nullptr;
2277 if (Parser.parseExpression(Expr)) {
2278 // We have no way of knowing if a symbol was consumed so we must ParseFail
2279 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002280 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002281 Operands.push_back(
2282 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002283 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002284}
2285
Vladimir Medic2b953d02013-10-01 09:48:56 +00002286MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002287MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002288 const MCExpr *IdVal;
2289 // If the first token is '$' we may have register operand.
2290 if (Parser.getTok().is(AsmToken::Dollar))
2291 return MatchOperand_NoMatch;
2292 SMLoc S = Parser.getTok().getLoc();
2293 if (getParser().parseExpression(IdVal))
2294 return MatchOperand_ParseFail;
2295 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002296 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002297 int64_t Val = MCE->getValue();
2298 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2299 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002300 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002301 return MatchOperand_Success;
2302}
2303
Matheus Almeida779c5932013-11-18 12:32:49 +00002304MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002305MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002306 switch (getLexer().getKind()) {
2307 default:
2308 return MatchOperand_NoMatch;
2309 case AsmToken::LParen:
2310 case AsmToken::Plus:
2311 case AsmToken::Minus:
2312 case AsmToken::Integer:
2313 break;
2314 }
2315
2316 const MCExpr *Expr;
2317 SMLoc S = Parser.getTok().getLoc();
2318
2319 if (getParser().parseExpression(Expr))
2320 return MatchOperand_ParseFail;
2321
2322 int64_t Val;
2323 if (!Expr->EvaluateAsAbsolute(Val)) {
2324 Error(S, "expected immediate value");
2325 return MatchOperand_ParseFail;
2326 }
2327
2328 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2329 // and because the CPU always adds one to the immediate field, the allowed
2330 // range becomes 1..4. We'll only check the range here and will deal
2331 // with the addition/subtraction when actually decoding/encoding
2332 // the instruction.
2333 if (Val < 1 || Val > 4) {
2334 Error(S, "immediate not in range (1..4)");
2335 return MatchOperand_ParseFail;
2336 }
2337
Jack Carter3b2c96e2014-01-22 23:31:38 +00002338 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002339 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002340 return MatchOperand_Success;
2341}
2342
Jack Carterdc1e35d2012-09-06 20:00:02 +00002343MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2344
Vladimir Medic4c299852013-11-06 11:27:05 +00002345 MCSymbolRefExpr::VariantKind VK =
2346 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2347 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2348 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2349 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2350 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2351 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2352 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2353 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2354 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2355 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2356 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2357 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2358 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2359 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2360 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2361 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2362 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2363 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002364 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2365 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2366 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2367 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2368 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2369 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002370 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2371 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002372 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002373
Matheus Almeida2852af82014-04-22 10:15:54 +00002374 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002375
Jack Carterdc1e35d2012-09-06 20:00:02 +00002376 return VK;
2377}
Jack Cartera63b16a2012-09-07 00:23:42 +00002378
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002379/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2380/// either this.
2381/// ::= '(', register, ')'
2382/// handle it before we iterate so we don't get tripped up by the lack of
2383/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002384bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002385 if (getLexer().is(AsmToken::LParen)) {
2386 Operands.push_back(
2387 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2388 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002389 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002390 SMLoc Loc = getLexer().getLoc();
2391 Parser.eatToEndOfStatement();
2392 return Error(Loc, "unexpected token in argument list");
2393 }
2394 if (Parser.getTok().isNot(AsmToken::RParen)) {
2395 SMLoc Loc = getLexer().getLoc();
2396 Parser.eatToEndOfStatement();
2397 return Error(Loc, "unexpected token, expected ')'");
2398 }
2399 Operands.push_back(
2400 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2401 Parser.Lex();
2402 }
2403 return false;
2404}
2405
2406/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2407/// either one of these.
2408/// ::= '[', register, ']'
2409/// ::= '[', integer, ']'
2410/// handle it before we iterate so we don't get tripped up by the lack of
2411/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002412bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002413 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002414 if (getLexer().is(AsmToken::LBrac)) {
2415 Operands.push_back(
2416 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2417 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002418 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002419 SMLoc Loc = getLexer().getLoc();
2420 Parser.eatToEndOfStatement();
2421 return Error(Loc, "unexpected token in argument list");
2422 }
2423 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2424 SMLoc Loc = getLexer().getLoc();
2425 Parser.eatToEndOfStatement();
2426 return Error(Loc, "unexpected token, expected ']'");
2427 }
2428 Operands.push_back(
2429 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2430 Parser.Lex();
2431 }
2432 return false;
2433}
2434
David Blaikie960ea3f2014-06-08 16:18:35 +00002435bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2436 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002437 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002438
2439 // We have reached first instruction, module directive are now forbidden.
2440 getTargetStreamer().forbidModuleDirective();
2441
Vladimir Medic74593e62013-07-17 15:00:42 +00002442 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002443 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002444 Parser.eatToEndOfStatement();
2445 return Error(NameLoc, "Unknown instruction");
2446 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002447 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002448 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002449
2450 // Read the remaining operands.
2451 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2452 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002453 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002454 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002455 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002456 return Error(Loc, "unexpected token in argument list");
2457 }
Toma Tabacu13964452014-09-04 13:23:44 +00002458 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002459 return true;
2460 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002461
Jack Carterd0bd6422013-04-18 00:41:53 +00002462 while (getLexer().is(AsmToken::Comma)) {
2463 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002464 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002465 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002466 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002467 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002468 return Error(Loc, "unexpected token in argument list");
2469 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002470 // Parse bracket and parenthesis suffixes before we iterate
2471 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002472 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002473 return true;
2474 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002475 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002476 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002477 }
2478 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002479 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2480 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002481 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002482 return Error(Loc, "unexpected token in argument list");
2483 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002484 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002485 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002486}
2487
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002488bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002489 SMLoc Loc = getLexer().getLoc();
2490 Parser.eatToEndOfStatement();
2491 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002492}
2493
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002494bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002495 return Error(Loc, ErrorMsg);
2496}
2497
Jack Carter0b744b32012-10-04 02:29:46 +00002498bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002499 // Line should look like: ".set noat".
2500 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002501 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002502 // eat noat
2503 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002504 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002505 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2506 reportParseError("unexpected token in statement");
2507 return false;
2508 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002509 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002510 return false;
2511}
Jack Carterd0bd6422013-04-18 00:41:53 +00002512
Jack Carter0b744b32012-10-04 02:29:46 +00002513bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002514 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002515 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002516 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002517 getParser().Lex();
2518 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002519 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002520 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002521 return false;
2522 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002523 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002524 if (getLexer().isNot(AsmToken::Dollar)) {
2525 reportParseError("unexpected token in statement");
2526 return false;
2527 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002528 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002529 const AsmToken &Reg = Parser.getTok();
2530 if (Reg.is(AsmToken::Identifier)) {
2531 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2532 } else if (Reg.is(AsmToken::Integer)) {
2533 AtRegNo = Reg.getIntVal();
2534 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002535 reportParseError("unexpected token in statement");
2536 return false;
2537 }
Jack Carter1ac53222013-02-20 23:11:17 +00002538
Daniel Sanders71a89d922014-03-25 13:01:06 +00002539 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002540 reportParseError("unexpected token in statement");
2541 return false;
2542 }
2543
Toma Tabacu9db22db2014-09-09 10:15:38 +00002544 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002545 reportParseError("unexpected token in statement");
2546 return false;
2547 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002548 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002549
2550 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2551 reportParseError("unexpected token in statement");
2552 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002553 }
2554 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002555 return false;
2556 } else {
2557 reportParseError("unexpected token in statement");
2558 return false;
2559 }
2560}
2561
2562bool MipsAsmParser::parseSetReorderDirective() {
2563 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002564 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002565 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2566 reportParseError("unexpected token in statement");
2567 return false;
2568 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002569 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002570 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002572 return false;
2573}
2574
2575bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002576 Parser.Lex();
2577 // If this is not the end of the statement, report an error.
2578 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2579 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002580 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002581 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002582 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002583 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002584 Parser.Lex(); // Consume the EndOfStatement.
2585 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002586}
2587
2588bool MipsAsmParser::parseSetMacroDirective() {
2589 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002591 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2592 reportParseError("unexpected token in statement");
2593 return false;
2594 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002595 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002596 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002597 return false;
2598}
2599
2600bool MipsAsmParser::parseSetNoMacroDirective() {
2601 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002602 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002603 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2604 reportParseError("`noreorder' must be set before `nomacro'");
2605 return false;
2606 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002607 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002608 reportParseError("`noreorder' must be set before `nomacro'");
2609 return false;
2610 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002611 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002612 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002613 return false;
2614}
Jack Carterd76b2372013-03-21 21:44:16 +00002615
Daniel Sanders44934432014-08-07 12:03:36 +00002616bool MipsAsmParser::parseSetMsaDirective() {
2617 Parser.Lex();
2618
2619 // If this is not the end of the statement, report an error.
2620 if (getLexer().isNot(AsmToken::EndOfStatement))
2621 return reportParseError("unexpected token in statement");
2622
2623 setFeatureBits(Mips::FeatureMSA, "msa");
2624 getTargetStreamer().emitDirectiveSetMsa();
2625 return false;
2626}
2627
2628bool MipsAsmParser::parseSetNoMsaDirective() {
2629 Parser.Lex();
2630
2631 // If this is not the end of the statement, report an error.
2632 if (getLexer().isNot(AsmToken::EndOfStatement))
2633 return reportParseError("unexpected token in statement");
2634
2635 clearFeatureBits(Mips::FeatureMSA, "msa");
2636 getTargetStreamer().emitDirectiveSetNoMsa();
2637 return false;
2638}
2639
Jack Carter39536722014-01-22 23:08:42 +00002640bool MipsAsmParser::parseSetNoMips16Directive() {
2641 Parser.Lex();
2642 // If this is not the end of the statement, report an error.
2643 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2644 reportParseError("unexpected token in statement");
2645 return false;
2646 }
2647 // For now do nothing.
2648 Parser.Lex(); // Consume the EndOfStatement.
2649 return false;
2650}
2651
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002652bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002653 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002654 // Line can be: .set fp=32
2655 // .set fp=xx
2656 // .set fp=64
2657 Parser.Lex(); // Eat fp token
2658 AsmToken Tok = Parser.getTok();
2659 if (Tok.isNot(AsmToken::Equal)) {
2660 reportParseError("unexpected token in statement");
2661 return false;
2662 }
2663 Parser.Lex(); // Eat '=' token.
2664 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002665
2666 if (!parseFpABIValue(FpAbiVal, ".set"))
2667 return false;
2668
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002669 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2670 reportParseError("unexpected token in statement");
2671 return false;
2672 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002673 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002674 Parser.Lex(); // Consume the EndOfStatement.
2675 return false;
2676}
2677
Toma Tabacu9db22db2014-09-09 10:15:38 +00002678bool MipsAsmParser::parseSetPopDirective() {
2679 SMLoc Loc = getLexer().getLoc();
2680
2681 Parser.Lex();
2682 if (getLexer().isNot(AsmToken::EndOfStatement))
2683 return reportParseError("unexpected token, expected end of statement");
2684
2685 // Always keep an element on the options "stack" to prevent the user
2686 // from changing the initial options. This is how we remember them.
2687 if (AssemblerOptions.size() == 2)
2688 return reportParseError(Loc, ".set pop with no .set push");
2689
2690 AssemblerOptions.pop_back();
2691 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2692
2693 getTargetStreamer().emitDirectiveSetPop();
2694 return false;
2695}
2696
2697bool MipsAsmParser::parseSetPushDirective() {
2698 Parser.Lex();
2699 if (getLexer().isNot(AsmToken::EndOfStatement))
2700 return reportParseError("unexpected token, expected end of statement");
2701
2702 // Create a copy of the current assembler options environment and push it.
2703 MipsAssemblerOptions *TmpAOPtr =
2704 new MipsAssemblerOptions(AssemblerOptions.back().get());
2705 AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
2706
2707 getTargetStreamer().emitDirectiveSetPush();
2708 return false;
2709}
2710
Jack Carterd76b2372013-03-21 21:44:16 +00002711bool MipsAsmParser::parseSetAssignment() {
2712 StringRef Name;
2713 const MCExpr *Value;
2714
2715 if (Parser.parseIdentifier(Name))
2716 reportParseError("expected identifier after .set");
2717
2718 if (getLexer().isNot(AsmToken::Comma))
2719 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002720 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002721
Jack Carter3b2c96e2014-01-22 23:31:38 +00002722 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002723 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002724
Jack Carterd0bd6422013-04-18 00:41:53 +00002725 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002726 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002727 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002728 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002729 Sym = getContext().GetOrCreateSymbol(Name);
2730 Sym->setVariableValue(Value);
2731
2732 return false;
2733}
Jack Carterd0bd6422013-04-18 00:41:53 +00002734
Toma Tabacu26647792014-09-09 12:52:14 +00002735bool MipsAsmParser::parseSetMips0Directive() {
2736 Parser.Lex();
2737 if (getLexer().isNot(AsmToken::EndOfStatement))
2738 return reportParseError("unexpected token, expected end of statement");
2739
2740 // Reset assembler options to their initial values.
2741 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
2742 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
2743
2744 getTargetStreamer().emitDirectiveSetMips0();
2745 return false;
2746}
2747
Toma Tabacu85618b32014-08-19 14:22:52 +00002748bool MipsAsmParser::parseSetArchDirective() {
2749 Parser.Lex();
2750 if (getLexer().isNot(AsmToken::Equal))
2751 return reportParseError("unexpected token, expected equals sign");
2752
2753 Parser.Lex();
2754 StringRef Arch;
2755 if (Parser.parseIdentifier(Arch))
2756 return reportParseError("expected arch identifier");
2757
2758 StringRef ArchFeatureName =
2759 StringSwitch<StringRef>(Arch)
2760 .Case("mips1", "mips1")
2761 .Case("mips2", "mips2")
2762 .Case("mips3", "mips3")
2763 .Case("mips4", "mips4")
2764 .Case("mips5", "mips5")
2765 .Case("mips32", "mips32")
2766 .Case("mips32r2", "mips32r2")
2767 .Case("mips32r6", "mips32r6")
2768 .Case("mips64", "mips64")
2769 .Case("mips64r2", "mips64r2")
2770 .Case("mips64r6", "mips64r6")
2771 .Case("cnmips", "cnmips")
2772 .Case("r4000", "mips3") // This is an implementation of Mips3.
2773 .Default("");
2774
2775 if (ArchFeatureName.empty())
2776 return reportParseError("unsupported architecture");
2777
2778 selectArch(ArchFeatureName);
2779 getTargetStreamer().emitDirectiveSetArch(Arch);
2780 return false;
2781}
2782
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002783bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2784 Parser.Lex();
2785 if (getLexer().isNot(AsmToken::EndOfStatement))
2786 return reportParseError("unexpected token in .set directive");
2787
Matheus Almeida2852af82014-04-22 10:15:54 +00002788 switch (Feature) {
2789 default:
2790 llvm_unreachable("Unimplemented feature");
2791 case Mips::FeatureDSP:
2792 setFeatureBits(Mips::FeatureDSP, "dsp");
2793 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002794 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002795 case Mips::FeatureMicroMips:
2796 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002797 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002798 case Mips::FeatureMips16:
2799 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002800 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002801 case Mips::FeatureMips1:
2802 selectArch("mips1");
2803 getTargetStreamer().emitDirectiveSetMips1();
2804 break;
2805 case Mips::FeatureMips2:
2806 selectArch("mips2");
2807 getTargetStreamer().emitDirectiveSetMips2();
2808 break;
2809 case Mips::FeatureMips3:
2810 selectArch("mips3");
2811 getTargetStreamer().emitDirectiveSetMips3();
2812 break;
2813 case Mips::FeatureMips4:
2814 selectArch("mips4");
2815 getTargetStreamer().emitDirectiveSetMips4();
2816 break;
2817 case Mips::FeatureMips5:
2818 selectArch("mips5");
2819 getTargetStreamer().emitDirectiveSetMips5();
2820 break;
2821 case Mips::FeatureMips32:
2822 selectArch("mips32");
2823 getTargetStreamer().emitDirectiveSetMips32();
2824 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002825 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002826 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002827 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002828 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002829 case Mips::FeatureMips32r6:
2830 selectArch("mips32r6");
2831 getTargetStreamer().emitDirectiveSetMips32R6();
2832 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002833 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002834 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002835 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002836 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002837 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002838 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002839 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002840 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002841 case Mips::FeatureMips64r6:
2842 selectArch("mips64r6");
2843 getTargetStreamer().emitDirectiveSetMips64R6();
2844 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002845 }
2846 return false;
2847}
2848
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002849bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2850 if (getLexer().isNot(AsmToken::Comma)) {
2851 SMLoc Loc = getLexer().getLoc();
2852 Parser.eatToEndOfStatement();
2853 return Error(Loc, ErrorStr);
2854 }
2855
Matheus Almeida2852af82014-04-22 10:15:54 +00002856 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002857 return true;
2858}
2859
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002860bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002861 if (AssemblerOptions.back()->isReorder())
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002862 Warning(Loc, ".cpload in reorder section");
2863
2864 // FIXME: Warn if cpload is used in Mips16 mode.
2865
David Blaikie960ea3f2014-06-08 16:18:35 +00002866 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00002867 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002868 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2869 reportParseError("expected register containing function address");
2870 return false;
2871 }
2872
David Blaikie960ea3f2014-06-08 16:18:35 +00002873 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2874 if (!RegOpnd.isGPRAsmReg()) {
2875 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002876 return false;
2877 }
2878
David Blaikie960ea3f2014-06-08 16:18:35 +00002879 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002880 return false;
2881}
2882
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002883bool MipsAsmParser::parseDirectiveCPSetup() {
2884 unsigned FuncReg;
2885 unsigned Save;
2886 bool SaveIsReg = true;
2887
Matheus Almeida7e815762014-06-18 13:08:59 +00002888 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00002889 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002890 if (ResTy == MatchOperand_NoMatch) {
2891 reportParseError("expected register containing function address");
2892 Parser.eatToEndOfStatement();
2893 return false;
2894 }
2895
2896 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2897 if (!FuncRegOpnd.isGPRAsmReg()) {
2898 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2899 Parser.eatToEndOfStatement();
2900 return false;
2901 }
2902
2903 FuncReg = FuncRegOpnd.getGPR32Reg();
2904 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002905
2906 if (!eatComma("expected comma parsing directive"))
2907 return true;
2908
Toma Tabacu13964452014-09-04 13:23:44 +00002909 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002910 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002911 const AsmToken &Tok = Parser.getTok();
2912 if (Tok.is(AsmToken::Integer)) {
2913 Save = Tok.getIntVal();
2914 SaveIsReg = false;
2915 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002916 } else {
2917 reportParseError("expected save register or stack offset");
2918 Parser.eatToEndOfStatement();
2919 return false;
2920 }
2921 } else {
2922 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2923 if (!SaveOpnd.isGPRAsmReg()) {
2924 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2925 Parser.eatToEndOfStatement();
2926 return false;
2927 }
2928 Save = SaveOpnd.getGPR32Reg();
2929 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002930
2931 if (!eatComma("expected comma parsing directive"))
2932 return true;
2933
2934 StringRef Name;
2935 if (Parser.parseIdentifier(Name))
2936 reportParseError("expected identifier");
2937 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002938
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002939 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002940 return false;
2941}
2942
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002943bool MipsAsmParser::parseDirectiveNaN() {
2944 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2945 const AsmToken &Tok = Parser.getTok();
2946
2947 if (Tok.getString() == "2008") {
2948 Parser.Lex();
2949 getTargetStreamer().emitDirectiveNaN2008();
2950 return false;
2951 } else if (Tok.getString() == "legacy") {
2952 Parser.Lex();
2953 getTargetStreamer().emitDirectiveNaNLegacy();
2954 return false;
2955 }
2956 }
2957 // If we don't recognize the option passed to the .nan
2958 // directive (e.g. no option or unknown option), emit an error.
2959 reportParseError("invalid option in .nan directive");
2960 return false;
2961}
2962
Jack Carter0b744b32012-10-04 02:29:46 +00002963bool MipsAsmParser::parseDirectiveSet() {
2964
Jack Carterd0bd6422013-04-18 00:41:53 +00002965 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002966 const AsmToken &Tok = Parser.getTok();
2967
2968 if (Tok.getString() == "noat") {
2969 return parseSetNoAtDirective();
2970 } else if (Tok.getString() == "at") {
2971 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00002972 } else if (Tok.getString() == "arch") {
2973 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002974 } else if (Tok.getString() == "fp") {
2975 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00002976 } else if (Tok.getString() == "pop") {
2977 return parseSetPopDirective();
2978 } else if (Tok.getString() == "push") {
2979 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002980 } else if (Tok.getString() == "reorder") {
2981 return parseSetReorderDirective();
2982 } else if (Tok.getString() == "noreorder") {
2983 return parseSetNoReorderDirective();
2984 } else if (Tok.getString() == "macro") {
2985 return parseSetMacroDirective();
2986 } else if (Tok.getString() == "nomacro") {
2987 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002988 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002989 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002990 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002991 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002992 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002993 getTargetStreamer().emitDirectiveSetNoMicroMips();
2994 Parser.eatToEndOfStatement();
2995 return false;
2996 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002997 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00002998 } else if (Tok.getString() == "mips0") {
2999 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003000 } else if (Tok.getString() == "mips1") {
3001 return parseSetFeature(Mips::FeatureMips1);
3002 } else if (Tok.getString() == "mips2") {
3003 return parseSetFeature(Mips::FeatureMips2);
3004 } else if (Tok.getString() == "mips3") {
3005 return parseSetFeature(Mips::FeatureMips3);
3006 } else if (Tok.getString() == "mips4") {
3007 return parseSetFeature(Mips::FeatureMips4);
3008 } else if (Tok.getString() == "mips5") {
3009 return parseSetFeature(Mips::FeatureMips5);
3010 } else if (Tok.getString() == "mips32") {
3011 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003012 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003013 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003014 } else if (Tok.getString() == "mips32r6") {
3015 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003016 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003017 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003018 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003019 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003020 } else if (Tok.getString() == "mips64r6") {
3021 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003022 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003023 return parseSetFeature(Mips::FeatureDSP);
Daniel Sanders44934432014-08-07 12:03:36 +00003024 } else if (Tok.getString() == "msa") {
3025 return parseSetMsaDirective();
3026 } else if (Tok.getString() == "nomsa") {
3027 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003028 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003029 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003030 parseSetAssignment();
3031 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003032 }
Jack Carter07c818d2013-01-25 01:31:34 +00003033
Jack Carter0b744b32012-10-04 02:29:46 +00003034 return true;
3035}
3036
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003037/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003038/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003039bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00003040 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3041 for (;;) {
3042 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003043 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003044 return true;
3045
3046 getParser().getStreamer().EmitValue(Value, Size);
3047
3048 if (getLexer().is(AsmToken::EndOfStatement))
3049 break;
3050
3051 // FIXME: Improve diagnostic.
3052 if (getLexer().isNot(AsmToken::Comma))
3053 return Error(L, "unexpected token in directive");
3054 Parser.Lex();
3055 }
3056 }
3057
3058 Parser.Lex();
3059 return false;
3060}
3061
Vladimir Medic4c299852013-11-06 11:27:05 +00003062/// parseDirectiveGpWord
3063/// ::= .gpword local_sym
3064bool MipsAsmParser::parseDirectiveGpWord() {
3065 const MCExpr *Value;
3066 // EmitGPRel32Value requires an expression, so we are using base class
3067 // method to evaluate the expression.
3068 if (getParser().parseExpression(Value))
3069 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003070 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003071
Vladimir Medice10c1122013-11-13 13:18:04 +00003072 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00003073 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00003074 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003075 return false;
3076}
3077
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003078/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003079/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003080bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00003081 const MCExpr *Value;
3082 // EmitGPRel64Value requires an expression, so we are using base class
3083 // method to evaluate the expression.
3084 if (getParser().parseExpression(Value))
3085 return true;
3086 getParser().getStreamer().EmitGPRel64Value(Value);
3087
3088 if (getLexer().isNot(AsmToken::EndOfStatement))
3089 return Error(getLexer().getLoc(), "unexpected token in directive");
3090 Parser.Lex(); // Eat EndOfStatement token.
3091 return false;
3092}
3093
Jack Carter0cd3c192014-01-06 23:27:31 +00003094bool MipsAsmParser::parseDirectiveOption() {
3095 // Get the option token.
3096 AsmToken Tok = Parser.getTok();
3097 // At the moment only identifiers are supported.
3098 if (Tok.isNot(AsmToken::Identifier)) {
3099 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
3100 Parser.eatToEndOfStatement();
3101 return false;
3102 }
3103
3104 StringRef Option = Tok.getIdentifier();
3105
3106 if (Option == "pic0") {
3107 getTargetStreamer().emitDirectiveOptionPic0();
3108 Parser.Lex();
3109 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3110 Error(Parser.getTok().getLoc(),
3111 "unexpected token in .option pic0 directive");
3112 Parser.eatToEndOfStatement();
3113 }
3114 return false;
3115 }
3116
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003117 if (Option == "pic2") {
3118 getTargetStreamer().emitDirectiveOptionPic2();
3119 Parser.Lex();
3120 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3121 Error(Parser.getTok().getLoc(),
3122 "unexpected token in .option pic2 directive");
3123 Parser.eatToEndOfStatement();
3124 }
3125 return false;
3126 }
3127
Jack Carter0cd3c192014-01-06 23:27:31 +00003128 // Unknown option.
3129 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
3130 Parser.eatToEndOfStatement();
3131 return false;
3132}
3133
Daniel Sanders7e527422014-07-10 13:38:23 +00003134/// parseDirectiveModule
3135/// ::= .module oddspreg
3136/// ::= .module nooddspreg
3137/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003138bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003139 MCAsmLexer &Lexer = getLexer();
3140 SMLoc L = Lexer.getLoc();
3141
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003142 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003143 // TODO : get a better message.
3144 reportParseError(".module directive must appear before any code");
3145 return false;
3146 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003147
3148 if (Lexer.is(AsmToken::Identifier)) {
3149 StringRef Option = Parser.getTok().getString();
3150 Parser.Lex();
3151
3152 if (Option == "oddspreg") {
3153 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3154 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3155
3156 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3157 reportParseError("Expected end of statement");
3158 return false;
3159 }
3160
3161 return false;
3162 } else if (Option == "nooddspreg") {
3163 if (!isABI_O32()) {
3164 Error(L, "'.module nooddspreg' requires the O32 ABI");
3165 return false;
3166 }
3167
3168 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3169 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3170
3171 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3172 reportParseError("Expected end of statement");
3173 return false;
3174 }
3175
3176 return false;
3177 } else if (Option == "fp") {
3178 return parseDirectiveModuleFP();
3179 }
3180
3181 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003182 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003183
3184 return false;
3185}
3186
3187/// parseDirectiveModuleFP
3188/// ::= =32
3189/// ::= =xx
3190/// ::= =64
3191bool MipsAsmParser::parseDirectiveModuleFP() {
3192 MCAsmLexer &Lexer = getLexer();
3193
3194 if (Lexer.isNot(AsmToken::Equal)) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003195 reportParseError("unexpected token in statement");
3196 return false;
3197 }
3198 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003199
Daniel Sanders7e527422014-07-10 13:38:23 +00003200 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003201 if (!parseFpABIValue(FpABI, ".module"))
3202 return false;
3203
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003204 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3205 reportParseError("unexpected token in statement");
3206 return false;
3207 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003208
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003209 // Emit appropriate flags.
3210 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003211 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003212 return false;
3213}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003214
Daniel Sanders7e527422014-07-10 13:38:23 +00003215bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003216 StringRef Directive) {
3217 MCAsmLexer &Lexer = getLexer();
3218
3219 if (Lexer.is(AsmToken::Identifier)) {
3220 StringRef Value = Parser.getTok().getString();
3221 Parser.Lex();
3222
3223 if (Value != "xx") {
3224 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3225 return false;
3226 }
3227
3228 if (!isABI_O32()) {
3229 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3230 return false;
3231 }
3232
Daniel Sanders7e527422014-07-10 13:38:23 +00003233 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003234 return true;
3235 }
3236
3237 if (Lexer.is(AsmToken::Integer)) {
3238 unsigned Value = Parser.getTok().getIntVal();
3239 Parser.Lex();
3240
3241 if (Value != 32 && Value != 64) {
3242 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3243 return false;
3244 }
3245
3246 if (Value == 32) {
3247 if (!isABI_O32()) {
3248 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3249 return false;
3250 }
3251
Daniel Sanders7e527422014-07-10 13:38:23 +00003252 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3253 } else
3254 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003255
Daniel Sanders7e527422014-07-10 13:38:23 +00003256 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003257 }
3258
3259 return false;
3260}
3261
Jack Carter0b744b32012-10-04 02:29:46 +00003262bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003263 StringRef IDVal = DirectiveID.getString();
3264
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003265 if (IDVal == ".cpload")
3266 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003267 if (IDVal == ".dword") {
3268 parseDataDirective(8, DirectiveID.getLoc());
3269 return false;
3270 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003271 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003272 StringRef SymbolName;
3273
3274 if (Parser.parseIdentifier(SymbolName)) {
3275 reportParseError("expected identifier after .ent");
3276 return false;
3277 }
3278
3279 // There's an undocumented extension that allows an integer to
3280 // follow the name of the procedure which AFAICS is ignored by GAS.
3281 // Example: .ent foo,2
3282 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3283 if (getLexer().isNot(AsmToken::Comma)) {
3284 // Even though we accept this undocumented extension for compatibility
3285 // reasons, the additional integer argument does not actually change
3286 // the behaviour of the '.ent' directive, so we would like to discourage
3287 // its use. We do this by not referring to the extended version in
3288 // error messages which are not directly related to its use.
3289 reportParseError("unexpected token, expected end of statement");
3290 return false;
3291 }
3292 Parser.Lex(); // Eat the comma.
3293 const MCExpr *DummyNumber;
3294 int64_t DummyNumberVal;
3295 // If the user was explicitly trying to use the extended version,
3296 // we still give helpful extension-related error messages.
3297 if (Parser.parseExpression(DummyNumber)) {
3298 reportParseError("expected number after comma");
3299 return false;
3300 }
3301 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3302 reportParseError("expected an absolute expression after comma");
3303 return false;
3304 }
3305 }
3306
3307 // If this is not the end of the statement, report an error.
3308 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3309 reportParseError("unexpected token, expected end of statement");
3310 return false;
3311 }
3312
3313 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3314
3315 getTargetStreamer().emitDirectiveEnt(*Sym);
3316 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003317 return false;
3318 }
3319
Jack Carter07c818d2013-01-25 01:31:34 +00003320 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003321 StringRef SymbolName;
3322
3323 if (Parser.parseIdentifier(SymbolName)) {
3324 reportParseError("expected identifier after .end");
3325 return false;
3326 }
3327
3328 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3329 reportParseError("unexpected token, expected end of statement");
3330 return false;
3331 }
3332
3333 if (CurrentFn == nullptr) {
3334 reportParseError(".end used without .ent");
3335 return false;
3336 }
3337
3338 if ((SymbolName != CurrentFn->getName())) {
3339 reportParseError(".end symbol does not match .ent symbol");
3340 return false;
3341 }
3342
3343 getTargetStreamer().emitDirectiveEnd(SymbolName);
3344 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003345 return false;
3346 }
3347
Jack Carter07c818d2013-01-25 01:31:34 +00003348 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003349 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3350 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003351 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003352 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3353 reportParseError("expected stack register");
3354 return false;
3355 }
3356
3357 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3358 if (!StackRegOpnd.isGPRAsmReg()) {
3359 reportParseError(StackRegOpnd.getStartLoc(),
3360 "expected general purpose register");
3361 return false;
3362 }
3363 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3364
3365 if (Parser.getTok().is(AsmToken::Comma))
3366 Parser.Lex();
3367 else {
3368 reportParseError("unexpected token, expected comma");
3369 return false;
3370 }
3371
3372 // Parse the frame size.
3373 const MCExpr *FrameSize;
3374 int64_t FrameSizeVal;
3375
3376 if (Parser.parseExpression(FrameSize)) {
3377 reportParseError("expected frame size value");
3378 return false;
3379 }
3380
3381 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3382 reportParseError("frame size not an absolute expression");
3383 return false;
3384 }
3385
3386 if (Parser.getTok().is(AsmToken::Comma))
3387 Parser.Lex();
3388 else {
3389 reportParseError("unexpected token, expected comma");
3390 return false;
3391 }
3392
3393 // Parse the return register.
3394 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003395 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003396 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3397 reportParseError("expected return register");
3398 return false;
3399 }
3400
3401 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3402 if (!ReturnRegOpnd.isGPRAsmReg()) {
3403 reportParseError(ReturnRegOpnd.getStartLoc(),
3404 "expected general purpose register");
3405 return false;
3406 }
3407
3408 // If this is not the end of the statement, report an error.
3409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3410 reportParseError("unexpected token, expected end of statement");
3411 return false;
3412 }
3413
3414 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3415 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003416 return false;
3417 }
3418
Jack Carter07c818d2013-01-25 01:31:34 +00003419 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003420 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003421 }
3422
Daniel Sandersd97a6342014-08-13 10:07:34 +00003423 if (IDVal == ".mask" || IDVal == ".fmask") {
3424 // .mask bitmask, frame_offset
3425 // bitmask: One bit for each register used.
3426 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3427 // first register is expected to be saved.
3428 // Examples:
3429 // .mask 0x80000000, -4
3430 // .fmask 0x80000000, -4
3431 //
Jack Carterbe332172012-09-07 00:48:02 +00003432
Daniel Sandersd97a6342014-08-13 10:07:34 +00003433 // Parse the bitmask
3434 const MCExpr *BitMask;
3435 int64_t BitMaskVal;
3436
3437 if (Parser.parseExpression(BitMask)) {
3438 reportParseError("expected bitmask value");
3439 return false;
3440 }
3441
3442 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3443 reportParseError("bitmask not an absolute expression");
3444 return false;
3445 }
3446
3447 if (Parser.getTok().is(AsmToken::Comma))
3448 Parser.Lex();
3449 else {
3450 reportParseError("unexpected token, expected comma");
3451 return false;
3452 }
3453
3454 // Parse the frame_offset
3455 const MCExpr *FrameOffset;
3456 int64_t FrameOffsetVal;
3457
3458 if (Parser.parseExpression(FrameOffset)) {
3459 reportParseError("expected frame offset value");
3460 return false;
3461 }
3462
3463 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3464 reportParseError("frame offset not an absolute expression");
3465 return false;
3466 }
3467
3468 // If this is not the end of the statement, report an error.
3469 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3470 reportParseError("unexpected token, expected end of statement");
3471 return false;
3472 }
3473
3474 if (IDVal == ".mask")
3475 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3476 else
3477 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003478 return false;
3479 }
3480
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003481 if (IDVal == ".nan")
3482 return parseDirectiveNaN();
3483
Jack Carter07c818d2013-01-25 01:31:34 +00003484 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003485 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003486 return false;
3487 }
3488
Rafael Espindolab59fb732014-03-28 18:50:26 +00003489 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003490 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003491 return false;
3492 }
3493
Jack Carter07c818d2013-01-25 01:31:34 +00003494 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003495 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003496 return false;
3497 }
3498
Jack Carter0cd3c192014-01-06 23:27:31 +00003499 if (IDVal == ".option")
3500 return parseDirectiveOption();
3501
3502 if (IDVal == ".abicalls") {
3503 getTargetStreamer().emitDirectiveAbiCalls();
3504 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3505 Error(Parser.getTok().getLoc(), "unexpected token in directive");
3506 // Clear line
3507 Parser.eatToEndOfStatement();
3508 }
3509 return false;
3510 }
3511
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003512 if (IDVal == ".cpsetup")
3513 return parseDirectiveCPSetup();
3514
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003515 if (IDVal == ".module")
3516 return parseDirectiveModule();
3517
Rafael Espindola870c4e92012-01-11 03:56:41 +00003518 return true;
3519}
3520
Rafael Espindola870c4e92012-01-11 03:56:41 +00003521extern "C" void LLVMInitializeMipsAsmParser() {
3522 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3523 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3524 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3525 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3526}
Jack Carterb4dbc172012-09-05 23:34:03 +00003527
3528#define GET_REGISTER_MATCHER
3529#define GET_MATCHER_IMPLEMENTATION
3530#include "MipsGenAsmMatcher.inc"