blob: b3018c960297f9da89cf0a1c1e7b520913f523fd [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; }
179
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000180 bool parseRegister(unsigned &RegNum);
181
182 bool eatComma(StringRef ErrorStr);
183
Jack Carter1ac53222013-02-20 23:11:17 +0000184 int matchCPURegisterName(StringRef Symbol);
185
Jack Carter873c7242013-01-12 01:03:14 +0000186 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000187
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000188 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000189
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000190 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000191
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000192 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000193
Jack Carter5dc8ac92013-09-25 23:50:44 +0000194 int matchMSA128RegisterName(StringRef Name);
195
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000196 int matchMSA128CtrlRegisterName(StringRef Name);
197
Jack Carterd0bd6422013-04-18 00:41:53 +0000198 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000199
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000200 unsigned getGPR(int RegNo);
201
Jack Carter1ac53222013-02-20 23:11:17 +0000202 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000203
204 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000205 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000206
207 // Helper function that checks if the value of a vector index is within the
208 // boundaries of accepted values for each RegisterKind
209 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
210 bool validateMSAIndex(int Val, int RegKind);
211
Vladimir Medic615b26e2014-03-04 09:54:09 +0000212 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
213 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000214 setAvailableFeatures(
215 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000216 }
217 }
218
219 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
220 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000221 setAvailableFeatures(
222 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000223 }
224 }
225
Rafael Espindola870c4e92012-01-11 03:56:41 +0000226public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000227 enum MipsMatchResultTy {
228 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
229#define GET_OPERAND_DIAGNOSTIC_TYPES
230#include "MipsGenAsmMatcher.inc"
231#undef GET_OPERAND_DIAGNOSTIC_TYPES
232
233 };
234
Joey Gouly0e76fa72013-09-12 10:28:05 +0000235 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000236 const MCInstrInfo &MII,
237 const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000238 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000239 // Initialize the set of available features.
240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000241
242 // Assert exactly one ABI was chosen.
243 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
244 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
245 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
246 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000247 }
248
Jack Carterb4dbc172012-09-05 23:34:03 +0000249 MCAsmParser &getParser() const { return Parser; }
250 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000251
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000252 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
253 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
254
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000255 /// Warn if RegNo is the current assembler temporary.
256 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000257};
258}
259
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000260namespace {
261
262/// MipsOperand - Instances of this class represent a parsed Mips machine
263/// instruction.
264class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000265public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000266 /// Broad categories of register classes
267 /// The exact class is finalized by the render method.
268 enum RegKind {
269 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
270 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
271 /// isFP64())
272 RegKind_FCC = 4, /// FCC
273 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
274 RegKind_MSACtrl = 16, /// MSA control registers
275 RegKind_COP2 = 32, /// COP2
276 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
277 /// context).
278 RegKind_CCR = 128, /// CCR
279 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000280 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000281
282 /// Potentially any (e.g. $1)
283 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
284 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000285 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000286 };
287
288private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000289 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000290 k_Immediate, /// An immediate (possibly involving symbol references)
291 k_Memory, /// Base + Offset Memory Address
292 k_PhysRegister, /// A physical register from the Mips namespace
293 k_RegisterIndex, /// A register index in one or more RegKind.
294 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000295 } Kind;
296
David Blaikie960ea3f2014-06-08 16:18:35 +0000297public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000298 MipsOperand(KindTy K, MipsAsmParser &Parser)
299 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
300
David Blaikie960ea3f2014-06-08 16:18:35 +0000301private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000302 /// For diagnostics, and checking the assembler temporary
303 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000304
Eric Christopher8996c5d2013-03-15 00:42:55 +0000305 struct Token {
306 const char *Data;
307 unsigned Length;
308 };
309
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000310 struct PhysRegOp {
311 unsigned Num; /// Register Number
312 };
313
314 struct RegIdxOp {
315 unsigned Index; /// Index into the register class
316 RegKind Kind; /// Bitfield of the kinds it could possibly be
317 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000318 };
319
320 struct ImmOp {
321 const MCExpr *Val;
322 };
323
324 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000325 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000326 const MCExpr *Off;
327 };
328
Jack Carterb4dbc172012-09-05 23:34:03 +0000329 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000330 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000331 struct PhysRegOp PhysReg;
332 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000333 struct ImmOp Imm;
334 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000335 };
336
337 SMLoc StartLoc, EndLoc;
338
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000339 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000340 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
341 const MCRegisterInfo *RegInfo,
342 SMLoc S, SMLoc E,
343 MipsAsmParser &Parser) {
344 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000345 Op->RegIdx.Index = Index;
346 Op->RegIdx.RegInfo = RegInfo;
347 Op->RegIdx.Kind = RegKind;
348 Op->StartLoc = S;
349 Op->EndLoc = E;
350 return Op;
351 }
352
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000353public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000354 /// Coerce the register to GPR32 and return the real register for the current
355 /// target.
356 unsigned getGPR32Reg() const {
357 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
358 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
359 unsigned ClassID = Mips::GPR32RegClassID;
360 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000361 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000362
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000363 /// Coerce the register to GPR64 and return the real register for the current
364 /// target.
365 unsigned getGPR64Reg() const {
366 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
367 unsigned ClassID = Mips::GPR64RegClassID;
368 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000369 }
370
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000371private:
372 /// Coerce the register to AFGR64 and return the real register for the current
373 /// target.
374 unsigned getAFGR64Reg() const {
375 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
376 if (RegIdx.Index % 2 != 0)
377 AsmParser.Warning(StartLoc, "Float register should be even.");
378 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
379 .getRegister(RegIdx.Index / 2);
380 }
381
382 /// Coerce the register to FGR64 and return the real register for the current
383 /// target.
384 unsigned getFGR64Reg() const {
385 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
386 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
387 .getRegister(RegIdx.Index);
388 }
389
390 /// Coerce the register to FGR32 and return the real register for the current
391 /// target.
392 unsigned getFGR32Reg() const {
393 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
394 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
395 .getRegister(RegIdx.Index);
396 }
397
398 /// Coerce the register to FGRH32 and return the real register for the current
399 /// target.
400 unsigned getFGRH32Reg() const {
401 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
402 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
403 .getRegister(RegIdx.Index);
404 }
405
406 /// Coerce the register to FCC and return the real register for the current
407 /// target.
408 unsigned getFCCReg() const {
409 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
410 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
411 .getRegister(RegIdx.Index);
412 }
413
414 /// Coerce the register to MSA128 and return the real register for the current
415 /// target.
416 unsigned getMSA128Reg() const {
417 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
418 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
419 // identical
420 unsigned ClassID = Mips::MSA128BRegClassID;
421 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
422 }
423
424 /// Coerce the register to MSACtrl and return the real register for the
425 /// current target.
426 unsigned getMSACtrlReg() const {
427 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
428 unsigned ClassID = Mips::MSACtrlRegClassID;
429 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
430 }
431
432 /// Coerce the register to COP2 and return the real register for the
433 /// current target.
434 unsigned getCOP2Reg() const {
435 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
436 unsigned ClassID = Mips::COP2RegClassID;
437 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
438 }
439
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000440 /// Coerce the register to COP3 and return the real register for the
441 /// current target.
442 unsigned getCOP3Reg() const {
443 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
444 unsigned ClassID = Mips::COP3RegClassID;
445 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
446 }
447
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000448 /// Coerce the register to ACC64DSP and return the real register for the
449 /// current target.
450 unsigned getACC64DSPReg() const {
451 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
452 unsigned ClassID = Mips::ACC64DSPRegClassID;
453 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
454 }
455
456 /// Coerce the register to HI32DSP and return the real register for the
457 /// current target.
458 unsigned getHI32DSPReg() const {
459 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
460 unsigned ClassID = Mips::HI32DSPRegClassID;
461 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
462 }
463
464 /// Coerce the register to LO32DSP and return the real register for the
465 /// current target.
466 unsigned getLO32DSPReg() const {
467 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
468 unsigned ClassID = Mips::LO32DSPRegClassID;
469 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
470 }
471
472 /// Coerce the register to CCR and return the real register for the
473 /// current target.
474 unsigned getCCRReg() const {
475 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
476 unsigned ClassID = Mips::CCRRegClassID;
477 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
478 }
479
480 /// Coerce the register to HWRegs and return the real register for the
481 /// current target.
482 unsigned getHWRegsReg() const {
483 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
484 unsigned ClassID = Mips::HWRegsRegClassID;
485 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
486 }
487
488public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000489 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000490 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000491 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000492 Inst.addOperand(MCOperand::CreateImm(0));
493 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
494 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
495 else
496 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000497 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000498
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000499 void addRegOperands(MCInst &Inst, unsigned N) const {
500 llvm_unreachable("Use a custom parser instead");
501 }
502
Daniel Sanders21bce302014-04-01 12:35:23 +0000503 /// Render the operand to an MCInst as a GPR32
504 /// Asserts if the wrong number of operands are requested, or the operand
505 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000506 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
507 assert(N == 1 && "Invalid number of operands!");
508 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
509 }
510
Daniel Sanders21bce302014-04-01 12:35:23 +0000511 /// Render the operand to an MCInst as a GPR64
512 /// Asserts if the wrong number of operands are requested, or the operand
513 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000514 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
515 assert(N == 1 && "Invalid number of operands!");
516 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
517 }
518
519 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
520 assert(N == 1 && "Invalid number of operands!");
521 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
522 }
523
524 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
525 assert(N == 1 && "Invalid number of operands!");
526 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
527 }
528
529 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
530 assert(N == 1 && "Invalid number of operands!");
531 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
532 }
533
534 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
535 assert(N == 1 && "Invalid number of operands!");
536 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
537 }
538
539 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
540 assert(N == 1 && "Invalid number of operands!");
541 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
542 }
543
544 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
545 assert(N == 1 && "Invalid number of operands!");
546 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
547 }
548
549 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
550 assert(N == 1 && "Invalid number of operands!");
551 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
552 }
553
554 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
555 assert(N == 1 && "Invalid number of operands!");
556 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
557 }
558
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000559 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
560 assert(N == 1 && "Invalid number of operands!");
561 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
562 }
563
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000564 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
565 assert(N == 1 && "Invalid number of operands!");
566 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
567 }
568
569 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
570 assert(N == 1 && "Invalid number of operands!");
571 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
572 }
573
574 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
575 assert(N == 1 && "Invalid number of operands!");
576 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
577 }
578
579 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
580 assert(N == 1 && "Invalid number of operands!");
581 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
582 }
583
584 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
585 assert(N == 1 && "Invalid number of operands!");
586 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
587 }
588
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000589 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000590 assert(N == 1 && "Invalid number of operands!");
591 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000592 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000593 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000594
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000595 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000596 assert(N == 2 && "Invalid number of operands!");
597
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000599
600 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000601 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000602 }
603
Craig Topper56c590a2014-04-29 07:58:02 +0000604 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000605 // As a special case until we sort out the definition of div/divu, pretend
606 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
607 if (isGPRAsmReg() && RegIdx.Index == 0)
608 return true;
609
610 return Kind == k_PhysRegister;
611 }
612 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000613 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000614 bool isConstantImm() const {
615 return isImm() && dyn_cast<MCConstantExpr>(getImm());
616 }
Craig Topper56c590a2014-04-29 07:58:02 +0000617 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000618 // Note: It's not possible to pretend that other operand kinds are tokens.
619 // The matcher emitter checks tokens first.
620 return Kind == k_Token;
621 }
Craig Topper56c590a2014-04-29 07:58:02 +0000622 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000623 bool isConstantMemOff() const {
624 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
625 }
626 template <unsigned Bits> bool isMemWithSimmOffset() const {
627 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
628 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000629 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000630 bool isLSAImm() const {
631 if (!isConstantImm())
632 return false;
633 int64_t Val = getConstantImm();
634 return 1 <= Val && Val <= 4;
635 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000636
637 StringRef getToken() const {
638 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000639 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000640 }
641
Craig Topper56c590a2014-04-29 07:58:02 +0000642 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000643 // As a special case until we sort out the definition of div/divu, pretend
644 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
645 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
646 RegIdx.Kind & RegKind_GPR)
647 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000648
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 assert(Kind == k_PhysRegister && "Invalid access!");
650 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000651 }
652
Jack Carterb4dbc172012-09-05 23:34:03 +0000653 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000654 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000655 return Imm.Val;
656 }
657
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000658 int64_t getConstantImm() const {
659 const MCExpr *Val = getImm();
660 return static_cast<const MCConstantExpr *>(Val)->getValue();
661 }
662
663 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000664 assert((Kind == k_Memory) && "Invalid access!");
665 return Mem.Base;
666 }
667
668 const MCExpr *getMemOff() const {
669 assert((Kind == k_Memory) && "Invalid access!");
670 return Mem.Off;
671 }
672
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000673 int64_t getConstantMemOff() const {
674 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
675 }
676
David Blaikie960ea3f2014-06-08 16:18:35 +0000677 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
678 MipsAsmParser &Parser) {
679 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000680 Op->Tok.Data = Str.data();
681 Op->Tok.Length = Str.size();
682 Op->StartLoc = S;
683 Op->EndLoc = S;
684 return Op;
685 }
686
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000687 /// Create a numeric register (e.g. $1). The exact register remains
688 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000689 static std::unique_ptr<MipsOperand>
690 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
691 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000692 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
693 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000694 }
695
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000696 /// Create a register that is definitely a GPR.
697 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000698 static std::unique_ptr<MipsOperand>
699 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
700 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000701 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000702 }
703
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000704 /// Create a register that is definitely a FGR.
705 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000706 static std::unique_ptr<MipsOperand>
707 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
708 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000709 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
710 }
711
712 /// Create a register that is definitely an FCC.
713 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000714 static std::unique_ptr<MipsOperand>
715 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
716 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000717 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
718 }
719
720 /// Create a register that is definitely an ACC.
721 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000722 static std::unique_ptr<MipsOperand>
723 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
724 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000725 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
726 }
727
728 /// Create a register that is definitely an MSA128.
729 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000730 static std::unique_ptr<MipsOperand>
731 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
732 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000733 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
734 }
735
736 /// Create a register that is definitely an MSACtrl.
737 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000738 static std::unique_ptr<MipsOperand>
739 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
740 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
742 }
743
David Blaikie960ea3f2014-06-08 16:18:35 +0000744 static std::unique_ptr<MipsOperand>
745 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
746 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000747 Op->Imm.Val = Val;
748 Op->StartLoc = S;
749 Op->EndLoc = E;
750 return Op;
751 }
752
David Blaikie960ea3f2014-06-08 16:18:35 +0000753 static std::unique_ptr<MipsOperand>
754 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
755 SMLoc E, MipsAsmParser &Parser) {
756 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
757 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000758 Op->Mem.Off = Off;
759 Op->StartLoc = S;
760 Op->EndLoc = E;
761 return Op;
762 }
763
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000764 bool isGPRAsmReg() const {
765 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000766 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 bool isFGRAsmReg() const {
768 // AFGR64 is $0-$15 but we handle this in getAFGR64()
769 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000770 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 bool isHWRegsAsmReg() const {
772 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000773 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 bool isCCRAsmReg() const {
775 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000776 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000777 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000778 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
779 return false;
780 if (!AsmParser.hasEightFccRegisters())
781 return RegIdx.Index == 0;
782 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000783 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000784 bool isACCAsmReg() const {
785 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000786 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000787 bool isCOP2AsmReg() const {
788 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000789 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000790 bool isCOP3AsmReg() const {
791 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
792 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 bool isMSA128AsmReg() const {
794 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000795 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 bool isMSACtrlAsmReg() const {
797 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000798 }
799
Jack Carterb4dbc172012-09-05 23:34:03 +0000800 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000801 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000802 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000803 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000804
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000805 virtual ~MipsOperand() {
806 switch (Kind) {
807 case k_Immediate:
808 break;
809 case k_Memory:
810 delete Mem.Base;
811 break;
812 case k_PhysRegister:
813 case k_RegisterIndex:
814 case k_Token:
815 break;
816 }
817 }
818
Craig Topper56c590a2014-04-29 07:58:02 +0000819 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 switch (Kind) {
821 case k_Immediate:
822 OS << "Imm<";
823 Imm.Val->print(OS);
824 OS << ">";
825 break;
826 case k_Memory:
827 OS << "Mem<";
828 Mem.Base->print(OS);
829 OS << ", ";
830 Mem.Off->print(OS);
831 OS << ">";
832 break;
833 case k_PhysRegister:
834 OS << "PhysReg<" << PhysReg.Num << ">";
835 break;
836 case k_RegisterIndex:
837 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
838 break;
839 case k_Token:
840 OS << Tok.Data;
841 break;
842 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000843 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000844}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000845} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000846
Jack Carter9e65aa32013-03-22 00:05:30 +0000847namespace llvm {
848extern const MCInstrDesc MipsInsts[];
849}
850static const MCInstrDesc &getInstDesc(unsigned Opcode) {
851 return MipsInsts[Opcode];
852}
853
854bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000855 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000856 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000857
Jack Carter9e65aa32013-03-22 00:05:30 +0000858 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000859
860 if (MCID.isBranch() || MCID.isCall()) {
861 const unsigned Opcode = Inst.getOpcode();
862 MCOperand Offset;
863
864 switch (Opcode) {
865 default:
866 break;
867 case Mips::BEQ:
868 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 case Mips::BEQ_MM:
870 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000871 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000872 Offset = Inst.getOperand(2);
873 if (!Offset.isImm())
874 break; // We'll deal with this situation later on when applying fixups.
875 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
876 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000877 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000878 return Error(IDLoc, "branch to misaligned address");
879 break;
880 case Mips::BGEZ:
881 case Mips::BGTZ:
882 case Mips::BLEZ:
883 case Mips::BLTZ:
884 case Mips::BGEZAL:
885 case Mips::BLTZAL:
886 case Mips::BC1F:
887 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000888 case Mips::BGEZ_MM:
889 case Mips::BGTZ_MM:
890 case Mips::BLEZ_MM:
891 case Mips::BLTZ_MM:
892 case Mips::BGEZAL_MM:
893 case Mips::BLTZAL_MM:
894 case Mips::BC1F_MM:
895 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000896 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000897 Offset = Inst.getOperand(1);
898 if (!Offset.isImm())
899 break; // We'll deal with this situation later on when applying fixups.
900 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
901 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000902 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000903 return Error(IDLoc, "branch to misaligned address");
904 break;
905 }
906 }
907
Jack Carterc15c1d22013-04-25 23:31:35 +0000908 if (MCID.hasDelaySlot() && Options.isReorder()) {
909 // If this instruction has a delay slot and .set reorder is active,
910 // emit a NOP after it.
911 Instructions.push_back(Inst);
912 MCInst NopInst;
913 NopInst.setOpcode(Mips::SLL);
914 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
915 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
916 NopInst.addOperand(MCOperand::CreateImm(0));
917 Instructions.push_back(NopInst);
918 return false;
919 }
920
Jack Carter9e65aa32013-03-22 00:05:30 +0000921 if (MCID.mayLoad() || MCID.mayStore()) {
922 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000923 // reference or immediate we may have to expand instructions.
924 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000925 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000926 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
927 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000928 MCOperand &Op = Inst.getOperand(i);
929 if (Op.isImm()) {
930 int MemOffset = Op.getImm();
931 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000932 // Offset can't exceed 16bit value.
933 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000934 return false;
935 }
936 } else if (Op.isExpr()) {
937 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000938 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000939 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000940 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000941 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000942 // Expand symbol.
943 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000944 return false;
945 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000946 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000947 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000948 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000949 }
950 }
951 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000952 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000953 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000954
955 if (needsExpansion(Inst))
956 expandInstruction(Inst, IDLoc, Instructions);
957 else
958 Instructions.push_back(Inst);
959
960 return false;
961}
962
Jack Carter30a59822012-10-04 04:03:53 +0000963bool MipsAsmParser::needsExpansion(MCInst &Inst) {
964
Jack Carterd0bd6422013-04-18 00:41:53 +0000965 switch (Inst.getOpcode()) {
966 case Mips::LoadImm32Reg:
967 case Mips::LoadAddr32Imm:
968 case Mips::LoadAddr32Reg:
969 return true;
970 default:
971 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000972 }
973}
Jack Carter92995f12012-10-06 00:53:28 +0000974
Jack Carter30a59822012-10-04 04:03:53 +0000975void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000976 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000977 switch (Inst.getOpcode()) {
978 case Mips::LoadImm32Reg:
979 return expandLoadImm(Inst, IDLoc, Instructions);
980 case Mips::LoadAddr32Imm:
981 return expandLoadAddressImm(Inst, IDLoc, Instructions);
982 case Mips::LoadAddr32Reg:
983 return expandLoadAddressReg(Inst, IDLoc, Instructions);
984 }
Jack Carter30a59822012-10-04 04:03:53 +0000985}
Jack Carter92995f12012-10-06 00:53:28 +0000986
Jack Carter30a59822012-10-04 04:03:53 +0000987void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000988 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000989 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000990 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000991 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000992 const MCOperand &RegOp = Inst.getOperand(0);
993 assert(RegOp.isReg() && "expected register operand kind");
994
995 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000996 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000997 if (0 <= ImmValue && ImmValue <= 65535) {
998 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000999 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001000 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001001 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001002 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001003 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001004 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001005 } else if (ImmValue < 0 && ImmValue >= -32768) {
1006 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001007 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001008 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001009 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001010 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001011 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001012 Instructions.push_back(tmpInst);
1013 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001014 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +00001015 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001016 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001017 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001018 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1019 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001020 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +00001021 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001022 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001023 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1024 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1025 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1026 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +00001027 Instructions.push_back(tmpInst);
1028 }
1029}
Jack Carter92995f12012-10-06 00:53:28 +00001030
Vladimir Medic4c299852013-11-06 11:27:05 +00001031void
1032MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1033 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001034 MCInst tmpInst;
1035 const MCOperand &ImmOp = Inst.getOperand(2);
1036 assert(ImmOp.isImm() && "expected immediate operand kind");
1037 const MCOperand &SrcRegOp = Inst.getOperand(1);
1038 assert(SrcRegOp.isReg() && "expected register operand kind");
1039 const MCOperand &DstRegOp = Inst.getOperand(0);
1040 assert(DstRegOp.isReg() && "expected register operand kind");
1041 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001042 if (-32768 <= ImmValue && ImmValue <= 65535) {
1043 // For -32768 <= j <= 65535.
1044 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001045 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001046 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1047 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1048 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1049 Instructions.push_back(tmpInst);
1050 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001051 // For any other value of j that is representable as a 32-bit integer.
1052 // la d,j(s) => lui d,hi16(j)
1053 // ori d,d,lo16(j)
1054 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001055 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001056 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1057 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1058 Instructions.push_back(tmpInst);
1059 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001060 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001061 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1062 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1063 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1064 Instructions.push_back(tmpInst);
1065 tmpInst.clear();
1066 tmpInst.setOpcode(Mips::ADDu);
1067 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1068 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1069 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1070 Instructions.push_back(tmpInst);
1071 }
1072}
1073
Vladimir Medic4c299852013-11-06 11:27:05 +00001074void
1075MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1076 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001077 MCInst tmpInst;
1078 const MCOperand &ImmOp = Inst.getOperand(1);
1079 assert(ImmOp.isImm() && "expected immediate operand kind");
1080 const MCOperand &RegOp = Inst.getOperand(0);
1081 assert(RegOp.isReg() && "expected register operand kind");
1082 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001083 if (-32768 <= ImmValue && ImmValue <= 65535) {
1084 // For -32768 <= j <= 65535.
1085 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001086 tmpInst.setOpcode(Mips::ADDiu);
1087 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001089 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1090 Instructions.push_back(tmpInst);
1091 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001092 // For any other value of j that is representable as a 32-bit integer.
1093 // la d,j => lui d,hi16(j)
1094 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001095 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001096 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1097 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1098 Instructions.push_back(tmpInst);
1099 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001100 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001101 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1102 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1103 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1104 Instructions.push_back(tmpInst);
1105 }
1106}
1107
Jack Carter9e65aa32013-03-22 00:05:30 +00001108void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001109 SmallVectorImpl<MCInst> &Instructions,
1110 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001111 const MCSymbolRefExpr *SR;
1112 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001113 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001114 const MCExpr *ExprOffset;
1115 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +00001116 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001117 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +00001118 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001119 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1120 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001121 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001122 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1123 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001124 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001125 if (isImmOpnd) {
1126 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1127 ImmOffset = Inst.getOperand(2).getImm();
1128 LoOffset = ImmOffset & 0x0000ffff;
1129 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001130 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001131 if (LoOffset & 0x8000)
1132 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001133 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001134 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001135 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001136 TempInst.setLoc(IDLoc);
1137 // 1st instruction in expansion is LUi. For load instruction we can use
1138 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001139 // but for stores we must use $at.
1140 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +00001141 TempInst.setOpcode(Mips::LUi);
1142 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1143 if (isImmOpnd)
1144 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1145 else {
1146 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001147 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001148 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1149 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1150 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001151 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001152 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001153 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001154 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001155 }
1156 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001157 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001158 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001159 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001160 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001161 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001162 TempInst.setOpcode(Mips::ADDu);
1163 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1164 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1165 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1166 Instructions.push_back(TempInst);
1167 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001168 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001169 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001170 TempInst.setOpcode(Inst.getOpcode());
1171 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1172 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1173 if (isImmOpnd)
1174 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1175 else {
1176 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001177 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1178 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1179 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001180 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001181 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001182 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001183 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001184 }
1185 }
1186 Instructions.push_back(TempInst);
1187 TempInst.clear();
1188}
1189
Matheus Almeida595fcab2014-06-11 15:05:56 +00001190unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1191 // As described by the Mips32r2 spec, the registers Rd and Rs for
1192 // jalr.hb must be different.
1193 unsigned Opcode = Inst.getOpcode();
1194
1195 if (Opcode == Mips::JALR_HB &&
1196 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1197 return Match_RequiresDifferentSrcAndDst;
1198
1199 return Match_Success;
1200}
1201
David Blaikie960ea3f2014-06-08 16:18:35 +00001202bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1203 OperandVector &Operands,
1204 MCStreamer &Out,
1205 unsigned &ErrorInfo,
1206 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001207
Jack Carterb4dbc172012-09-05 23:34:03 +00001208 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001209 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001210 unsigned MatchResult =
1211 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001212
1213 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001214 default:
1215 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001216 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001217 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001218 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001219 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001220 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001221 return false;
1222 }
1223 case Match_MissingFeature:
1224 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1225 return true;
1226 case Match_InvalidOperand: {
1227 SMLoc ErrorLoc = IDLoc;
1228 if (ErrorInfo != ~0U) {
1229 if (ErrorInfo >= Operands.size())
1230 return Error(IDLoc, "too few operands for instruction");
1231
David Blaikie960ea3f2014-06-08 16:18:35 +00001232 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001233 if (ErrorLoc == SMLoc())
1234 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001235 }
1236
1237 return Error(ErrorLoc, "invalid operand for instruction");
1238 }
1239 case Match_MnemonicFail:
1240 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001241 case Match_RequiresDifferentSrcAndDst:
1242 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001243 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001244 return true;
1245}
1246
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001247void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1248 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1249 if (RegIndex == 1)
1250 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001251 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001252 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1253 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001254 }
1255}
1256
Jack Carter1ac53222013-02-20 23:11:17 +00001257int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001258 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001259
Vladimir Medic4c299852013-11-06 11:27:05 +00001260 CC = StringSwitch<unsigned>(Name)
1261 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001262 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001263 .Case("a0", 4)
1264 .Case("a1", 5)
1265 .Case("a2", 6)
1266 .Case("a3", 7)
1267 .Case("v0", 2)
1268 .Case("v1", 3)
1269 .Case("s0", 16)
1270 .Case("s1", 17)
1271 .Case("s2", 18)
1272 .Case("s3", 19)
1273 .Case("s4", 20)
1274 .Case("s5", 21)
1275 .Case("s6", 22)
1276 .Case("s7", 23)
1277 .Case("k0", 26)
1278 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001279 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001280 .Case("sp", 29)
1281 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001282 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001283 .Case("ra", 31)
1284 .Case("t0", 8)
1285 .Case("t1", 9)
1286 .Case("t2", 10)
1287 .Case("t3", 11)
1288 .Case("t4", 12)
1289 .Case("t5", 13)
1290 .Case("t6", 14)
1291 .Case("t7", 15)
1292 .Case("t8", 24)
1293 .Case("t9", 25)
1294 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001295
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001296 if (isN32() || isN64()) {
1297 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1298 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1299 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1300 if (8 <= CC && CC <= 11)
1301 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001302
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001303 if (CC == -1)
1304 CC = StringSwitch<unsigned>(Name)
1305 .Case("a4", 8)
1306 .Case("a5", 9)
1307 .Case("a6", 10)
1308 .Case("a7", 11)
1309 .Case("kt0", 26)
1310 .Case("kt1", 27)
1311 .Default(-1);
1312 }
Jack Carter1ac53222013-02-20 23:11:17 +00001313
1314 return CC;
1315}
Jack Carterd0bd6422013-04-18 00:41:53 +00001316
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001317int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001318
Jack Cartera63b16a2012-09-07 00:23:42 +00001319 if (Name[0] == 'f') {
1320 StringRef NumString = Name.substr(1);
1321 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001322 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001323 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001324 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001325 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001326 return IntVal;
1327 }
1328 return -1;
1329}
Jack Cartera63b16a2012-09-07 00:23:42 +00001330
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001331int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1332
1333 if (Name.startswith("fcc")) {
1334 StringRef NumString = Name.substr(3);
1335 unsigned IntVal;
1336 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 > 7) // There are only 8 fcc registers.
1339 return -1;
1340 return IntVal;
1341 }
1342 return -1;
1343}
1344
1345int MipsAsmParser::matchACRegisterName(StringRef Name) {
1346
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001347 if (Name.startswith("ac")) {
1348 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001349 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 > 3) // There are only 3 acc registers.
1353 return -1;
1354 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001355 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001356 return -1;
1357}
Jack Carterd0bd6422013-04-18 00:41:53 +00001358
Jack Carter5dc8ac92013-09-25 23:50:44 +00001359int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1360 unsigned IntVal;
1361
1362 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1363 return -1;
1364
1365 if (IntVal > 31)
1366 return -1;
1367
1368 return IntVal;
1369}
1370
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001371int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1372 int CC;
1373
1374 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001375 .Case("msair", 0)
1376 .Case("msacsr", 1)
1377 .Case("msaaccess", 2)
1378 .Case("msasave", 3)
1379 .Case("msamodify", 4)
1380 .Case("msarequest", 5)
1381 .Case("msamap", 6)
1382 .Case("msaunmap", 7)
1383 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001384
1385 return CC;
1386}
1387
Jack Carter0b744b32012-10-04 02:29:46 +00001388bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1389 if (Reg > 31)
1390 return false;
1391
1392 aTReg = Reg;
1393 return true;
1394}
1395
Daniel Sandersd89b1362014-03-24 16:48:01 +00001396int MipsAsmParser::getATReg() {
1397 int AT = Options.getATRegNum();
1398 if (AT == 0)
1399 TokError("Pseudo instruction requires $at, which is not available");
1400 return AT;
1401}
Jack Carter0b744b32012-10-04 02:29:46 +00001402
Jack Carterd0bd6422013-04-18 00:41:53 +00001403unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001404 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001405}
1406
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001407unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001408 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1409 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001410}
1411
Jack Carter873c7242013-01-12 01:03:14 +00001412int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001413 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001414 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001415 return -1;
1416
Jack Carter873c7242013-01-12 01:03:14 +00001417 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001418}
1419
David Blaikie960ea3f2014-06-08 16:18:35 +00001420bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001421 DEBUG(dbgs() << "ParseOperand\n");
1422
Jack Carter30a59822012-10-04 04:03:53 +00001423 // Check if the current operand has a custom associated parser, if so, try to
1424 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001425 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1426 if (ResTy == MatchOperand_Success)
1427 return false;
1428 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1429 // there was a match, but an error occurred, in which case, just return that
1430 // the operand parsing failed.
1431 if (ResTy == MatchOperand_ParseFail)
1432 return true;
1433
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001434 DEBUG(dbgs() << ".. Generic Parser\n");
1435
Jack Carterb4dbc172012-09-05 23:34:03 +00001436 switch (getLexer().getKind()) {
1437 default:
1438 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1439 return true;
1440 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001441 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001442 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001443
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001444 // Almost all registers have been parsed by custom parsers. There is only
1445 // one exception to this. $zero (and it's alias $0) will reach this point
1446 // for div, divu, and similar instructions because it is not an operand
1447 // to the instruction definition but an explicit register. Special case
1448 // this situation for now.
1449 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001450 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001451
Jack Carterd0bd6422013-04-18 00:41:53 +00001452 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001453 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001454 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001455 return true;
1456
Jack Carter873c7242013-01-12 01:03:14 +00001457 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001458 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001459 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001460 const MCExpr *Res =
1461 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001462
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001463 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001464 return false;
1465 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001466 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001467 case AsmToken::LParen:
1468 case AsmToken::Minus:
1469 case AsmToken::Plus:
1470 case AsmToken::Integer:
1471 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001472 DEBUG(dbgs() << ".. generic integer\n");
1473 OperandMatchResultTy ResTy = ParseImm(Operands);
1474 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001475 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001476 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001477 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001478 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001479 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001480 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001481 return true;
1482
Jack Carter873c7242013-01-12 01:03:14 +00001483 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1484
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001485 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001486 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001487 } // case AsmToken::Percent
1488 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001489 return true;
1490}
1491
Vladimir Medic4c299852013-11-06 11:27:05 +00001492const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001493 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001494 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001495 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001496 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001497 // It's a constant, evaluate reloc value.
1498 int16_t Val;
1499 switch (getVariantKind(RelocStr)) {
1500 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1501 // Get the 1st 16-bits.
1502 Val = MCE->getValue() & 0xffff;
1503 break;
1504 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1505 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1506 // 16 bits being negative.
1507 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1508 break;
1509 case MCSymbolRefExpr::VK_Mips_HIGHER:
1510 // Get the 3rd 16-bits.
1511 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1512 break;
1513 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1514 // Get the 4th 16-bits.
1515 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1516 break;
1517 default:
1518 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001519 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001520 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001521 }
1522
Jack Carterb5cf5902013-04-17 00:18:04 +00001523 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001524 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001525 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001526 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001527 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001528 return Res;
1529 }
1530
1531 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001532 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1533
Sasa Stankovic06c47802014-04-03 10:37:45 +00001534 // Try to create target expression.
1535 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1536 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001537
Jack Carterd0bd6422013-04-18 00:41:53 +00001538 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1539 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001540 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1541 return Res;
1542 }
1543
1544 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001545 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1546 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1547 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001548 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001549 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001550 return Expr;
1551}
1552
1553bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1554
1555 switch (Expr->getKind()) {
1556 case MCExpr::Constant:
1557 return true;
1558 case MCExpr::SymbolRef:
1559 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1560 case MCExpr::Binary:
1561 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1562 if (!isEvaluated(BE->getLHS()))
1563 return false;
1564 return isEvaluated(BE->getRHS());
1565 }
1566 case MCExpr::Unary:
1567 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001568 case MCExpr::Target:
1569 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001570 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001571 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001572}
Jack Carterd0bd6422013-04-18 00:41:53 +00001573
Jack Carterb5cf5902013-04-17 00:18:04 +00001574bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001575 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001576 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001577 if (Tok.isNot(AsmToken::Identifier))
1578 return true;
1579
1580 std::string Str = Tok.getIdentifier().str();
1581
Jack Carterd0bd6422013-04-18 00:41:53 +00001582 Parser.Lex(); // Eat the identifier.
1583 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001584 const MCExpr *IdVal;
1585 SMLoc EndLoc;
1586
1587 if (getLexer().getKind() == AsmToken::LParen) {
1588 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001589 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001590 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001591 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001592 const AsmToken &nextTok = Parser.getTok();
1593 if (nextTok.isNot(AsmToken::Identifier))
1594 return true;
1595 Str += "(%";
1596 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001597 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001598 if (getLexer().getKind() != AsmToken::LParen)
1599 return true;
1600 } else
1601 break;
1602 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001604 return true;
1605
1606 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001607 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001608
1609 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001610 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001611
Jack Carterd0bd6422013-04-18 00:41:53 +00001612 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001613 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001614}
1615
Jack Carterb4dbc172012-09-05 23:34:03 +00001616bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1617 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001618 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001619 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1620 if (ResTy == MatchOperand_Success) {
1621 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001622 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001623 StartLoc = Operand.getStartLoc();
1624 EndLoc = Operand.getEndLoc();
1625
1626 // AFAIK, we only support numeric registers and named GPR's in CFI
1627 // directives.
1628 // Don't worry about eating tokens before failing. Using an unrecognised
1629 // register is a parse error.
1630 if (Operand.isGPRAsmReg()) {
1631 // Resolve to GPR32 or GPR64 appropriately.
1632 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1633 }
1634
1635 return (RegNo == (unsigned)-1);
1636 }
1637
1638 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001639 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001640}
1641
Jack Carterb5cf5902013-04-17 00:18:04 +00001642bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001643 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001644 bool Result = true;
1645
1646 while (getLexer().getKind() == AsmToken::LParen)
1647 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001648
Jack Carterd0bd6422013-04-18 00:41:53 +00001649 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001650 default:
1651 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001652 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001653 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001654 case AsmToken::Integer:
1655 case AsmToken::Minus:
1656 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001657 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001658 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001659 else
1660 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001661 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001662 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001663 break;
Jack Carter873c7242013-01-12 01:03:14 +00001664 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001665 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001666 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001667 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001668}
1669
David Blaikie960ea3f2014-06-08 16:18:35 +00001670MipsAsmParser::OperandMatchResultTy
1671MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001672 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001673 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001674 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001675 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001676 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001677 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001678 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001679
Jack Carterb5cf5902013-04-17 00:18:04 +00001680 if (getLexer().getKind() == AsmToken::LParen) {
1681 Parser.Lex();
1682 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001683 }
1684
Jack Carterb5cf5902013-04-17 00:18:04 +00001685 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001686 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001687 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001688
Jack Carterd0bd6422013-04-18 00:41:53 +00001689 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001690 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001691 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1692 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001693 SMLoc E =
1694 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001695 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001696 return MatchOperand_Success;
1697 }
1698 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001699 SMLoc E =
1700 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001701
Jack Carterd0bd6422013-04-18 00:41:53 +00001702 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001703 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001704 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1705 S, E, *this);
1706 Operands.push_back(
1707 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001708 return MatchOperand_Success;
1709 }
1710 Error(Parser.getTok().getLoc(), "'(' expected");
1711 return MatchOperand_ParseFail;
1712 }
1713
Jack Carterd0bd6422013-04-18 00:41:53 +00001714 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001715 }
1716
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001717 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001718 if (Res != MatchOperand_Success)
1719 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001720
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001721 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001722 Error(Parser.getTok().getLoc(), "')' expected");
1723 return MatchOperand_ParseFail;
1724 }
1725
Jack Carter873c7242013-01-12 01:03:14 +00001726 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1727
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001729
Craig Topper062a2ba2014-04-25 05:30:21 +00001730 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001731 IdVal = MCConstantExpr::Create(0, getContext());
1732
Jack Carterd0bd6422013-04-18 00:41:53 +00001733 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001734 std::unique_ptr<MipsOperand> op(
1735 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001736 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001737 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001738 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001739 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001740 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1741 int64_t Imm;
1742 if (IdVal->EvaluateAsAbsolute(Imm))
1743 IdVal = MCConstantExpr::Create(Imm, getContext());
1744 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1745 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1746 getContext());
1747 }
1748
David Blaikie960ea3f2014-06-08 16:18:35 +00001749 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001750 return MatchOperand_Success;
1751}
1752
David Blaikie960ea3f2014-06-08 16:18:35 +00001753bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001754
Jack Carterd76b2372013-03-21 21:44:16 +00001755 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1756 if (Sym) {
1757 SMLoc S = Parser.getTok().getLoc();
1758 const MCExpr *Expr;
1759 if (Sym->isVariable())
1760 Expr = Sym->getVariableValue();
1761 else
1762 return false;
1763 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001764 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001765 const StringRef DefSymbol = Ref->getSymbol().getName();
1766 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001767 OperandMatchResultTy ResTy =
1768 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001769 if (ResTy == MatchOperand_Success) {
1770 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001771 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001772 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001773 llvm_unreachable("Should never ParseFail");
1774 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001775 }
1776 } else if (Expr->getKind() == MCExpr::Constant) {
1777 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001778 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001779 Operands.push_back(
1780 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001781 return true;
1782 }
1783 }
1784 return false;
1785}
Jack Carterd0bd6422013-04-18 00:41:53 +00001786
Jack Carter873c7242013-01-12 01:03:14 +00001787MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001788MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1789 StringRef Identifier,
1790 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001791 int Index = matchCPURegisterName(Identifier);
1792 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001793 Operands.push_back(MipsOperand::CreateGPRReg(
1794 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1795 return MatchOperand_Success;
1796 }
1797
1798 Index = matchFPURegisterName(Identifier);
1799 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001800 Operands.push_back(MipsOperand::CreateFGRReg(
1801 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1802 return MatchOperand_Success;
1803 }
1804
1805 Index = matchFCCRegisterName(Identifier);
1806 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001807 Operands.push_back(MipsOperand::CreateFCCReg(
1808 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1809 return MatchOperand_Success;
1810 }
1811
1812 Index = matchACRegisterName(Identifier);
1813 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001814 Operands.push_back(MipsOperand::CreateACCReg(
1815 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1816 return MatchOperand_Success;
1817 }
1818
1819 Index = matchMSA128RegisterName(Identifier);
1820 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001821 Operands.push_back(MipsOperand::CreateMSA128Reg(
1822 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1823 return MatchOperand_Success;
1824 }
1825
1826 Index = matchMSA128CtrlRegisterName(Identifier);
1827 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001828 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1829 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1830 return MatchOperand_Success;
1831 }
1832
1833 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001834}
1835
1836MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001837MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001838 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001839
1840 if (Token.is(AsmToken::Identifier)) {
1841 DEBUG(dbgs() << ".. identifier\n");
1842 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001843 OperandMatchResultTy ResTy =
1844 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001845 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001846 } else if (Token.is(AsmToken::Integer)) {
1847 DEBUG(dbgs() << ".. integer\n");
1848 Operands.push_back(MipsOperand::CreateNumericReg(
1849 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1850 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001851 return MatchOperand_Success;
1852 }
1853
1854 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1855
1856 return MatchOperand_NoMatch;
1857}
1858
David Blaikie960ea3f2014-06-08 16:18:35 +00001859MipsAsmParser::OperandMatchResultTy
1860MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001861 DEBUG(dbgs() << "ParseAnyRegister\n");
1862
1863 auto Token = Parser.getTok();
1864
1865 SMLoc S = Token.getLoc();
1866
1867 if (Token.isNot(AsmToken::Dollar)) {
1868 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1869 if (Token.is(AsmToken::Identifier)) {
1870 if (searchSymbolAlias(Operands))
1871 return MatchOperand_Success;
1872 }
1873 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1874 return MatchOperand_NoMatch;
1875 }
1876 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001877
Daniel Sanders21bce302014-04-01 12:35:23 +00001878 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001879 if (ResTy == MatchOperand_Success) {
1880 Parser.Lex(); // $
1881 Parser.Lex(); // identifier
1882 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001883 return ResTy;
1884}
1885
1886MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001887MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001888 switch (getLexer().getKind()) {
1889 default:
1890 return MatchOperand_NoMatch;
1891 case AsmToken::LParen:
1892 case AsmToken::Minus:
1893 case AsmToken::Plus:
1894 case AsmToken::Integer:
1895 case AsmToken::String:
1896 break;
1897 }
1898
1899 const MCExpr *IdVal;
1900 SMLoc S = Parser.getTok().getLoc();
1901 if (getParser().parseExpression(IdVal))
1902 return MatchOperand_ParseFail;
1903
1904 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1905 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1906 return MatchOperand_Success;
1907}
1908
David Blaikie960ea3f2014-06-08 16:18:35 +00001909MipsAsmParser::OperandMatchResultTy
1910MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001911 DEBUG(dbgs() << "ParseJumpTarget\n");
1912
1913 SMLoc S = getLexer().getLoc();
1914
1915 // Integers and expressions are acceptable
1916 OperandMatchResultTy ResTy = ParseImm(Operands);
1917 if (ResTy != MatchOperand_NoMatch)
1918 return ResTy;
1919
Daniel Sanders315386c2014-04-01 10:40:14 +00001920 // Registers are a valid target and have priority over symbols.
1921 ResTy = ParseAnyRegister(Operands);
1922 if (ResTy != MatchOperand_NoMatch)
1923 return ResTy;
1924
Daniel Sandersffd84362014-04-01 10:41:48 +00001925 const MCExpr *Expr = nullptr;
1926 if (Parser.parseExpression(Expr)) {
1927 // We have no way of knowing if a symbol was consumed so we must ParseFail
1928 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001929 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001930 Operands.push_back(
1931 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001932 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001933}
1934
Vladimir Medic2b953d02013-10-01 09:48:56 +00001935MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001936MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001937 const MCExpr *IdVal;
1938 // If the first token is '$' we may have register operand.
1939 if (Parser.getTok().is(AsmToken::Dollar))
1940 return MatchOperand_NoMatch;
1941 SMLoc S = Parser.getTok().getLoc();
1942 if (getParser().parseExpression(IdVal))
1943 return MatchOperand_ParseFail;
1944 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001945 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001946 int64_t Val = MCE->getValue();
1947 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1948 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001949 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001950 return MatchOperand_Success;
1951}
1952
Matheus Almeida779c5932013-11-18 12:32:49 +00001953MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001954MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001955 switch (getLexer().getKind()) {
1956 default:
1957 return MatchOperand_NoMatch;
1958 case AsmToken::LParen:
1959 case AsmToken::Plus:
1960 case AsmToken::Minus:
1961 case AsmToken::Integer:
1962 break;
1963 }
1964
1965 const MCExpr *Expr;
1966 SMLoc S = Parser.getTok().getLoc();
1967
1968 if (getParser().parseExpression(Expr))
1969 return MatchOperand_ParseFail;
1970
1971 int64_t Val;
1972 if (!Expr->EvaluateAsAbsolute(Val)) {
1973 Error(S, "expected immediate value");
1974 return MatchOperand_ParseFail;
1975 }
1976
1977 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1978 // and because the CPU always adds one to the immediate field, the allowed
1979 // range becomes 1..4. We'll only check the range here and will deal
1980 // with the addition/subtraction when actually decoding/encoding
1981 // the instruction.
1982 if (Val < 1 || Val > 4) {
1983 Error(S, "immediate not in range (1..4)");
1984 return MatchOperand_ParseFail;
1985 }
1986
Jack Carter3b2c96e2014-01-22 23:31:38 +00001987 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001988 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00001989 return MatchOperand_Success;
1990}
1991
Jack Carterdc1e35d2012-09-06 20:00:02 +00001992MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1993
Vladimir Medic4c299852013-11-06 11:27:05 +00001994 MCSymbolRefExpr::VariantKind VK =
1995 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1996 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1997 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1998 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1999 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2000 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2001 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2002 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2003 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2004 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2005 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2006 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2007 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2008 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2009 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2010 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2011 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2012 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002013 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2014 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2015 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2016 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2017 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2018 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002019 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2020 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002021 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002022
Matheus Almeida2852af82014-04-22 10:15:54 +00002023 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002024
Jack Carterdc1e35d2012-09-06 20:00:02 +00002025 return VK;
2026}
Jack Cartera63b16a2012-09-07 00:23:42 +00002027
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002028/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2029/// either this.
2030/// ::= '(', register, ')'
2031/// handle it before we iterate so we don't get tripped up by the lack of
2032/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002033bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002034 if (getLexer().is(AsmToken::LParen)) {
2035 Operands.push_back(
2036 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2037 Parser.Lex();
2038 if (ParseOperand(Operands, Name)) {
2039 SMLoc Loc = getLexer().getLoc();
2040 Parser.eatToEndOfStatement();
2041 return Error(Loc, "unexpected token in argument list");
2042 }
2043 if (Parser.getTok().isNot(AsmToken::RParen)) {
2044 SMLoc Loc = getLexer().getLoc();
2045 Parser.eatToEndOfStatement();
2046 return Error(Loc, "unexpected token, expected ')'");
2047 }
2048 Operands.push_back(
2049 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2050 Parser.Lex();
2051 }
2052 return false;
2053}
2054
2055/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2056/// either one of these.
2057/// ::= '[', register, ']'
2058/// ::= '[', integer, ']'
2059/// handle it before we iterate so we don't get tripped up by the lack of
2060/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002061bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2062 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002063 if (getLexer().is(AsmToken::LBrac)) {
2064 Operands.push_back(
2065 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2066 Parser.Lex();
2067 if (ParseOperand(Operands, Name)) {
2068 SMLoc Loc = getLexer().getLoc();
2069 Parser.eatToEndOfStatement();
2070 return Error(Loc, "unexpected token in argument list");
2071 }
2072 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2073 SMLoc Loc = getLexer().getLoc();
2074 Parser.eatToEndOfStatement();
2075 return Error(Loc, "unexpected token, expected ']'");
2076 }
2077 Operands.push_back(
2078 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2079 Parser.Lex();
2080 }
2081 return false;
2082}
2083
David Blaikie960ea3f2014-06-08 16:18:35 +00002084bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2085 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002086 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002087 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002088 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002089 Parser.eatToEndOfStatement();
2090 return Error(NameLoc, "Unknown instruction");
2091 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002092 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002093 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002094
2095 // Read the remaining operands.
2096 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2097 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002098 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002099 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002100 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002101 return Error(Loc, "unexpected token in argument list");
2102 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002103 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2104 return true;
2105 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002106
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 while (getLexer().is(AsmToken::Comma)) {
2108 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002109 // Parse and remember the operand.
2110 if (ParseOperand(Operands, Name)) {
2111 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002112 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002113 return Error(Loc, "unexpected token in argument list");
2114 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002115 // Parse bracket and parenthesis suffixes before we iterate
2116 if (getLexer().is(AsmToken::LBrac)) {
2117 if (ParseBracketSuffix(Name, Operands))
2118 return true;
2119 } else if (getLexer().is(AsmToken::LParen) &&
2120 ParseParenSuffix(Name, Operands))
2121 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002122 }
2123 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002124 if (getLexer().isNot(AsmToken::EndOfStatement)) {
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 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002129 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002130 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002131}
2132
Jack Carter0b744b32012-10-04 02:29:46 +00002133bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002134 SMLoc Loc = getLexer().getLoc();
2135 Parser.eatToEndOfStatement();
2136 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002137}
2138
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002139bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2140 return Error(Loc, ErrorMsg);
2141}
2142
Jack Carter0b744b32012-10-04 02:29:46 +00002143bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002144 // Line should look like: ".set noat".
2145 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002146 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002147 // eat noat
2148 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002149 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002150 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2151 reportParseError("unexpected token in statement");
2152 return false;
2153 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002154 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002155 return false;
2156}
Jack Carterd0bd6422013-04-18 00:41:53 +00002157
Jack Carter0b744b32012-10-04 02:29:46 +00002158bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002159 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002160 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002161 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002162 getParser().Lex();
2163 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002164 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002165 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002166 return false;
2167 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002168 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002169 if (getLexer().isNot(AsmToken::Dollar)) {
2170 reportParseError("unexpected token in statement");
2171 return false;
2172 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002173 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002174 const AsmToken &Reg = Parser.getTok();
2175 if (Reg.is(AsmToken::Identifier)) {
2176 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2177 } else if (Reg.is(AsmToken::Integer)) {
2178 AtRegNo = Reg.getIntVal();
2179 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002180 reportParseError("unexpected token in statement");
2181 return false;
2182 }
Jack Carter1ac53222013-02-20 23:11:17 +00002183
Daniel Sanders71a89d922014-03-25 13:01:06 +00002184 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002185 reportParseError("unexpected token in statement");
2186 return false;
2187 }
2188
2189 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002190 reportParseError("unexpected token in statement");
2191 return false;
2192 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002193 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002194
2195 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2196 reportParseError("unexpected token in statement");
2197 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002198 }
2199 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002200 return false;
2201 } else {
2202 reportParseError("unexpected token in statement");
2203 return false;
2204 }
2205}
2206
2207bool MipsAsmParser::parseSetReorderDirective() {
2208 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002209 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002210 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2211 reportParseError("unexpected token in statement");
2212 return false;
2213 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002214 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002215 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002216 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002217 return false;
2218}
2219
2220bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002221 Parser.Lex();
2222 // If this is not the end of the statement, report an error.
2223 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2224 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002225 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002226 }
2227 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002228 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002229 Parser.Lex(); // Consume the EndOfStatement.
2230 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002231}
2232
2233bool MipsAsmParser::parseSetMacroDirective() {
2234 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002235 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002236 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2237 reportParseError("unexpected token in statement");
2238 return false;
2239 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002240 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002241 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002242 return false;
2243}
2244
2245bool MipsAsmParser::parseSetNoMacroDirective() {
2246 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002247 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002248 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2249 reportParseError("`noreorder' must be set before `nomacro'");
2250 return false;
2251 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002252 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002253 reportParseError("`noreorder' must be set before `nomacro'");
2254 return false;
2255 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002256 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002257 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002258 return false;
2259}
Jack Carterd76b2372013-03-21 21:44:16 +00002260
Jack Carter39536722014-01-22 23:08:42 +00002261bool MipsAsmParser::parseSetNoMips16Directive() {
2262 Parser.Lex();
2263 // If this is not the end of the statement, report an error.
2264 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2265 reportParseError("unexpected token in statement");
2266 return false;
2267 }
2268 // For now do nothing.
2269 Parser.Lex(); // Consume the EndOfStatement.
2270 return false;
2271}
2272
Jack Carterd76b2372013-03-21 21:44:16 +00002273bool MipsAsmParser::parseSetAssignment() {
2274 StringRef Name;
2275 const MCExpr *Value;
2276
2277 if (Parser.parseIdentifier(Name))
2278 reportParseError("expected identifier after .set");
2279
2280 if (getLexer().isNot(AsmToken::Comma))
2281 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002282 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002283
Jack Carter3b2c96e2014-01-22 23:31:38 +00002284 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002285 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002286
Jack Carterd0bd6422013-04-18 00:41:53 +00002287 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002288 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002289 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002290 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002291 Sym = getContext().GetOrCreateSymbol(Name);
2292 Sym->setVariableValue(Value);
2293
2294 return false;
2295}
Jack Carterd0bd6422013-04-18 00:41:53 +00002296
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002297bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2298 Parser.Lex();
2299 if (getLexer().isNot(AsmToken::EndOfStatement))
2300 return reportParseError("unexpected token in .set directive");
2301
Matheus Almeida2852af82014-04-22 10:15:54 +00002302 switch (Feature) {
2303 default:
2304 llvm_unreachable("Unimplemented feature");
2305 case Mips::FeatureDSP:
2306 setFeatureBits(Mips::FeatureDSP, "dsp");
2307 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002308 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002309 case Mips::FeatureMicroMips:
2310 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002311 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002312 case Mips::FeatureMips16:
2313 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002314 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002315 case Mips::FeatureMips32r2:
2316 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2317 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002318 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002319 case Mips::FeatureMips64:
2320 setFeatureBits(Mips::FeatureMips64, "mips64");
2321 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002322 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002323 case Mips::FeatureMips64r2:
2324 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2325 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002326 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002327 }
2328 return false;
2329}
2330
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002331bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2332 if (!getLexer().is(AsmToken::Dollar))
2333 return false;
2334
2335 Parser.Lex();
2336
2337 const AsmToken &Reg = Parser.getTok();
2338 if (Reg.is(AsmToken::Identifier)) {
2339 RegNum = matchCPURegisterName(Reg.getIdentifier());
2340 } else if (Reg.is(AsmToken::Integer)) {
2341 RegNum = Reg.getIntVal();
2342 } else {
2343 return false;
2344 }
2345
2346 Parser.Lex();
2347 return true;
2348}
2349
2350bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2351 if (getLexer().isNot(AsmToken::Comma)) {
2352 SMLoc Loc = getLexer().getLoc();
2353 Parser.eatToEndOfStatement();
2354 return Error(Loc, ErrorStr);
2355 }
2356
Matheus Almeida2852af82014-04-22 10:15:54 +00002357 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002358 return true;
2359}
2360
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002361bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2362 if (Options.isReorder())
2363 Warning(Loc, ".cpload in reorder section");
2364
2365 // FIXME: Warn if cpload is used in Mips16 mode.
2366
David Blaikie960ea3f2014-06-08 16:18:35 +00002367 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002368 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2369 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2370 reportParseError("expected register containing function address");
2371 return false;
2372 }
2373
David Blaikie960ea3f2014-06-08 16:18:35 +00002374 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2375 if (!RegOpnd.isGPRAsmReg()) {
2376 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002377 return false;
2378 }
2379
David Blaikie960ea3f2014-06-08 16:18:35 +00002380 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002381 return false;
2382}
2383
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002384bool MipsAsmParser::parseDirectiveCPSetup() {
2385 unsigned FuncReg;
2386 unsigned Save;
2387 bool SaveIsReg = true;
2388
2389 if (!parseRegister(FuncReg))
2390 return reportParseError("expected register containing function address");
2391 FuncReg = getGPR(FuncReg);
2392
2393 if (!eatComma("expected comma parsing directive"))
2394 return true;
2395
2396 if (!parseRegister(Save)) {
2397 const AsmToken &Tok = Parser.getTok();
2398 if (Tok.is(AsmToken::Integer)) {
2399 Save = Tok.getIntVal();
2400 SaveIsReg = false;
2401 Parser.Lex();
2402 } else
2403 return reportParseError("expected save register or stack offset");
2404 } else
2405 Save = getGPR(Save);
2406
2407 if (!eatComma("expected comma parsing directive"))
2408 return true;
2409
2410 StringRef Name;
2411 if (Parser.parseIdentifier(Name))
2412 reportParseError("expected identifier");
2413 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002414
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002415 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002416 return false;
2417}
2418
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002419bool MipsAsmParser::parseDirectiveNaN() {
2420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2421 const AsmToken &Tok = Parser.getTok();
2422
2423 if (Tok.getString() == "2008") {
2424 Parser.Lex();
2425 getTargetStreamer().emitDirectiveNaN2008();
2426 return false;
2427 } else if (Tok.getString() == "legacy") {
2428 Parser.Lex();
2429 getTargetStreamer().emitDirectiveNaNLegacy();
2430 return false;
2431 }
2432 }
2433 // If we don't recognize the option passed to the .nan
2434 // directive (e.g. no option or unknown option), emit an error.
2435 reportParseError("invalid option in .nan directive");
2436 return false;
2437}
2438
Jack Carter0b744b32012-10-04 02:29:46 +00002439bool MipsAsmParser::parseDirectiveSet() {
2440
Jack Carterd0bd6422013-04-18 00:41:53 +00002441 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002442 const AsmToken &Tok = Parser.getTok();
2443
2444 if (Tok.getString() == "noat") {
2445 return parseSetNoAtDirective();
2446 } else if (Tok.getString() == "at") {
2447 return parseSetAtDirective();
2448 } else if (Tok.getString() == "reorder") {
2449 return parseSetReorderDirective();
2450 } else if (Tok.getString() == "noreorder") {
2451 return parseSetNoReorderDirective();
2452 } else if (Tok.getString() == "macro") {
2453 return parseSetMacroDirective();
2454 } else if (Tok.getString() == "nomacro") {
2455 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002456 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002457 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002458 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002459 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002460 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002461 getTargetStreamer().emitDirectiveSetNoMicroMips();
2462 Parser.eatToEndOfStatement();
2463 return false;
2464 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002465 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002466 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002467 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002468 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002469 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002470 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002471 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002472 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002473 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002474 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002475 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002476 parseSetAssignment();
2477 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002478 }
Jack Carter07c818d2013-01-25 01:31:34 +00002479
Jack Carter0b744b32012-10-04 02:29:46 +00002480 return true;
2481}
2482
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002483/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002484/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002485bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002486 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2487 for (;;) {
2488 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002489 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002490 return true;
2491
2492 getParser().getStreamer().EmitValue(Value, Size);
2493
2494 if (getLexer().is(AsmToken::EndOfStatement))
2495 break;
2496
2497 // FIXME: Improve diagnostic.
2498 if (getLexer().isNot(AsmToken::Comma))
2499 return Error(L, "unexpected token in directive");
2500 Parser.Lex();
2501 }
2502 }
2503
2504 Parser.Lex();
2505 return false;
2506}
2507
Vladimir Medic4c299852013-11-06 11:27:05 +00002508/// parseDirectiveGpWord
2509/// ::= .gpword local_sym
2510bool MipsAsmParser::parseDirectiveGpWord() {
2511 const MCExpr *Value;
2512 // EmitGPRel32Value requires an expression, so we are using base class
2513 // method to evaluate the expression.
2514 if (getParser().parseExpression(Value))
2515 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002516 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002517
Vladimir Medice10c1122013-11-13 13:18:04 +00002518 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002519 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002520 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002521 return false;
2522}
2523
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002524/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002525/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002526bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002527 const MCExpr *Value;
2528 // EmitGPRel64Value requires an expression, so we are using base class
2529 // method to evaluate the expression.
2530 if (getParser().parseExpression(Value))
2531 return true;
2532 getParser().getStreamer().EmitGPRel64Value(Value);
2533
2534 if (getLexer().isNot(AsmToken::EndOfStatement))
2535 return Error(getLexer().getLoc(), "unexpected token in directive");
2536 Parser.Lex(); // Eat EndOfStatement token.
2537 return false;
2538}
2539
Jack Carter0cd3c192014-01-06 23:27:31 +00002540bool MipsAsmParser::parseDirectiveOption() {
2541 // Get the option token.
2542 AsmToken Tok = Parser.getTok();
2543 // At the moment only identifiers are supported.
2544 if (Tok.isNot(AsmToken::Identifier)) {
2545 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2546 Parser.eatToEndOfStatement();
2547 return false;
2548 }
2549
2550 StringRef Option = Tok.getIdentifier();
2551
2552 if (Option == "pic0") {
2553 getTargetStreamer().emitDirectiveOptionPic0();
2554 Parser.Lex();
2555 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2556 Error(Parser.getTok().getLoc(),
2557 "unexpected token in .option pic0 directive");
2558 Parser.eatToEndOfStatement();
2559 }
2560 return false;
2561 }
2562
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002563 if (Option == "pic2") {
2564 getTargetStreamer().emitDirectiveOptionPic2();
2565 Parser.Lex();
2566 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2567 Error(Parser.getTok().getLoc(),
2568 "unexpected token in .option pic2 directive");
2569 Parser.eatToEndOfStatement();
2570 }
2571 return false;
2572 }
2573
Jack Carter0cd3c192014-01-06 23:27:31 +00002574 // Unknown option.
2575 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2576 Parser.eatToEndOfStatement();
2577 return false;
2578}
2579
Jack Carter0b744b32012-10-04 02:29:46 +00002580bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002581 StringRef IDVal = DirectiveID.getString();
2582
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002583 if (IDVal == ".cpload")
2584 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002585 if (IDVal == ".dword") {
2586 parseDataDirective(8, DirectiveID.getLoc());
2587 return false;
2588 }
2589
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 if (IDVal == ".ent") {
2591 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002592 Parser.Lex();
2593 return false;
2594 }
2595
Jack Carter07c818d2013-01-25 01:31:34 +00002596 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002597 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002598 Parser.Lex();
2599 return false;
2600 }
2601
Jack Carter07c818d2013-01-25 01:31:34 +00002602 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002603 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002604 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002605 return false;
2606 }
2607
Jack Carter07c818d2013-01-25 01:31:34 +00002608 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002609 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002610 }
2611
Jack Carter07c818d2013-01-25 01:31:34 +00002612 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002613 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002614 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002615 return false;
2616 }
2617
Jack Carter07c818d2013-01-25 01:31:34 +00002618 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002619 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002620 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002621 return false;
2622 }
2623
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002624 if (IDVal == ".nan")
2625 return parseDirectiveNaN();
2626
Jack Carter07c818d2013-01-25 01:31:34 +00002627 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002628 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002629 return false;
2630 }
2631
Rafael Espindolab59fb732014-03-28 18:50:26 +00002632 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002633 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002634 return false;
2635 }
2636
Jack Carter07c818d2013-01-25 01:31:34 +00002637 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002638 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002639 return false;
2640 }
2641
Jack Carter0cd3c192014-01-06 23:27:31 +00002642 if (IDVal == ".option")
2643 return parseDirectiveOption();
2644
2645 if (IDVal == ".abicalls") {
2646 getTargetStreamer().emitDirectiveAbiCalls();
2647 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2648 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2649 // Clear line
2650 Parser.eatToEndOfStatement();
2651 }
2652 return false;
2653 }
2654
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002655 if (IDVal == ".cpsetup")
2656 return parseDirectiveCPSetup();
2657
Rafael Espindola870c4e92012-01-11 03:56:41 +00002658 return true;
2659}
2660
Rafael Espindola870c4e92012-01-11 03:56:41 +00002661extern "C" void LLVMInitializeMipsAsmParser() {
2662 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2663 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2664 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2665 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2666}
Jack Carterb4dbc172012-09-05 23:34:03 +00002667
2668#define GET_REGISTER_MATCHER
2669#define GET_MATCHER_IMPLEMENTATION
2670#include "MipsGenAsmMatcher.inc"