blob: 3133a51b3f9e833d59da02653383fe8403a06bed [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 parseRegister(unsigned &RegNum);
187
188 bool eatComma(StringRef ErrorStr);
189
Jack Carter1ac53222013-02-20 23:11:17 +0000190 int matchCPURegisterName(StringRef Symbol);
191
Jack Carter873c7242013-01-12 01:03:14 +0000192 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000193
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000194 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000195
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000196 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000197
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000198 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000199
Jack Carter5dc8ac92013-09-25 23:50:44 +0000200 int matchMSA128RegisterName(StringRef Name);
201
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000202 int matchMSA128CtrlRegisterName(StringRef Name);
203
Jack Carterd0bd6422013-04-18 00:41:53 +0000204 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000205
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000206 unsigned getGPR(int RegNo);
207
Jack Carter1ac53222013-02-20 23:11:17 +0000208 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000209
210 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000211 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000212
213 // Helper function that checks if the value of a vector index is within the
214 // boundaries of accepted values for each RegisterKind
215 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
216 bool validateMSAIndex(int Val, int RegKind);
217
Vladimir Medic615b26e2014-03-04 09:54:09 +0000218 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
219 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000220 setAvailableFeatures(
221 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000222 }
223 }
224
225 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
226 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000227 setAvailableFeatures(
228 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000229 }
230 }
231
Rafael Espindola870c4e92012-01-11 03:56:41 +0000232public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000233 enum MipsMatchResultTy {
234 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
235#define GET_OPERAND_DIAGNOSTIC_TYPES
236#include "MipsGenAsmMatcher.inc"
237#undef GET_OPERAND_DIAGNOSTIC_TYPES
238
239 };
240
Joey Gouly0e76fa72013-09-12 10:28:05 +0000241 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000242 const MCInstrInfo &MII,
243 const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000244 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000245 // Initialize the set of available features.
246 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000247
248 // Assert exactly one ABI was chosen.
249 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
250 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
251 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
252 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000253 }
254
Jack Carterb4dbc172012-09-05 23:34:03 +0000255 MCAsmParser &getParser() const { return Parser; }
256 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000257
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000258 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
259 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
260
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000261 /// Warn if RegNo is the current assembler temporary.
262 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000263};
264}
265
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000266namespace {
267
268/// MipsOperand - Instances of this class represent a parsed Mips machine
269/// instruction.
270class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000271public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000272 /// Broad categories of register classes
273 /// The exact class is finalized by the render method.
274 enum RegKind {
275 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
276 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
277 /// isFP64())
278 RegKind_FCC = 4, /// FCC
279 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
280 RegKind_MSACtrl = 16, /// MSA control registers
281 RegKind_COP2 = 32, /// COP2
282 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
283 /// context).
284 RegKind_CCR = 128, /// CCR
285 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000286 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000287
288 /// Potentially any (e.g. $1)
289 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
290 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000291 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000292 };
293
294private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000295 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000296 k_Immediate, /// An immediate (possibly involving symbol references)
297 k_Memory, /// Base + Offset Memory Address
298 k_PhysRegister, /// A physical register from the Mips namespace
299 k_RegisterIndex, /// A register index in one or more RegKind.
300 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000301 } Kind;
302
David Blaikie960ea3f2014-06-08 16:18:35 +0000303public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000304 MipsOperand(KindTy K, MipsAsmParser &Parser)
305 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
306
David Blaikie960ea3f2014-06-08 16:18:35 +0000307private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000308 /// For diagnostics, and checking the assembler temporary
309 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000310
Eric Christopher8996c5d2013-03-15 00:42:55 +0000311 struct Token {
312 const char *Data;
313 unsigned Length;
314 };
315
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000316 struct PhysRegOp {
317 unsigned Num; /// Register Number
318 };
319
320 struct RegIdxOp {
321 unsigned Index; /// Index into the register class
322 RegKind Kind; /// Bitfield of the kinds it could possibly be
323 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000324 };
325
326 struct ImmOp {
327 const MCExpr *Val;
328 };
329
330 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000331 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000332 const MCExpr *Off;
333 };
334
Jack Carterb4dbc172012-09-05 23:34:03 +0000335 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000336 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000337 struct PhysRegOp PhysReg;
338 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000339 struct ImmOp Imm;
340 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000341 };
342
343 SMLoc StartLoc, EndLoc;
344
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000345 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000346 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
347 const MCRegisterInfo *RegInfo,
348 SMLoc S, SMLoc E,
349 MipsAsmParser &Parser) {
350 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000351 Op->RegIdx.Index = Index;
352 Op->RegIdx.RegInfo = RegInfo;
353 Op->RegIdx.Kind = RegKind;
354 Op->StartLoc = S;
355 Op->EndLoc = E;
356 return Op;
357 }
358
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000359public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000360 /// Coerce the register to GPR32 and return the real register for the current
361 /// target.
362 unsigned getGPR32Reg() const {
363 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
364 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
365 unsigned ClassID = Mips::GPR32RegClassID;
366 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000367 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000368
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000369 /// Coerce the register to GPR64 and return the real register for the current
370 /// target.
371 unsigned getGPR64Reg() const {
372 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
373 unsigned ClassID = Mips::GPR64RegClassID;
374 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000375 }
376
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000377private:
378 /// Coerce the register to AFGR64 and return the real register for the current
379 /// target.
380 unsigned getAFGR64Reg() const {
381 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
382 if (RegIdx.Index % 2 != 0)
383 AsmParser.Warning(StartLoc, "Float register should be even.");
384 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
385 .getRegister(RegIdx.Index / 2);
386 }
387
388 /// Coerce the register to FGR64 and return the real register for the current
389 /// target.
390 unsigned getFGR64Reg() const {
391 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
392 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
393 .getRegister(RegIdx.Index);
394 }
395
396 /// Coerce the register to FGR32 and return the real register for the current
397 /// target.
398 unsigned getFGR32Reg() const {
399 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
400 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
401 .getRegister(RegIdx.Index);
402 }
403
404 /// Coerce the register to FGRH32 and return the real register for the current
405 /// target.
406 unsigned getFGRH32Reg() const {
407 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
408 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
409 .getRegister(RegIdx.Index);
410 }
411
412 /// Coerce the register to FCC and return the real register for the current
413 /// target.
414 unsigned getFCCReg() const {
415 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
416 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
417 .getRegister(RegIdx.Index);
418 }
419
420 /// Coerce the register to MSA128 and return the real register for the current
421 /// target.
422 unsigned getMSA128Reg() const {
423 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
424 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
425 // identical
426 unsigned ClassID = Mips::MSA128BRegClassID;
427 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
428 }
429
430 /// Coerce the register to MSACtrl and return the real register for the
431 /// current target.
432 unsigned getMSACtrlReg() const {
433 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
434 unsigned ClassID = Mips::MSACtrlRegClassID;
435 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
436 }
437
438 /// Coerce the register to COP2 and return the real register for the
439 /// current target.
440 unsigned getCOP2Reg() const {
441 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
442 unsigned ClassID = Mips::COP2RegClassID;
443 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
444 }
445
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000446 /// Coerce the register to COP3 and return the real register for the
447 /// current target.
448 unsigned getCOP3Reg() const {
449 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
450 unsigned ClassID = Mips::COP3RegClassID;
451 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
452 }
453
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000454 /// Coerce the register to ACC64DSP and return the real register for the
455 /// current target.
456 unsigned getACC64DSPReg() const {
457 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
458 unsigned ClassID = Mips::ACC64DSPRegClassID;
459 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
460 }
461
462 /// Coerce the register to HI32DSP and return the real register for the
463 /// current target.
464 unsigned getHI32DSPReg() const {
465 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
466 unsigned ClassID = Mips::HI32DSPRegClassID;
467 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
468 }
469
470 /// Coerce the register to LO32DSP and return the real register for the
471 /// current target.
472 unsigned getLO32DSPReg() const {
473 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
474 unsigned ClassID = Mips::LO32DSPRegClassID;
475 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
476 }
477
478 /// Coerce the register to CCR and return the real register for the
479 /// current target.
480 unsigned getCCRReg() const {
481 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
482 unsigned ClassID = Mips::CCRRegClassID;
483 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
484 }
485
486 /// Coerce the register to HWRegs and return the real register for the
487 /// current target.
488 unsigned getHWRegsReg() const {
489 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
490 unsigned ClassID = Mips::HWRegsRegClassID;
491 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
492 }
493
494public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000495 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000496 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000497 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000498 Inst.addOperand(MCOperand::CreateImm(0));
499 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
500 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
501 else
502 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000503 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000504
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000505 void addRegOperands(MCInst &Inst, unsigned N) const {
506 llvm_unreachable("Use a custom parser instead");
507 }
508
Daniel Sanders21bce302014-04-01 12:35:23 +0000509 /// Render the operand to an MCInst as a GPR32
510 /// Asserts if the wrong number of operands are requested, or the operand
511 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000512 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
513 assert(N == 1 && "Invalid number of operands!");
514 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
515 }
516
Daniel Sanders21bce302014-04-01 12:35:23 +0000517 /// Render the operand to an MCInst as a GPR64
518 /// Asserts if the wrong number of operands are requested, or the operand
519 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000520 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
521 assert(N == 1 && "Invalid number of operands!");
522 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
523 }
524
525 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
526 assert(N == 1 && "Invalid number of operands!");
527 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
528 }
529
530 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
531 assert(N == 1 && "Invalid number of operands!");
532 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
533 }
534
535 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
536 assert(N == 1 && "Invalid number of operands!");
537 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
538 }
539
540 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
541 assert(N == 1 && "Invalid number of operands!");
542 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
543 }
544
545 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
546 assert(N == 1 && "Invalid number of operands!");
547 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
548 }
549
550 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
551 assert(N == 1 && "Invalid number of operands!");
552 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
553 }
554
555 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
556 assert(N == 1 && "Invalid number of operands!");
557 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
558 }
559
560 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
561 assert(N == 1 && "Invalid number of operands!");
562 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
563 }
564
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000565 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
566 assert(N == 1 && "Invalid number of operands!");
567 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
568 }
569
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
571 assert(N == 1 && "Invalid number of operands!");
572 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
573 }
574
575 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
576 assert(N == 1 && "Invalid number of operands!");
577 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
578 }
579
580 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
581 assert(N == 1 && "Invalid number of operands!");
582 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
583 }
584
585 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
586 assert(N == 1 && "Invalid number of operands!");
587 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
588 }
589
590 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
591 assert(N == 1 && "Invalid number of operands!");
592 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
593 }
594
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000595 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000596 assert(N == 1 && "Invalid number of operands!");
597 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000598 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000599 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000600
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000601 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000602 assert(N == 2 && "Invalid number of operands!");
603
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000605
606 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000607 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000608 }
609
Craig Topper56c590a2014-04-29 07:58:02 +0000610 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000611 // As a special case until we sort out the definition of div/divu, pretend
612 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
613 if (isGPRAsmReg() && RegIdx.Index == 0)
614 return true;
615
616 return Kind == k_PhysRegister;
617 }
618 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000619 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000620 bool isConstantImm() const {
621 return isImm() && dyn_cast<MCConstantExpr>(getImm());
622 }
Craig Topper56c590a2014-04-29 07:58:02 +0000623 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000624 // Note: It's not possible to pretend that other operand kinds are tokens.
625 // The matcher emitter checks tokens first.
626 return Kind == k_Token;
627 }
Craig Topper56c590a2014-04-29 07:58:02 +0000628 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000629 bool isConstantMemOff() const {
630 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
631 }
632 template <unsigned Bits> bool isMemWithSimmOffset() const {
633 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
634 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000635 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000636 bool isLSAImm() const {
637 if (!isConstantImm())
638 return false;
639 int64_t Val = getConstantImm();
640 return 1 <= Val && Val <= 4;
641 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000642
643 StringRef getToken() const {
644 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000645 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000646 }
647
Craig Topper56c590a2014-04-29 07:58:02 +0000648 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 // As a special case until we sort out the definition of div/divu, pretend
650 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
651 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
652 RegIdx.Kind & RegKind_GPR)
653 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000654
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000655 assert(Kind == k_PhysRegister && "Invalid access!");
656 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000657 }
658
Jack Carterb4dbc172012-09-05 23:34:03 +0000659 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000660 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000661 return Imm.Val;
662 }
663
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 int64_t getConstantImm() const {
665 const MCExpr *Val = getImm();
666 return static_cast<const MCConstantExpr *>(Val)->getValue();
667 }
668
669 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000670 assert((Kind == k_Memory) && "Invalid access!");
671 return Mem.Base;
672 }
673
674 const MCExpr *getMemOff() const {
675 assert((Kind == k_Memory) && "Invalid access!");
676 return Mem.Off;
677 }
678
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000679 int64_t getConstantMemOff() const {
680 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
681 }
682
David Blaikie960ea3f2014-06-08 16:18:35 +0000683 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
684 MipsAsmParser &Parser) {
685 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000686 Op->Tok.Data = Str.data();
687 Op->Tok.Length = Str.size();
688 Op->StartLoc = S;
689 Op->EndLoc = S;
690 return Op;
691 }
692
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000693 /// Create a numeric register (e.g. $1). The exact register remains
694 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000695 static std::unique_ptr<MipsOperand>
696 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
697 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000698 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
699 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000700 }
701
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000702 /// Create a register that is definitely a GPR.
703 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000704 static std::unique_ptr<MipsOperand>
705 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
706 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000708 }
709
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000710 /// Create a register that is definitely a FGR.
711 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000712 static std::unique_ptr<MipsOperand>
713 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
714 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
716 }
717
718 /// Create a register that is definitely an FCC.
719 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000720 static std::unique_ptr<MipsOperand>
721 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
722 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000723 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
724 }
725
726 /// Create a register that is definitely an ACC.
727 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000728 static std::unique_ptr<MipsOperand>
729 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
730 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
732 }
733
734 /// Create a register that is definitely an MSA128.
735 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000736 static std::unique_ptr<MipsOperand>
737 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
738 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000739 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
740 }
741
742 /// Create a register that is definitely an MSACtrl.
743 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000744 static std::unique_ptr<MipsOperand>
745 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
746 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
748 }
749
David Blaikie960ea3f2014-06-08 16:18:35 +0000750 static std::unique_ptr<MipsOperand>
751 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
752 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000753 Op->Imm.Val = Val;
754 Op->StartLoc = S;
755 Op->EndLoc = E;
756 return Op;
757 }
758
David Blaikie960ea3f2014-06-08 16:18:35 +0000759 static std::unique_ptr<MipsOperand>
760 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
761 SMLoc E, MipsAsmParser &Parser) {
762 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
763 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000764 Op->Mem.Off = Off;
765 Op->StartLoc = S;
766 Op->EndLoc = E;
767 return Op;
768 }
769
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000770 bool isGPRAsmReg() const {
771 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000772 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000773 bool isFGRAsmReg() const {
774 // AFGR64 is $0-$15 but we handle this in getAFGR64()
775 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000776 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000777 bool isHWRegsAsmReg() const {
778 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000779 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000780 bool isCCRAsmReg() const {
781 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000782 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000783 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000784 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
785 return false;
786 if (!AsmParser.hasEightFccRegisters())
787 return RegIdx.Index == 0;
788 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000789 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000790 bool isACCAsmReg() const {
791 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000792 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 bool isCOP2AsmReg() const {
794 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000795 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000796 bool isCOP3AsmReg() const {
797 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
798 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 bool isMSA128AsmReg() const {
800 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000801 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000802 bool isMSACtrlAsmReg() const {
803 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000804 }
805
Jack Carterb4dbc172012-09-05 23:34:03 +0000806 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000807 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000808 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000809 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000810
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000811 virtual ~MipsOperand() {
812 switch (Kind) {
813 case k_Immediate:
814 break;
815 case k_Memory:
816 delete Mem.Base;
817 break;
818 case k_PhysRegister:
819 case k_RegisterIndex:
820 case k_Token:
821 break;
822 }
823 }
824
Craig Topper56c590a2014-04-29 07:58:02 +0000825 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 switch (Kind) {
827 case k_Immediate:
828 OS << "Imm<";
829 Imm.Val->print(OS);
830 OS << ">";
831 break;
832 case k_Memory:
833 OS << "Mem<";
834 Mem.Base->print(OS);
835 OS << ", ";
836 Mem.Off->print(OS);
837 OS << ">";
838 break;
839 case k_PhysRegister:
840 OS << "PhysReg<" << PhysReg.Num << ">";
841 break;
842 case k_RegisterIndex:
843 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
844 break;
845 case k_Token:
846 OS << Tok.Data;
847 break;
848 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000849 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000850}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000851} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000852
Jack Carter9e65aa32013-03-22 00:05:30 +0000853namespace llvm {
854extern const MCInstrDesc MipsInsts[];
855}
856static const MCInstrDesc &getInstDesc(unsigned Opcode) {
857 return MipsInsts[Opcode];
858}
859
860bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000861 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000862 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000863
Jack Carter9e65aa32013-03-22 00:05:30 +0000864 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000865
866 if (MCID.isBranch() || MCID.isCall()) {
867 const unsigned Opcode = Inst.getOpcode();
868 MCOperand Offset;
869
870 switch (Opcode) {
871 default:
872 break;
873 case Mips::BEQ:
874 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 case Mips::BEQ_MM:
876 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000877 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000878 Offset = Inst.getOperand(2);
879 if (!Offset.isImm())
880 break; // We'll deal with this situation later on when applying fixups.
881 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
882 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000883 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000884 return Error(IDLoc, "branch to misaligned address");
885 break;
886 case Mips::BGEZ:
887 case Mips::BGTZ:
888 case Mips::BLEZ:
889 case Mips::BLTZ:
890 case Mips::BGEZAL:
891 case Mips::BLTZAL:
892 case Mips::BC1F:
893 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000894 case Mips::BGEZ_MM:
895 case Mips::BGTZ_MM:
896 case Mips::BLEZ_MM:
897 case Mips::BLTZ_MM:
898 case Mips::BGEZAL_MM:
899 case Mips::BLTZAL_MM:
900 case Mips::BC1F_MM:
901 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000902 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000903 Offset = Inst.getOperand(1);
904 if (!Offset.isImm())
905 break; // We'll deal with this situation later on when applying fixups.
906 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
907 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000908 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000909 return Error(IDLoc, "branch to misaligned address");
910 break;
911 }
912 }
913
Daniel Sandersa84989a2014-06-16 13:25:35 +0000914 // SSNOP is deprecated on MIPS32r6/MIPS64r6
915 // We still accept it but it is a normal nop.
916 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
917 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
918 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
919 "nop instruction");
920 }
921
Jack Carterc15c1d22013-04-25 23:31:35 +0000922 if (MCID.hasDelaySlot() && Options.isReorder()) {
923 // If this instruction has a delay slot and .set reorder is active,
924 // emit a NOP after it.
925 Instructions.push_back(Inst);
926 MCInst NopInst;
927 NopInst.setOpcode(Mips::SLL);
928 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
929 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
930 NopInst.addOperand(MCOperand::CreateImm(0));
931 Instructions.push_back(NopInst);
932 return false;
933 }
934
Jack Carter9e65aa32013-03-22 00:05:30 +0000935 if (MCID.mayLoad() || MCID.mayStore()) {
936 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000937 // reference or immediate we may have to expand instructions.
938 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000939 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000940 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
941 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000942 MCOperand &Op = Inst.getOperand(i);
943 if (Op.isImm()) {
944 int MemOffset = Op.getImm();
945 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000946 // Offset can't exceed 16bit value.
947 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000948 return false;
949 }
950 } else if (Op.isExpr()) {
951 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000952 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000953 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000954 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000955 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000956 // Expand symbol.
957 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000958 return false;
959 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000960 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000961 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000962 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000963 }
964 }
965 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000966 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000967 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000968
969 if (needsExpansion(Inst))
970 expandInstruction(Inst, IDLoc, Instructions);
971 else
972 Instructions.push_back(Inst);
973
974 return false;
975}
976
Jack Carter30a59822012-10-04 04:03:53 +0000977bool MipsAsmParser::needsExpansion(MCInst &Inst) {
978
Jack Carterd0bd6422013-04-18 00:41:53 +0000979 switch (Inst.getOpcode()) {
980 case Mips::LoadImm32Reg:
981 case Mips::LoadAddr32Imm:
982 case Mips::LoadAddr32Reg:
983 return true;
984 default:
985 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000986 }
987}
Jack Carter92995f12012-10-06 00:53:28 +0000988
Jack Carter30a59822012-10-04 04:03:53 +0000989void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000990 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000991 switch (Inst.getOpcode()) {
992 case Mips::LoadImm32Reg:
993 return expandLoadImm(Inst, IDLoc, Instructions);
994 case Mips::LoadAddr32Imm:
995 return expandLoadAddressImm(Inst, IDLoc, Instructions);
996 case Mips::LoadAddr32Reg:
997 return expandLoadAddressReg(Inst, IDLoc, Instructions);
998 }
Jack Carter30a59822012-10-04 04:03:53 +0000999}
Jack Carter92995f12012-10-06 00:53:28 +00001000
Jack Carter30a59822012-10-04 04:03:53 +00001001void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001002 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001003 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001004 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001005 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001006 const MCOperand &RegOp = Inst.getOperand(0);
1007 assert(RegOp.isReg() && "expected register operand kind");
1008
1009 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001010 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +00001011 if (0 <= ImmValue && ImmValue <= 65535) {
1012 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001013 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001014 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001015 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001016 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001017 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001018 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001019 } else if (ImmValue < 0 && ImmValue >= -32768) {
1020 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001021 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001022 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001023 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001024 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001025 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001026 Instructions.push_back(tmpInst);
1027 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001028 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +00001029 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001030 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001031 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001032 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1033 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001034 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +00001035 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001036 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001037 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1038 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1039 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1040 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +00001041 Instructions.push_back(tmpInst);
1042 }
1043}
Jack Carter92995f12012-10-06 00:53:28 +00001044
Vladimir Medic4c299852013-11-06 11:27:05 +00001045void
1046MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1047 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001048 MCInst tmpInst;
1049 const MCOperand &ImmOp = Inst.getOperand(2);
1050 assert(ImmOp.isImm() && "expected immediate operand kind");
1051 const MCOperand &SrcRegOp = Inst.getOperand(1);
1052 assert(SrcRegOp.isReg() && "expected register operand kind");
1053 const MCOperand &DstRegOp = Inst.getOperand(0);
1054 assert(DstRegOp.isReg() && "expected register operand kind");
1055 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001056 if (-32768 <= ImmValue && ImmValue <= 65535) {
1057 // For -32768 <= j <= 65535.
1058 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001059 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001060 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1061 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1062 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1063 Instructions.push_back(tmpInst);
1064 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001065 // For any other value of j that is representable as a 32-bit integer.
1066 // la d,j(s) => lui d,hi16(j)
1067 // ori d,d,lo16(j)
1068 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001069 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001070 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1071 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1072 Instructions.push_back(tmpInst);
1073 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001074 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001075 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1076 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1077 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1078 Instructions.push_back(tmpInst);
1079 tmpInst.clear();
1080 tmpInst.setOpcode(Mips::ADDu);
1081 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1082 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1083 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1084 Instructions.push_back(tmpInst);
1085 }
1086}
1087
Vladimir Medic4c299852013-11-06 11:27:05 +00001088void
1089MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1090 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001091 MCInst tmpInst;
1092 const MCOperand &ImmOp = Inst.getOperand(1);
1093 assert(ImmOp.isImm() && "expected immediate operand kind");
1094 const MCOperand &RegOp = Inst.getOperand(0);
1095 assert(RegOp.isReg() && "expected register operand kind");
1096 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001097 if (-32768 <= ImmValue && ImmValue <= 65535) {
1098 // For -32768 <= j <= 65535.
1099 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001100 tmpInst.setOpcode(Mips::ADDiu);
1101 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001102 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001103 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1104 Instructions.push_back(tmpInst);
1105 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001106 // For any other value of j that is representable as a 32-bit integer.
1107 // la d,j => lui d,hi16(j)
1108 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001109 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001110 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1111 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1112 Instructions.push_back(tmpInst);
1113 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001114 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001115 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1116 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1117 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1118 Instructions.push_back(tmpInst);
1119 }
1120}
1121
Jack Carter9e65aa32013-03-22 00:05:30 +00001122void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001123 SmallVectorImpl<MCInst> &Instructions,
1124 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001125 const MCSymbolRefExpr *SR;
1126 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001127 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001128 const MCExpr *ExprOffset;
1129 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +00001130 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001131 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +00001132 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001133 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1134 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001135 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001136 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1137 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001138 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001139 if (isImmOpnd) {
1140 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1141 ImmOffset = Inst.getOperand(2).getImm();
1142 LoOffset = ImmOffset & 0x0000ffff;
1143 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001144 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001145 if (LoOffset & 0x8000)
1146 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001147 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001148 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001149 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001150 TempInst.setLoc(IDLoc);
1151 // 1st instruction in expansion is LUi. For load instruction we can use
1152 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001153 // but for stores we must use $at.
1154 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +00001155 TempInst.setOpcode(Mips::LUi);
1156 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1157 if (isImmOpnd)
1158 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1159 else {
1160 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001161 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001162 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1163 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1164 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001165 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001166 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001167 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001168 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001169 }
1170 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001171 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001172 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001173 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001174 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001175 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001176 TempInst.setOpcode(Mips::ADDu);
1177 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1178 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1179 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1180 Instructions.push_back(TempInst);
1181 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001182 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001183 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001184 TempInst.setOpcode(Inst.getOpcode());
1185 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1186 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1187 if (isImmOpnd)
1188 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1189 else {
1190 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001191 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1192 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1193 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001194 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001195 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001196 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001197 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001198 }
1199 }
1200 Instructions.push_back(TempInst);
1201 TempInst.clear();
1202}
1203
Matheus Almeida595fcab2014-06-11 15:05:56 +00001204unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1205 // As described by the Mips32r2 spec, the registers Rd and Rs for
1206 // jalr.hb must be different.
1207 unsigned Opcode = Inst.getOpcode();
1208
1209 if (Opcode == Mips::JALR_HB &&
1210 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1211 return Match_RequiresDifferentSrcAndDst;
1212
1213 return Match_Success;
1214}
1215
David Blaikie960ea3f2014-06-08 16:18:35 +00001216bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1217 OperandVector &Operands,
1218 MCStreamer &Out,
1219 unsigned &ErrorInfo,
1220 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001221
Jack Carterb4dbc172012-09-05 23:34:03 +00001222 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001223 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001224 unsigned MatchResult =
1225 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001226
1227 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001228 default:
1229 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001230 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001231 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001232 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001233 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001234 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001235 return false;
1236 }
1237 case Match_MissingFeature:
1238 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1239 return true;
1240 case Match_InvalidOperand: {
1241 SMLoc ErrorLoc = IDLoc;
1242 if (ErrorInfo != ~0U) {
1243 if (ErrorInfo >= Operands.size())
1244 return Error(IDLoc, "too few operands for instruction");
1245
David Blaikie960ea3f2014-06-08 16:18:35 +00001246 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001247 if (ErrorLoc == SMLoc())
1248 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001249 }
1250
1251 return Error(ErrorLoc, "invalid operand for instruction");
1252 }
1253 case Match_MnemonicFail:
1254 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001255 case Match_RequiresDifferentSrcAndDst:
1256 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001257 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001258 return true;
1259}
1260
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001261void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1262 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1263 if (RegIndex == 1)
1264 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001265 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001266 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1267 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001268 }
1269}
1270
Jack Carter1ac53222013-02-20 23:11:17 +00001271int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001272 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001273
Vladimir Medic4c299852013-11-06 11:27:05 +00001274 CC = StringSwitch<unsigned>(Name)
1275 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001276 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001277 .Case("a0", 4)
1278 .Case("a1", 5)
1279 .Case("a2", 6)
1280 .Case("a3", 7)
1281 .Case("v0", 2)
1282 .Case("v1", 3)
1283 .Case("s0", 16)
1284 .Case("s1", 17)
1285 .Case("s2", 18)
1286 .Case("s3", 19)
1287 .Case("s4", 20)
1288 .Case("s5", 21)
1289 .Case("s6", 22)
1290 .Case("s7", 23)
1291 .Case("k0", 26)
1292 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001293 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001294 .Case("sp", 29)
1295 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001296 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001297 .Case("ra", 31)
1298 .Case("t0", 8)
1299 .Case("t1", 9)
1300 .Case("t2", 10)
1301 .Case("t3", 11)
1302 .Case("t4", 12)
1303 .Case("t5", 13)
1304 .Case("t6", 14)
1305 .Case("t7", 15)
1306 .Case("t8", 24)
1307 .Case("t9", 25)
1308 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001309
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001310 if (isN32() || isN64()) {
1311 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1312 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1313 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1314 if (8 <= CC && CC <= 11)
1315 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001316
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001317 if (CC == -1)
1318 CC = StringSwitch<unsigned>(Name)
1319 .Case("a4", 8)
1320 .Case("a5", 9)
1321 .Case("a6", 10)
1322 .Case("a7", 11)
1323 .Case("kt0", 26)
1324 .Case("kt1", 27)
1325 .Default(-1);
1326 }
Jack Carter1ac53222013-02-20 23:11:17 +00001327
1328 return CC;
1329}
Jack Carterd0bd6422013-04-18 00:41:53 +00001330
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001331int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001332
Jack Cartera63b16a2012-09-07 00:23:42 +00001333 if (Name[0] == 'f') {
1334 StringRef NumString = Name.substr(1);
1335 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001336 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001337 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001338 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001339 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001340 return IntVal;
1341 }
1342 return -1;
1343}
Jack Cartera63b16a2012-09-07 00:23:42 +00001344
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001345int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1346
1347 if (Name.startswith("fcc")) {
1348 StringRef NumString = Name.substr(3);
1349 unsigned IntVal;
1350 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001351 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001352 if (IntVal > 7) // There are only 8 fcc registers.
1353 return -1;
1354 return IntVal;
1355 }
1356 return -1;
1357}
1358
1359int MipsAsmParser::matchACRegisterName(StringRef Name) {
1360
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001361 if (Name.startswith("ac")) {
1362 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001363 unsigned IntVal;
1364 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001365 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001366 if (IntVal > 3) // There are only 3 acc registers.
1367 return -1;
1368 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001369 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001370 return -1;
1371}
Jack Carterd0bd6422013-04-18 00:41:53 +00001372
Jack Carter5dc8ac92013-09-25 23:50:44 +00001373int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1374 unsigned IntVal;
1375
1376 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1377 return -1;
1378
1379 if (IntVal > 31)
1380 return -1;
1381
1382 return IntVal;
1383}
1384
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001385int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1386 int CC;
1387
1388 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001389 .Case("msair", 0)
1390 .Case("msacsr", 1)
1391 .Case("msaaccess", 2)
1392 .Case("msasave", 3)
1393 .Case("msamodify", 4)
1394 .Case("msarequest", 5)
1395 .Case("msamap", 6)
1396 .Case("msaunmap", 7)
1397 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001398
1399 return CC;
1400}
1401
Jack Carter0b744b32012-10-04 02:29:46 +00001402bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1403 if (Reg > 31)
1404 return false;
1405
1406 aTReg = Reg;
1407 return true;
1408}
1409
Daniel Sandersd89b1362014-03-24 16:48:01 +00001410int MipsAsmParser::getATReg() {
1411 int AT = Options.getATRegNum();
1412 if (AT == 0)
1413 TokError("Pseudo instruction requires $at, which is not available");
1414 return AT;
1415}
Jack Carter0b744b32012-10-04 02:29:46 +00001416
Jack Carterd0bd6422013-04-18 00:41:53 +00001417unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001418 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001419}
1420
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001421unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001422 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1423 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001424}
1425
Jack Carter873c7242013-01-12 01:03:14 +00001426int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001427 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001428 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001429 return -1;
1430
Jack Carter873c7242013-01-12 01:03:14 +00001431 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001432}
1433
David Blaikie960ea3f2014-06-08 16:18:35 +00001434bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001435 DEBUG(dbgs() << "ParseOperand\n");
1436
Jack Carter30a59822012-10-04 04:03:53 +00001437 // Check if the current operand has a custom associated parser, if so, try to
1438 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001439 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1440 if (ResTy == MatchOperand_Success)
1441 return false;
1442 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1443 // there was a match, but an error occurred, in which case, just return that
1444 // the operand parsing failed.
1445 if (ResTy == MatchOperand_ParseFail)
1446 return true;
1447
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001448 DEBUG(dbgs() << ".. Generic Parser\n");
1449
Jack Carterb4dbc172012-09-05 23:34:03 +00001450 switch (getLexer().getKind()) {
1451 default:
1452 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1453 return true;
1454 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001455 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001456 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001457
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001458 // Almost all registers have been parsed by custom parsers. There is only
1459 // one exception to this. $zero (and it's alias $0) will reach this point
1460 // for div, divu, and similar instructions because it is not an operand
1461 // to the instruction definition but an explicit register. Special case
1462 // this situation for now.
1463 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001464 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001465
Jack Carterd0bd6422013-04-18 00:41:53 +00001466 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001467 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001468 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001469 return true;
1470
Jack Carter873c7242013-01-12 01:03:14 +00001471 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001472 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001473 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001474 const MCExpr *Res =
1475 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001476
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001477 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001478 return false;
1479 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001480 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001481 case AsmToken::LParen:
1482 case AsmToken::Minus:
1483 case AsmToken::Plus:
1484 case AsmToken::Integer:
1485 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001486 DEBUG(dbgs() << ".. generic integer\n");
1487 OperandMatchResultTy ResTy = ParseImm(Operands);
1488 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001489 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001490 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001491 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001492 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001493 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001494 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001495 return true;
1496
Jack Carter873c7242013-01-12 01:03:14 +00001497 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1498
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001499 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001500 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001501 } // case AsmToken::Percent
1502 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001503 return true;
1504}
1505
Vladimir Medic4c299852013-11-06 11:27:05 +00001506const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001507 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001508 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001509 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001510 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001511 // It's a constant, evaluate reloc value.
1512 int16_t Val;
1513 switch (getVariantKind(RelocStr)) {
1514 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1515 // Get the 1st 16-bits.
1516 Val = MCE->getValue() & 0xffff;
1517 break;
1518 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1519 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1520 // 16 bits being negative.
1521 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1522 break;
1523 case MCSymbolRefExpr::VK_Mips_HIGHER:
1524 // Get the 3rd 16-bits.
1525 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1526 break;
1527 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1528 // Get the 4th 16-bits.
1529 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1530 break;
1531 default:
1532 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001533 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001534 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001535 }
1536
Jack Carterb5cf5902013-04-17 00:18:04 +00001537 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001538 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001539 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001540 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001541 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001542 return Res;
1543 }
1544
1545 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001546 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1547
Sasa Stankovic06c47802014-04-03 10:37:45 +00001548 // Try to create target expression.
1549 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1550 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001551
Jack Carterd0bd6422013-04-18 00:41:53 +00001552 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1553 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001554 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1555 return Res;
1556 }
1557
1558 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001559 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1560 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1561 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001562 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001563 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001564 return Expr;
1565}
1566
1567bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1568
1569 switch (Expr->getKind()) {
1570 case MCExpr::Constant:
1571 return true;
1572 case MCExpr::SymbolRef:
1573 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1574 case MCExpr::Binary:
1575 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1576 if (!isEvaluated(BE->getLHS()))
1577 return false;
1578 return isEvaluated(BE->getRHS());
1579 }
1580 case MCExpr::Unary:
1581 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001582 case MCExpr::Target:
1583 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001584 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001585 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001586}
Jack Carterd0bd6422013-04-18 00:41:53 +00001587
Jack Carterb5cf5902013-04-17 00:18:04 +00001588bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001589 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001590 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001591 if (Tok.isNot(AsmToken::Identifier))
1592 return true;
1593
1594 std::string Str = Tok.getIdentifier().str();
1595
Jack Carterd0bd6422013-04-18 00:41:53 +00001596 Parser.Lex(); // Eat the identifier.
1597 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001598 const MCExpr *IdVal;
1599 SMLoc EndLoc;
1600
1601 if (getLexer().getKind() == AsmToken::LParen) {
1602 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001604 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001605 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001606 const AsmToken &nextTok = Parser.getTok();
1607 if (nextTok.isNot(AsmToken::Identifier))
1608 return true;
1609 Str += "(%";
1610 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001611 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001612 if (getLexer().getKind() != AsmToken::LParen)
1613 return true;
1614 } else
1615 break;
1616 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001617 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001618 return true;
1619
1620 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001621 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001622
1623 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001625
Jack Carterd0bd6422013-04-18 00:41:53 +00001626 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001627 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001628}
1629
Jack Carterb4dbc172012-09-05 23:34:03 +00001630bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1631 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001632 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001633 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1634 if (ResTy == MatchOperand_Success) {
1635 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001636 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001637 StartLoc = Operand.getStartLoc();
1638 EndLoc = Operand.getEndLoc();
1639
1640 // AFAIK, we only support numeric registers and named GPR's in CFI
1641 // directives.
1642 // Don't worry about eating tokens before failing. Using an unrecognised
1643 // register is a parse error.
1644 if (Operand.isGPRAsmReg()) {
1645 // Resolve to GPR32 or GPR64 appropriately.
1646 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1647 }
1648
1649 return (RegNo == (unsigned)-1);
1650 }
1651
1652 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001653 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001654}
1655
Jack Carterb5cf5902013-04-17 00:18:04 +00001656bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001657 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001658 bool Result = true;
1659
1660 while (getLexer().getKind() == AsmToken::LParen)
1661 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001662
Jack Carterd0bd6422013-04-18 00:41:53 +00001663 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001664 default:
1665 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001666 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001667 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001668 case AsmToken::Integer:
1669 case AsmToken::Minus:
1670 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001671 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001672 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001673 else
1674 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001675 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001676 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001677 break;
Jack Carter873c7242013-01-12 01:03:14 +00001678 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001679 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001680 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001681 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001682}
1683
David Blaikie960ea3f2014-06-08 16:18:35 +00001684MipsAsmParser::OperandMatchResultTy
1685MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001686 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001687 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001688 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001689 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001690 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001691 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001692 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001693
Jack Carterb5cf5902013-04-17 00:18:04 +00001694 if (getLexer().getKind() == AsmToken::LParen) {
1695 Parser.Lex();
1696 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001697 }
1698
Jack Carterb5cf5902013-04-17 00:18:04 +00001699 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001700 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001701 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001702
Jack Carterd0bd6422013-04-18 00:41:53 +00001703 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001704 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001705 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1706 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001707 SMLoc E =
1708 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001709 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001710 return MatchOperand_Success;
1711 }
1712 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001713 SMLoc E =
1714 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001715
Jack Carterd0bd6422013-04-18 00:41:53 +00001716 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001717 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001718 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1719 S, E, *this);
1720 Operands.push_back(
1721 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001722 return MatchOperand_Success;
1723 }
1724 Error(Parser.getTok().getLoc(), "'(' expected");
1725 return MatchOperand_ParseFail;
1726 }
1727
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001729 }
1730
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001731 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001732 if (Res != MatchOperand_Success)
1733 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001734
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001735 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001736 Error(Parser.getTok().getLoc(), "')' expected");
1737 return MatchOperand_ParseFail;
1738 }
1739
Jack Carter873c7242013-01-12 01:03:14 +00001740 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1741
Jack Carterd0bd6422013-04-18 00:41:53 +00001742 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001743
Craig Topper062a2ba2014-04-25 05:30:21 +00001744 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001745 IdVal = MCConstantExpr::Create(0, getContext());
1746
Jack Carterd0bd6422013-04-18 00:41:53 +00001747 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001748 std::unique_ptr<MipsOperand> op(
1749 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001750 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001751 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001752 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001753 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001754 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1755 int64_t Imm;
1756 if (IdVal->EvaluateAsAbsolute(Imm))
1757 IdVal = MCConstantExpr::Create(Imm, getContext());
1758 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1759 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1760 getContext());
1761 }
1762
David Blaikie960ea3f2014-06-08 16:18:35 +00001763 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001764 return MatchOperand_Success;
1765}
1766
David Blaikie960ea3f2014-06-08 16:18:35 +00001767bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001768
Jack Carterd76b2372013-03-21 21:44:16 +00001769 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1770 if (Sym) {
1771 SMLoc S = Parser.getTok().getLoc();
1772 const MCExpr *Expr;
1773 if (Sym->isVariable())
1774 Expr = Sym->getVariableValue();
1775 else
1776 return false;
1777 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001778 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001779 const StringRef DefSymbol = Ref->getSymbol().getName();
1780 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001781 OperandMatchResultTy ResTy =
1782 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001783 if (ResTy == MatchOperand_Success) {
1784 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001785 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001786 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001787 llvm_unreachable("Should never ParseFail");
1788 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001789 }
1790 } else if (Expr->getKind() == MCExpr::Constant) {
1791 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001792 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001793 Operands.push_back(
1794 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001795 return true;
1796 }
1797 }
1798 return false;
1799}
Jack Carterd0bd6422013-04-18 00:41:53 +00001800
Jack Carter873c7242013-01-12 01:03:14 +00001801MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001802MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1803 StringRef Identifier,
1804 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001805 int Index = matchCPURegisterName(Identifier);
1806 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001807 Operands.push_back(MipsOperand::CreateGPRReg(
1808 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1809 return MatchOperand_Success;
1810 }
1811
1812 Index = matchFPURegisterName(Identifier);
1813 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001814 Operands.push_back(MipsOperand::CreateFGRReg(
1815 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1816 return MatchOperand_Success;
1817 }
1818
1819 Index = matchFCCRegisterName(Identifier);
1820 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001821 Operands.push_back(MipsOperand::CreateFCCReg(
1822 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1823 return MatchOperand_Success;
1824 }
1825
1826 Index = matchACRegisterName(Identifier);
1827 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001828 Operands.push_back(MipsOperand::CreateACCReg(
1829 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1830 return MatchOperand_Success;
1831 }
1832
1833 Index = matchMSA128RegisterName(Identifier);
1834 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001835 Operands.push_back(MipsOperand::CreateMSA128Reg(
1836 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1837 return MatchOperand_Success;
1838 }
1839
1840 Index = matchMSA128CtrlRegisterName(Identifier);
1841 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001842 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1843 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1844 return MatchOperand_Success;
1845 }
1846
1847 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001848}
1849
1850MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001851MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001852 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001853
1854 if (Token.is(AsmToken::Identifier)) {
1855 DEBUG(dbgs() << ".. identifier\n");
1856 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001857 OperandMatchResultTy ResTy =
1858 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001859 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001860 } else if (Token.is(AsmToken::Integer)) {
1861 DEBUG(dbgs() << ".. integer\n");
1862 Operands.push_back(MipsOperand::CreateNumericReg(
1863 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1864 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001865 return MatchOperand_Success;
1866 }
1867
1868 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1869
1870 return MatchOperand_NoMatch;
1871}
1872
David Blaikie960ea3f2014-06-08 16:18:35 +00001873MipsAsmParser::OperandMatchResultTy
1874MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001875 DEBUG(dbgs() << "ParseAnyRegister\n");
1876
1877 auto Token = Parser.getTok();
1878
1879 SMLoc S = Token.getLoc();
1880
1881 if (Token.isNot(AsmToken::Dollar)) {
1882 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1883 if (Token.is(AsmToken::Identifier)) {
1884 if (searchSymbolAlias(Operands))
1885 return MatchOperand_Success;
1886 }
1887 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1888 return MatchOperand_NoMatch;
1889 }
1890 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001891
Daniel Sanders21bce302014-04-01 12:35:23 +00001892 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001893 if (ResTy == MatchOperand_Success) {
1894 Parser.Lex(); // $
1895 Parser.Lex(); // identifier
1896 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001897 return ResTy;
1898}
1899
1900MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001901MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001902 switch (getLexer().getKind()) {
1903 default:
1904 return MatchOperand_NoMatch;
1905 case AsmToken::LParen:
1906 case AsmToken::Minus:
1907 case AsmToken::Plus:
1908 case AsmToken::Integer:
1909 case AsmToken::String:
1910 break;
1911 }
1912
1913 const MCExpr *IdVal;
1914 SMLoc S = Parser.getTok().getLoc();
1915 if (getParser().parseExpression(IdVal))
1916 return MatchOperand_ParseFail;
1917
1918 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1919 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1920 return MatchOperand_Success;
1921}
1922
David Blaikie960ea3f2014-06-08 16:18:35 +00001923MipsAsmParser::OperandMatchResultTy
1924MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001925 DEBUG(dbgs() << "ParseJumpTarget\n");
1926
1927 SMLoc S = getLexer().getLoc();
1928
1929 // Integers and expressions are acceptable
1930 OperandMatchResultTy ResTy = ParseImm(Operands);
1931 if (ResTy != MatchOperand_NoMatch)
1932 return ResTy;
1933
Daniel Sanders315386c2014-04-01 10:40:14 +00001934 // Registers are a valid target and have priority over symbols.
1935 ResTy = ParseAnyRegister(Operands);
1936 if (ResTy != MatchOperand_NoMatch)
1937 return ResTy;
1938
Daniel Sandersffd84362014-04-01 10:41:48 +00001939 const MCExpr *Expr = nullptr;
1940 if (Parser.parseExpression(Expr)) {
1941 // We have no way of knowing if a symbol was consumed so we must ParseFail
1942 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001943 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001944 Operands.push_back(
1945 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001946 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001947}
1948
Vladimir Medic2b953d02013-10-01 09:48:56 +00001949MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001950MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001951 const MCExpr *IdVal;
1952 // If the first token is '$' we may have register operand.
1953 if (Parser.getTok().is(AsmToken::Dollar))
1954 return MatchOperand_NoMatch;
1955 SMLoc S = Parser.getTok().getLoc();
1956 if (getParser().parseExpression(IdVal))
1957 return MatchOperand_ParseFail;
1958 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001959 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001960 int64_t Val = MCE->getValue();
1961 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1962 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001963 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001964 return MatchOperand_Success;
1965}
1966
Matheus Almeida779c5932013-11-18 12:32:49 +00001967MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001968MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001969 switch (getLexer().getKind()) {
1970 default:
1971 return MatchOperand_NoMatch;
1972 case AsmToken::LParen:
1973 case AsmToken::Plus:
1974 case AsmToken::Minus:
1975 case AsmToken::Integer:
1976 break;
1977 }
1978
1979 const MCExpr *Expr;
1980 SMLoc S = Parser.getTok().getLoc();
1981
1982 if (getParser().parseExpression(Expr))
1983 return MatchOperand_ParseFail;
1984
1985 int64_t Val;
1986 if (!Expr->EvaluateAsAbsolute(Val)) {
1987 Error(S, "expected immediate value");
1988 return MatchOperand_ParseFail;
1989 }
1990
1991 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1992 // and because the CPU always adds one to the immediate field, the allowed
1993 // range becomes 1..4. We'll only check the range here and will deal
1994 // with the addition/subtraction when actually decoding/encoding
1995 // the instruction.
1996 if (Val < 1 || Val > 4) {
1997 Error(S, "immediate not in range (1..4)");
1998 return MatchOperand_ParseFail;
1999 }
2000
Jack Carter3b2c96e2014-01-22 23:31:38 +00002001 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002002 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002003 return MatchOperand_Success;
2004}
2005
Jack Carterdc1e35d2012-09-06 20:00:02 +00002006MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2007
Vladimir Medic4c299852013-11-06 11:27:05 +00002008 MCSymbolRefExpr::VariantKind VK =
2009 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2010 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2011 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2012 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2013 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2014 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2015 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2016 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2017 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2018 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2019 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2020 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2021 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2022 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2023 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2024 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2025 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2026 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002027 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2028 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2029 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2030 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2031 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2032 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002033 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2034 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002035 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002036
Matheus Almeida2852af82014-04-22 10:15:54 +00002037 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002038
Jack Carterdc1e35d2012-09-06 20:00:02 +00002039 return VK;
2040}
Jack Cartera63b16a2012-09-07 00:23:42 +00002041
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002042/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2043/// either this.
2044/// ::= '(', register, ')'
2045/// handle it before we iterate so we don't get tripped up by the lack of
2046/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002047bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002048 if (getLexer().is(AsmToken::LParen)) {
2049 Operands.push_back(
2050 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2051 Parser.Lex();
2052 if (ParseOperand(Operands, Name)) {
2053 SMLoc Loc = getLexer().getLoc();
2054 Parser.eatToEndOfStatement();
2055 return Error(Loc, "unexpected token in argument list");
2056 }
2057 if (Parser.getTok().isNot(AsmToken::RParen)) {
2058 SMLoc Loc = getLexer().getLoc();
2059 Parser.eatToEndOfStatement();
2060 return Error(Loc, "unexpected token, expected ')'");
2061 }
2062 Operands.push_back(
2063 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2064 Parser.Lex();
2065 }
2066 return false;
2067}
2068
2069/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2070/// either one of these.
2071/// ::= '[', register, ']'
2072/// ::= '[', integer, ']'
2073/// handle it before we iterate so we don't get tripped up by the lack of
2074/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002075bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2076 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002077 if (getLexer().is(AsmToken::LBrac)) {
2078 Operands.push_back(
2079 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2080 Parser.Lex();
2081 if (ParseOperand(Operands, Name)) {
2082 SMLoc Loc = getLexer().getLoc();
2083 Parser.eatToEndOfStatement();
2084 return Error(Loc, "unexpected token in argument list");
2085 }
2086 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2087 SMLoc Loc = getLexer().getLoc();
2088 Parser.eatToEndOfStatement();
2089 return Error(Loc, "unexpected token, expected ']'");
2090 }
2091 Operands.push_back(
2092 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2093 Parser.Lex();
2094 }
2095 return false;
2096}
2097
David Blaikie960ea3f2014-06-08 16:18:35 +00002098bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2099 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002100 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002101 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002102 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002103 Parser.eatToEndOfStatement();
2104 return Error(NameLoc, "Unknown instruction");
2105 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002106 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002107 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002108
2109 // Read the remaining operands.
2110 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2111 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002112 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002113 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002114 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002115 return Error(Loc, "unexpected token in argument list");
2116 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002117 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2118 return true;
2119 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002120
Jack Carterd0bd6422013-04-18 00:41:53 +00002121 while (getLexer().is(AsmToken::Comma)) {
2122 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002123 // Parse and remember the operand.
2124 if (ParseOperand(Operands, Name)) {
2125 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002126 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002127 return Error(Loc, "unexpected token in argument list");
2128 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002129 // Parse bracket and parenthesis suffixes before we iterate
2130 if (getLexer().is(AsmToken::LBrac)) {
2131 if (ParseBracketSuffix(Name, Operands))
2132 return true;
2133 } else if (getLexer().is(AsmToken::LParen) &&
2134 ParseParenSuffix(Name, Operands))
2135 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002136 }
2137 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002138 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2139 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002140 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002141 return Error(Loc, "unexpected token in argument list");
2142 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002143 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002144 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002145}
2146
Jack Carter0b744b32012-10-04 02:29:46 +00002147bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002148 SMLoc Loc = getLexer().getLoc();
2149 Parser.eatToEndOfStatement();
2150 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002151}
2152
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002153bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2154 return Error(Loc, ErrorMsg);
2155}
2156
Jack Carter0b744b32012-10-04 02:29:46 +00002157bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002158 // Line should look like: ".set noat".
2159 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002160 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002161 // eat noat
2162 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002163 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002164 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2165 reportParseError("unexpected token in statement");
2166 return false;
2167 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002168 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002169 return false;
2170}
Jack Carterd0bd6422013-04-18 00:41:53 +00002171
Jack Carter0b744b32012-10-04 02:29:46 +00002172bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002173 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002174 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002175 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002176 getParser().Lex();
2177 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002178 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002179 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002180 return false;
2181 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002182 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002183 if (getLexer().isNot(AsmToken::Dollar)) {
2184 reportParseError("unexpected token in statement");
2185 return false;
2186 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002187 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002188 const AsmToken &Reg = Parser.getTok();
2189 if (Reg.is(AsmToken::Identifier)) {
2190 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2191 } else if (Reg.is(AsmToken::Integer)) {
2192 AtRegNo = Reg.getIntVal();
2193 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002194 reportParseError("unexpected token in statement");
2195 return false;
2196 }
Jack Carter1ac53222013-02-20 23:11:17 +00002197
Daniel Sanders71a89d922014-03-25 13:01:06 +00002198 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002199 reportParseError("unexpected token in statement");
2200 return false;
2201 }
2202
2203 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002204 reportParseError("unexpected token in statement");
2205 return false;
2206 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002207 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002208
2209 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2210 reportParseError("unexpected token in statement");
2211 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002212 }
2213 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002214 return false;
2215 } else {
2216 reportParseError("unexpected token in statement");
2217 return false;
2218 }
2219}
2220
2221bool MipsAsmParser::parseSetReorderDirective() {
2222 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002223 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002224 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2225 reportParseError("unexpected token in statement");
2226 return false;
2227 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002228 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002229 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002230 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002231 return false;
2232}
2233
2234bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002235 Parser.Lex();
2236 // If this is not the end of the statement, report an error.
2237 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2238 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002239 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002240 }
2241 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002242 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002243 Parser.Lex(); // Consume the EndOfStatement.
2244 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002245}
2246
2247bool MipsAsmParser::parseSetMacroDirective() {
2248 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002249 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002250 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2251 reportParseError("unexpected token in statement");
2252 return false;
2253 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002254 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002255 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002256 return false;
2257}
2258
2259bool MipsAsmParser::parseSetNoMacroDirective() {
2260 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002261 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002262 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2263 reportParseError("`noreorder' must be set before `nomacro'");
2264 return false;
2265 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002266 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002267 reportParseError("`noreorder' must be set before `nomacro'");
2268 return false;
2269 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002270 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002271 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002272 return false;
2273}
Jack Carterd76b2372013-03-21 21:44:16 +00002274
Jack Carter39536722014-01-22 23:08:42 +00002275bool MipsAsmParser::parseSetNoMips16Directive() {
2276 Parser.Lex();
2277 // If this is not the end of the statement, report an error.
2278 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2279 reportParseError("unexpected token in statement");
2280 return false;
2281 }
2282 // For now do nothing.
2283 Parser.Lex(); // Consume the EndOfStatement.
2284 return false;
2285}
2286
Jack Carterd76b2372013-03-21 21:44:16 +00002287bool MipsAsmParser::parseSetAssignment() {
2288 StringRef Name;
2289 const MCExpr *Value;
2290
2291 if (Parser.parseIdentifier(Name))
2292 reportParseError("expected identifier after .set");
2293
2294 if (getLexer().isNot(AsmToken::Comma))
2295 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002296 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002297
Jack Carter3b2c96e2014-01-22 23:31:38 +00002298 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002299 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002300
Jack Carterd0bd6422013-04-18 00:41:53 +00002301 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002302 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002303 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002304 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002305 Sym = getContext().GetOrCreateSymbol(Name);
2306 Sym->setVariableValue(Value);
2307
2308 return false;
2309}
Jack Carterd0bd6422013-04-18 00:41:53 +00002310
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002311bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2312 Parser.Lex();
2313 if (getLexer().isNot(AsmToken::EndOfStatement))
2314 return reportParseError("unexpected token in .set directive");
2315
Matheus Almeida2852af82014-04-22 10:15:54 +00002316 switch (Feature) {
2317 default:
2318 llvm_unreachable("Unimplemented feature");
2319 case Mips::FeatureDSP:
2320 setFeatureBits(Mips::FeatureDSP, "dsp");
2321 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002322 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002323 case Mips::FeatureMicroMips:
2324 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002325 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002326 case Mips::FeatureMips16:
2327 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002328 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002329 case Mips::FeatureMips32r2:
2330 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2331 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002332 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002333 case Mips::FeatureMips64:
2334 setFeatureBits(Mips::FeatureMips64, "mips64");
2335 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002336 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002337 case Mips::FeatureMips64r2:
2338 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2339 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002340 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002341 }
2342 return false;
2343}
2344
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002345bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2346 if (!getLexer().is(AsmToken::Dollar))
2347 return false;
2348
2349 Parser.Lex();
2350
2351 const AsmToken &Reg = Parser.getTok();
2352 if (Reg.is(AsmToken::Identifier)) {
2353 RegNum = matchCPURegisterName(Reg.getIdentifier());
2354 } else if (Reg.is(AsmToken::Integer)) {
2355 RegNum = Reg.getIntVal();
2356 } else {
2357 return false;
2358 }
2359
2360 Parser.Lex();
2361 return true;
2362}
2363
2364bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2365 if (getLexer().isNot(AsmToken::Comma)) {
2366 SMLoc Loc = getLexer().getLoc();
2367 Parser.eatToEndOfStatement();
2368 return Error(Loc, ErrorStr);
2369 }
2370
Matheus Almeida2852af82014-04-22 10:15:54 +00002371 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002372 return true;
2373}
2374
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002375bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2376 if (Options.isReorder())
2377 Warning(Loc, ".cpload in reorder section");
2378
2379 // FIXME: Warn if cpload is used in Mips16 mode.
2380
David Blaikie960ea3f2014-06-08 16:18:35 +00002381 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002382 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2383 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2384 reportParseError("expected register containing function address");
2385 return false;
2386 }
2387
David Blaikie960ea3f2014-06-08 16:18:35 +00002388 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2389 if (!RegOpnd.isGPRAsmReg()) {
2390 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002391 return false;
2392 }
2393
David Blaikie960ea3f2014-06-08 16:18:35 +00002394 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002395 return false;
2396}
2397
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002398bool MipsAsmParser::parseDirectiveCPSetup() {
2399 unsigned FuncReg;
2400 unsigned Save;
2401 bool SaveIsReg = true;
2402
2403 if (!parseRegister(FuncReg))
2404 return reportParseError("expected register containing function address");
2405 FuncReg = getGPR(FuncReg);
2406
2407 if (!eatComma("expected comma parsing directive"))
2408 return true;
2409
2410 if (!parseRegister(Save)) {
2411 const AsmToken &Tok = Parser.getTok();
2412 if (Tok.is(AsmToken::Integer)) {
2413 Save = Tok.getIntVal();
2414 SaveIsReg = false;
2415 Parser.Lex();
2416 } else
2417 return reportParseError("expected save register or stack offset");
2418 } else
2419 Save = getGPR(Save);
2420
2421 if (!eatComma("expected comma parsing directive"))
2422 return true;
2423
2424 StringRef Name;
2425 if (Parser.parseIdentifier(Name))
2426 reportParseError("expected identifier");
2427 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002428
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002429 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002430 return false;
2431}
2432
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002433bool MipsAsmParser::parseDirectiveNaN() {
2434 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2435 const AsmToken &Tok = Parser.getTok();
2436
2437 if (Tok.getString() == "2008") {
2438 Parser.Lex();
2439 getTargetStreamer().emitDirectiveNaN2008();
2440 return false;
2441 } else if (Tok.getString() == "legacy") {
2442 Parser.Lex();
2443 getTargetStreamer().emitDirectiveNaNLegacy();
2444 return false;
2445 }
2446 }
2447 // If we don't recognize the option passed to the .nan
2448 // directive (e.g. no option or unknown option), emit an error.
2449 reportParseError("invalid option in .nan directive");
2450 return false;
2451}
2452
Jack Carter0b744b32012-10-04 02:29:46 +00002453bool MipsAsmParser::parseDirectiveSet() {
2454
Jack Carterd0bd6422013-04-18 00:41:53 +00002455 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002456 const AsmToken &Tok = Parser.getTok();
2457
2458 if (Tok.getString() == "noat") {
2459 return parseSetNoAtDirective();
2460 } else if (Tok.getString() == "at") {
2461 return parseSetAtDirective();
2462 } else if (Tok.getString() == "reorder") {
2463 return parseSetReorderDirective();
2464 } else if (Tok.getString() == "noreorder") {
2465 return parseSetNoReorderDirective();
2466 } else if (Tok.getString() == "macro") {
2467 return parseSetMacroDirective();
2468 } else if (Tok.getString() == "nomacro") {
2469 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002470 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002471 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002472 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002473 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002474 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002475 getTargetStreamer().emitDirectiveSetNoMicroMips();
2476 Parser.eatToEndOfStatement();
2477 return false;
2478 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002479 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002480 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002481 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002482 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002483 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002484 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002485 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002486 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002487 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002488 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002489 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002490 parseSetAssignment();
2491 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002492 }
Jack Carter07c818d2013-01-25 01:31:34 +00002493
Jack Carter0b744b32012-10-04 02:29:46 +00002494 return true;
2495}
2496
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002497/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002498/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002499bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2501 for (;;) {
2502 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002503 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002504 return true;
2505
2506 getParser().getStreamer().EmitValue(Value, Size);
2507
2508 if (getLexer().is(AsmToken::EndOfStatement))
2509 break;
2510
2511 // FIXME: Improve diagnostic.
2512 if (getLexer().isNot(AsmToken::Comma))
2513 return Error(L, "unexpected token in directive");
2514 Parser.Lex();
2515 }
2516 }
2517
2518 Parser.Lex();
2519 return false;
2520}
2521
Vladimir Medic4c299852013-11-06 11:27:05 +00002522/// parseDirectiveGpWord
2523/// ::= .gpword local_sym
2524bool MipsAsmParser::parseDirectiveGpWord() {
2525 const MCExpr *Value;
2526 // EmitGPRel32Value requires an expression, so we are using base class
2527 // method to evaluate the expression.
2528 if (getParser().parseExpression(Value))
2529 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002530 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002531
Vladimir Medice10c1122013-11-13 13:18:04 +00002532 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002533 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002534 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002535 return false;
2536}
2537
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002538/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002539/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002540bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002541 const MCExpr *Value;
2542 // EmitGPRel64Value requires an expression, so we are using base class
2543 // method to evaluate the expression.
2544 if (getParser().parseExpression(Value))
2545 return true;
2546 getParser().getStreamer().EmitGPRel64Value(Value);
2547
2548 if (getLexer().isNot(AsmToken::EndOfStatement))
2549 return Error(getLexer().getLoc(), "unexpected token in directive");
2550 Parser.Lex(); // Eat EndOfStatement token.
2551 return false;
2552}
2553
Jack Carter0cd3c192014-01-06 23:27:31 +00002554bool MipsAsmParser::parseDirectiveOption() {
2555 // Get the option token.
2556 AsmToken Tok = Parser.getTok();
2557 // At the moment only identifiers are supported.
2558 if (Tok.isNot(AsmToken::Identifier)) {
2559 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2560 Parser.eatToEndOfStatement();
2561 return false;
2562 }
2563
2564 StringRef Option = Tok.getIdentifier();
2565
2566 if (Option == "pic0") {
2567 getTargetStreamer().emitDirectiveOptionPic0();
2568 Parser.Lex();
2569 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2570 Error(Parser.getTok().getLoc(),
2571 "unexpected token in .option pic0 directive");
2572 Parser.eatToEndOfStatement();
2573 }
2574 return false;
2575 }
2576
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002577 if (Option == "pic2") {
2578 getTargetStreamer().emitDirectiveOptionPic2();
2579 Parser.Lex();
2580 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2581 Error(Parser.getTok().getLoc(),
2582 "unexpected token in .option pic2 directive");
2583 Parser.eatToEndOfStatement();
2584 }
2585 return false;
2586 }
2587
Jack Carter0cd3c192014-01-06 23:27:31 +00002588 // Unknown option.
2589 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2590 Parser.eatToEndOfStatement();
2591 return false;
2592}
2593
Jack Carter0b744b32012-10-04 02:29:46 +00002594bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002595 StringRef IDVal = DirectiveID.getString();
2596
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002597 if (IDVal == ".cpload")
2598 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002599 if (IDVal == ".dword") {
2600 parseDataDirective(8, DirectiveID.getLoc());
2601 return false;
2602 }
2603
Jack Carterd0bd6422013-04-18 00:41:53 +00002604 if (IDVal == ".ent") {
2605 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002606 Parser.Lex();
2607 return false;
2608 }
2609
Jack Carter07c818d2013-01-25 01:31:34 +00002610 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002611 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002612 Parser.Lex();
2613 return false;
2614 }
2615
Jack Carter07c818d2013-01-25 01:31:34 +00002616 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002617 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002618 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002619 return false;
2620 }
2621
Jack Carter07c818d2013-01-25 01:31:34 +00002622 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002623 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002624 }
2625
Jack Carter07c818d2013-01-25 01:31:34 +00002626 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002627 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002628 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002629 return false;
2630 }
2631
Jack Carter07c818d2013-01-25 01:31:34 +00002632 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002633 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002634 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002635 return false;
2636 }
2637
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002638 if (IDVal == ".nan")
2639 return parseDirectiveNaN();
2640
Jack Carter07c818d2013-01-25 01:31:34 +00002641 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002642 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002643 return false;
2644 }
2645
Rafael Espindolab59fb732014-03-28 18:50:26 +00002646 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002647 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002648 return false;
2649 }
2650
Jack Carter07c818d2013-01-25 01:31:34 +00002651 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002652 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002653 return false;
2654 }
2655
Jack Carter0cd3c192014-01-06 23:27:31 +00002656 if (IDVal == ".option")
2657 return parseDirectiveOption();
2658
2659 if (IDVal == ".abicalls") {
2660 getTargetStreamer().emitDirectiveAbiCalls();
2661 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2662 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2663 // Clear line
2664 Parser.eatToEndOfStatement();
2665 }
2666 return false;
2667 }
2668
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002669 if (IDVal == ".cpsetup")
2670 return parseDirectiveCPSetup();
2671
Rafael Espindola870c4e92012-01-11 03:56:41 +00002672 return true;
2673}
2674
Rafael Espindola870c4e92012-01-11 03:56:41 +00002675extern "C" void LLVMInitializeMipsAsmParser() {
2676 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2677 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2678 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2679 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2680}
Jack Carterb4dbc172012-09-05 23:34:03 +00002681
2682#define GET_REGISTER_MATCHER
2683#define GET_MATCHER_IMPLEMENTATION
2684#include "MipsGenAsmMatcher.inc"