blob: 1c1a8265dee2781b7ed01c40dd77c79c4fa93ff9 [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:
1483 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001484 DEBUG(dbgs() << ".. generic integer\n");
1485 OperandMatchResultTy ResTy = ParseImm(Operands);
1486 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001487 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001488 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001489 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001490 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001491 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001492 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001493 return true;
1494
Jack Carter873c7242013-01-12 01:03:14 +00001495 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1496
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001497 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001498 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001499 } // case AsmToken::Percent
1500 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001501 return true;
1502}
1503
Vladimir Medic4c299852013-11-06 11:27:05 +00001504const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001505 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001506 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001507 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001508 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001509 // It's a constant, evaluate reloc value.
1510 int16_t Val;
1511 switch (getVariantKind(RelocStr)) {
1512 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1513 // Get the 1st 16-bits.
1514 Val = MCE->getValue() & 0xffff;
1515 break;
1516 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1517 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1518 // 16 bits being negative.
1519 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1520 break;
1521 case MCSymbolRefExpr::VK_Mips_HIGHER:
1522 // Get the 3rd 16-bits.
1523 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1524 break;
1525 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1526 // Get the 4th 16-bits.
1527 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1528 break;
1529 default:
1530 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001531 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001532 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001533 }
1534
Jack Carterb5cf5902013-04-17 00:18:04 +00001535 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001536 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001537 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001538 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001539 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001540 return Res;
1541 }
1542
1543 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001544 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1545
Sasa Stankovic06c47802014-04-03 10:37:45 +00001546 // Try to create target expression.
1547 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1548 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001549
Jack Carterd0bd6422013-04-18 00:41:53 +00001550 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1551 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001552 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1553 return Res;
1554 }
1555
1556 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001557 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1558 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1559 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001560 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001561 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001562 return Expr;
1563}
1564
1565bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1566
1567 switch (Expr->getKind()) {
1568 case MCExpr::Constant:
1569 return true;
1570 case MCExpr::SymbolRef:
1571 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1572 case MCExpr::Binary:
1573 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1574 if (!isEvaluated(BE->getLHS()))
1575 return false;
1576 return isEvaluated(BE->getRHS());
1577 }
1578 case MCExpr::Unary:
1579 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001580 case MCExpr::Target:
1581 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001582 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001583 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001584}
Jack Carterd0bd6422013-04-18 00:41:53 +00001585
Jack Carterb5cf5902013-04-17 00:18:04 +00001586bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001587 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001588 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001589 if (Tok.isNot(AsmToken::Identifier))
1590 return true;
1591
1592 std::string Str = Tok.getIdentifier().str();
1593
Jack Carterd0bd6422013-04-18 00:41:53 +00001594 Parser.Lex(); // Eat the identifier.
1595 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001596 const MCExpr *IdVal;
1597 SMLoc EndLoc;
1598
1599 if (getLexer().getKind() == AsmToken::LParen) {
1600 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001601 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001602 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001604 const AsmToken &nextTok = Parser.getTok();
1605 if (nextTok.isNot(AsmToken::Identifier))
1606 return true;
1607 Str += "(%";
1608 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001609 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001610 if (getLexer().getKind() != AsmToken::LParen)
1611 return true;
1612 } else
1613 break;
1614 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001615 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001616 return true;
1617
1618 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001620
1621 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001623
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001625 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001626}
1627
Jack Carterb4dbc172012-09-05 23:34:03 +00001628bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1629 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001630 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1632 if (ResTy == MatchOperand_Success) {
1633 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001634 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001635 StartLoc = Operand.getStartLoc();
1636 EndLoc = Operand.getEndLoc();
1637
1638 // AFAIK, we only support numeric registers and named GPR's in CFI
1639 // directives.
1640 // Don't worry about eating tokens before failing. Using an unrecognised
1641 // register is a parse error.
1642 if (Operand.isGPRAsmReg()) {
1643 // Resolve to GPR32 or GPR64 appropriately.
1644 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1645 }
1646
1647 return (RegNo == (unsigned)-1);
1648 }
1649
1650 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001651 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001652}
1653
Jack Carterb5cf5902013-04-17 00:18:04 +00001654bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001655 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001656 bool Result = true;
1657
1658 while (getLexer().getKind() == AsmToken::LParen)
1659 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001660
Jack Carterd0bd6422013-04-18 00:41:53 +00001661 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001662 default:
1663 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001664 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001665 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001666 case AsmToken::Integer:
1667 case AsmToken::Minus:
1668 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001669 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001670 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001671 else
1672 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001673 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001674 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001675 break;
Jack Carter873c7242013-01-12 01:03:14 +00001676 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001677 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001678 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001679 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001680}
1681
David Blaikie960ea3f2014-06-08 16:18:35 +00001682MipsAsmParser::OperandMatchResultTy
1683MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001684 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001685 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001686 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001687 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001688 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001689 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001690 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001691
Jack Carterb5cf5902013-04-17 00:18:04 +00001692 if (getLexer().getKind() == AsmToken::LParen) {
1693 Parser.Lex();
1694 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001695 }
1696
Jack Carterb5cf5902013-04-17 00:18:04 +00001697 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001698 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001699 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001700
Jack Carterd0bd6422013-04-18 00:41:53 +00001701 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001702 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001703 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1704 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001705 SMLoc E =
1706 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001707 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001708 return MatchOperand_Success;
1709 }
1710 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001711 SMLoc E =
1712 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001713
Jack Carterd0bd6422013-04-18 00:41:53 +00001714 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001715 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001716 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1717 S, E, *this);
1718 Operands.push_back(
1719 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001720 return MatchOperand_Success;
1721 }
1722 Error(Parser.getTok().getLoc(), "'(' expected");
1723 return MatchOperand_ParseFail;
1724 }
1725
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001727 }
1728
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001729 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001730 if (Res != MatchOperand_Success)
1731 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001732
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001733 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001734 Error(Parser.getTok().getLoc(), "')' expected");
1735 return MatchOperand_ParseFail;
1736 }
1737
Jack Carter873c7242013-01-12 01:03:14 +00001738 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1739
Jack Carterd0bd6422013-04-18 00:41:53 +00001740 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001741
Craig Topper062a2ba2014-04-25 05:30:21 +00001742 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001743 IdVal = MCConstantExpr::Create(0, getContext());
1744
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001746 std::unique_ptr<MipsOperand> op(
1747 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001748 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001749 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001750 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001751 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001752 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1753 int64_t Imm;
1754 if (IdVal->EvaluateAsAbsolute(Imm))
1755 IdVal = MCConstantExpr::Create(Imm, getContext());
1756 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1757 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1758 getContext());
1759 }
1760
David Blaikie960ea3f2014-06-08 16:18:35 +00001761 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001762 return MatchOperand_Success;
1763}
1764
David Blaikie960ea3f2014-06-08 16:18:35 +00001765bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001766
Jack Carterd76b2372013-03-21 21:44:16 +00001767 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1768 if (Sym) {
1769 SMLoc S = Parser.getTok().getLoc();
1770 const MCExpr *Expr;
1771 if (Sym->isVariable())
1772 Expr = Sym->getVariableValue();
1773 else
1774 return false;
1775 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001776 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001777 const StringRef DefSymbol = Ref->getSymbol().getName();
1778 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001779 OperandMatchResultTy ResTy =
1780 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001781 if (ResTy == MatchOperand_Success) {
1782 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001783 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001784 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001785 llvm_unreachable("Should never ParseFail");
1786 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001787 }
1788 } else if (Expr->getKind() == MCExpr::Constant) {
1789 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001790 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001791 Operands.push_back(
1792 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001793 return true;
1794 }
1795 }
1796 return false;
1797}
Jack Carterd0bd6422013-04-18 00:41:53 +00001798
Jack Carter873c7242013-01-12 01:03:14 +00001799MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001800MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1801 StringRef Identifier,
1802 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001803 int Index = matchCPURegisterName(Identifier);
1804 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001805 Operands.push_back(MipsOperand::CreateGPRReg(
1806 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1807 return MatchOperand_Success;
1808 }
1809
1810 Index = matchFPURegisterName(Identifier);
1811 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001812 Operands.push_back(MipsOperand::CreateFGRReg(
1813 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1814 return MatchOperand_Success;
1815 }
1816
1817 Index = matchFCCRegisterName(Identifier);
1818 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001819 Operands.push_back(MipsOperand::CreateFCCReg(
1820 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1821 return MatchOperand_Success;
1822 }
1823
1824 Index = matchACRegisterName(Identifier);
1825 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001826 Operands.push_back(MipsOperand::CreateACCReg(
1827 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1828 return MatchOperand_Success;
1829 }
1830
1831 Index = matchMSA128RegisterName(Identifier);
1832 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001833 Operands.push_back(MipsOperand::CreateMSA128Reg(
1834 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1835 return MatchOperand_Success;
1836 }
1837
1838 Index = matchMSA128CtrlRegisterName(Identifier);
1839 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001840 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1841 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1842 return MatchOperand_Success;
1843 }
1844
1845 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001846}
1847
1848MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001849MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001850 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001851
1852 if (Token.is(AsmToken::Identifier)) {
1853 DEBUG(dbgs() << ".. identifier\n");
1854 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001855 OperandMatchResultTy ResTy =
1856 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001857 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001858 } else if (Token.is(AsmToken::Integer)) {
1859 DEBUG(dbgs() << ".. integer\n");
1860 Operands.push_back(MipsOperand::CreateNumericReg(
1861 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1862 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001863 return MatchOperand_Success;
1864 }
1865
1866 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1867
1868 return MatchOperand_NoMatch;
1869}
1870
David Blaikie960ea3f2014-06-08 16:18:35 +00001871MipsAsmParser::OperandMatchResultTy
1872MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001873 DEBUG(dbgs() << "ParseAnyRegister\n");
1874
1875 auto Token = Parser.getTok();
1876
1877 SMLoc S = Token.getLoc();
1878
1879 if (Token.isNot(AsmToken::Dollar)) {
1880 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1881 if (Token.is(AsmToken::Identifier)) {
1882 if (searchSymbolAlias(Operands))
1883 return MatchOperand_Success;
1884 }
1885 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1886 return MatchOperand_NoMatch;
1887 }
1888 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001889
Daniel Sanders21bce302014-04-01 12:35:23 +00001890 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001891 if (ResTy == MatchOperand_Success) {
1892 Parser.Lex(); // $
1893 Parser.Lex(); // identifier
1894 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001895 return ResTy;
1896}
1897
1898MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001899MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001900 switch (getLexer().getKind()) {
1901 default:
1902 return MatchOperand_NoMatch;
1903 case AsmToken::LParen:
1904 case AsmToken::Minus:
1905 case AsmToken::Plus:
1906 case AsmToken::Integer:
1907 case AsmToken::String:
1908 break;
1909 }
1910
1911 const MCExpr *IdVal;
1912 SMLoc S = Parser.getTok().getLoc();
1913 if (getParser().parseExpression(IdVal))
1914 return MatchOperand_ParseFail;
1915
1916 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1917 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1918 return MatchOperand_Success;
1919}
1920
David Blaikie960ea3f2014-06-08 16:18:35 +00001921MipsAsmParser::OperandMatchResultTy
1922MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001923 DEBUG(dbgs() << "ParseJumpTarget\n");
1924
1925 SMLoc S = getLexer().getLoc();
1926
1927 // Integers and expressions are acceptable
1928 OperandMatchResultTy ResTy = ParseImm(Operands);
1929 if (ResTy != MatchOperand_NoMatch)
1930 return ResTy;
1931
Daniel Sanders315386c2014-04-01 10:40:14 +00001932 // Registers are a valid target and have priority over symbols.
1933 ResTy = ParseAnyRegister(Operands);
1934 if (ResTy != MatchOperand_NoMatch)
1935 return ResTy;
1936
Daniel Sandersffd84362014-04-01 10:41:48 +00001937 const MCExpr *Expr = nullptr;
1938 if (Parser.parseExpression(Expr)) {
1939 // We have no way of knowing if a symbol was consumed so we must ParseFail
1940 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001941 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001942 Operands.push_back(
1943 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001944 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001945}
1946
Vladimir Medic2b953d02013-10-01 09:48:56 +00001947MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001948MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001949 const MCExpr *IdVal;
1950 // If the first token is '$' we may have register operand.
1951 if (Parser.getTok().is(AsmToken::Dollar))
1952 return MatchOperand_NoMatch;
1953 SMLoc S = Parser.getTok().getLoc();
1954 if (getParser().parseExpression(IdVal))
1955 return MatchOperand_ParseFail;
1956 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001957 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001958 int64_t Val = MCE->getValue();
1959 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1960 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001961 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001962 return MatchOperand_Success;
1963}
1964
Matheus Almeida779c5932013-11-18 12:32:49 +00001965MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001966MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001967 switch (getLexer().getKind()) {
1968 default:
1969 return MatchOperand_NoMatch;
1970 case AsmToken::LParen:
1971 case AsmToken::Plus:
1972 case AsmToken::Minus:
1973 case AsmToken::Integer:
1974 break;
1975 }
1976
1977 const MCExpr *Expr;
1978 SMLoc S = Parser.getTok().getLoc();
1979
1980 if (getParser().parseExpression(Expr))
1981 return MatchOperand_ParseFail;
1982
1983 int64_t Val;
1984 if (!Expr->EvaluateAsAbsolute(Val)) {
1985 Error(S, "expected immediate value");
1986 return MatchOperand_ParseFail;
1987 }
1988
1989 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1990 // and because the CPU always adds one to the immediate field, the allowed
1991 // range becomes 1..4. We'll only check the range here and will deal
1992 // with the addition/subtraction when actually decoding/encoding
1993 // the instruction.
1994 if (Val < 1 || Val > 4) {
1995 Error(S, "immediate not in range (1..4)");
1996 return MatchOperand_ParseFail;
1997 }
1998
Jack Carter3b2c96e2014-01-22 23:31:38 +00001999 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002000 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002001 return MatchOperand_Success;
2002}
2003
Jack Carterdc1e35d2012-09-06 20:00:02 +00002004MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2005
Vladimir Medic4c299852013-11-06 11:27:05 +00002006 MCSymbolRefExpr::VariantKind VK =
2007 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2008 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2009 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2010 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2011 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2012 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2013 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2014 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2015 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2016 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2017 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2018 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2019 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2020 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2021 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2022 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2023 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2024 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002025 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2026 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2027 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2028 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2029 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2030 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002031 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2032 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002033 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002034
Matheus Almeida2852af82014-04-22 10:15:54 +00002035 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002036
Jack Carterdc1e35d2012-09-06 20:00:02 +00002037 return VK;
2038}
Jack Cartera63b16a2012-09-07 00:23:42 +00002039
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002040/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2041/// either this.
2042/// ::= '(', register, ')'
2043/// handle it before we iterate so we don't get tripped up by the lack of
2044/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002045bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002046 if (getLexer().is(AsmToken::LParen)) {
2047 Operands.push_back(
2048 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2049 Parser.Lex();
2050 if (ParseOperand(Operands, Name)) {
2051 SMLoc Loc = getLexer().getLoc();
2052 Parser.eatToEndOfStatement();
2053 return Error(Loc, "unexpected token in argument list");
2054 }
2055 if (Parser.getTok().isNot(AsmToken::RParen)) {
2056 SMLoc Loc = getLexer().getLoc();
2057 Parser.eatToEndOfStatement();
2058 return Error(Loc, "unexpected token, expected ')'");
2059 }
2060 Operands.push_back(
2061 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2062 Parser.Lex();
2063 }
2064 return false;
2065}
2066
2067/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2068/// either one of these.
2069/// ::= '[', register, ']'
2070/// ::= '[', integer, ']'
2071/// handle it before we iterate so we don't get tripped up by the lack of
2072/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002073bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2074 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002075 if (getLexer().is(AsmToken::LBrac)) {
2076 Operands.push_back(
2077 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2078 Parser.Lex();
2079 if (ParseOperand(Operands, Name)) {
2080 SMLoc Loc = getLexer().getLoc();
2081 Parser.eatToEndOfStatement();
2082 return Error(Loc, "unexpected token in argument list");
2083 }
2084 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2085 SMLoc Loc = getLexer().getLoc();
2086 Parser.eatToEndOfStatement();
2087 return Error(Loc, "unexpected token, expected ']'");
2088 }
2089 Operands.push_back(
2090 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2091 Parser.Lex();
2092 }
2093 return false;
2094}
2095
David Blaikie960ea3f2014-06-08 16:18:35 +00002096bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2097 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002098 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002099 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002100 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002101 Parser.eatToEndOfStatement();
2102 return Error(NameLoc, "Unknown instruction");
2103 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002104 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002105 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002106
2107 // Read the remaining operands.
2108 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2109 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002110 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002111 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002112 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002113 return Error(Loc, "unexpected token in argument list");
2114 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002115 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2116 return true;
2117 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002118
Jack Carterd0bd6422013-04-18 00:41:53 +00002119 while (getLexer().is(AsmToken::Comma)) {
2120 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002121 // Parse and remember the operand.
2122 if (ParseOperand(Operands, Name)) {
2123 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002124 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002125 return Error(Loc, "unexpected token in argument list");
2126 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002127 // Parse bracket and parenthesis suffixes before we iterate
2128 if (getLexer().is(AsmToken::LBrac)) {
2129 if (ParseBracketSuffix(Name, Operands))
2130 return true;
2131 } else if (getLexer().is(AsmToken::LParen) &&
2132 ParseParenSuffix(Name, Operands))
2133 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002134 }
2135 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002136 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2137 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002138 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002139 return Error(Loc, "unexpected token in argument list");
2140 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002141 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002142 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002143}
2144
Jack Carter0b744b32012-10-04 02:29:46 +00002145bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002146 SMLoc Loc = getLexer().getLoc();
2147 Parser.eatToEndOfStatement();
2148 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002149}
2150
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002151bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2152 return Error(Loc, ErrorMsg);
2153}
2154
Jack Carter0b744b32012-10-04 02:29:46 +00002155bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002156 // Line should look like: ".set noat".
2157 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002158 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002159 // eat noat
2160 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002161 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002162 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2163 reportParseError("unexpected token in statement");
2164 return false;
2165 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002166 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002167 return false;
2168}
Jack Carterd0bd6422013-04-18 00:41:53 +00002169
Jack Carter0b744b32012-10-04 02:29:46 +00002170bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002171 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002172 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002173 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002174 getParser().Lex();
2175 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002176 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002177 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002178 return false;
2179 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002180 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002181 if (getLexer().isNot(AsmToken::Dollar)) {
2182 reportParseError("unexpected token in statement");
2183 return false;
2184 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002185 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002186 const AsmToken &Reg = Parser.getTok();
2187 if (Reg.is(AsmToken::Identifier)) {
2188 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2189 } else if (Reg.is(AsmToken::Integer)) {
2190 AtRegNo = Reg.getIntVal();
2191 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002192 reportParseError("unexpected token in statement");
2193 return false;
2194 }
Jack Carter1ac53222013-02-20 23:11:17 +00002195
Daniel Sanders71a89d922014-03-25 13:01:06 +00002196 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002197 reportParseError("unexpected token in statement");
2198 return false;
2199 }
2200
2201 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002202 reportParseError("unexpected token in statement");
2203 return false;
2204 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002205 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002206
2207 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2208 reportParseError("unexpected token in statement");
2209 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002210 }
2211 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002212 return false;
2213 } else {
2214 reportParseError("unexpected token in statement");
2215 return false;
2216 }
2217}
2218
2219bool MipsAsmParser::parseSetReorderDirective() {
2220 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002221 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002222 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2223 reportParseError("unexpected token in statement");
2224 return false;
2225 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002226 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002227 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002228 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002229 return false;
2230}
2231
2232bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002233 Parser.Lex();
2234 // If this is not the end of the statement, report an error.
2235 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2236 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002237 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002238 }
2239 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002240 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002241 Parser.Lex(); // Consume the EndOfStatement.
2242 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002243}
2244
2245bool MipsAsmParser::parseSetMacroDirective() {
2246 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002247 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002248 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2249 reportParseError("unexpected token in statement");
2250 return false;
2251 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002252 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002253 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002254 return false;
2255}
2256
2257bool MipsAsmParser::parseSetNoMacroDirective() {
2258 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002259 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002260 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2261 reportParseError("`noreorder' must be set before `nomacro'");
2262 return false;
2263 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002264 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002265 reportParseError("`noreorder' must be set before `nomacro'");
2266 return false;
2267 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002268 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002269 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002270 return false;
2271}
Jack Carterd76b2372013-03-21 21:44:16 +00002272
Jack Carter39536722014-01-22 23:08:42 +00002273bool MipsAsmParser::parseSetNoMips16Directive() {
2274 Parser.Lex();
2275 // If this is not the end of the statement, report an error.
2276 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2277 reportParseError("unexpected token in statement");
2278 return false;
2279 }
2280 // For now do nothing.
2281 Parser.Lex(); // Consume the EndOfStatement.
2282 return false;
2283}
2284
Jack Carterd76b2372013-03-21 21:44:16 +00002285bool MipsAsmParser::parseSetAssignment() {
2286 StringRef Name;
2287 const MCExpr *Value;
2288
2289 if (Parser.parseIdentifier(Name))
2290 reportParseError("expected identifier after .set");
2291
2292 if (getLexer().isNot(AsmToken::Comma))
2293 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002294 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002295
Jack Carter3b2c96e2014-01-22 23:31:38 +00002296 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002297 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002298
Jack Carterd0bd6422013-04-18 00:41:53 +00002299 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002300 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002301 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002302 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002303 Sym = getContext().GetOrCreateSymbol(Name);
2304 Sym->setVariableValue(Value);
2305
2306 return false;
2307}
Jack Carterd0bd6422013-04-18 00:41:53 +00002308
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002309bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2310 Parser.Lex();
2311 if (getLexer().isNot(AsmToken::EndOfStatement))
2312 return reportParseError("unexpected token in .set directive");
2313
Matheus Almeida2852af82014-04-22 10:15:54 +00002314 switch (Feature) {
2315 default:
2316 llvm_unreachable("Unimplemented feature");
2317 case Mips::FeatureDSP:
2318 setFeatureBits(Mips::FeatureDSP, "dsp");
2319 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002320 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002321 case Mips::FeatureMicroMips:
2322 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002323 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002324 case Mips::FeatureMips16:
2325 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002326 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002327 case Mips::FeatureMips32r2:
2328 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2329 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002330 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002331 case Mips::FeatureMips64:
2332 setFeatureBits(Mips::FeatureMips64, "mips64");
2333 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002334 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002335 case Mips::FeatureMips64r2:
2336 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2337 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002338 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002339 }
2340 return false;
2341}
2342
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002343bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2344 if (getLexer().isNot(AsmToken::Comma)) {
2345 SMLoc Loc = getLexer().getLoc();
2346 Parser.eatToEndOfStatement();
2347 return Error(Loc, ErrorStr);
2348 }
2349
Matheus Almeida2852af82014-04-22 10:15:54 +00002350 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002351 return true;
2352}
2353
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002354bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2355 if (Options.isReorder())
2356 Warning(Loc, ".cpload in reorder section");
2357
2358 // FIXME: Warn if cpload is used in Mips16 mode.
2359
David Blaikie960ea3f2014-06-08 16:18:35 +00002360 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002361 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2362 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2363 reportParseError("expected register containing function address");
2364 return false;
2365 }
2366
David Blaikie960ea3f2014-06-08 16:18:35 +00002367 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2368 if (!RegOpnd.isGPRAsmReg()) {
2369 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002370 return false;
2371 }
2372
David Blaikie960ea3f2014-06-08 16:18:35 +00002373 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002374 return false;
2375}
2376
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002377bool MipsAsmParser::parseDirectiveCPSetup() {
2378 unsigned FuncReg;
2379 unsigned Save;
2380 bool SaveIsReg = true;
2381
Matheus Almeida7e815762014-06-18 13:08:59 +00002382 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2383 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2384 if (ResTy == MatchOperand_NoMatch) {
2385 reportParseError("expected register containing function address");
2386 Parser.eatToEndOfStatement();
2387 return false;
2388 }
2389
2390 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2391 if (!FuncRegOpnd.isGPRAsmReg()) {
2392 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2393 Parser.eatToEndOfStatement();
2394 return false;
2395 }
2396
2397 FuncReg = FuncRegOpnd.getGPR32Reg();
2398 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002399
2400 if (!eatComma("expected comma parsing directive"))
2401 return true;
2402
Matheus Almeida7e815762014-06-18 13:08:59 +00002403 ResTy = ParseAnyRegister(TmpReg);
2404 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002405 const AsmToken &Tok = Parser.getTok();
2406 if (Tok.is(AsmToken::Integer)) {
2407 Save = Tok.getIntVal();
2408 SaveIsReg = false;
2409 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002410 } else {
2411 reportParseError("expected save register or stack offset");
2412 Parser.eatToEndOfStatement();
2413 return false;
2414 }
2415 } else {
2416 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2417 if (!SaveOpnd.isGPRAsmReg()) {
2418 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2419 Parser.eatToEndOfStatement();
2420 return false;
2421 }
2422 Save = SaveOpnd.getGPR32Reg();
2423 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002424
2425 if (!eatComma("expected comma parsing directive"))
2426 return true;
2427
2428 StringRef Name;
2429 if (Parser.parseIdentifier(Name))
2430 reportParseError("expected identifier");
2431 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002432
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002433 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002434 return false;
2435}
2436
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002437bool MipsAsmParser::parseDirectiveNaN() {
2438 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2439 const AsmToken &Tok = Parser.getTok();
2440
2441 if (Tok.getString() == "2008") {
2442 Parser.Lex();
2443 getTargetStreamer().emitDirectiveNaN2008();
2444 return false;
2445 } else if (Tok.getString() == "legacy") {
2446 Parser.Lex();
2447 getTargetStreamer().emitDirectiveNaNLegacy();
2448 return false;
2449 }
2450 }
2451 // If we don't recognize the option passed to the .nan
2452 // directive (e.g. no option or unknown option), emit an error.
2453 reportParseError("invalid option in .nan directive");
2454 return false;
2455}
2456
Jack Carter0b744b32012-10-04 02:29:46 +00002457bool MipsAsmParser::parseDirectiveSet() {
2458
Jack Carterd0bd6422013-04-18 00:41:53 +00002459 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002460 const AsmToken &Tok = Parser.getTok();
2461
2462 if (Tok.getString() == "noat") {
2463 return parseSetNoAtDirective();
2464 } else if (Tok.getString() == "at") {
2465 return parseSetAtDirective();
2466 } else if (Tok.getString() == "reorder") {
2467 return parseSetReorderDirective();
2468 } else if (Tok.getString() == "noreorder") {
2469 return parseSetNoReorderDirective();
2470 } else if (Tok.getString() == "macro") {
2471 return parseSetMacroDirective();
2472 } else if (Tok.getString() == "nomacro") {
2473 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002474 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002475 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002476 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002477 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002478 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002479 getTargetStreamer().emitDirectiveSetNoMicroMips();
2480 Parser.eatToEndOfStatement();
2481 return false;
2482 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002483 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002484 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002485 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002486 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002487 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002488 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002489 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002490 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002491 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002492 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002493 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002494 parseSetAssignment();
2495 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002496 }
Jack Carter07c818d2013-01-25 01:31:34 +00002497
Jack Carter0b744b32012-10-04 02:29:46 +00002498 return true;
2499}
2500
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002501/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002502/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002503bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002504 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2505 for (;;) {
2506 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002507 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002508 return true;
2509
2510 getParser().getStreamer().EmitValue(Value, Size);
2511
2512 if (getLexer().is(AsmToken::EndOfStatement))
2513 break;
2514
2515 // FIXME: Improve diagnostic.
2516 if (getLexer().isNot(AsmToken::Comma))
2517 return Error(L, "unexpected token in directive");
2518 Parser.Lex();
2519 }
2520 }
2521
2522 Parser.Lex();
2523 return false;
2524}
2525
Vladimir Medic4c299852013-11-06 11:27:05 +00002526/// parseDirectiveGpWord
2527/// ::= .gpword local_sym
2528bool MipsAsmParser::parseDirectiveGpWord() {
2529 const MCExpr *Value;
2530 // EmitGPRel32Value requires an expression, so we are using base class
2531 // method to evaluate the expression.
2532 if (getParser().parseExpression(Value))
2533 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002534 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002535
Vladimir Medice10c1122013-11-13 13:18:04 +00002536 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002537 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002538 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002539 return false;
2540}
2541
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002542/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002543/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002544bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002545 const MCExpr *Value;
2546 // EmitGPRel64Value requires an expression, so we are using base class
2547 // method to evaluate the expression.
2548 if (getParser().parseExpression(Value))
2549 return true;
2550 getParser().getStreamer().EmitGPRel64Value(Value);
2551
2552 if (getLexer().isNot(AsmToken::EndOfStatement))
2553 return Error(getLexer().getLoc(), "unexpected token in directive");
2554 Parser.Lex(); // Eat EndOfStatement token.
2555 return false;
2556}
2557
Jack Carter0cd3c192014-01-06 23:27:31 +00002558bool MipsAsmParser::parseDirectiveOption() {
2559 // Get the option token.
2560 AsmToken Tok = Parser.getTok();
2561 // At the moment only identifiers are supported.
2562 if (Tok.isNot(AsmToken::Identifier)) {
2563 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2564 Parser.eatToEndOfStatement();
2565 return false;
2566 }
2567
2568 StringRef Option = Tok.getIdentifier();
2569
2570 if (Option == "pic0") {
2571 getTargetStreamer().emitDirectiveOptionPic0();
2572 Parser.Lex();
2573 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2574 Error(Parser.getTok().getLoc(),
2575 "unexpected token in .option pic0 directive");
2576 Parser.eatToEndOfStatement();
2577 }
2578 return false;
2579 }
2580
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002581 if (Option == "pic2") {
2582 getTargetStreamer().emitDirectiveOptionPic2();
2583 Parser.Lex();
2584 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2585 Error(Parser.getTok().getLoc(),
2586 "unexpected token in .option pic2 directive");
2587 Parser.eatToEndOfStatement();
2588 }
2589 return false;
2590 }
2591
Jack Carter0cd3c192014-01-06 23:27:31 +00002592 // Unknown option.
2593 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2594 Parser.eatToEndOfStatement();
2595 return false;
2596}
2597
Jack Carter0b744b32012-10-04 02:29:46 +00002598bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002599 StringRef IDVal = DirectiveID.getString();
2600
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002601 if (IDVal == ".cpload")
2602 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002603 if (IDVal == ".dword") {
2604 parseDataDirective(8, DirectiveID.getLoc());
2605 return false;
2606 }
2607
Jack Carterd0bd6422013-04-18 00:41:53 +00002608 if (IDVal == ".ent") {
2609 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002610 Parser.Lex();
2611 return false;
2612 }
2613
Jack Carter07c818d2013-01-25 01:31:34 +00002614 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002615 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002616 Parser.Lex();
2617 return false;
2618 }
2619
Jack Carter07c818d2013-01-25 01:31:34 +00002620 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002621 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002622 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002623 return false;
2624 }
2625
Jack Carter07c818d2013-01-25 01:31:34 +00002626 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002627 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002628 }
2629
Jack Carter07c818d2013-01-25 01:31:34 +00002630 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002631 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002632 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002633 return false;
2634 }
2635
Jack Carter07c818d2013-01-25 01:31:34 +00002636 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002637 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002638 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002639 return false;
2640 }
2641
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002642 if (IDVal == ".nan")
2643 return parseDirectiveNaN();
2644
Jack Carter07c818d2013-01-25 01:31:34 +00002645 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002646 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002647 return false;
2648 }
2649
Rafael Espindolab59fb732014-03-28 18:50:26 +00002650 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002651 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002652 return false;
2653 }
2654
Jack Carter07c818d2013-01-25 01:31:34 +00002655 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002656 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002657 return false;
2658 }
2659
Jack Carter0cd3c192014-01-06 23:27:31 +00002660 if (IDVal == ".option")
2661 return parseDirectiveOption();
2662
2663 if (IDVal == ".abicalls") {
2664 getTargetStreamer().emitDirectiveAbiCalls();
2665 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2666 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2667 // Clear line
2668 Parser.eatToEndOfStatement();
2669 }
2670 return false;
2671 }
2672
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002673 if (IDVal == ".cpsetup")
2674 return parseDirectiveCPSetup();
2675
Rafael Espindola870c4e92012-01-11 03:56:41 +00002676 return true;
2677}
2678
Rafael Espindola870c4e92012-01-11 03:56:41 +00002679extern "C" void LLVMInitializeMipsAsmParser() {
2680 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2681 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2682 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2683 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2684}
Jack Carterb4dbc172012-09-05 23:34:03 +00002685
2686#define GET_REGISTER_MATCHER
2687#define GET_MATCHER_IMPLEMENTATION
2688#include "MipsGenAsmMatcher.inc"