blob: 70a7d341d3f6a3060d0c82c1848a40f169c5a9b4 [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;
Vladimir Medic4c299852013-11-06 11:27:05 +00001128 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001129 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +00001130 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001131 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1132 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001133 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001134 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1135 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001136 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001137 if (isImmOpnd) {
1138 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1139 ImmOffset = Inst.getOperand(2).getImm();
1140 LoOffset = ImmOffset & 0x0000ffff;
1141 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001142 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001143 if (LoOffset & 0x8000)
1144 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001145 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001146 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001147 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001148 TempInst.setLoc(IDLoc);
1149 // 1st instruction in expansion is LUi. For load instruction we can use
1150 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001151 // but for stores we must use $at.
1152 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +00001153 TempInst.setOpcode(Mips::LUi);
1154 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1155 if (isImmOpnd)
1156 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1157 else {
1158 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001159 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001160 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1161 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1162 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001163 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001164 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001165 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001166 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001167 }
1168 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001169 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001170 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001171 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001172 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001173 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001174 TempInst.setOpcode(Mips::ADDu);
1175 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1176 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1177 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1178 Instructions.push_back(TempInst);
1179 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001180 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001181 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001182 TempInst.setOpcode(Inst.getOpcode());
1183 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1184 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1185 if (isImmOpnd)
1186 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1187 else {
1188 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001189 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1190 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1191 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001192 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001193 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001194 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001195 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001196 }
1197 }
1198 Instructions.push_back(TempInst);
1199 TempInst.clear();
1200}
1201
Matheus Almeida595fcab2014-06-11 15:05:56 +00001202unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1203 // As described by the Mips32r2 spec, the registers Rd and Rs for
1204 // jalr.hb must be different.
1205 unsigned Opcode = Inst.getOpcode();
1206
1207 if (Opcode == Mips::JALR_HB &&
1208 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1209 return Match_RequiresDifferentSrcAndDst;
1210
1211 return Match_Success;
1212}
1213
David Blaikie960ea3f2014-06-08 16:18:35 +00001214bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1215 OperandVector &Operands,
1216 MCStreamer &Out,
1217 unsigned &ErrorInfo,
1218 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001219
Jack Carterb4dbc172012-09-05 23:34:03 +00001220 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001221 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001222 unsigned MatchResult =
1223 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001224
1225 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001226 default:
1227 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001228 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001229 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001230 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001231 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001232 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001233 return false;
1234 }
1235 case Match_MissingFeature:
1236 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1237 return true;
1238 case Match_InvalidOperand: {
1239 SMLoc ErrorLoc = IDLoc;
1240 if (ErrorInfo != ~0U) {
1241 if (ErrorInfo >= Operands.size())
1242 return Error(IDLoc, "too few operands for instruction");
1243
David Blaikie960ea3f2014-06-08 16:18:35 +00001244 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001245 if (ErrorLoc == SMLoc())
1246 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001247 }
1248
1249 return Error(ErrorLoc, "invalid operand for instruction");
1250 }
1251 case Match_MnemonicFail:
1252 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001253 case Match_RequiresDifferentSrcAndDst:
1254 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001255 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001256 return true;
1257}
1258
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001259void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1260 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1261 if (RegIndex == 1)
1262 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001263 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001264 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1265 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001266 }
1267}
1268
Jack Carter1ac53222013-02-20 23:11:17 +00001269int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001270 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001271
Vladimir Medic4c299852013-11-06 11:27:05 +00001272 CC = StringSwitch<unsigned>(Name)
1273 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001274 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001275 .Case("a0", 4)
1276 .Case("a1", 5)
1277 .Case("a2", 6)
1278 .Case("a3", 7)
1279 .Case("v0", 2)
1280 .Case("v1", 3)
1281 .Case("s0", 16)
1282 .Case("s1", 17)
1283 .Case("s2", 18)
1284 .Case("s3", 19)
1285 .Case("s4", 20)
1286 .Case("s5", 21)
1287 .Case("s6", 22)
1288 .Case("s7", 23)
1289 .Case("k0", 26)
1290 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001291 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001292 .Case("sp", 29)
1293 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001294 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001295 .Case("ra", 31)
1296 .Case("t0", 8)
1297 .Case("t1", 9)
1298 .Case("t2", 10)
1299 .Case("t3", 11)
1300 .Case("t4", 12)
1301 .Case("t5", 13)
1302 .Case("t6", 14)
1303 .Case("t7", 15)
1304 .Case("t8", 24)
1305 .Case("t9", 25)
1306 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001307
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001308 if (isN32() || isN64()) {
1309 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1310 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1311 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1312 if (8 <= CC && CC <= 11)
1313 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001314
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001315 if (CC == -1)
1316 CC = StringSwitch<unsigned>(Name)
1317 .Case("a4", 8)
1318 .Case("a5", 9)
1319 .Case("a6", 10)
1320 .Case("a7", 11)
1321 .Case("kt0", 26)
1322 .Case("kt1", 27)
1323 .Default(-1);
1324 }
Jack Carter1ac53222013-02-20 23:11:17 +00001325
1326 return CC;
1327}
Jack Carterd0bd6422013-04-18 00:41:53 +00001328
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001329int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001330
Jack Cartera63b16a2012-09-07 00:23:42 +00001331 if (Name[0] == 'f') {
1332 StringRef NumString = Name.substr(1);
1333 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001334 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001335 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001336 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001337 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001338 return IntVal;
1339 }
1340 return -1;
1341}
Jack Cartera63b16a2012-09-07 00:23:42 +00001342
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001343int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1344
1345 if (Name.startswith("fcc")) {
1346 StringRef NumString = Name.substr(3);
1347 unsigned IntVal;
1348 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001349 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001350 if (IntVal > 7) // There are only 8 fcc registers.
1351 return -1;
1352 return IntVal;
1353 }
1354 return -1;
1355}
1356
1357int MipsAsmParser::matchACRegisterName(StringRef Name) {
1358
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001359 if (Name.startswith("ac")) {
1360 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001361 unsigned IntVal;
1362 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001363 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001364 if (IntVal > 3) // There are only 3 acc registers.
1365 return -1;
1366 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001367 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001368 return -1;
1369}
Jack Carterd0bd6422013-04-18 00:41:53 +00001370
Jack Carter5dc8ac92013-09-25 23:50:44 +00001371int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1372 unsigned IntVal;
1373
1374 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1375 return -1;
1376
1377 if (IntVal > 31)
1378 return -1;
1379
1380 return IntVal;
1381}
1382
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001383int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1384 int CC;
1385
1386 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001387 .Case("msair", 0)
1388 .Case("msacsr", 1)
1389 .Case("msaaccess", 2)
1390 .Case("msasave", 3)
1391 .Case("msamodify", 4)
1392 .Case("msarequest", 5)
1393 .Case("msamap", 6)
1394 .Case("msaunmap", 7)
1395 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001396
1397 return CC;
1398}
1399
Jack Carter0b744b32012-10-04 02:29:46 +00001400bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1401 if (Reg > 31)
1402 return false;
1403
1404 aTReg = Reg;
1405 return true;
1406}
1407
Daniel Sandersd89b1362014-03-24 16:48:01 +00001408int MipsAsmParser::getATReg() {
1409 int AT = Options.getATRegNum();
1410 if (AT == 0)
1411 TokError("Pseudo instruction requires $at, which is not available");
1412 return AT;
1413}
Jack Carter0b744b32012-10-04 02:29:46 +00001414
Jack Carterd0bd6422013-04-18 00:41:53 +00001415unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001416 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001417}
1418
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001419unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001420 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1421 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001422}
1423
Jack Carter873c7242013-01-12 01:03:14 +00001424int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001425 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001426 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001427 return -1;
1428
Jack Carter873c7242013-01-12 01:03:14 +00001429 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001430}
1431
David Blaikie960ea3f2014-06-08 16:18:35 +00001432bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001433 DEBUG(dbgs() << "ParseOperand\n");
1434
Jack Carter30a59822012-10-04 04:03:53 +00001435 // Check if the current operand has a custom associated parser, if so, try to
1436 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001437 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1438 if (ResTy == MatchOperand_Success)
1439 return false;
1440 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1441 // there was a match, but an error occurred, in which case, just return that
1442 // the operand parsing failed.
1443 if (ResTy == MatchOperand_ParseFail)
1444 return true;
1445
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001446 DEBUG(dbgs() << ".. Generic Parser\n");
1447
Jack Carterb4dbc172012-09-05 23:34:03 +00001448 switch (getLexer().getKind()) {
1449 default:
1450 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1451 return true;
1452 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001453 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001454 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001455
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001456 // Almost all registers have been parsed by custom parsers. There is only
1457 // one exception to this. $zero (and it's alias $0) will reach this point
1458 // for div, divu, and similar instructions because it is not an operand
1459 // to the instruction definition but an explicit register. Special case
1460 // this situation for now.
1461 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001462 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001463
Jack Carterd0bd6422013-04-18 00:41:53 +00001464 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001465 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001466 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001467 return true;
1468
Jack Carter873c7242013-01-12 01:03:14 +00001469 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001470 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001471 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001472 const MCExpr *Res =
1473 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001474
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001475 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001476 return false;
1477 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001478 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001479 case AsmToken::LParen:
1480 case AsmToken::Minus:
1481 case AsmToken::Plus:
1482 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001483 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001484 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001485 DEBUG(dbgs() << ".. generic integer\n");
1486 OperandMatchResultTy ResTy = ParseImm(Operands);
1487 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001488 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001489 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001490 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001491 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001492 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001493 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001494 return true;
1495
Jack Carter873c7242013-01-12 01:03:14 +00001496 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1497
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001498 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001499 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001500 } // case AsmToken::Percent
1501 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001502 return true;
1503}
1504
Vladimir Medic4c299852013-11-06 11:27:05 +00001505const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001506 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001507 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001508 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001509 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001510 // It's a constant, evaluate reloc value.
1511 int16_t Val;
1512 switch (getVariantKind(RelocStr)) {
1513 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1514 // Get the 1st 16-bits.
1515 Val = MCE->getValue() & 0xffff;
1516 break;
1517 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1518 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1519 // 16 bits being negative.
1520 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1521 break;
1522 case MCSymbolRefExpr::VK_Mips_HIGHER:
1523 // Get the 3rd 16-bits.
1524 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1525 break;
1526 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1527 // Get the 4th 16-bits.
1528 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1529 break;
1530 default:
1531 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001532 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001533 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001534 }
1535
Jack Carterb5cf5902013-04-17 00:18:04 +00001536 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001537 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001538 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001539 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001540 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001541 return Res;
1542 }
1543
1544 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001545 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1546
Sasa Stankovic06c47802014-04-03 10:37:45 +00001547 // Try to create target expression.
1548 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1549 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001550
Jack Carterd0bd6422013-04-18 00:41:53 +00001551 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1552 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001553 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1554 return Res;
1555 }
1556
1557 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001558 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1559 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1560 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001561 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001562 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001563 return Expr;
1564}
1565
1566bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1567
1568 switch (Expr->getKind()) {
1569 case MCExpr::Constant:
1570 return true;
1571 case MCExpr::SymbolRef:
1572 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1573 case MCExpr::Binary:
1574 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1575 if (!isEvaluated(BE->getLHS()))
1576 return false;
1577 return isEvaluated(BE->getRHS());
1578 }
1579 case MCExpr::Unary:
1580 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001581 case MCExpr::Target:
1582 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001583 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001584 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001585}
Jack Carterd0bd6422013-04-18 00:41:53 +00001586
Jack Carterb5cf5902013-04-17 00:18:04 +00001587bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001588 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001589 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001590 if (Tok.isNot(AsmToken::Identifier))
1591 return true;
1592
1593 std::string Str = Tok.getIdentifier().str();
1594
Jack Carterd0bd6422013-04-18 00:41:53 +00001595 Parser.Lex(); // Eat the identifier.
1596 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001597 const MCExpr *IdVal;
1598 SMLoc EndLoc;
1599
1600 if (getLexer().getKind() == AsmToken::LParen) {
1601 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001602 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001603 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001604 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001605 const AsmToken &nextTok = Parser.getTok();
1606 if (nextTok.isNot(AsmToken::Identifier))
1607 return true;
1608 Str += "(%";
1609 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001610 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001611 if (getLexer().getKind() != AsmToken::LParen)
1612 return true;
1613 } else
1614 break;
1615 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001617 return true;
1618
1619 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001620 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001621
1622 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001623 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001624
Jack Carterd0bd6422013-04-18 00:41:53 +00001625 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001626 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001627}
1628
Jack Carterb4dbc172012-09-05 23:34:03 +00001629bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1630 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001631 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001632 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1633 if (ResTy == MatchOperand_Success) {
1634 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001635 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001636 StartLoc = Operand.getStartLoc();
1637 EndLoc = Operand.getEndLoc();
1638
1639 // AFAIK, we only support numeric registers and named GPR's in CFI
1640 // directives.
1641 // Don't worry about eating tokens before failing. Using an unrecognised
1642 // register is a parse error.
1643 if (Operand.isGPRAsmReg()) {
1644 // Resolve to GPR32 or GPR64 appropriately.
1645 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1646 }
1647
1648 return (RegNo == (unsigned)-1);
1649 }
1650
1651 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001652 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001653}
1654
Jack Carterb5cf5902013-04-17 00:18:04 +00001655bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001656 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001657 bool Result = true;
1658
1659 while (getLexer().getKind() == AsmToken::LParen)
1660 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001661
Jack Carterd0bd6422013-04-18 00:41:53 +00001662 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001663 default:
1664 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001665 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001666 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001667 case AsmToken::Integer:
1668 case AsmToken::Minus:
1669 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001670 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001671 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001672 else
1673 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001674 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001675 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 break;
Jack Carter873c7242013-01-12 01:03:14 +00001677 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001678 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001679 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001680 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001681}
1682
David Blaikie960ea3f2014-06-08 16:18:35 +00001683MipsAsmParser::OperandMatchResultTy
1684MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001685 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001686 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001687 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001688 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001689 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001690 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001691 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001692
Jack Carterb5cf5902013-04-17 00:18:04 +00001693 if (getLexer().getKind() == AsmToken::LParen) {
1694 Parser.Lex();
1695 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001696 }
1697
Jack Carterb5cf5902013-04-17 00:18:04 +00001698 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001699 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001700 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001701
Jack Carterd0bd6422013-04-18 00:41:53 +00001702 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001703 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001704 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1705 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001706 SMLoc E =
1707 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001708 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001709 return MatchOperand_Success;
1710 }
1711 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001712 SMLoc E =
1713 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001714
Jack Carterd0bd6422013-04-18 00:41:53 +00001715 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001716 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001717 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1718 S, E, *this);
1719 Operands.push_back(
1720 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001721 return MatchOperand_Success;
1722 }
1723 Error(Parser.getTok().getLoc(), "'(' expected");
1724 return MatchOperand_ParseFail;
1725 }
1726
Jack Carterd0bd6422013-04-18 00:41:53 +00001727 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001728 }
1729
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001730 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001731 if (Res != MatchOperand_Success)
1732 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001733
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001734 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001735 Error(Parser.getTok().getLoc(), "')' expected");
1736 return MatchOperand_ParseFail;
1737 }
1738
Jack Carter873c7242013-01-12 01:03:14 +00001739 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1740
Jack Carterd0bd6422013-04-18 00:41:53 +00001741 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001742
Craig Topper062a2ba2014-04-25 05:30:21 +00001743 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001744 IdVal = MCConstantExpr::Create(0, getContext());
1745
Jack Carterd0bd6422013-04-18 00:41:53 +00001746 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001747 std::unique_ptr<MipsOperand> op(
1748 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001749 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001750 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001751 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001752 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001753 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1754 int64_t Imm;
1755 if (IdVal->EvaluateAsAbsolute(Imm))
1756 IdVal = MCConstantExpr::Create(Imm, getContext());
1757 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1758 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1759 getContext());
1760 }
1761
David Blaikie960ea3f2014-06-08 16:18:35 +00001762 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001763 return MatchOperand_Success;
1764}
1765
David Blaikie960ea3f2014-06-08 16:18:35 +00001766bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001767
Jack Carterd76b2372013-03-21 21:44:16 +00001768 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1769 if (Sym) {
1770 SMLoc S = Parser.getTok().getLoc();
1771 const MCExpr *Expr;
1772 if (Sym->isVariable())
1773 Expr = Sym->getVariableValue();
1774 else
1775 return false;
1776 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001777 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001778 const StringRef DefSymbol = Ref->getSymbol().getName();
1779 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001780 OperandMatchResultTy ResTy =
1781 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001782 if (ResTy == MatchOperand_Success) {
1783 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001784 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001785 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001786 llvm_unreachable("Should never ParseFail");
1787 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001788 }
1789 } else if (Expr->getKind() == MCExpr::Constant) {
1790 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001791 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001792 Operands.push_back(
1793 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001794 return true;
1795 }
1796 }
1797 return false;
1798}
Jack Carterd0bd6422013-04-18 00:41:53 +00001799
Jack Carter873c7242013-01-12 01:03:14 +00001800MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001801MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1802 StringRef Identifier,
1803 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001804 int Index = matchCPURegisterName(Identifier);
1805 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001806 Operands.push_back(MipsOperand::CreateGPRReg(
1807 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1808 return MatchOperand_Success;
1809 }
1810
1811 Index = matchFPURegisterName(Identifier);
1812 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001813 Operands.push_back(MipsOperand::CreateFGRReg(
1814 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1815 return MatchOperand_Success;
1816 }
1817
1818 Index = matchFCCRegisterName(Identifier);
1819 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001820 Operands.push_back(MipsOperand::CreateFCCReg(
1821 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1822 return MatchOperand_Success;
1823 }
1824
1825 Index = matchACRegisterName(Identifier);
1826 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001827 Operands.push_back(MipsOperand::CreateACCReg(
1828 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1829 return MatchOperand_Success;
1830 }
1831
1832 Index = matchMSA128RegisterName(Identifier);
1833 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001834 Operands.push_back(MipsOperand::CreateMSA128Reg(
1835 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1836 return MatchOperand_Success;
1837 }
1838
1839 Index = matchMSA128CtrlRegisterName(Identifier);
1840 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001841 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1842 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1843 return MatchOperand_Success;
1844 }
1845
1846 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001847}
1848
1849MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001850MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001851 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001852
1853 if (Token.is(AsmToken::Identifier)) {
1854 DEBUG(dbgs() << ".. identifier\n");
1855 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001856 OperandMatchResultTy ResTy =
1857 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001858 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001859 } else if (Token.is(AsmToken::Integer)) {
1860 DEBUG(dbgs() << ".. integer\n");
1861 Operands.push_back(MipsOperand::CreateNumericReg(
1862 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1863 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001864 return MatchOperand_Success;
1865 }
1866
1867 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1868
1869 return MatchOperand_NoMatch;
1870}
1871
David Blaikie960ea3f2014-06-08 16:18:35 +00001872MipsAsmParser::OperandMatchResultTy
1873MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001874 DEBUG(dbgs() << "ParseAnyRegister\n");
1875
1876 auto Token = Parser.getTok();
1877
1878 SMLoc S = Token.getLoc();
1879
1880 if (Token.isNot(AsmToken::Dollar)) {
1881 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1882 if (Token.is(AsmToken::Identifier)) {
1883 if (searchSymbolAlias(Operands))
1884 return MatchOperand_Success;
1885 }
1886 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1887 return MatchOperand_NoMatch;
1888 }
1889 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001890
Daniel Sanders21bce302014-04-01 12:35:23 +00001891 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001892 if (ResTy == MatchOperand_Success) {
1893 Parser.Lex(); // $
1894 Parser.Lex(); // identifier
1895 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001896 return ResTy;
1897}
1898
1899MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001900MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001901 switch (getLexer().getKind()) {
1902 default:
1903 return MatchOperand_NoMatch;
1904 case AsmToken::LParen:
1905 case AsmToken::Minus:
1906 case AsmToken::Plus:
1907 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001908 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001909 case AsmToken::String:
1910 break;
1911 }
1912
1913 const MCExpr *IdVal;
1914 SMLoc S = Parser.getTok().getLoc();
1915 if (getParser().parseExpression(IdVal))
1916 return MatchOperand_ParseFail;
1917
1918 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1919 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1920 return MatchOperand_Success;
1921}
1922
David Blaikie960ea3f2014-06-08 16:18:35 +00001923MipsAsmParser::OperandMatchResultTy
1924MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001925 DEBUG(dbgs() << "ParseJumpTarget\n");
1926
1927 SMLoc S = getLexer().getLoc();
1928
1929 // Integers and expressions are acceptable
1930 OperandMatchResultTy ResTy = ParseImm(Operands);
1931 if (ResTy != MatchOperand_NoMatch)
1932 return ResTy;
1933
Daniel Sanders315386c2014-04-01 10:40:14 +00001934 // Registers are a valid target and have priority over symbols.
1935 ResTy = ParseAnyRegister(Operands);
1936 if (ResTy != MatchOperand_NoMatch)
1937 return ResTy;
1938
Daniel Sandersffd84362014-04-01 10:41:48 +00001939 const MCExpr *Expr = nullptr;
1940 if (Parser.parseExpression(Expr)) {
1941 // We have no way of knowing if a symbol was consumed so we must ParseFail
1942 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001943 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001944 Operands.push_back(
1945 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001946 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001947}
1948
Vladimir Medic2b953d02013-10-01 09:48:56 +00001949MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001950MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001951 const MCExpr *IdVal;
1952 // If the first token is '$' we may have register operand.
1953 if (Parser.getTok().is(AsmToken::Dollar))
1954 return MatchOperand_NoMatch;
1955 SMLoc S = Parser.getTok().getLoc();
1956 if (getParser().parseExpression(IdVal))
1957 return MatchOperand_ParseFail;
1958 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001959 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001960 int64_t Val = MCE->getValue();
1961 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1962 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001963 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001964 return MatchOperand_Success;
1965}
1966
Matheus Almeida779c5932013-11-18 12:32:49 +00001967MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001968MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001969 switch (getLexer().getKind()) {
1970 default:
1971 return MatchOperand_NoMatch;
1972 case AsmToken::LParen:
1973 case AsmToken::Plus:
1974 case AsmToken::Minus:
1975 case AsmToken::Integer:
1976 break;
1977 }
1978
1979 const MCExpr *Expr;
1980 SMLoc S = Parser.getTok().getLoc();
1981
1982 if (getParser().parseExpression(Expr))
1983 return MatchOperand_ParseFail;
1984
1985 int64_t Val;
1986 if (!Expr->EvaluateAsAbsolute(Val)) {
1987 Error(S, "expected immediate value");
1988 return MatchOperand_ParseFail;
1989 }
1990
1991 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1992 // and because the CPU always adds one to the immediate field, the allowed
1993 // range becomes 1..4. We'll only check the range here and will deal
1994 // with the addition/subtraction when actually decoding/encoding
1995 // the instruction.
1996 if (Val < 1 || Val > 4) {
1997 Error(S, "immediate not in range (1..4)");
1998 return MatchOperand_ParseFail;
1999 }
2000
Jack Carter3b2c96e2014-01-22 23:31:38 +00002001 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002002 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002003 return MatchOperand_Success;
2004}
2005
Jack Carterdc1e35d2012-09-06 20:00:02 +00002006MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2007
Vladimir Medic4c299852013-11-06 11:27:05 +00002008 MCSymbolRefExpr::VariantKind VK =
2009 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2010 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2011 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2012 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2013 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2014 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2015 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2016 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2017 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2018 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2019 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2020 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2021 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2022 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2023 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2024 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2025 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2026 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002027 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2028 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2029 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2030 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2031 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2032 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002033 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2034 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002035 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002036
Matheus Almeida2852af82014-04-22 10:15:54 +00002037 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002038
Jack Carterdc1e35d2012-09-06 20:00:02 +00002039 return VK;
2040}
Jack Cartera63b16a2012-09-07 00:23:42 +00002041
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002042/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2043/// either this.
2044/// ::= '(', register, ')'
2045/// handle it before we iterate so we don't get tripped up by the lack of
2046/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002047bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002048 if (getLexer().is(AsmToken::LParen)) {
2049 Operands.push_back(
2050 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2051 Parser.Lex();
2052 if (ParseOperand(Operands, Name)) {
2053 SMLoc Loc = getLexer().getLoc();
2054 Parser.eatToEndOfStatement();
2055 return Error(Loc, "unexpected token in argument list");
2056 }
2057 if (Parser.getTok().isNot(AsmToken::RParen)) {
2058 SMLoc Loc = getLexer().getLoc();
2059 Parser.eatToEndOfStatement();
2060 return Error(Loc, "unexpected token, expected ')'");
2061 }
2062 Operands.push_back(
2063 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2064 Parser.Lex();
2065 }
2066 return false;
2067}
2068
2069/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2070/// either one of these.
2071/// ::= '[', register, ']'
2072/// ::= '[', integer, ']'
2073/// handle it before we iterate so we don't get tripped up by the lack of
2074/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002075bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2076 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002077 if (getLexer().is(AsmToken::LBrac)) {
2078 Operands.push_back(
2079 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2080 Parser.Lex();
2081 if (ParseOperand(Operands, Name)) {
2082 SMLoc Loc = getLexer().getLoc();
2083 Parser.eatToEndOfStatement();
2084 return Error(Loc, "unexpected token in argument list");
2085 }
2086 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2087 SMLoc Loc = getLexer().getLoc();
2088 Parser.eatToEndOfStatement();
2089 return Error(Loc, "unexpected token, expected ']'");
2090 }
2091 Operands.push_back(
2092 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2093 Parser.Lex();
2094 }
2095 return false;
2096}
2097
David Blaikie960ea3f2014-06-08 16:18:35 +00002098bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2099 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002100 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002101 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002102 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002103 Parser.eatToEndOfStatement();
2104 return Error(NameLoc, "Unknown instruction");
2105 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002106 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002107 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002108
2109 // Read the remaining operands.
2110 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2111 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002112 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002113 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002114 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002115 return Error(Loc, "unexpected token in argument list");
2116 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002117 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2118 return true;
2119 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002120
Jack Carterd0bd6422013-04-18 00:41:53 +00002121 while (getLexer().is(AsmToken::Comma)) {
2122 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002123 // Parse and remember the operand.
2124 if (ParseOperand(Operands, Name)) {
2125 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002126 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002127 return Error(Loc, "unexpected token in argument list");
2128 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002129 // Parse bracket and parenthesis suffixes before we iterate
2130 if (getLexer().is(AsmToken::LBrac)) {
2131 if (ParseBracketSuffix(Name, Operands))
2132 return true;
2133 } else if (getLexer().is(AsmToken::LParen) &&
2134 ParseParenSuffix(Name, Operands))
2135 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002136 }
2137 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002138 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2139 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002140 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002141 return Error(Loc, "unexpected token in argument list");
2142 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002143 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002144 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002145}
2146
Jack Carter0b744b32012-10-04 02:29:46 +00002147bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002148 SMLoc Loc = getLexer().getLoc();
2149 Parser.eatToEndOfStatement();
2150 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002151}
2152
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002153bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2154 return Error(Loc, ErrorMsg);
2155}
2156
Jack Carter0b744b32012-10-04 02:29:46 +00002157bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002158 // Line should look like: ".set noat".
2159 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002160 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002161 // eat noat
2162 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002163 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002164 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2165 reportParseError("unexpected token in statement");
2166 return false;
2167 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002168 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002169 return false;
2170}
Jack Carterd0bd6422013-04-18 00:41:53 +00002171
Jack Carter0b744b32012-10-04 02:29:46 +00002172bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002173 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002174 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002175 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002176 getParser().Lex();
2177 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002178 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002179 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002180 return false;
2181 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002182 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002183 if (getLexer().isNot(AsmToken::Dollar)) {
2184 reportParseError("unexpected token in statement");
2185 return false;
2186 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002187 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002188 const AsmToken &Reg = Parser.getTok();
2189 if (Reg.is(AsmToken::Identifier)) {
2190 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2191 } else if (Reg.is(AsmToken::Integer)) {
2192 AtRegNo = Reg.getIntVal();
2193 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002194 reportParseError("unexpected token in statement");
2195 return false;
2196 }
Jack Carter1ac53222013-02-20 23:11:17 +00002197
Daniel Sanders71a89d922014-03-25 13:01:06 +00002198 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002199 reportParseError("unexpected token in statement");
2200 return false;
2201 }
2202
2203 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002204 reportParseError("unexpected token in statement");
2205 return false;
2206 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002207 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002208
2209 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2210 reportParseError("unexpected token in statement");
2211 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002212 }
2213 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002214 return false;
2215 } else {
2216 reportParseError("unexpected token in statement");
2217 return false;
2218 }
2219}
2220
2221bool MipsAsmParser::parseSetReorderDirective() {
2222 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002223 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002224 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2225 reportParseError("unexpected token in statement");
2226 return false;
2227 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002228 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002229 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002230 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002231 return false;
2232}
2233
2234bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002235 Parser.Lex();
2236 // If this is not the end of the statement, report an error.
2237 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2238 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002239 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002240 }
2241 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002242 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002243 Parser.Lex(); // Consume the EndOfStatement.
2244 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002245}
2246
2247bool MipsAsmParser::parseSetMacroDirective() {
2248 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002249 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002250 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2251 reportParseError("unexpected token in statement");
2252 return false;
2253 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002254 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002255 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002256 return false;
2257}
2258
2259bool MipsAsmParser::parseSetNoMacroDirective() {
2260 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002261 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002262 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2263 reportParseError("`noreorder' must be set before `nomacro'");
2264 return false;
2265 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002266 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002267 reportParseError("`noreorder' must be set before `nomacro'");
2268 return false;
2269 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002270 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002271 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002272 return false;
2273}
Jack Carterd76b2372013-03-21 21:44:16 +00002274
Jack Carter39536722014-01-22 23:08:42 +00002275bool MipsAsmParser::parseSetNoMips16Directive() {
2276 Parser.Lex();
2277 // If this is not the end of the statement, report an error.
2278 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2279 reportParseError("unexpected token in statement");
2280 return false;
2281 }
2282 // For now do nothing.
2283 Parser.Lex(); // Consume the EndOfStatement.
2284 return false;
2285}
2286
Jack Carterd76b2372013-03-21 21:44:16 +00002287bool MipsAsmParser::parseSetAssignment() {
2288 StringRef Name;
2289 const MCExpr *Value;
2290
2291 if (Parser.parseIdentifier(Name))
2292 reportParseError("expected identifier after .set");
2293
2294 if (getLexer().isNot(AsmToken::Comma))
2295 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002296 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002297
Jack Carter3b2c96e2014-01-22 23:31:38 +00002298 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002299 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002300
Jack Carterd0bd6422013-04-18 00:41:53 +00002301 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002302 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002303 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002304 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002305 Sym = getContext().GetOrCreateSymbol(Name);
2306 Sym->setVariableValue(Value);
2307
2308 return false;
2309}
Jack Carterd0bd6422013-04-18 00:41:53 +00002310
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002311bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2312 Parser.Lex();
2313 if (getLexer().isNot(AsmToken::EndOfStatement))
2314 return reportParseError("unexpected token in .set directive");
2315
Matheus Almeida2852af82014-04-22 10:15:54 +00002316 switch (Feature) {
2317 default:
2318 llvm_unreachable("Unimplemented feature");
2319 case Mips::FeatureDSP:
2320 setFeatureBits(Mips::FeatureDSP, "dsp");
2321 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002322 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002323 case Mips::FeatureMicroMips:
2324 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002325 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002326 case Mips::FeatureMips16:
2327 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002328 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002329 case Mips::FeatureMips32r2:
2330 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2331 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002332 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002333 case Mips::FeatureMips64:
2334 setFeatureBits(Mips::FeatureMips64, "mips64");
2335 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002336 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002337 case Mips::FeatureMips64r2:
2338 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2339 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002340 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002341 }
2342 return false;
2343}
2344
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002345bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2346 if (getLexer().isNot(AsmToken::Comma)) {
2347 SMLoc Loc = getLexer().getLoc();
2348 Parser.eatToEndOfStatement();
2349 return Error(Loc, ErrorStr);
2350 }
2351
Matheus Almeida2852af82014-04-22 10:15:54 +00002352 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002353 return true;
2354}
2355
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002356bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2357 if (Options.isReorder())
2358 Warning(Loc, ".cpload in reorder section");
2359
2360 // FIXME: Warn if cpload is used in Mips16 mode.
2361
David Blaikie960ea3f2014-06-08 16:18:35 +00002362 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002363 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2364 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2365 reportParseError("expected register containing function address");
2366 return false;
2367 }
2368
David Blaikie960ea3f2014-06-08 16:18:35 +00002369 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2370 if (!RegOpnd.isGPRAsmReg()) {
2371 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002372 return false;
2373 }
2374
David Blaikie960ea3f2014-06-08 16:18:35 +00002375 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002376 return false;
2377}
2378
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002379bool MipsAsmParser::parseDirectiveCPSetup() {
2380 unsigned FuncReg;
2381 unsigned Save;
2382 bool SaveIsReg = true;
2383
Matheus Almeida7e815762014-06-18 13:08:59 +00002384 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2385 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2386 if (ResTy == MatchOperand_NoMatch) {
2387 reportParseError("expected register containing function address");
2388 Parser.eatToEndOfStatement();
2389 return false;
2390 }
2391
2392 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2393 if (!FuncRegOpnd.isGPRAsmReg()) {
2394 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2395 Parser.eatToEndOfStatement();
2396 return false;
2397 }
2398
2399 FuncReg = FuncRegOpnd.getGPR32Reg();
2400 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002401
2402 if (!eatComma("expected comma parsing directive"))
2403 return true;
2404
Matheus Almeida7e815762014-06-18 13:08:59 +00002405 ResTy = ParseAnyRegister(TmpReg);
2406 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002407 const AsmToken &Tok = Parser.getTok();
2408 if (Tok.is(AsmToken::Integer)) {
2409 Save = Tok.getIntVal();
2410 SaveIsReg = false;
2411 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002412 } else {
2413 reportParseError("expected save register or stack offset");
2414 Parser.eatToEndOfStatement();
2415 return false;
2416 }
2417 } else {
2418 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2419 if (!SaveOpnd.isGPRAsmReg()) {
2420 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2421 Parser.eatToEndOfStatement();
2422 return false;
2423 }
2424 Save = SaveOpnd.getGPR32Reg();
2425 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002426
2427 if (!eatComma("expected comma parsing directive"))
2428 return true;
2429
2430 StringRef Name;
2431 if (Parser.parseIdentifier(Name))
2432 reportParseError("expected identifier");
2433 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002434
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002435 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002436 return false;
2437}
2438
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002439bool MipsAsmParser::parseDirectiveNaN() {
2440 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2441 const AsmToken &Tok = Parser.getTok();
2442
2443 if (Tok.getString() == "2008") {
2444 Parser.Lex();
2445 getTargetStreamer().emitDirectiveNaN2008();
2446 return false;
2447 } else if (Tok.getString() == "legacy") {
2448 Parser.Lex();
2449 getTargetStreamer().emitDirectiveNaNLegacy();
2450 return false;
2451 }
2452 }
2453 // If we don't recognize the option passed to the .nan
2454 // directive (e.g. no option or unknown option), emit an error.
2455 reportParseError("invalid option in .nan directive");
2456 return false;
2457}
2458
Jack Carter0b744b32012-10-04 02:29:46 +00002459bool MipsAsmParser::parseDirectiveSet() {
2460
Jack Carterd0bd6422013-04-18 00:41:53 +00002461 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002462 const AsmToken &Tok = Parser.getTok();
2463
2464 if (Tok.getString() == "noat") {
2465 return parseSetNoAtDirective();
2466 } else if (Tok.getString() == "at") {
2467 return parseSetAtDirective();
2468 } else if (Tok.getString() == "reorder") {
2469 return parseSetReorderDirective();
2470 } else if (Tok.getString() == "noreorder") {
2471 return parseSetNoReorderDirective();
2472 } else if (Tok.getString() == "macro") {
2473 return parseSetMacroDirective();
2474 } else if (Tok.getString() == "nomacro") {
2475 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002476 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002477 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002478 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002479 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002480 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002481 getTargetStreamer().emitDirectiveSetNoMicroMips();
2482 Parser.eatToEndOfStatement();
2483 return false;
2484 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002485 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002486 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002487 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002488 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002489 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002490 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002491 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002492 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002493 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002494 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002495 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002496 parseSetAssignment();
2497 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002498 }
Jack Carter07c818d2013-01-25 01:31:34 +00002499
Jack Carter0b744b32012-10-04 02:29:46 +00002500 return true;
2501}
2502
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002503/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002504/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002505bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002506 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2507 for (;;) {
2508 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002509 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002510 return true;
2511
2512 getParser().getStreamer().EmitValue(Value, Size);
2513
2514 if (getLexer().is(AsmToken::EndOfStatement))
2515 break;
2516
2517 // FIXME: Improve diagnostic.
2518 if (getLexer().isNot(AsmToken::Comma))
2519 return Error(L, "unexpected token in directive");
2520 Parser.Lex();
2521 }
2522 }
2523
2524 Parser.Lex();
2525 return false;
2526}
2527
Vladimir Medic4c299852013-11-06 11:27:05 +00002528/// parseDirectiveGpWord
2529/// ::= .gpword local_sym
2530bool MipsAsmParser::parseDirectiveGpWord() {
2531 const MCExpr *Value;
2532 // EmitGPRel32Value requires an expression, so we are using base class
2533 // method to evaluate the expression.
2534 if (getParser().parseExpression(Value))
2535 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002536 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002537
Vladimir Medice10c1122013-11-13 13:18:04 +00002538 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002539 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002540 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002541 return false;
2542}
2543
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002544/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002545/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002546bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002547 const MCExpr *Value;
2548 // EmitGPRel64Value requires an expression, so we are using base class
2549 // method to evaluate the expression.
2550 if (getParser().parseExpression(Value))
2551 return true;
2552 getParser().getStreamer().EmitGPRel64Value(Value);
2553
2554 if (getLexer().isNot(AsmToken::EndOfStatement))
2555 return Error(getLexer().getLoc(), "unexpected token in directive");
2556 Parser.Lex(); // Eat EndOfStatement token.
2557 return false;
2558}
2559
Jack Carter0cd3c192014-01-06 23:27:31 +00002560bool MipsAsmParser::parseDirectiveOption() {
2561 // Get the option token.
2562 AsmToken Tok = Parser.getTok();
2563 // At the moment only identifiers are supported.
2564 if (Tok.isNot(AsmToken::Identifier)) {
2565 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2566 Parser.eatToEndOfStatement();
2567 return false;
2568 }
2569
2570 StringRef Option = Tok.getIdentifier();
2571
2572 if (Option == "pic0") {
2573 getTargetStreamer().emitDirectiveOptionPic0();
2574 Parser.Lex();
2575 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2576 Error(Parser.getTok().getLoc(),
2577 "unexpected token in .option pic0 directive");
2578 Parser.eatToEndOfStatement();
2579 }
2580 return false;
2581 }
2582
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002583 if (Option == "pic2") {
2584 getTargetStreamer().emitDirectiveOptionPic2();
2585 Parser.Lex();
2586 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2587 Error(Parser.getTok().getLoc(),
2588 "unexpected token in .option pic2 directive");
2589 Parser.eatToEndOfStatement();
2590 }
2591 return false;
2592 }
2593
Jack Carter0cd3c192014-01-06 23:27:31 +00002594 // Unknown option.
2595 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2596 Parser.eatToEndOfStatement();
2597 return false;
2598}
2599
Jack Carter0b744b32012-10-04 02:29:46 +00002600bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002601 StringRef IDVal = DirectiveID.getString();
2602
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002603 if (IDVal == ".cpload")
2604 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002605 if (IDVal == ".dword") {
2606 parseDataDirective(8, DirectiveID.getLoc());
2607 return false;
2608 }
2609
Jack Carterd0bd6422013-04-18 00:41:53 +00002610 if (IDVal == ".ent") {
2611 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002612 Parser.Lex();
2613 return false;
2614 }
2615
Jack Carter07c818d2013-01-25 01:31:34 +00002616 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002617 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002618 Parser.Lex();
2619 return false;
2620 }
2621
Jack Carter07c818d2013-01-25 01:31:34 +00002622 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002623 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002624 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002625 return false;
2626 }
2627
Jack Carter07c818d2013-01-25 01:31:34 +00002628 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002629 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002630 }
2631
Jack Carter07c818d2013-01-25 01:31:34 +00002632 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002633 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002634 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002635 return false;
2636 }
2637
Jack Carter07c818d2013-01-25 01:31:34 +00002638 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002639 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002640 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002641 return false;
2642 }
2643
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002644 if (IDVal == ".nan")
2645 return parseDirectiveNaN();
2646
Jack Carter07c818d2013-01-25 01:31:34 +00002647 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002648 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002649 return false;
2650 }
2651
Rafael Espindolab59fb732014-03-28 18:50:26 +00002652 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002653 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002654 return false;
2655 }
2656
Jack Carter07c818d2013-01-25 01:31:34 +00002657 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002658 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002659 return false;
2660 }
2661
Jack Carter0cd3c192014-01-06 23:27:31 +00002662 if (IDVal == ".option")
2663 return parseDirectiveOption();
2664
2665 if (IDVal == ".abicalls") {
2666 getTargetStreamer().emitDirectiveAbiCalls();
2667 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2668 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2669 // Clear line
2670 Parser.eatToEndOfStatement();
2671 }
2672 return false;
2673 }
2674
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002675 if (IDVal == ".cpsetup")
2676 return parseDirectiveCPSetup();
2677
Rafael Espindola870c4e92012-01-11 03:56:41 +00002678 return true;
2679}
2680
Rafael Espindola870c4e92012-01-11 03:56:41 +00002681extern "C" void LLVMInitializeMipsAsmParser() {
2682 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2683 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2684 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2685 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2686}
Jack Carterb4dbc172012-09-05 23:34:03 +00002687
2688#define GET_REGISTER_MATCHER
2689#define GET_MATCHER_IMPLEMENTATION
2690#include "MipsGenAsmMatcher.inc"