blob: 8286f51b3ee2e655feec980acbf978f1de6353ba [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"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000019#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000020#include "llvm/MC/MCParser/MCAsmLexer.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000025#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000026#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000027#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000028#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000029
30using namespace llvm;
31
Chandler Carruthe96dd892014-04-21 22:55:11 +000032#define DEBUG_TYPE "mips-asm-parser"
33
Joey Gouly0e76fa72013-09-12 10:28:05 +000034namespace llvm {
35class MCInstrInfo;
36}
37
Rafael Espindola870c4e92012-01-11 03:56:41 +000038namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000039class MipsAssemblerOptions {
40public:
Vladimir Medic4c299852013-11-06 11:27:05 +000041 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000042
Vladimir Medic4c299852013-11-06 11:27:05 +000043 unsigned getATRegNum() { return aTReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000044 bool setATReg(unsigned Reg);
45
Vladimir Medic4c299852013-11-06 11:27:05 +000046 bool isReorder() { return reorder; }
47 void setReorder() { reorder = true; }
48 void setNoreorder() { reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000049
Vladimir Medic4c299852013-11-06 11:27:05 +000050 bool isMacro() { return macro; }
51 void setMacro() { macro = true; }
52 void setNomacro() { macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000053
54private:
55 unsigned aTReg;
56 bool reorder;
57 bool macro;
58};
59}
60
61namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000062class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000063 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000064 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000065 return static_cast<MipsTargetStreamer &>(TS);
66 }
67
Jack Carterb4dbc172012-09-05 23:34:03 +000068 MCSubtargetInfo &STI;
69 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000070 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000071
Akira Hatanaka7605630c2012-08-17 20:16:42 +000072#define GET_ASSEMBLER_HEADER
73#include "MipsGenAsmMatcher.inc"
74
Matheus Almeida595fcab2014-06-11 15:05:56 +000075 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
76
Chad Rosier49963552012-10-13 00:26:04 +000077 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +000078 OperandVector &Operands, MCStreamer &Out,
79 unsigned &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +000080 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000081
Daniel Sandersb50ccf82014-04-01 10:35:28 +000082 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +000083 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000084
David Blaikie960ea3f2014-06-08 16:18:35 +000085 bool ParseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +000086
David Blaikie960ea3f2014-06-08 16:18:35 +000087 bool ParseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +000088
David Blaikie960ea3f2014-06-08 16:18:35 +000089 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
90 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000091
Craig Topper56c590a2014-04-29 07:58:02 +000092 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000093
David Blaikie960ea3f2014-06-08 16:18:35 +000094 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000095
96 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +000097 MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
98 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000099
Jack Carter873c7242013-01-12 01:03:14 +0000100 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +0000101 MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000102
David Blaikie960ea3f2014-06-08 16:18:35 +0000103 MipsAsmParser::OperandMatchResultTy ParseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000104
David Blaikie960ea3f2014-06-08 16:18:35 +0000105 MipsAsmParser::OperandMatchResultTy ParseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000106
David Blaikie960ea3f2014-06-08 16:18:35 +0000107 MipsAsmParser::OperandMatchResultTy ParseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000108
David Blaikie960ea3f2014-06-08 16:18:35 +0000109 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000110
David Blaikie960ea3f2014-06-08 16:18:35 +0000111 MipsAsmParser::OperandMatchResultTy ParseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000112
David Blaikie960ea3f2014-06-08 16:18:35 +0000113 bool searchSymbolAlias(OperandVector &Operands);
114
115 bool ParseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000116
Jack Carter30a59822012-10-04 04:03:53 +0000117 bool needsExpansion(MCInst &Inst);
118
119 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000120 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000121 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000122 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000123 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
124 SmallVectorImpl<MCInst> &Instructions);
125 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
126 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000127 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000128 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
129 bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000130 bool reportParseError(StringRef ErrorMsg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000131 bool reportParseError(SMLoc Loc, StringRef ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000132
Jack Carterb5cf5902013-04-17 00:18:04 +0000133 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000134 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000135
Vladimir Medic4c299852013-11-06 11:27:05 +0000136 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000137
138 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000139 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000140 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000141 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000142 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000143 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000144 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000145
146 bool parseSetAtDirective();
147 bool parseSetNoAtDirective();
148 bool parseSetMacroDirective();
149 bool parseSetNoMacroDirective();
150 bool parseSetReorderDirective();
151 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000152 bool parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +0000153
Jack Carterd76b2372013-03-21 21:44:16 +0000154 bool parseSetAssignment();
155
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000156 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000157 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000158 bool parseDirectiveGpDWord();
Jack Carter07c818d2013-01-25 01:31:34 +0000159
Jack Carterdc1e35d2012-09-06 20:00:02 +0000160 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000161
Daniel Sanders5e94e682014-03-27 16:42:17 +0000162 bool isGP64() const {
163 return (STI.getFeatureBits() & Mips::FeatureGP64Bit) != 0;
Jack Carterb4dbc172012-09-05 23:34:03 +0000164 }
165
Jack Cartera63b16a2012-09-07 00:23:42 +0000166 bool isFP64() const {
167 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
168 }
169
Daniel Sandersa4b0c742014-03-26 11:39:07 +0000170 bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
Vladimir Medic4c299852013-11-06 11:27:05 +0000171 bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000172
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000173 bool isMicroMips() const {
174 return STI.getFeatureBits() & Mips::FeatureMicroMips;
175 }
176
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000177 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
178 bool hasMips32() const { return STI.getFeatureBits() & Mips::FeatureMips32; }
Daniel Sandersa84989a2014-06-16 13:25:35 +0000179 bool hasMips32r6() const {
180 return STI.getFeatureBits() & Mips::FeatureMips32r6;
181 }
182 bool hasMips64r6() const {
183 return STI.getFeatureBits() & Mips::FeatureMips64r6;
184 }
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000185
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000186 bool eatComma(StringRef ErrorStr);
187
Jack Carter1ac53222013-02-20 23:11:17 +0000188 int matchCPURegisterName(StringRef Symbol);
189
Jack Carter873c7242013-01-12 01:03:14 +0000190 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000191
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000192 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000193
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000194 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000195
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000196 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000197
Jack Carter5dc8ac92013-09-25 23:50:44 +0000198 int matchMSA128RegisterName(StringRef Name);
199
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000200 int matchMSA128CtrlRegisterName(StringRef Name);
201
Jack Carterd0bd6422013-04-18 00:41:53 +0000202 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000203
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000204 unsigned getGPR(int RegNo);
205
Jack Carter1ac53222013-02-20 23:11:17 +0000206 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000207
208 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000209 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000210
211 // Helper function that checks if the value of a vector index is within the
212 // boundaries of accepted values for each RegisterKind
213 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
214 bool validateMSAIndex(int Val, int RegKind);
215
Vladimir Medic615b26e2014-03-04 09:54:09 +0000216 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
217 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000218 setAvailableFeatures(
219 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000220 }
221 }
222
223 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
224 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000225 setAvailableFeatures(
226 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000227 }
228 }
229
Rafael Espindola870c4e92012-01-11 03:56:41 +0000230public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000231 enum MipsMatchResultTy {
232 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
233#define GET_OPERAND_DIAGNOSTIC_TYPES
234#include "MipsGenAsmMatcher.inc"
235#undef GET_OPERAND_DIAGNOSTIC_TYPES
236
237 };
238
Joey Gouly0e76fa72013-09-12 10:28:05 +0000239 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000240 const MCInstrInfo &MII,
241 const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000242 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000243 // Initialize the set of available features.
244 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000245
246 // Assert exactly one ABI was chosen.
247 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
248 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
249 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
250 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000251 }
252
Jack Carterb4dbc172012-09-05 23:34:03 +0000253 MCAsmParser &getParser() const { return Parser; }
254 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000255
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000256 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
257 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
258
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000259 /// Warn if RegNo is the current assembler temporary.
260 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000261};
262}
263
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000264namespace {
265
266/// MipsOperand - Instances of this class represent a parsed Mips machine
267/// instruction.
268class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000269public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000270 /// Broad categories of register classes
271 /// The exact class is finalized by the render method.
272 enum RegKind {
273 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
274 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
275 /// isFP64())
276 RegKind_FCC = 4, /// FCC
277 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
278 RegKind_MSACtrl = 16, /// MSA control registers
279 RegKind_COP2 = 32, /// COP2
280 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
281 /// context).
282 RegKind_CCR = 128, /// CCR
283 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000284 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000285
286 /// Potentially any (e.g. $1)
287 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
288 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000289 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000290 };
291
292private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000293 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000294 k_Immediate, /// An immediate (possibly involving symbol references)
295 k_Memory, /// Base + Offset Memory Address
296 k_PhysRegister, /// A physical register from the Mips namespace
297 k_RegisterIndex, /// A register index in one or more RegKind.
298 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000299 } Kind;
300
David Blaikie960ea3f2014-06-08 16:18:35 +0000301public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000302 MipsOperand(KindTy K, MipsAsmParser &Parser)
303 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
304
David Blaikie960ea3f2014-06-08 16:18:35 +0000305private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000306 /// For diagnostics, and checking the assembler temporary
307 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000308
Eric Christopher8996c5d2013-03-15 00:42:55 +0000309 struct Token {
310 const char *Data;
311 unsigned Length;
312 };
313
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000314 struct PhysRegOp {
315 unsigned Num; /// Register Number
316 };
317
318 struct RegIdxOp {
319 unsigned Index; /// Index into the register class
320 RegKind Kind; /// Bitfield of the kinds it could possibly be
321 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000322 };
323
324 struct ImmOp {
325 const MCExpr *Val;
326 };
327
328 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000329 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000330 const MCExpr *Off;
331 };
332
Jack Carterb4dbc172012-09-05 23:34:03 +0000333 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000334 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000335 struct PhysRegOp PhysReg;
336 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000337 struct ImmOp Imm;
338 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000339 };
340
341 SMLoc StartLoc, EndLoc;
342
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000343 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000344 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
345 const MCRegisterInfo *RegInfo,
346 SMLoc S, SMLoc E,
347 MipsAsmParser &Parser) {
348 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000349 Op->RegIdx.Index = Index;
350 Op->RegIdx.RegInfo = RegInfo;
351 Op->RegIdx.Kind = RegKind;
352 Op->StartLoc = S;
353 Op->EndLoc = E;
354 return Op;
355 }
356
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000357public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000358 /// Coerce the register to GPR32 and return the real register for the current
359 /// target.
360 unsigned getGPR32Reg() const {
361 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
362 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
363 unsigned ClassID = Mips::GPR32RegClassID;
364 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000365 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000366
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000367 /// Coerce the register to GPR64 and return the real register for the current
368 /// target.
369 unsigned getGPR64Reg() const {
370 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
371 unsigned ClassID = Mips::GPR64RegClassID;
372 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000373 }
374
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000375private:
376 /// Coerce the register to AFGR64 and return the real register for the current
377 /// target.
378 unsigned getAFGR64Reg() const {
379 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
380 if (RegIdx.Index % 2 != 0)
381 AsmParser.Warning(StartLoc, "Float register should be even.");
382 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
383 .getRegister(RegIdx.Index / 2);
384 }
385
386 /// Coerce the register to FGR64 and return the real register for the current
387 /// target.
388 unsigned getFGR64Reg() const {
389 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
390 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
391 .getRegister(RegIdx.Index);
392 }
393
394 /// Coerce the register to FGR32 and return the real register for the current
395 /// target.
396 unsigned getFGR32Reg() const {
397 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
398 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
399 .getRegister(RegIdx.Index);
400 }
401
402 /// Coerce the register to FGRH32 and return the real register for the current
403 /// target.
404 unsigned getFGRH32Reg() const {
405 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
406 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
407 .getRegister(RegIdx.Index);
408 }
409
410 /// Coerce the register to FCC and return the real register for the current
411 /// target.
412 unsigned getFCCReg() const {
413 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
414 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
415 .getRegister(RegIdx.Index);
416 }
417
418 /// Coerce the register to MSA128 and return the real register for the current
419 /// target.
420 unsigned getMSA128Reg() const {
421 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
422 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
423 // identical
424 unsigned ClassID = Mips::MSA128BRegClassID;
425 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
426 }
427
428 /// Coerce the register to MSACtrl and return the real register for the
429 /// current target.
430 unsigned getMSACtrlReg() const {
431 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
432 unsigned ClassID = Mips::MSACtrlRegClassID;
433 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
434 }
435
436 /// Coerce the register to COP2 and return the real register for the
437 /// current target.
438 unsigned getCOP2Reg() const {
439 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
440 unsigned ClassID = Mips::COP2RegClassID;
441 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
442 }
443
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000444 /// Coerce the register to COP3 and return the real register for the
445 /// current target.
446 unsigned getCOP3Reg() const {
447 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
448 unsigned ClassID = Mips::COP3RegClassID;
449 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
450 }
451
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000452 /// Coerce the register to ACC64DSP and return the real register for the
453 /// current target.
454 unsigned getACC64DSPReg() const {
455 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
456 unsigned ClassID = Mips::ACC64DSPRegClassID;
457 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
458 }
459
460 /// Coerce the register to HI32DSP and return the real register for the
461 /// current target.
462 unsigned getHI32DSPReg() const {
463 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
464 unsigned ClassID = Mips::HI32DSPRegClassID;
465 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
466 }
467
468 /// Coerce the register to LO32DSP and return the real register for the
469 /// current target.
470 unsigned getLO32DSPReg() const {
471 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
472 unsigned ClassID = Mips::LO32DSPRegClassID;
473 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
474 }
475
476 /// Coerce the register to CCR and return the real register for the
477 /// current target.
478 unsigned getCCRReg() const {
479 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
480 unsigned ClassID = Mips::CCRRegClassID;
481 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
482 }
483
484 /// Coerce the register to HWRegs and return the real register for the
485 /// current target.
486 unsigned getHWRegsReg() const {
487 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
488 unsigned ClassID = Mips::HWRegsRegClassID;
489 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
490 }
491
492public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000493 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000494 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000495 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000496 Inst.addOperand(MCOperand::CreateImm(0));
497 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
498 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
499 else
500 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000501 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000502
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000503 void addRegOperands(MCInst &Inst, unsigned N) const {
504 llvm_unreachable("Use a custom parser instead");
505 }
506
Daniel Sanders21bce302014-04-01 12:35:23 +0000507 /// Render the operand to an MCInst as a GPR32
508 /// Asserts if the wrong number of operands are requested, or the operand
509 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000510 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
511 assert(N == 1 && "Invalid number of operands!");
512 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
513 }
514
Daniel Sanders21bce302014-04-01 12:35:23 +0000515 /// Render the operand to an MCInst as a GPR64
516 /// Asserts if the wrong number of operands are requested, or the operand
517 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000518 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
519 assert(N == 1 && "Invalid number of operands!");
520 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
521 }
522
523 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
524 assert(N == 1 && "Invalid number of operands!");
525 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
526 }
527
528 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
529 assert(N == 1 && "Invalid number of operands!");
530 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
531 }
532
533 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
534 assert(N == 1 && "Invalid number of operands!");
535 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
536 }
537
538 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
539 assert(N == 1 && "Invalid number of operands!");
540 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
541 }
542
543 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
544 assert(N == 1 && "Invalid number of operands!");
545 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
546 }
547
548 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
549 assert(N == 1 && "Invalid number of operands!");
550 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
551 }
552
553 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
554 assert(N == 1 && "Invalid number of operands!");
555 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
556 }
557
558 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
559 assert(N == 1 && "Invalid number of operands!");
560 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
561 }
562
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000563 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
564 assert(N == 1 && "Invalid number of operands!");
565 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
566 }
567
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000568 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
569 assert(N == 1 && "Invalid number of operands!");
570 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
571 }
572
573 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
574 assert(N == 1 && "Invalid number of operands!");
575 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
576 }
577
578 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
579 assert(N == 1 && "Invalid number of operands!");
580 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
581 }
582
583 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
584 assert(N == 1 && "Invalid number of operands!");
585 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
586 }
587
588 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
589 assert(N == 1 && "Invalid number of operands!");
590 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
591 }
592
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000593 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000594 assert(N == 1 && "Invalid number of operands!");
595 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000596 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000597 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000598
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000599 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000600 assert(N == 2 && "Invalid number of operands!");
601
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000603
604 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000605 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000606 }
607
Craig Topper56c590a2014-04-29 07:58:02 +0000608 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000609 // As a special case until we sort out the definition of div/divu, pretend
610 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
611 if (isGPRAsmReg() && RegIdx.Index == 0)
612 return true;
613
614 return Kind == k_PhysRegister;
615 }
616 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000617 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000618 bool isConstantImm() const {
619 return isImm() && dyn_cast<MCConstantExpr>(getImm());
620 }
Craig Topper56c590a2014-04-29 07:58:02 +0000621 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000622 // Note: It's not possible to pretend that other operand kinds are tokens.
623 // The matcher emitter checks tokens first.
624 return Kind == k_Token;
625 }
Craig Topper56c590a2014-04-29 07:58:02 +0000626 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000627 bool isConstantMemOff() const {
628 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
629 }
630 template <unsigned Bits> bool isMemWithSimmOffset() const {
631 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
632 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000633 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 bool isLSAImm() const {
635 if (!isConstantImm())
636 return false;
637 int64_t Val = getConstantImm();
638 return 1 <= Val && Val <= 4;
639 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000640
641 StringRef getToken() const {
642 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000643 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000644 }
645
Craig Topper56c590a2014-04-29 07:58:02 +0000646 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000647 // As a special case until we sort out the definition of div/divu, pretend
648 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
649 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
650 RegIdx.Kind & RegKind_GPR)
651 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000652
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000653 assert(Kind == k_PhysRegister && "Invalid access!");
654 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000655 }
656
Jack Carterb4dbc172012-09-05 23:34:03 +0000657 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000658 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000659 return Imm.Val;
660 }
661
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000662 int64_t getConstantImm() const {
663 const MCExpr *Val = getImm();
664 return static_cast<const MCConstantExpr *>(Val)->getValue();
665 }
666
667 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000668 assert((Kind == k_Memory) && "Invalid access!");
669 return Mem.Base;
670 }
671
672 const MCExpr *getMemOff() const {
673 assert((Kind == k_Memory) && "Invalid access!");
674 return Mem.Off;
675 }
676
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000677 int64_t getConstantMemOff() const {
678 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
679 }
680
David Blaikie960ea3f2014-06-08 16:18:35 +0000681 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
682 MipsAsmParser &Parser) {
683 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000684 Op->Tok.Data = Str.data();
685 Op->Tok.Length = Str.size();
686 Op->StartLoc = S;
687 Op->EndLoc = S;
688 return Op;
689 }
690
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000691 /// Create a numeric register (e.g. $1). The exact register remains
692 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000693 static std::unique_ptr<MipsOperand>
694 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
695 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000696 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
697 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000698 }
699
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000700 /// Create a register that is definitely a GPR.
701 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000702 static std::unique_ptr<MipsOperand>
703 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
704 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000705 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000706 }
707
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000708 /// Create a register that is definitely a FGR.
709 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000710 static std::unique_ptr<MipsOperand>
711 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
712 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000713 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
714 }
715
716 /// Create a register that is definitely an FCC.
717 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000718 static std::unique_ptr<MipsOperand>
719 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
720 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000721 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
722 }
723
724 /// Create a register that is definitely an ACC.
725 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000726 static std::unique_ptr<MipsOperand>
727 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
728 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000729 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
730 }
731
732 /// Create a register that is definitely an MSA128.
733 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000734 static std::unique_ptr<MipsOperand>
735 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
736 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000737 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
738 }
739
740 /// Create a register that is definitely an MSACtrl.
741 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000742 static std::unique_ptr<MipsOperand>
743 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
744 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000745 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
746 }
747
David Blaikie960ea3f2014-06-08 16:18:35 +0000748 static std::unique_ptr<MipsOperand>
749 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
750 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000751 Op->Imm.Val = Val;
752 Op->StartLoc = S;
753 Op->EndLoc = E;
754 return Op;
755 }
756
David Blaikie960ea3f2014-06-08 16:18:35 +0000757 static std::unique_ptr<MipsOperand>
758 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
759 SMLoc E, MipsAsmParser &Parser) {
760 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
761 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000762 Op->Mem.Off = Off;
763 Op->StartLoc = S;
764 Op->EndLoc = E;
765 return Op;
766 }
767
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 bool isGPRAsmReg() const {
769 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000770 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 bool isFGRAsmReg() const {
772 // AFGR64 is $0-$15 but we handle this in getAFGR64()
773 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000774 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 bool isHWRegsAsmReg() const {
776 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000777 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000778 bool isCCRAsmReg() const {
779 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000780 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000782 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
783 return false;
784 if (!AsmParser.hasEightFccRegisters())
785 return RegIdx.Index == 0;
786 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000787 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 bool isACCAsmReg() const {
789 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000790 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 bool isCOP2AsmReg() const {
792 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000793 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000794 bool isCOP3AsmReg() const {
795 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
796 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000797 bool isMSA128AsmReg() const {
798 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000799 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000800 bool isMSACtrlAsmReg() const {
801 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000802 }
803
Jack Carterb4dbc172012-09-05 23:34:03 +0000804 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000805 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000806 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000807 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000808
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000809 virtual ~MipsOperand() {
810 switch (Kind) {
811 case k_Immediate:
812 break;
813 case k_Memory:
814 delete Mem.Base;
815 break;
816 case k_PhysRegister:
817 case k_RegisterIndex:
818 case k_Token:
819 break;
820 }
821 }
822
Craig Topper56c590a2014-04-29 07:58:02 +0000823 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000824 switch (Kind) {
825 case k_Immediate:
826 OS << "Imm<";
827 Imm.Val->print(OS);
828 OS << ">";
829 break;
830 case k_Memory:
831 OS << "Mem<";
832 Mem.Base->print(OS);
833 OS << ", ";
834 Mem.Off->print(OS);
835 OS << ">";
836 break;
837 case k_PhysRegister:
838 OS << "PhysReg<" << PhysReg.Num << ">";
839 break;
840 case k_RegisterIndex:
841 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
842 break;
843 case k_Token:
844 OS << Tok.Data;
845 break;
846 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000847 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000848}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000849} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000850
Jack Carter9e65aa32013-03-22 00:05:30 +0000851namespace llvm {
852extern const MCInstrDesc MipsInsts[];
853}
854static const MCInstrDesc &getInstDesc(unsigned Opcode) {
855 return MipsInsts[Opcode];
856}
857
858bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000859 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000860 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000861
Jack Carter9e65aa32013-03-22 00:05:30 +0000862 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000863
864 if (MCID.isBranch() || MCID.isCall()) {
865 const unsigned Opcode = Inst.getOpcode();
866 MCOperand Offset;
867
868 switch (Opcode) {
869 default:
870 break;
871 case Mips::BEQ:
872 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 case Mips::BEQ_MM:
874 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000875 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000876 Offset = Inst.getOperand(2);
877 if (!Offset.isImm())
878 break; // We'll deal with this situation later on when applying fixups.
879 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
880 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000881 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000882 return Error(IDLoc, "branch to misaligned address");
883 break;
884 case Mips::BGEZ:
885 case Mips::BGTZ:
886 case Mips::BLEZ:
887 case Mips::BLTZ:
888 case Mips::BGEZAL:
889 case Mips::BLTZAL:
890 case Mips::BC1F:
891 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000892 case Mips::BGEZ_MM:
893 case Mips::BGTZ_MM:
894 case Mips::BLEZ_MM:
895 case Mips::BLTZ_MM:
896 case Mips::BGEZAL_MM:
897 case Mips::BLTZAL_MM:
898 case Mips::BC1F_MM:
899 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000900 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000901 Offset = Inst.getOperand(1);
902 if (!Offset.isImm())
903 break; // We'll deal with this situation later on when applying fixups.
904 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
905 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000906 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000907 return Error(IDLoc, "branch to misaligned address");
908 break;
909 }
910 }
911
Daniel Sandersa84989a2014-06-16 13:25:35 +0000912 // SSNOP is deprecated on MIPS32r6/MIPS64r6
913 // We still accept it but it is a normal nop.
914 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
915 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
916 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
917 "nop instruction");
918 }
919
Jack Carterc15c1d22013-04-25 23:31:35 +0000920 if (MCID.hasDelaySlot() && Options.isReorder()) {
921 // If this instruction has a delay slot and .set reorder is active,
922 // emit a NOP after it.
923 Instructions.push_back(Inst);
924 MCInst NopInst;
925 NopInst.setOpcode(Mips::SLL);
926 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
927 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
928 NopInst.addOperand(MCOperand::CreateImm(0));
929 Instructions.push_back(NopInst);
930 return false;
931 }
932
Jack Carter9e65aa32013-03-22 00:05:30 +0000933 if (MCID.mayLoad() || MCID.mayStore()) {
934 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000935 // reference or immediate we may have to expand instructions.
936 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000937 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000938 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
939 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000940 MCOperand &Op = Inst.getOperand(i);
941 if (Op.isImm()) {
942 int MemOffset = Op.getImm();
943 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000944 // Offset can't exceed 16bit value.
945 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000946 return false;
947 }
948 } else if (Op.isExpr()) {
949 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000950 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000951 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000952 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000953 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000954 // Expand symbol.
955 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000956 return false;
957 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000958 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000959 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000960 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000961 }
962 }
963 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000964 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000965 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000966
967 if (needsExpansion(Inst))
968 expandInstruction(Inst, IDLoc, Instructions);
969 else
970 Instructions.push_back(Inst);
971
972 return false;
973}
974
Jack Carter30a59822012-10-04 04:03:53 +0000975bool MipsAsmParser::needsExpansion(MCInst &Inst) {
976
Jack Carterd0bd6422013-04-18 00:41:53 +0000977 switch (Inst.getOpcode()) {
978 case Mips::LoadImm32Reg:
979 case Mips::LoadAddr32Imm:
980 case Mips::LoadAddr32Reg:
981 return true;
982 default:
983 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000984 }
985}
Jack Carter92995f12012-10-06 00:53:28 +0000986
Jack Carter30a59822012-10-04 04:03:53 +0000987void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000988 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000989 switch (Inst.getOpcode()) {
990 case Mips::LoadImm32Reg:
991 return expandLoadImm(Inst, IDLoc, Instructions);
992 case Mips::LoadAddr32Imm:
993 return expandLoadAddressImm(Inst, IDLoc, Instructions);
994 case Mips::LoadAddr32Reg:
995 return expandLoadAddressReg(Inst, IDLoc, Instructions);
996 }
Jack Carter30a59822012-10-04 04:03:53 +0000997}
Jack Carter92995f12012-10-06 00:53:28 +0000998
Jack Carter30a59822012-10-04 04:03:53 +0000999void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001000 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001001 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001002 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001003 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001004 const MCOperand &RegOp = Inst.getOperand(0);
1005 assert(RegOp.isReg() && "expected register operand kind");
1006
1007 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001008 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +00001009 if (0 <= ImmValue && ImmValue <= 65535) {
1010 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001011 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001012 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001013 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001014 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001015 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001016 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001017 } else if (ImmValue < 0 && ImmValue >= -32768) {
1018 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001019 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001020 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001021 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001022 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001023 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001024 Instructions.push_back(tmpInst);
1025 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001026 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +00001027 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001028 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001029 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001030 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1031 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001032 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +00001033 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001034 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001035 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1036 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1037 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1038 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +00001039 Instructions.push_back(tmpInst);
1040 }
1041}
Jack Carter92995f12012-10-06 00:53:28 +00001042
Vladimir Medic4c299852013-11-06 11:27:05 +00001043void
1044MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1045 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001046 MCInst tmpInst;
1047 const MCOperand &ImmOp = Inst.getOperand(2);
1048 assert(ImmOp.isImm() && "expected immediate operand kind");
1049 const MCOperand &SrcRegOp = Inst.getOperand(1);
1050 assert(SrcRegOp.isReg() && "expected register operand kind");
1051 const MCOperand &DstRegOp = Inst.getOperand(0);
1052 assert(DstRegOp.isReg() && "expected register operand kind");
1053 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001054 if (-32768 <= ImmValue && ImmValue <= 65535) {
1055 // For -32768 <= j <= 65535.
1056 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001057 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001058 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1059 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1060 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1061 Instructions.push_back(tmpInst);
1062 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001063 // For any other value of j that is representable as a 32-bit integer.
1064 // la d,j(s) => lui d,hi16(j)
1065 // ori d,d,lo16(j)
1066 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001067 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001068 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1069 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1070 Instructions.push_back(tmpInst);
1071 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001072 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001073 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1074 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1075 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1076 Instructions.push_back(tmpInst);
1077 tmpInst.clear();
1078 tmpInst.setOpcode(Mips::ADDu);
1079 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1080 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1081 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1082 Instructions.push_back(tmpInst);
1083 }
1084}
1085
Vladimir Medic4c299852013-11-06 11:27:05 +00001086void
1087MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1088 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001089 MCInst tmpInst;
1090 const MCOperand &ImmOp = Inst.getOperand(1);
1091 assert(ImmOp.isImm() && "expected immediate operand kind");
1092 const MCOperand &RegOp = Inst.getOperand(0);
1093 assert(RegOp.isReg() && "expected register operand kind");
1094 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001095 if (-32768 <= ImmValue && ImmValue <= 65535) {
1096 // For -32768 <= j <= 65535.
1097 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001098 tmpInst.setOpcode(Mips::ADDiu);
1099 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001100 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001101 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1102 Instructions.push_back(tmpInst);
1103 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001104 // For any other value of j that is representable as a 32-bit integer.
1105 // la d,j => lui d,hi16(j)
1106 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001107 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001108 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1109 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1110 Instructions.push_back(tmpInst);
1111 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001112 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001113 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1114 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1115 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1116 Instructions.push_back(tmpInst);
1117 }
1118}
1119
Jack Carter9e65aa32013-03-22 00:05:30 +00001120void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001121 SmallVectorImpl<MCInst> &Instructions,
1122 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001123 const MCSymbolRefExpr *SR;
1124 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001125 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001126 const MCExpr *ExprOffset;
1127 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001128 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001129 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1130 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001131 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001132 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1133 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001134 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001135 if (isImmOpnd) {
1136 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1137 ImmOffset = Inst.getOperand(2).getImm();
1138 LoOffset = ImmOffset & 0x0000ffff;
1139 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001140 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001141 if (LoOffset & 0x8000)
1142 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001143 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001144 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001145 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001146 TempInst.setLoc(IDLoc);
1147 // 1st instruction in expansion is LUi. For load instruction we can use
1148 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001149 // but for stores we must use $at.
Matheus Almeida29e254f2014-06-18 14:15:42 +00001150 if (isLoad && (BaseRegNum != RegOpNum))
1151 TmpRegNum = RegOpNum;
1152 else
1153 TmpRegNum = getReg(
1154 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
1155
Jack Carter9e65aa32013-03-22 00:05:30 +00001156 TempInst.setOpcode(Mips::LUi);
1157 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1158 if (isImmOpnd)
1159 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1160 else {
1161 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001162 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001163 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1164 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1165 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001166 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001167 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001168 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001169 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001170 }
1171 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001172 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001173 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001174 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001175 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001176 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001177 TempInst.setOpcode(Mips::ADDu);
1178 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1179 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1180 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1181 Instructions.push_back(TempInst);
1182 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001183 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001184 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001185 TempInst.setOpcode(Inst.getOpcode());
1186 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1187 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1188 if (isImmOpnd)
1189 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1190 else {
1191 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001192 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1193 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1194 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001195 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001196 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001197 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001198 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001199 }
1200 }
1201 Instructions.push_back(TempInst);
1202 TempInst.clear();
1203}
1204
Matheus Almeida595fcab2014-06-11 15:05:56 +00001205unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1206 // As described by the Mips32r2 spec, the registers Rd and Rs for
1207 // jalr.hb must be different.
1208 unsigned Opcode = Inst.getOpcode();
1209
1210 if (Opcode == Mips::JALR_HB &&
1211 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1212 return Match_RequiresDifferentSrcAndDst;
1213
1214 return Match_Success;
1215}
1216
David Blaikie960ea3f2014-06-08 16:18:35 +00001217bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1218 OperandVector &Operands,
1219 MCStreamer &Out,
1220 unsigned &ErrorInfo,
1221 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001222
Jack Carterb4dbc172012-09-05 23:34:03 +00001223 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001224 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001225 unsigned MatchResult =
1226 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001227
1228 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001229 default:
1230 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001231 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001232 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001233 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001234 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001235 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001236 return false;
1237 }
1238 case Match_MissingFeature:
1239 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1240 return true;
1241 case Match_InvalidOperand: {
1242 SMLoc ErrorLoc = IDLoc;
1243 if (ErrorInfo != ~0U) {
1244 if (ErrorInfo >= Operands.size())
1245 return Error(IDLoc, "too few operands for instruction");
1246
David Blaikie960ea3f2014-06-08 16:18:35 +00001247 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001248 if (ErrorLoc == SMLoc())
1249 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001250 }
1251
1252 return Error(ErrorLoc, "invalid operand for instruction");
1253 }
1254 case Match_MnemonicFail:
1255 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001256 case Match_RequiresDifferentSrcAndDst:
1257 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001258 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001259 return true;
1260}
1261
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001262void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1263 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1264 if (RegIndex == 1)
1265 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001266 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001267 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1268 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001269 }
1270}
1271
Jack Carter1ac53222013-02-20 23:11:17 +00001272int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001273 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001274
Vladimir Medic4c299852013-11-06 11:27:05 +00001275 CC = StringSwitch<unsigned>(Name)
1276 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001277 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001278 .Case("a0", 4)
1279 .Case("a1", 5)
1280 .Case("a2", 6)
1281 .Case("a3", 7)
1282 .Case("v0", 2)
1283 .Case("v1", 3)
1284 .Case("s0", 16)
1285 .Case("s1", 17)
1286 .Case("s2", 18)
1287 .Case("s3", 19)
1288 .Case("s4", 20)
1289 .Case("s5", 21)
1290 .Case("s6", 22)
1291 .Case("s7", 23)
1292 .Case("k0", 26)
1293 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001294 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001295 .Case("sp", 29)
1296 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001297 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001298 .Case("ra", 31)
1299 .Case("t0", 8)
1300 .Case("t1", 9)
1301 .Case("t2", 10)
1302 .Case("t3", 11)
1303 .Case("t4", 12)
1304 .Case("t5", 13)
1305 .Case("t6", 14)
1306 .Case("t7", 15)
1307 .Case("t8", 24)
1308 .Case("t9", 25)
1309 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001310
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001311 if (isN32() || isN64()) {
1312 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1313 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1314 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1315 if (8 <= CC && CC <= 11)
1316 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001317
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001318 if (CC == -1)
1319 CC = StringSwitch<unsigned>(Name)
1320 .Case("a4", 8)
1321 .Case("a5", 9)
1322 .Case("a6", 10)
1323 .Case("a7", 11)
1324 .Case("kt0", 26)
1325 .Case("kt1", 27)
1326 .Default(-1);
1327 }
Jack Carter1ac53222013-02-20 23:11:17 +00001328
1329 return CC;
1330}
Jack Carterd0bd6422013-04-18 00:41:53 +00001331
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001332int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001333
Jack Cartera63b16a2012-09-07 00:23:42 +00001334 if (Name[0] == 'f') {
1335 StringRef NumString = Name.substr(1);
1336 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001337 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001338 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001339 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001340 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001341 return IntVal;
1342 }
1343 return -1;
1344}
Jack Cartera63b16a2012-09-07 00:23:42 +00001345
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001346int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1347
1348 if (Name.startswith("fcc")) {
1349 StringRef NumString = Name.substr(3);
1350 unsigned IntVal;
1351 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001352 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001353 if (IntVal > 7) // There are only 8 fcc registers.
1354 return -1;
1355 return IntVal;
1356 }
1357 return -1;
1358}
1359
1360int MipsAsmParser::matchACRegisterName(StringRef Name) {
1361
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001362 if (Name.startswith("ac")) {
1363 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001364 unsigned IntVal;
1365 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001366 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001367 if (IntVal > 3) // There are only 3 acc registers.
1368 return -1;
1369 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001370 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001371 return -1;
1372}
Jack Carterd0bd6422013-04-18 00:41:53 +00001373
Jack Carter5dc8ac92013-09-25 23:50:44 +00001374int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1375 unsigned IntVal;
1376
1377 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1378 return -1;
1379
1380 if (IntVal > 31)
1381 return -1;
1382
1383 return IntVal;
1384}
1385
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001386int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1387 int CC;
1388
1389 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001390 .Case("msair", 0)
1391 .Case("msacsr", 1)
1392 .Case("msaaccess", 2)
1393 .Case("msasave", 3)
1394 .Case("msamodify", 4)
1395 .Case("msarequest", 5)
1396 .Case("msamap", 6)
1397 .Case("msaunmap", 7)
1398 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001399
1400 return CC;
1401}
1402
Jack Carter0b744b32012-10-04 02:29:46 +00001403bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1404 if (Reg > 31)
1405 return false;
1406
1407 aTReg = Reg;
1408 return true;
1409}
1410
Daniel Sandersd89b1362014-03-24 16:48:01 +00001411int MipsAsmParser::getATReg() {
1412 int AT = Options.getATRegNum();
1413 if (AT == 0)
1414 TokError("Pseudo instruction requires $at, which is not available");
1415 return AT;
1416}
Jack Carter0b744b32012-10-04 02:29:46 +00001417
Jack Carterd0bd6422013-04-18 00:41:53 +00001418unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001419 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001420}
1421
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001422unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001423 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1424 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001425}
1426
Jack Carter873c7242013-01-12 01:03:14 +00001427int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001428 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001429 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001430 return -1;
1431
Jack Carter873c7242013-01-12 01:03:14 +00001432 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001433}
1434
David Blaikie960ea3f2014-06-08 16:18:35 +00001435bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001436 DEBUG(dbgs() << "ParseOperand\n");
1437
Jack Carter30a59822012-10-04 04:03:53 +00001438 // Check if the current operand has a custom associated parser, if so, try to
1439 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001440 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1441 if (ResTy == MatchOperand_Success)
1442 return false;
1443 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1444 // there was a match, but an error occurred, in which case, just return that
1445 // the operand parsing failed.
1446 if (ResTy == MatchOperand_ParseFail)
1447 return true;
1448
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001449 DEBUG(dbgs() << ".. Generic Parser\n");
1450
Jack Carterb4dbc172012-09-05 23:34:03 +00001451 switch (getLexer().getKind()) {
1452 default:
1453 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1454 return true;
1455 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001456 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001457 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001458
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001459 // Almost all registers have been parsed by custom parsers. There is only
1460 // one exception to this. $zero (and it's alias $0) will reach this point
1461 // for div, divu, and similar instructions because it is not an operand
1462 // to the instruction definition but an explicit register. Special case
1463 // this situation for now.
1464 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001465 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001466
Jack Carterd0bd6422013-04-18 00:41:53 +00001467 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001468 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001469 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001470 return true;
1471
Jack Carter873c7242013-01-12 01:03:14 +00001472 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001473 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001474 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001475 const MCExpr *Res =
1476 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001477
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001478 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001479 return false;
1480 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001481 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001482 case AsmToken::LParen:
1483 case AsmToken::Minus:
1484 case AsmToken::Plus:
1485 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001486 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001487 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001488 DEBUG(dbgs() << ".. generic integer\n");
1489 OperandMatchResultTy ResTy = ParseImm(Operands);
1490 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001491 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001492 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001493 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001494 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001495 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001496 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001497 return true;
1498
Jack Carter873c7242013-01-12 01:03:14 +00001499 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1500
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001501 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001502 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001503 } // case AsmToken::Percent
1504 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001505 return true;
1506}
1507
Vladimir Medic4c299852013-11-06 11:27:05 +00001508const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001509 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001510 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001511 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001512 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001513 // It's a constant, evaluate reloc value.
1514 int16_t Val;
1515 switch (getVariantKind(RelocStr)) {
1516 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1517 // Get the 1st 16-bits.
1518 Val = MCE->getValue() & 0xffff;
1519 break;
1520 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1521 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1522 // 16 bits being negative.
1523 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1524 break;
1525 case MCSymbolRefExpr::VK_Mips_HIGHER:
1526 // Get the 3rd 16-bits.
1527 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1528 break;
1529 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1530 // Get the 4th 16-bits.
1531 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1532 break;
1533 default:
1534 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001535 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001536 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001537 }
1538
Jack Carterb5cf5902013-04-17 00:18:04 +00001539 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001540 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001541 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001542 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001543 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001544 return Res;
1545 }
1546
1547 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001548 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1549
Sasa Stankovic06c47802014-04-03 10:37:45 +00001550 // Try to create target expression.
1551 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1552 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001553
Jack Carterd0bd6422013-04-18 00:41:53 +00001554 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1555 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001556 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1557 return Res;
1558 }
1559
1560 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001561 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1562 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1563 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001564 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001565 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001566 return Expr;
1567}
1568
1569bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1570
1571 switch (Expr->getKind()) {
1572 case MCExpr::Constant:
1573 return true;
1574 case MCExpr::SymbolRef:
1575 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1576 case MCExpr::Binary:
1577 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1578 if (!isEvaluated(BE->getLHS()))
1579 return false;
1580 return isEvaluated(BE->getRHS());
1581 }
1582 case MCExpr::Unary:
1583 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001584 case MCExpr::Target:
1585 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001586 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001587 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001588}
Jack Carterd0bd6422013-04-18 00:41:53 +00001589
Jack Carterb5cf5902013-04-17 00:18:04 +00001590bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001591 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001592 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001593 if (Tok.isNot(AsmToken::Identifier))
1594 return true;
1595
1596 std::string Str = Tok.getIdentifier().str();
1597
Jack Carterd0bd6422013-04-18 00:41:53 +00001598 Parser.Lex(); // Eat the identifier.
1599 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001600 const MCExpr *IdVal;
1601 SMLoc EndLoc;
1602
1603 if (getLexer().getKind() == AsmToken::LParen) {
1604 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001605 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001606 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001607 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001608 const AsmToken &nextTok = Parser.getTok();
1609 if (nextTok.isNot(AsmToken::Identifier))
1610 return true;
1611 Str += "(%";
1612 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001613 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001614 if (getLexer().getKind() != AsmToken::LParen)
1615 return true;
1616 } else
1617 break;
1618 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001620 return true;
1621
1622 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001623 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001624
1625 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001626 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001627
Jack Carterd0bd6422013-04-18 00:41:53 +00001628 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001629 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001630}
1631
Jack Carterb4dbc172012-09-05 23:34:03 +00001632bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1633 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001634 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001635 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1636 if (ResTy == MatchOperand_Success) {
1637 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001638 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001639 StartLoc = Operand.getStartLoc();
1640 EndLoc = Operand.getEndLoc();
1641
1642 // AFAIK, we only support numeric registers and named GPR's in CFI
1643 // directives.
1644 // Don't worry about eating tokens before failing. Using an unrecognised
1645 // register is a parse error.
1646 if (Operand.isGPRAsmReg()) {
1647 // Resolve to GPR32 or GPR64 appropriately.
1648 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1649 }
1650
1651 return (RegNo == (unsigned)-1);
1652 }
1653
1654 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001655 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001656}
1657
Jack Carterb5cf5902013-04-17 00:18:04 +00001658bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001659 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001660 bool Result = true;
1661
1662 while (getLexer().getKind() == AsmToken::LParen)
1663 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001664
Jack Carterd0bd6422013-04-18 00:41:53 +00001665 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001666 default:
1667 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001668 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001669 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001670 case AsmToken::Integer:
1671 case AsmToken::Minus:
1672 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001673 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001674 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001675 else
1676 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001677 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001678 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001679 break;
Jack Carter873c7242013-01-12 01:03:14 +00001680 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001681 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001682 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001683 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001684}
1685
David Blaikie960ea3f2014-06-08 16:18:35 +00001686MipsAsmParser::OperandMatchResultTy
1687MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001688 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001689 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001690 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001691 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001692 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001693 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001694 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001695
Jack Carterb5cf5902013-04-17 00:18:04 +00001696 if (getLexer().getKind() == AsmToken::LParen) {
1697 Parser.Lex();
1698 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001699 }
1700
Jack Carterb5cf5902013-04-17 00:18:04 +00001701 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001702 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001703 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001704
Jack Carterd0bd6422013-04-18 00:41:53 +00001705 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001706 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001707 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1708 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001709 SMLoc E =
1710 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001711 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001712 return MatchOperand_Success;
1713 }
1714 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001715 SMLoc E =
1716 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001717
Jack Carterd0bd6422013-04-18 00:41:53 +00001718 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001719 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001720 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1721 S, E, *this);
1722 Operands.push_back(
1723 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001724 return MatchOperand_Success;
1725 }
1726 Error(Parser.getTok().getLoc(), "'(' expected");
1727 return MatchOperand_ParseFail;
1728 }
1729
Jack Carterd0bd6422013-04-18 00:41:53 +00001730 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001731 }
1732
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001733 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001734 if (Res != MatchOperand_Success)
1735 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001736
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001737 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001738 Error(Parser.getTok().getLoc(), "')' expected");
1739 return MatchOperand_ParseFail;
1740 }
1741
Jack Carter873c7242013-01-12 01:03:14 +00001742 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1743
Jack Carterd0bd6422013-04-18 00:41:53 +00001744 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001745
Craig Topper062a2ba2014-04-25 05:30:21 +00001746 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001747 IdVal = MCConstantExpr::Create(0, getContext());
1748
Jack Carterd0bd6422013-04-18 00:41:53 +00001749 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001750 std::unique_ptr<MipsOperand> op(
1751 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001752 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001753 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001754 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001755 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001756 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1757 int64_t Imm;
1758 if (IdVal->EvaluateAsAbsolute(Imm))
1759 IdVal = MCConstantExpr::Create(Imm, getContext());
1760 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1761 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1762 getContext());
1763 }
1764
David Blaikie960ea3f2014-06-08 16:18:35 +00001765 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001766 return MatchOperand_Success;
1767}
1768
David Blaikie960ea3f2014-06-08 16:18:35 +00001769bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001770
Jack Carterd76b2372013-03-21 21:44:16 +00001771 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1772 if (Sym) {
1773 SMLoc S = Parser.getTok().getLoc();
1774 const MCExpr *Expr;
1775 if (Sym->isVariable())
1776 Expr = Sym->getVariableValue();
1777 else
1778 return false;
1779 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001780 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001781 const StringRef DefSymbol = Ref->getSymbol().getName();
1782 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001783 OperandMatchResultTy ResTy =
1784 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001785 if (ResTy == MatchOperand_Success) {
1786 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001787 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001788 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001789 llvm_unreachable("Should never ParseFail");
1790 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001791 }
1792 } else if (Expr->getKind() == MCExpr::Constant) {
1793 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001794 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001795 Operands.push_back(
1796 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001797 return true;
1798 }
1799 }
1800 return false;
1801}
Jack Carterd0bd6422013-04-18 00:41:53 +00001802
Jack Carter873c7242013-01-12 01:03:14 +00001803MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001804MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1805 StringRef Identifier,
1806 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001807 int Index = matchCPURegisterName(Identifier);
1808 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001809 Operands.push_back(MipsOperand::CreateGPRReg(
1810 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1811 return MatchOperand_Success;
1812 }
1813
1814 Index = matchFPURegisterName(Identifier);
1815 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001816 Operands.push_back(MipsOperand::CreateFGRReg(
1817 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1818 return MatchOperand_Success;
1819 }
1820
1821 Index = matchFCCRegisterName(Identifier);
1822 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001823 Operands.push_back(MipsOperand::CreateFCCReg(
1824 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1825 return MatchOperand_Success;
1826 }
1827
1828 Index = matchACRegisterName(Identifier);
1829 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001830 Operands.push_back(MipsOperand::CreateACCReg(
1831 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1832 return MatchOperand_Success;
1833 }
1834
1835 Index = matchMSA128RegisterName(Identifier);
1836 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001837 Operands.push_back(MipsOperand::CreateMSA128Reg(
1838 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1839 return MatchOperand_Success;
1840 }
1841
1842 Index = matchMSA128CtrlRegisterName(Identifier);
1843 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001844 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1845 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1846 return MatchOperand_Success;
1847 }
1848
1849 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001850}
1851
1852MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001853MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001854 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001855
1856 if (Token.is(AsmToken::Identifier)) {
1857 DEBUG(dbgs() << ".. identifier\n");
1858 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001859 OperandMatchResultTy ResTy =
1860 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001861 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001862 } else if (Token.is(AsmToken::Integer)) {
1863 DEBUG(dbgs() << ".. integer\n");
1864 Operands.push_back(MipsOperand::CreateNumericReg(
1865 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1866 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001867 return MatchOperand_Success;
1868 }
1869
1870 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1871
1872 return MatchOperand_NoMatch;
1873}
1874
David Blaikie960ea3f2014-06-08 16:18:35 +00001875MipsAsmParser::OperandMatchResultTy
1876MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001877 DEBUG(dbgs() << "ParseAnyRegister\n");
1878
1879 auto Token = Parser.getTok();
1880
1881 SMLoc S = Token.getLoc();
1882
1883 if (Token.isNot(AsmToken::Dollar)) {
1884 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1885 if (Token.is(AsmToken::Identifier)) {
1886 if (searchSymbolAlias(Operands))
1887 return MatchOperand_Success;
1888 }
1889 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1890 return MatchOperand_NoMatch;
1891 }
1892 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001893
Daniel Sanders21bce302014-04-01 12:35:23 +00001894 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001895 if (ResTy == MatchOperand_Success) {
1896 Parser.Lex(); // $
1897 Parser.Lex(); // identifier
1898 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001899 return ResTy;
1900}
1901
1902MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001903MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001904 switch (getLexer().getKind()) {
1905 default:
1906 return MatchOperand_NoMatch;
1907 case AsmToken::LParen:
1908 case AsmToken::Minus:
1909 case AsmToken::Plus:
1910 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001911 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001912 case AsmToken::String:
1913 break;
1914 }
1915
1916 const MCExpr *IdVal;
1917 SMLoc S = Parser.getTok().getLoc();
1918 if (getParser().parseExpression(IdVal))
1919 return MatchOperand_ParseFail;
1920
1921 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1922 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1923 return MatchOperand_Success;
1924}
1925
David Blaikie960ea3f2014-06-08 16:18:35 +00001926MipsAsmParser::OperandMatchResultTy
1927MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001928 DEBUG(dbgs() << "ParseJumpTarget\n");
1929
1930 SMLoc S = getLexer().getLoc();
1931
1932 // Integers and expressions are acceptable
1933 OperandMatchResultTy ResTy = ParseImm(Operands);
1934 if (ResTy != MatchOperand_NoMatch)
1935 return ResTy;
1936
Daniel Sanders315386c2014-04-01 10:40:14 +00001937 // Registers are a valid target and have priority over symbols.
1938 ResTy = ParseAnyRegister(Operands);
1939 if (ResTy != MatchOperand_NoMatch)
1940 return ResTy;
1941
Daniel Sandersffd84362014-04-01 10:41:48 +00001942 const MCExpr *Expr = nullptr;
1943 if (Parser.parseExpression(Expr)) {
1944 // We have no way of knowing if a symbol was consumed so we must ParseFail
1945 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001946 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001947 Operands.push_back(
1948 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001949 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001950}
1951
Vladimir Medic2b953d02013-10-01 09:48:56 +00001952MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001953MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001954 const MCExpr *IdVal;
1955 // If the first token is '$' we may have register operand.
1956 if (Parser.getTok().is(AsmToken::Dollar))
1957 return MatchOperand_NoMatch;
1958 SMLoc S = Parser.getTok().getLoc();
1959 if (getParser().parseExpression(IdVal))
1960 return MatchOperand_ParseFail;
1961 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001962 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001963 int64_t Val = MCE->getValue();
1964 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1965 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001966 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001967 return MatchOperand_Success;
1968}
1969
Matheus Almeida779c5932013-11-18 12:32:49 +00001970MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001971MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001972 switch (getLexer().getKind()) {
1973 default:
1974 return MatchOperand_NoMatch;
1975 case AsmToken::LParen:
1976 case AsmToken::Plus:
1977 case AsmToken::Minus:
1978 case AsmToken::Integer:
1979 break;
1980 }
1981
1982 const MCExpr *Expr;
1983 SMLoc S = Parser.getTok().getLoc();
1984
1985 if (getParser().parseExpression(Expr))
1986 return MatchOperand_ParseFail;
1987
1988 int64_t Val;
1989 if (!Expr->EvaluateAsAbsolute(Val)) {
1990 Error(S, "expected immediate value");
1991 return MatchOperand_ParseFail;
1992 }
1993
1994 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1995 // and because the CPU always adds one to the immediate field, the allowed
1996 // range becomes 1..4. We'll only check the range here and will deal
1997 // with the addition/subtraction when actually decoding/encoding
1998 // the instruction.
1999 if (Val < 1 || Val > 4) {
2000 Error(S, "immediate not in range (1..4)");
2001 return MatchOperand_ParseFail;
2002 }
2003
Jack Carter3b2c96e2014-01-22 23:31:38 +00002004 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002005 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002006 return MatchOperand_Success;
2007}
2008
Jack Carterdc1e35d2012-09-06 20:00:02 +00002009MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2010
Vladimir Medic4c299852013-11-06 11:27:05 +00002011 MCSymbolRefExpr::VariantKind VK =
2012 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2013 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2014 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2015 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2016 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2017 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2018 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2019 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2020 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2021 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2022 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2023 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2024 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2025 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2026 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2027 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2028 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2029 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002030 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2031 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2032 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2033 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2034 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2035 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002036 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2037 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002038 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002039
Matheus Almeida2852af82014-04-22 10:15:54 +00002040 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002041
Jack Carterdc1e35d2012-09-06 20:00:02 +00002042 return VK;
2043}
Jack Cartera63b16a2012-09-07 00:23:42 +00002044
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002045/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2046/// either this.
2047/// ::= '(', register, ')'
2048/// handle it before we iterate so we don't get tripped up by the lack of
2049/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002050bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002051 if (getLexer().is(AsmToken::LParen)) {
2052 Operands.push_back(
2053 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2054 Parser.Lex();
2055 if (ParseOperand(Operands, Name)) {
2056 SMLoc Loc = getLexer().getLoc();
2057 Parser.eatToEndOfStatement();
2058 return Error(Loc, "unexpected token in argument list");
2059 }
2060 if (Parser.getTok().isNot(AsmToken::RParen)) {
2061 SMLoc Loc = getLexer().getLoc();
2062 Parser.eatToEndOfStatement();
2063 return Error(Loc, "unexpected token, expected ')'");
2064 }
2065 Operands.push_back(
2066 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2067 Parser.Lex();
2068 }
2069 return false;
2070}
2071
2072/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2073/// either one of these.
2074/// ::= '[', register, ']'
2075/// ::= '[', integer, ']'
2076/// handle it before we iterate so we don't get tripped up by the lack of
2077/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002078bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2079 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002080 if (getLexer().is(AsmToken::LBrac)) {
2081 Operands.push_back(
2082 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2083 Parser.Lex();
2084 if (ParseOperand(Operands, Name)) {
2085 SMLoc Loc = getLexer().getLoc();
2086 Parser.eatToEndOfStatement();
2087 return Error(Loc, "unexpected token in argument list");
2088 }
2089 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2090 SMLoc Loc = getLexer().getLoc();
2091 Parser.eatToEndOfStatement();
2092 return Error(Loc, "unexpected token, expected ']'");
2093 }
2094 Operands.push_back(
2095 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2096 Parser.Lex();
2097 }
2098 return false;
2099}
2100
David Blaikie960ea3f2014-06-08 16:18:35 +00002101bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2102 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002103 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002104 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002105 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002106 Parser.eatToEndOfStatement();
2107 return Error(NameLoc, "Unknown instruction");
2108 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002109 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002110 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002111
2112 // Read the remaining operands.
2113 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2114 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002115 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002116 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002117 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002118 return Error(Loc, "unexpected token in argument list");
2119 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002120 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2121 return true;
2122 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002123
Jack Carterd0bd6422013-04-18 00:41:53 +00002124 while (getLexer().is(AsmToken::Comma)) {
2125 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002126 // Parse and remember the operand.
2127 if (ParseOperand(Operands, Name)) {
2128 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002129 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002130 return Error(Loc, "unexpected token in argument list");
2131 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002132 // Parse bracket and parenthesis suffixes before we iterate
2133 if (getLexer().is(AsmToken::LBrac)) {
2134 if (ParseBracketSuffix(Name, Operands))
2135 return true;
2136 } else if (getLexer().is(AsmToken::LParen) &&
2137 ParseParenSuffix(Name, Operands))
2138 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002139 }
2140 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002141 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2142 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002143 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002144 return Error(Loc, "unexpected token in argument list");
2145 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002146 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002147 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002148}
2149
Jack Carter0b744b32012-10-04 02:29:46 +00002150bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002151 SMLoc Loc = getLexer().getLoc();
2152 Parser.eatToEndOfStatement();
2153 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002154}
2155
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002156bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2157 return Error(Loc, ErrorMsg);
2158}
2159
Jack Carter0b744b32012-10-04 02:29:46 +00002160bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002161 // Line should look like: ".set noat".
2162 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002163 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002164 // eat noat
2165 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002166 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002167 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2168 reportParseError("unexpected token in statement");
2169 return false;
2170 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002171 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002172 return false;
2173}
Jack Carterd0bd6422013-04-18 00:41:53 +00002174
Jack Carter0b744b32012-10-04 02:29:46 +00002175bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002176 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002177 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002178 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002179 getParser().Lex();
2180 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002181 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002182 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002183 return false;
2184 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002185 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002186 if (getLexer().isNot(AsmToken::Dollar)) {
2187 reportParseError("unexpected token in statement");
2188 return false;
2189 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002190 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002191 const AsmToken &Reg = Parser.getTok();
2192 if (Reg.is(AsmToken::Identifier)) {
2193 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2194 } else if (Reg.is(AsmToken::Integer)) {
2195 AtRegNo = Reg.getIntVal();
2196 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002197 reportParseError("unexpected token in statement");
2198 return false;
2199 }
Jack Carter1ac53222013-02-20 23:11:17 +00002200
Daniel Sanders71a89d922014-03-25 13:01:06 +00002201 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002202 reportParseError("unexpected token in statement");
2203 return false;
2204 }
2205
2206 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002207 reportParseError("unexpected token in statement");
2208 return false;
2209 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002210 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002211
2212 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2213 reportParseError("unexpected token in statement");
2214 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002215 }
2216 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002217 return false;
2218 } else {
2219 reportParseError("unexpected token in statement");
2220 return false;
2221 }
2222}
2223
2224bool MipsAsmParser::parseSetReorderDirective() {
2225 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002226 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002227 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2228 reportParseError("unexpected token in statement");
2229 return false;
2230 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002231 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002232 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002233 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002234 return false;
2235}
2236
2237bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002238 Parser.Lex();
2239 // If this is not the end of the statement, report an error.
2240 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2241 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002242 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002243 }
2244 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002245 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002246 Parser.Lex(); // Consume the EndOfStatement.
2247 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002248}
2249
2250bool MipsAsmParser::parseSetMacroDirective() {
2251 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002252 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002253 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2254 reportParseError("unexpected token in statement");
2255 return false;
2256 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002257 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002258 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002259 return false;
2260}
2261
2262bool MipsAsmParser::parseSetNoMacroDirective() {
2263 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002264 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002265 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2266 reportParseError("`noreorder' must be set before `nomacro'");
2267 return false;
2268 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002269 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002270 reportParseError("`noreorder' must be set before `nomacro'");
2271 return false;
2272 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002273 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002274 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002275 return false;
2276}
Jack Carterd76b2372013-03-21 21:44:16 +00002277
Jack Carter39536722014-01-22 23:08:42 +00002278bool MipsAsmParser::parseSetNoMips16Directive() {
2279 Parser.Lex();
2280 // If this is not the end of the statement, report an error.
2281 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2282 reportParseError("unexpected token in statement");
2283 return false;
2284 }
2285 // For now do nothing.
2286 Parser.Lex(); // Consume the EndOfStatement.
2287 return false;
2288}
2289
Jack Carterd76b2372013-03-21 21:44:16 +00002290bool MipsAsmParser::parseSetAssignment() {
2291 StringRef Name;
2292 const MCExpr *Value;
2293
2294 if (Parser.parseIdentifier(Name))
2295 reportParseError("expected identifier after .set");
2296
2297 if (getLexer().isNot(AsmToken::Comma))
2298 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002299 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002300
Jack Carter3b2c96e2014-01-22 23:31:38 +00002301 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002302 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002303
Jack Carterd0bd6422013-04-18 00:41:53 +00002304 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002305 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002306 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002307 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002308 Sym = getContext().GetOrCreateSymbol(Name);
2309 Sym->setVariableValue(Value);
2310
2311 return false;
2312}
Jack Carterd0bd6422013-04-18 00:41:53 +00002313
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002314bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2315 Parser.Lex();
2316 if (getLexer().isNot(AsmToken::EndOfStatement))
2317 return reportParseError("unexpected token in .set directive");
2318
Matheus Almeida2852af82014-04-22 10:15:54 +00002319 switch (Feature) {
2320 default:
2321 llvm_unreachable("Unimplemented feature");
2322 case Mips::FeatureDSP:
2323 setFeatureBits(Mips::FeatureDSP, "dsp");
2324 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002325 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002326 case Mips::FeatureMicroMips:
2327 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002328 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002329 case Mips::FeatureMips16:
2330 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002331 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002332 case Mips::FeatureMips32r2:
2333 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2334 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002335 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002336 case Mips::FeatureMips64:
2337 setFeatureBits(Mips::FeatureMips64, "mips64");
2338 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002339 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002340 case Mips::FeatureMips64r2:
2341 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2342 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002343 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002344 }
2345 return false;
2346}
2347
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002348bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2349 if (getLexer().isNot(AsmToken::Comma)) {
2350 SMLoc Loc = getLexer().getLoc();
2351 Parser.eatToEndOfStatement();
2352 return Error(Loc, ErrorStr);
2353 }
2354
Matheus Almeida2852af82014-04-22 10:15:54 +00002355 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002356 return true;
2357}
2358
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002359bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2360 if (Options.isReorder())
2361 Warning(Loc, ".cpload in reorder section");
2362
2363 // FIXME: Warn if cpload is used in Mips16 mode.
2364
David Blaikie960ea3f2014-06-08 16:18:35 +00002365 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002366 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2367 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2368 reportParseError("expected register containing function address");
2369 return false;
2370 }
2371
David Blaikie960ea3f2014-06-08 16:18:35 +00002372 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2373 if (!RegOpnd.isGPRAsmReg()) {
2374 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002375 return false;
2376 }
2377
David Blaikie960ea3f2014-06-08 16:18:35 +00002378 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002379 return false;
2380}
2381
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002382bool MipsAsmParser::parseDirectiveCPSetup() {
2383 unsigned FuncReg;
2384 unsigned Save;
2385 bool SaveIsReg = true;
2386
Matheus Almeida7e815762014-06-18 13:08:59 +00002387 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2388 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2389 if (ResTy == MatchOperand_NoMatch) {
2390 reportParseError("expected register containing function address");
2391 Parser.eatToEndOfStatement();
2392 return false;
2393 }
2394
2395 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2396 if (!FuncRegOpnd.isGPRAsmReg()) {
2397 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2398 Parser.eatToEndOfStatement();
2399 return false;
2400 }
2401
2402 FuncReg = FuncRegOpnd.getGPR32Reg();
2403 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002404
2405 if (!eatComma("expected comma parsing directive"))
2406 return true;
2407
Matheus Almeida7e815762014-06-18 13:08:59 +00002408 ResTy = ParseAnyRegister(TmpReg);
2409 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002410 const AsmToken &Tok = Parser.getTok();
2411 if (Tok.is(AsmToken::Integer)) {
2412 Save = Tok.getIntVal();
2413 SaveIsReg = false;
2414 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002415 } else {
2416 reportParseError("expected save register or stack offset");
2417 Parser.eatToEndOfStatement();
2418 return false;
2419 }
2420 } else {
2421 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2422 if (!SaveOpnd.isGPRAsmReg()) {
2423 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2424 Parser.eatToEndOfStatement();
2425 return false;
2426 }
2427 Save = SaveOpnd.getGPR32Reg();
2428 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002429
2430 if (!eatComma("expected comma parsing directive"))
2431 return true;
2432
2433 StringRef Name;
2434 if (Parser.parseIdentifier(Name))
2435 reportParseError("expected identifier");
2436 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002437
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002438 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002439 return false;
2440}
2441
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002442bool MipsAsmParser::parseDirectiveNaN() {
2443 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2444 const AsmToken &Tok = Parser.getTok();
2445
2446 if (Tok.getString() == "2008") {
2447 Parser.Lex();
2448 getTargetStreamer().emitDirectiveNaN2008();
2449 return false;
2450 } else if (Tok.getString() == "legacy") {
2451 Parser.Lex();
2452 getTargetStreamer().emitDirectiveNaNLegacy();
2453 return false;
2454 }
2455 }
2456 // If we don't recognize the option passed to the .nan
2457 // directive (e.g. no option or unknown option), emit an error.
2458 reportParseError("invalid option in .nan directive");
2459 return false;
2460}
2461
Jack Carter0b744b32012-10-04 02:29:46 +00002462bool MipsAsmParser::parseDirectiveSet() {
2463
Jack Carterd0bd6422013-04-18 00:41:53 +00002464 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002465 const AsmToken &Tok = Parser.getTok();
2466
2467 if (Tok.getString() == "noat") {
2468 return parseSetNoAtDirective();
2469 } else if (Tok.getString() == "at") {
2470 return parseSetAtDirective();
2471 } else if (Tok.getString() == "reorder") {
2472 return parseSetReorderDirective();
2473 } else if (Tok.getString() == "noreorder") {
2474 return parseSetNoReorderDirective();
2475 } else if (Tok.getString() == "macro") {
2476 return parseSetMacroDirective();
2477 } else if (Tok.getString() == "nomacro") {
2478 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002479 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002480 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002481 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002482 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002483 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002484 getTargetStreamer().emitDirectiveSetNoMicroMips();
2485 Parser.eatToEndOfStatement();
2486 return false;
2487 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002488 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002489 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002490 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002491 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002492 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002493 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002494 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002495 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002496 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002497 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002498 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002499 parseSetAssignment();
2500 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002501 }
Jack Carter07c818d2013-01-25 01:31:34 +00002502
Jack Carter0b744b32012-10-04 02:29:46 +00002503 return true;
2504}
2505
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002506/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002507/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002508bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002509 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2510 for (;;) {
2511 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002512 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002513 return true;
2514
2515 getParser().getStreamer().EmitValue(Value, Size);
2516
2517 if (getLexer().is(AsmToken::EndOfStatement))
2518 break;
2519
2520 // FIXME: Improve diagnostic.
2521 if (getLexer().isNot(AsmToken::Comma))
2522 return Error(L, "unexpected token in directive");
2523 Parser.Lex();
2524 }
2525 }
2526
2527 Parser.Lex();
2528 return false;
2529}
2530
Vladimir Medic4c299852013-11-06 11:27:05 +00002531/// parseDirectiveGpWord
2532/// ::= .gpword local_sym
2533bool MipsAsmParser::parseDirectiveGpWord() {
2534 const MCExpr *Value;
2535 // EmitGPRel32Value requires an expression, so we are using base class
2536 // method to evaluate the expression.
2537 if (getParser().parseExpression(Value))
2538 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002539 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002540
Vladimir Medice10c1122013-11-13 13:18:04 +00002541 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002542 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002543 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002544 return false;
2545}
2546
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002547/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002548/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002549bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002550 const MCExpr *Value;
2551 // EmitGPRel64Value requires an expression, so we are using base class
2552 // method to evaluate the expression.
2553 if (getParser().parseExpression(Value))
2554 return true;
2555 getParser().getStreamer().EmitGPRel64Value(Value);
2556
2557 if (getLexer().isNot(AsmToken::EndOfStatement))
2558 return Error(getLexer().getLoc(), "unexpected token in directive");
2559 Parser.Lex(); // Eat EndOfStatement token.
2560 return false;
2561}
2562
Jack Carter0cd3c192014-01-06 23:27:31 +00002563bool MipsAsmParser::parseDirectiveOption() {
2564 // Get the option token.
2565 AsmToken Tok = Parser.getTok();
2566 // At the moment only identifiers are supported.
2567 if (Tok.isNot(AsmToken::Identifier)) {
2568 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2569 Parser.eatToEndOfStatement();
2570 return false;
2571 }
2572
2573 StringRef Option = Tok.getIdentifier();
2574
2575 if (Option == "pic0") {
2576 getTargetStreamer().emitDirectiveOptionPic0();
2577 Parser.Lex();
2578 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2579 Error(Parser.getTok().getLoc(),
2580 "unexpected token in .option pic0 directive");
2581 Parser.eatToEndOfStatement();
2582 }
2583 return false;
2584 }
2585
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002586 if (Option == "pic2") {
2587 getTargetStreamer().emitDirectiveOptionPic2();
2588 Parser.Lex();
2589 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2590 Error(Parser.getTok().getLoc(),
2591 "unexpected token in .option pic2 directive");
2592 Parser.eatToEndOfStatement();
2593 }
2594 return false;
2595 }
2596
Jack Carter0cd3c192014-01-06 23:27:31 +00002597 // Unknown option.
2598 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2599 Parser.eatToEndOfStatement();
2600 return false;
2601}
2602
Jack Carter0b744b32012-10-04 02:29:46 +00002603bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002604 StringRef IDVal = DirectiveID.getString();
2605
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002606 if (IDVal == ".cpload")
2607 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002608 if (IDVal == ".dword") {
2609 parseDataDirective(8, DirectiveID.getLoc());
2610 return false;
2611 }
2612
Jack Carterd0bd6422013-04-18 00:41:53 +00002613 if (IDVal == ".ent") {
2614 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002615 Parser.Lex();
2616 return false;
2617 }
2618
Jack Carter07c818d2013-01-25 01:31:34 +00002619 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002620 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002621 Parser.Lex();
2622 return false;
2623 }
2624
Jack Carter07c818d2013-01-25 01:31:34 +00002625 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002626 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002627 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002628 return false;
2629 }
2630
Jack Carter07c818d2013-01-25 01:31:34 +00002631 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002632 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002633 }
2634
Jack Carter07c818d2013-01-25 01:31:34 +00002635 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002636 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002637 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002638 return false;
2639 }
2640
Jack Carter07c818d2013-01-25 01:31:34 +00002641 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002642 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002643 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002644 return false;
2645 }
2646
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002647 if (IDVal == ".nan")
2648 return parseDirectiveNaN();
2649
Jack Carter07c818d2013-01-25 01:31:34 +00002650 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002651 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002652 return false;
2653 }
2654
Rafael Espindolab59fb732014-03-28 18:50:26 +00002655 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002656 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002657 return false;
2658 }
2659
Jack Carter07c818d2013-01-25 01:31:34 +00002660 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002661 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002662 return false;
2663 }
2664
Jack Carter0cd3c192014-01-06 23:27:31 +00002665 if (IDVal == ".option")
2666 return parseDirectiveOption();
2667
2668 if (IDVal == ".abicalls") {
2669 getTargetStreamer().emitDirectiveAbiCalls();
2670 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2671 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2672 // Clear line
2673 Parser.eatToEndOfStatement();
2674 }
2675 return false;
2676 }
2677
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002678 if (IDVal == ".cpsetup")
2679 return parseDirectiveCPSetup();
2680
Rafael Espindola870c4e92012-01-11 03:56:41 +00002681 return true;
2682}
2683
Rafael Espindola870c4e92012-01-11 03:56:41 +00002684extern "C" void LLVMInitializeMipsAsmParser() {
2685 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2686 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2687 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2688 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2689}
Jack Carterb4dbc172012-09-05 23:34:03 +00002690
2691#define GET_REGISTER_MATCHER
2692#define GET_MATCHER_IMPLEMENTATION
2693#include "MipsGenAsmMatcher.inc"