blob: c9deae6afb219b916e7a4695057b96a82eb366be [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; }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000623 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000624 bool isLSAImm() const {
625 if (!isConstantImm())
626 return false;
627 int64_t Val = getConstantImm();
628 return 1 <= Val && Val <= 4;
629 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000630
631 StringRef getToken() const {
632 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000633 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000634 }
635
Craig Topper56c590a2014-04-29 07:58:02 +0000636 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000637 // As a special case until we sort out the definition of div/divu, pretend
638 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
639 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
640 RegIdx.Kind & RegKind_GPR)
641 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000642
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000643 assert(Kind == k_PhysRegister && "Invalid access!");
644 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000645 }
646
Jack Carterb4dbc172012-09-05 23:34:03 +0000647 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000648 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000649 return Imm.Val;
650 }
651
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000652 int64_t getConstantImm() const {
653 const MCExpr *Val = getImm();
654 return static_cast<const MCConstantExpr *>(Val)->getValue();
655 }
656
657 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000658 assert((Kind == k_Memory) && "Invalid access!");
659 return Mem.Base;
660 }
661
662 const MCExpr *getMemOff() const {
663 assert((Kind == k_Memory) && "Invalid access!");
664 return Mem.Off;
665 }
666
David Blaikie960ea3f2014-06-08 16:18:35 +0000667 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
668 MipsAsmParser &Parser) {
669 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000670 Op->Tok.Data = Str.data();
671 Op->Tok.Length = Str.size();
672 Op->StartLoc = S;
673 Op->EndLoc = S;
674 return Op;
675 }
676
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000677 /// Create a numeric register (e.g. $1). The exact register remains
678 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000679 static std::unique_ptr<MipsOperand>
680 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
681 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000682 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
683 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000684 }
685
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000686 /// Create a register that is definitely a GPR.
687 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000688 static std::unique_ptr<MipsOperand>
689 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
690 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000691 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000692 }
693
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000694 /// Create a register that is definitely a FGR.
695 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000696 static std::unique_ptr<MipsOperand>
697 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
698 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000699 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
700 }
701
702 /// Create a register that is definitely an FCC.
703 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000704 static std::unique_ptr<MipsOperand>
705 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
706 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
708 }
709
710 /// Create a register that is definitely an ACC.
711 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000712 static std::unique_ptr<MipsOperand>
713 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
714 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
716 }
717
718 /// Create a register that is definitely an MSA128.
719 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000720 static std::unique_ptr<MipsOperand>
721 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
722 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000723 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
724 }
725
726 /// Create a register that is definitely an MSACtrl.
727 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000728 static std::unique_ptr<MipsOperand>
729 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
730 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
732 }
733
David Blaikie960ea3f2014-06-08 16:18:35 +0000734 static std::unique_ptr<MipsOperand>
735 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
736 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000737 Op->Imm.Val = Val;
738 Op->StartLoc = S;
739 Op->EndLoc = E;
740 return Op;
741 }
742
David Blaikie960ea3f2014-06-08 16:18:35 +0000743 static std::unique_ptr<MipsOperand>
744 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
745 SMLoc E, MipsAsmParser &Parser) {
746 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
747 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000748 Op->Mem.Off = Off;
749 Op->StartLoc = S;
750 Op->EndLoc = E;
751 return Op;
752 }
753
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000754 bool isGPRAsmReg() const {
755 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000756 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000757 bool isFGRAsmReg() const {
758 // AFGR64 is $0-$15 but we handle this in getAFGR64()
759 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000760 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000761 bool isHWRegsAsmReg() const {
762 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000763 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000764 bool isCCRAsmReg() const {
765 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000766 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000768 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
769 return false;
770 if (!AsmParser.hasEightFccRegisters())
771 return RegIdx.Index == 0;
772 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000773 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 bool isACCAsmReg() const {
775 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000776 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000777 bool isCOP2AsmReg() const {
778 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000779 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000780 bool isCOP3AsmReg() const {
781 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
782 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000783 bool isMSA128AsmReg() const {
784 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000785 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000786 bool isMSACtrlAsmReg() const {
787 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000788 }
789
Jack Carterb4dbc172012-09-05 23:34:03 +0000790 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000791 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000792 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000793 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000794
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000795 virtual ~MipsOperand() {
796 switch (Kind) {
797 case k_Immediate:
798 break;
799 case k_Memory:
800 delete Mem.Base;
801 break;
802 case k_PhysRegister:
803 case k_RegisterIndex:
804 case k_Token:
805 break;
806 }
807 }
808
Craig Topper56c590a2014-04-29 07:58:02 +0000809 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 switch (Kind) {
811 case k_Immediate:
812 OS << "Imm<";
813 Imm.Val->print(OS);
814 OS << ">";
815 break;
816 case k_Memory:
817 OS << "Mem<";
818 Mem.Base->print(OS);
819 OS << ", ";
820 Mem.Off->print(OS);
821 OS << ">";
822 break;
823 case k_PhysRegister:
824 OS << "PhysReg<" << PhysReg.Num << ">";
825 break;
826 case k_RegisterIndex:
827 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
828 break;
829 case k_Token:
830 OS << Tok.Data;
831 break;
832 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000833 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000834}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000835} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000836
Jack Carter9e65aa32013-03-22 00:05:30 +0000837namespace llvm {
838extern const MCInstrDesc MipsInsts[];
839}
840static const MCInstrDesc &getInstDesc(unsigned Opcode) {
841 return MipsInsts[Opcode];
842}
843
844bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000845 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000846 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000847
Jack Carter9e65aa32013-03-22 00:05:30 +0000848 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000849
850 if (MCID.isBranch() || MCID.isCall()) {
851 const unsigned Opcode = Inst.getOpcode();
852 MCOperand Offset;
853
854 switch (Opcode) {
855 default:
856 break;
857 case Mips::BEQ:
858 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000859 case Mips::BEQ_MM:
860 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000861 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000862 Offset = Inst.getOperand(2);
863 if (!Offset.isImm())
864 break; // We'll deal with this situation later on when applying fixups.
865 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
866 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000867 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000868 return Error(IDLoc, "branch to misaligned address");
869 break;
870 case Mips::BGEZ:
871 case Mips::BGTZ:
872 case Mips::BLEZ:
873 case Mips::BLTZ:
874 case Mips::BGEZAL:
875 case Mips::BLTZAL:
876 case Mips::BC1F:
877 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 case Mips::BGEZ_MM:
879 case Mips::BGTZ_MM:
880 case Mips::BLEZ_MM:
881 case Mips::BLTZ_MM:
882 case Mips::BGEZAL_MM:
883 case Mips::BLTZAL_MM:
884 case Mips::BC1F_MM:
885 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000886 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000887 Offset = Inst.getOperand(1);
888 if (!Offset.isImm())
889 break; // We'll deal with this situation later on when applying fixups.
890 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
891 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000892 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000893 return Error(IDLoc, "branch to misaligned address");
894 break;
895 }
896 }
897
Jack Carterc15c1d22013-04-25 23:31:35 +0000898 if (MCID.hasDelaySlot() && Options.isReorder()) {
899 // If this instruction has a delay slot and .set reorder is active,
900 // emit a NOP after it.
901 Instructions.push_back(Inst);
902 MCInst NopInst;
903 NopInst.setOpcode(Mips::SLL);
904 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
905 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
906 NopInst.addOperand(MCOperand::CreateImm(0));
907 Instructions.push_back(NopInst);
908 return false;
909 }
910
Jack Carter9e65aa32013-03-22 00:05:30 +0000911 if (MCID.mayLoad() || MCID.mayStore()) {
912 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000913 // reference or immediate we may have to expand instructions.
914 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000915 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000916 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
917 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000918 MCOperand &Op = Inst.getOperand(i);
919 if (Op.isImm()) {
920 int MemOffset = Op.getImm();
921 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000922 // Offset can't exceed 16bit value.
923 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000924 return false;
925 }
926 } else if (Op.isExpr()) {
927 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000928 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000929 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000930 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000931 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000932 // Expand symbol.
933 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000934 return false;
935 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000936 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000937 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000938 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000939 }
940 }
941 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000942 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000943 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000944
945 if (needsExpansion(Inst))
946 expandInstruction(Inst, IDLoc, Instructions);
947 else
948 Instructions.push_back(Inst);
949
950 return false;
951}
952
Jack Carter30a59822012-10-04 04:03:53 +0000953bool MipsAsmParser::needsExpansion(MCInst &Inst) {
954
Jack Carterd0bd6422013-04-18 00:41:53 +0000955 switch (Inst.getOpcode()) {
956 case Mips::LoadImm32Reg:
957 case Mips::LoadAddr32Imm:
958 case Mips::LoadAddr32Reg:
959 return true;
960 default:
961 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000962 }
963}
Jack Carter92995f12012-10-06 00:53:28 +0000964
Jack Carter30a59822012-10-04 04:03:53 +0000965void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000966 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000967 switch (Inst.getOpcode()) {
968 case Mips::LoadImm32Reg:
969 return expandLoadImm(Inst, IDLoc, Instructions);
970 case Mips::LoadAddr32Imm:
971 return expandLoadAddressImm(Inst, IDLoc, Instructions);
972 case Mips::LoadAddr32Reg:
973 return expandLoadAddressReg(Inst, IDLoc, Instructions);
974 }
Jack Carter30a59822012-10-04 04:03:53 +0000975}
Jack Carter92995f12012-10-06 00:53:28 +0000976
Jack Carter30a59822012-10-04 04:03:53 +0000977void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000978 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000979 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000980 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000981 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000982 const MCOperand &RegOp = Inst.getOperand(0);
983 assert(RegOp.isReg() && "expected register operand kind");
984
985 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000986 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000987 if (0 <= ImmValue && ImmValue <= 65535) {
988 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000989 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000990 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000991 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000992 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000993 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000994 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000995 } else if (ImmValue < 0 && ImmValue >= -32768) {
996 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000997 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000998 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000999 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001000 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001001 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001002 Instructions.push_back(tmpInst);
1003 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001004 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +00001005 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001006 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001007 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001008 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1009 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001010 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +00001011 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001012 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001013 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1014 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1015 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1016 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +00001017 Instructions.push_back(tmpInst);
1018 }
1019}
Jack Carter92995f12012-10-06 00:53:28 +00001020
Vladimir Medic4c299852013-11-06 11:27:05 +00001021void
1022MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1023 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001024 MCInst tmpInst;
1025 const MCOperand &ImmOp = Inst.getOperand(2);
1026 assert(ImmOp.isImm() && "expected immediate operand kind");
1027 const MCOperand &SrcRegOp = Inst.getOperand(1);
1028 assert(SrcRegOp.isReg() && "expected register operand kind");
1029 const MCOperand &DstRegOp = Inst.getOperand(0);
1030 assert(DstRegOp.isReg() && "expected register operand kind");
1031 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001032 if (-32768 <= ImmValue && ImmValue <= 65535) {
1033 // For -32768 <= j <= 65535.
1034 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001035 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001036 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1037 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1038 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1039 Instructions.push_back(tmpInst);
1040 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001041 // For any other value of j that is representable as a 32-bit integer.
1042 // la d,j(s) => lui d,hi16(j)
1043 // ori d,d,lo16(j)
1044 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001045 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001046 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1047 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1048 Instructions.push_back(tmpInst);
1049 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001050 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001051 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1052 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1053 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1054 Instructions.push_back(tmpInst);
1055 tmpInst.clear();
1056 tmpInst.setOpcode(Mips::ADDu);
1057 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1058 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1059 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1060 Instructions.push_back(tmpInst);
1061 }
1062}
1063
Vladimir Medic4c299852013-11-06 11:27:05 +00001064void
1065MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1066 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001067 MCInst tmpInst;
1068 const MCOperand &ImmOp = Inst.getOperand(1);
1069 assert(ImmOp.isImm() && "expected immediate operand kind");
1070 const MCOperand &RegOp = Inst.getOperand(0);
1071 assert(RegOp.isReg() && "expected register operand kind");
1072 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001073 if (-32768 <= ImmValue && ImmValue <= 65535) {
1074 // For -32768 <= j <= 65535.
1075 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001076 tmpInst.setOpcode(Mips::ADDiu);
1077 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001078 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001079 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1080 Instructions.push_back(tmpInst);
1081 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001082 // For any other value of j that is representable as a 32-bit integer.
1083 // la d,j => lui d,hi16(j)
1084 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001085 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001086 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1087 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1088 Instructions.push_back(tmpInst);
1089 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001090 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001091 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1092 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1093 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1094 Instructions.push_back(tmpInst);
1095 }
1096}
1097
Jack Carter9e65aa32013-03-22 00:05:30 +00001098void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001099 SmallVectorImpl<MCInst> &Instructions,
1100 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001101 const MCSymbolRefExpr *SR;
1102 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001103 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001104 const MCExpr *ExprOffset;
1105 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +00001106 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001107 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +00001108 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001109 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1110 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001111 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001112 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1113 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001114 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001115 if (isImmOpnd) {
1116 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1117 ImmOffset = Inst.getOperand(2).getImm();
1118 LoOffset = ImmOffset & 0x0000ffff;
1119 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001120 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001121 if (LoOffset & 0x8000)
1122 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001123 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001124 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001125 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001126 TempInst.setLoc(IDLoc);
1127 // 1st instruction in expansion is LUi. For load instruction we can use
1128 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001129 // but for stores we must use $at.
1130 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +00001131 TempInst.setOpcode(Mips::LUi);
1132 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1133 if (isImmOpnd)
1134 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1135 else {
1136 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001137 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001138 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1139 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1140 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001141 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001142 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001143 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001144 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001145 }
1146 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001147 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001148 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001149 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001150 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001151 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001152 TempInst.setOpcode(Mips::ADDu);
1153 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1154 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1155 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1156 Instructions.push_back(TempInst);
1157 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001158 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001159 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001160 TempInst.setOpcode(Inst.getOpcode());
1161 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1162 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1163 if (isImmOpnd)
1164 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1165 else {
1166 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001167 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1168 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1169 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001170 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001171 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001172 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001173 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001174 }
1175 }
1176 Instructions.push_back(TempInst);
1177 TempInst.clear();
1178}
1179
Matheus Almeida595fcab2014-06-11 15:05:56 +00001180unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1181 // As described by the Mips32r2 spec, the registers Rd and Rs for
1182 // jalr.hb must be different.
1183 unsigned Opcode = Inst.getOpcode();
1184
1185 if (Opcode == Mips::JALR_HB &&
1186 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1187 return Match_RequiresDifferentSrcAndDst;
1188
1189 return Match_Success;
1190}
1191
David Blaikie960ea3f2014-06-08 16:18:35 +00001192bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1193 OperandVector &Operands,
1194 MCStreamer &Out,
1195 unsigned &ErrorInfo,
1196 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001197
Jack Carterb4dbc172012-09-05 23:34:03 +00001198 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001199 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001200 unsigned MatchResult =
1201 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001202
1203 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001204 default:
1205 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001206 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001207 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001208 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001209 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001210 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001211 return false;
1212 }
1213 case Match_MissingFeature:
1214 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1215 return true;
1216 case Match_InvalidOperand: {
1217 SMLoc ErrorLoc = IDLoc;
1218 if (ErrorInfo != ~0U) {
1219 if (ErrorInfo >= Operands.size())
1220 return Error(IDLoc, "too few operands for instruction");
1221
David Blaikie960ea3f2014-06-08 16:18:35 +00001222 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001223 if (ErrorLoc == SMLoc())
1224 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001225 }
1226
1227 return Error(ErrorLoc, "invalid operand for instruction");
1228 }
1229 case Match_MnemonicFail:
1230 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001231 case Match_RequiresDifferentSrcAndDst:
1232 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001233 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001234 return true;
1235}
1236
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001237void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1238 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1239 if (RegIndex == 1)
1240 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001241 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001242 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1243 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001244 }
1245}
1246
Jack Carter1ac53222013-02-20 23:11:17 +00001247int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001248 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001249
Vladimir Medic4c299852013-11-06 11:27:05 +00001250 CC = StringSwitch<unsigned>(Name)
1251 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001252 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001253 .Case("a0", 4)
1254 .Case("a1", 5)
1255 .Case("a2", 6)
1256 .Case("a3", 7)
1257 .Case("v0", 2)
1258 .Case("v1", 3)
1259 .Case("s0", 16)
1260 .Case("s1", 17)
1261 .Case("s2", 18)
1262 .Case("s3", 19)
1263 .Case("s4", 20)
1264 .Case("s5", 21)
1265 .Case("s6", 22)
1266 .Case("s7", 23)
1267 .Case("k0", 26)
1268 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001269 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001270 .Case("sp", 29)
1271 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001272 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001273 .Case("ra", 31)
1274 .Case("t0", 8)
1275 .Case("t1", 9)
1276 .Case("t2", 10)
1277 .Case("t3", 11)
1278 .Case("t4", 12)
1279 .Case("t5", 13)
1280 .Case("t6", 14)
1281 .Case("t7", 15)
1282 .Case("t8", 24)
1283 .Case("t9", 25)
1284 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001285
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001286 if (isN32() || isN64()) {
1287 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1288 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1289 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1290 if (8 <= CC && CC <= 11)
1291 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001292
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001293 if (CC == -1)
1294 CC = StringSwitch<unsigned>(Name)
1295 .Case("a4", 8)
1296 .Case("a5", 9)
1297 .Case("a6", 10)
1298 .Case("a7", 11)
1299 .Case("kt0", 26)
1300 .Case("kt1", 27)
1301 .Default(-1);
1302 }
Jack Carter1ac53222013-02-20 23:11:17 +00001303
1304 return CC;
1305}
Jack Carterd0bd6422013-04-18 00:41:53 +00001306
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001307int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001308
Jack Cartera63b16a2012-09-07 00:23:42 +00001309 if (Name[0] == 'f') {
1310 StringRef NumString = Name.substr(1);
1311 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001312 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001313 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001314 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001315 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001316 return IntVal;
1317 }
1318 return -1;
1319}
Jack Cartera63b16a2012-09-07 00:23:42 +00001320
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001321int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1322
1323 if (Name.startswith("fcc")) {
1324 StringRef NumString = Name.substr(3);
1325 unsigned IntVal;
1326 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001327 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001328 if (IntVal > 7) // There are only 8 fcc registers.
1329 return -1;
1330 return IntVal;
1331 }
1332 return -1;
1333}
1334
1335int MipsAsmParser::matchACRegisterName(StringRef Name) {
1336
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001337 if (Name.startswith("ac")) {
1338 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001339 unsigned IntVal;
1340 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001341 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001342 if (IntVal > 3) // There are only 3 acc registers.
1343 return -1;
1344 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001345 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001346 return -1;
1347}
Jack Carterd0bd6422013-04-18 00:41:53 +00001348
Jack Carter5dc8ac92013-09-25 23:50:44 +00001349int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1350 unsigned IntVal;
1351
1352 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1353 return -1;
1354
1355 if (IntVal > 31)
1356 return -1;
1357
1358 return IntVal;
1359}
1360
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001361int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1362 int CC;
1363
1364 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001365 .Case("msair", 0)
1366 .Case("msacsr", 1)
1367 .Case("msaaccess", 2)
1368 .Case("msasave", 3)
1369 .Case("msamodify", 4)
1370 .Case("msarequest", 5)
1371 .Case("msamap", 6)
1372 .Case("msaunmap", 7)
1373 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001374
1375 return CC;
1376}
1377
Jack Carter0b744b32012-10-04 02:29:46 +00001378bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1379 if (Reg > 31)
1380 return false;
1381
1382 aTReg = Reg;
1383 return true;
1384}
1385
Daniel Sandersd89b1362014-03-24 16:48:01 +00001386int MipsAsmParser::getATReg() {
1387 int AT = Options.getATRegNum();
1388 if (AT == 0)
1389 TokError("Pseudo instruction requires $at, which is not available");
1390 return AT;
1391}
Jack Carter0b744b32012-10-04 02:29:46 +00001392
Jack Carterd0bd6422013-04-18 00:41:53 +00001393unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001394 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001395}
1396
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001397unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001398 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1399 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001400}
1401
Jack Carter873c7242013-01-12 01:03:14 +00001402int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001403 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001404 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001405 return -1;
1406
Jack Carter873c7242013-01-12 01:03:14 +00001407 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001408}
1409
David Blaikie960ea3f2014-06-08 16:18:35 +00001410bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001411 DEBUG(dbgs() << "ParseOperand\n");
1412
Jack Carter30a59822012-10-04 04:03:53 +00001413 // Check if the current operand has a custom associated parser, if so, try to
1414 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001415 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1416 if (ResTy == MatchOperand_Success)
1417 return false;
1418 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1419 // there was a match, but an error occurred, in which case, just return that
1420 // the operand parsing failed.
1421 if (ResTy == MatchOperand_ParseFail)
1422 return true;
1423
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001424 DEBUG(dbgs() << ".. Generic Parser\n");
1425
Jack Carterb4dbc172012-09-05 23:34:03 +00001426 switch (getLexer().getKind()) {
1427 default:
1428 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1429 return true;
1430 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001431 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001432 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001433
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001434 // Almost all registers have been parsed by custom parsers. There is only
1435 // one exception to this. $zero (and it's alias $0) will reach this point
1436 // for div, divu, and similar instructions because it is not an operand
1437 // to the instruction definition but an explicit register. Special case
1438 // this situation for now.
1439 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001440 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001441
Jack Carterd0bd6422013-04-18 00:41:53 +00001442 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001443 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001444 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001445 return true;
1446
Jack Carter873c7242013-01-12 01:03:14 +00001447 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001448 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001449 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001450 const MCExpr *Res =
1451 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001452
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001453 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001454 return false;
1455 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001456 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001457 case AsmToken::LParen:
1458 case AsmToken::Minus:
1459 case AsmToken::Plus:
1460 case AsmToken::Integer:
1461 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001462 DEBUG(dbgs() << ".. generic integer\n");
1463 OperandMatchResultTy ResTy = ParseImm(Operands);
1464 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001465 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001466 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001467 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001468 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001469 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001470 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001471 return true;
1472
Jack Carter873c7242013-01-12 01:03:14 +00001473 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1474
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001475 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001476 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001477 } // case AsmToken::Percent
1478 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001479 return true;
1480}
1481
Vladimir Medic4c299852013-11-06 11:27:05 +00001482const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001483 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001484 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001485 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001486 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001487 // It's a constant, evaluate reloc value.
1488 int16_t Val;
1489 switch (getVariantKind(RelocStr)) {
1490 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1491 // Get the 1st 16-bits.
1492 Val = MCE->getValue() & 0xffff;
1493 break;
1494 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1495 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1496 // 16 bits being negative.
1497 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1498 break;
1499 case MCSymbolRefExpr::VK_Mips_HIGHER:
1500 // Get the 3rd 16-bits.
1501 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1502 break;
1503 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1504 // Get the 4th 16-bits.
1505 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1506 break;
1507 default:
1508 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001509 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001510 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001511 }
1512
Jack Carterb5cf5902013-04-17 00:18:04 +00001513 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001514 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001515 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001516 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001517 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001518 return Res;
1519 }
1520
1521 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001522 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1523
Sasa Stankovic06c47802014-04-03 10:37:45 +00001524 // Try to create target expression.
1525 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1526 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001527
Jack Carterd0bd6422013-04-18 00:41:53 +00001528 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1529 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001530 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1531 return Res;
1532 }
1533
1534 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001535 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1536 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1537 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001538 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001539 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001540 return Expr;
1541}
1542
1543bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1544
1545 switch (Expr->getKind()) {
1546 case MCExpr::Constant:
1547 return true;
1548 case MCExpr::SymbolRef:
1549 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1550 case MCExpr::Binary:
1551 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1552 if (!isEvaluated(BE->getLHS()))
1553 return false;
1554 return isEvaluated(BE->getRHS());
1555 }
1556 case MCExpr::Unary:
1557 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001558 case MCExpr::Target:
1559 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001560 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001561 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001562}
Jack Carterd0bd6422013-04-18 00:41:53 +00001563
Jack Carterb5cf5902013-04-17 00:18:04 +00001564bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001565 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001566 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001567 if (Tok.isNot(AsmToken::Identifier))
1568 return true;
1569
1570 std::string Str = Tok.getIdentifier().str();
1571
Jack Carterd0bd6422013-04-18 00:41:53 +00001572 Parser.Lex(); // Eat the identifier.
1573 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001574 const MCExpr *IdVal;
1575 SMLoc EndLoc;
1576
1577 if (getLexer().getKind() == AsmToken::LParen) {
1578 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001579 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001580 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001581 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001582 const AsmToken &nextTok = Parser.getTok();
1583 if (nextTok.isNot(AsmToken::Identifier))
1584 return true;
1585 Str += "(%";
1586 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001587 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001588 if (getLexer().getKind() != AsmToken::LParen)
1589 return true;
1590 } else
1591 break;
1592 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001593 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001594 return true;
1595
1596 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001597 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001598
1599 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001600 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001601
Jack Carterd0bd6422013-04-18 00:41:53 +00001602 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001603 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001604}
1605
Jack Carterb4dbc172012-09-05 23:34:03 +00001606bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1607 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001608 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001609 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1610 if (ResTy == MatchOperand_Success) {
1611 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001612 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001613 StartLoc = Operand.getStartLoc();
1614 EndLoc = Operand.getEndLoc();
1615
1616 // AFAIK, we only support numeric registers and named GPR's in CFI
1617 // directives.
1618 // Don't worry about eating tokens before failing. Using an unrecognised
1619 // register is a parse error.
1620 if (Operand.isGPRAsmReg()) {
1621 // Resolve to GPR32 or GPR64 appropriately.
1622 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1623 }
1624
1625 return (RegNo == (unsigned)-1);
1626 }
1627
1628 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001629 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001630}
1631
Jack Carterb5cf5902013-04-17 00:18:04 +00001632bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001633 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001634 bool Result = true;
1635
1636 while (getLexer().getKind() == AsmToken::LParen)
1637 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001638
Jack Carterd0bd6422013-04-18 00:41:53 +00001639 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001640 default:
1641 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001642 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001643 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001644 case AsmToken::Integer:
1645 case AsmToken::Minus:
1646 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001647 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001648 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001649 else
1650 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001651 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001652 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001653 break;
Jack Carter873c7242013-01-12 01:03:14 +00001654 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001655 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001656 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001657 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001658}
1659
David Blaikie960ea3f2014-06-08 16:18:35 +00001660MipsAsmParser::OperandMatchResultTy
1661MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001662 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001663 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001664 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001665 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001666 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001667 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001668 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001669
Jack Carterb5cf5902013-04-17 00:18:04 +00001670 if (getLexer().getKind() == AsmToken::LParen) {
1671 Parser.Lex();
1672 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001673 }
1674
Jack Carterb5cf5902013-04-17 00:18:04 +00001675 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001677 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001678
Jack Carterd0bd6422013-04-18 00:41:53 +00001679 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001680 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001681 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1682 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001683 SMLoc E =
1684 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001685 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001686 return MatchOperand_Success;
1687 }
1688 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001689 SMLoc E =
1690 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001691
Jack Carterd0bd6422013-04-18 00:41:53 +00001692 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001693 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001694 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1695 S, E, *this);
1696 Operands.push_back(
1697 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001698 return MatchOperand_Success;
1699 }
1700 Error(Parser.getTok().getLoc(), "'(' expected");
1701 return MatchOperand_ParseFail;
1702 }
1703
Jack Carterd0bd6422013-04-18 00:41:53 +00001704 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001705 }
1706
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001707 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001708 if (Res != MatchOperand_Success)
1709 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001710
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001711 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001712 Error(Parser.getTok().getLoc(), "')' expected");
1713 return MatchOperand_ParseFail;
1714 }
1715
Jack Carter873c7242013-01-12 01:03:14 +00001716 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1717
Jack Carterd0bd6422013-04-18 00:41:53 +00001718 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001719
Craig Topper062a2ba2014-04-25 05:30:21 +00001720 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001721 IdVal = MCConstantExpr::Create(0, getContext());
1722
Jack Carterd0bd6422013-04-18 00:41:53 +00001723 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001724 std::unique_ptr<MipsOperand> op(
1725 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001727 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001728 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001729 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001730 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1731 int64_t Imm;
1732 if (IdVal->EvaluateAsAbsolute(Imm))
1733 IdVal = MCConstantExpr::Create(Imm, getContext());
1734 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1735 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1736 getContext());
1737 }
1738
David Blaikie960ea3f2014-06-08 16:18:35 +00001739 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001740 return MatchOperand_Success;
1741}
1742
David Blaikie960ea3f2014-06-08 16:18:35 +00001743bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001744
Jack Carterd76b2372013-03-21 21:44:16 +00001745 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1746 if (Sym) {
1747 SMLoc S = Parser.getTok().getLoc();
1748 const MCExpr *Expr;
1749 if (Sym->isVariable())
1750 Expr = Sym->getVariableValue();
1751 else
1752 return false;
1753 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001754 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001755 const StringRef DefSymbol = Ref->getSymbol().getName();
1756 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001757 OperandMatchResultTy ResTy =
1758 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001759 if (ResTy == MatchOperand_Success) {
1760 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001761 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001762 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001763 llvm_unreachable("Should never ParseFail");
1764 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001765 }
1766 } else if (Expr->getKind() == MCExpr::Constant) {
1767 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001768 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001769 Operands.push_back(
1770 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001771 return true;
1772 }
1773 }
1774 return false;
1775}
Jack Carterd0bd6422013-04-18 00:41:53 +00001776
Jack Carter873c7242013-01-12 01:03:14 +00001777MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001778MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1779 StringRef Identifier,
1780 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001781 int Index = matchCPURegisterName(Identifier);
1782 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001783 Operands.push_back(MipsOperand::CreateGPRReg(
1784 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1785 return MatchOperand_Success;
1786 }
1787
1788 Index = matchFPURegisterName(Identifier);
1789 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001790 Operands.push_back(MipsOperand::CreateFGRReg(
1791 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1792 return MatchOperand_Success;
1793 }
1794
1795 Index = matchFCCRegisterName(Identifier);
1796 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001797 Operands.push_back(MipsOperand::CreateFCCReg(
1798 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1799 return MatchOperand_Success;
1800 }
1801
1802 Index = matchACRegisterName(Identifier);
1803 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001804 Operands.push_back(MipsOperand::CreateACCReg(
1805 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1806 return MatchOperand_Success;
1807 }
1808
1809 Index = matchMSA128RegisterName(Identifier);
1810 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001811 Operands.push_back(MipsOperand::CreateMSA128Reg(
1812 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1813 return MatchOperand_Success;
1814 }
1815
1816 Index = matchMSA128CtrlRegisterName(Identifier);
1817 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001818 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1819 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1820 return MatchOperand_Success;
1821 }
1822
1823 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001824}
1825
1826MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001827MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001828 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001829
1830 if (Token.is(AsmToken::Identifier)) {
1831 DEBUG(dbgs() << ".. identifier\n");
1832 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001833 OperandMatchResultTy ResTy =
1834 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001835 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001836 } else if (Token.is(AsmToken::Integer)) {
1837 DEBUG(dbgs() << ".. integer\n");
1838 Operands.push_back(MipsOperand::CreateNumericReg(
1839 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1840 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001841 return MatchOperand_Success;
1842 }
1843
1844 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1845
1846 return MatchOperand_NoMatch;
1847}
1848
David Blaikie960ea3f2014-06-08 16:18:35 +00001849MipsAsmParser::OperandMatchResultTy
1850MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001851 DEBUG(dbgs() << "ParseAnyRegister\n");
1852
1853 auto Token = Parser.getTok();
1854
1855 SMLoc S = Token.getLoc();
1856
1857 if (Token.isNot(AsmToken::Dollar)) {
1858 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1859 if (Token.is(AsmToken::Identifier)) {
1860 if (searchSymbolAlias(Operands))
1861 return MatchOperand_Success;
1862 }
1863 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1864 return MatchOperand_NoMatch;
1865 }
1866 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001867
Daniel Sanders21bce302014-04-01 12:35:23 +00001868 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001869 if (ResTy == MatchOperand_Success) {
1870 Parser.Lex(); // $
1871 Parser.Lex(); // identifier
1872 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001873 return ResTy;
1874}
1875
1876MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001877MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001878 switch (getLexer().getKind()) {
1879 default:
1880 return MatchOperand_NoMatch;
1881 case AsmToken::LParen:
1882 case AsmToken::Minus:
1883 case AsmToken::Plus:
1884 case AsmToken::Integer:
1885 case AsmToken::String:
1886 break;
1887 }
1888
1889 const MCExpr *IdVal;
1890 SMLoc S = Parser.getTok().getLoc();
1891 if (getParser().parseExpression(IdVal))
1892 return MatchOperand_ParseFail;
1893
1894 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1895 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1896 return MatchOperand_Success;
1897}
1898
David Blaikie960ea3f2014-06-08 16:18:35 +00001899MipsAsmParser::OperandMatchResultTy
1900MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001901 DEBUG(dbgs() << "ParseJumpTarget\n");
1902
1903 SMLoc S = getLexer().getLoc();
1904
1905 // Integers and expressions are acceptable
1906 OperandMatchResultTy ResTy = ParseImm(Operands);
1907 if (ResTy != MatchOperand_NoMatch)
1908 return ResTy;
1909
Daniel Sanders315386c2014-04-01 10:40:14 +00001910 // Registers are a valid target and have priority over symbols.
1911 ResTy = ParseAnyRegister(Operands);
1912 if (ResTy != MatchOperand_NoMatch)
1913 return ResTy;
1914
Daniel Sandersffd84362014-04-01 10:41:48 +00001915 const MCExpr *Expr = nullptr;
1916 if (Parser.parseExpression(Expr)) {
1917 // We have no way of knowing if a symbol was consumed so we must ParseFail
1918 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001919 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001920 Operands.push_back(
1921 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001922 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001923}
1924
Vladimir Medic2b953d02013-10-01 09:48:56 +00001925MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001926MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001927 const MCExpr *IdVal;
1928 // If the first token is '$' we may have register operand.
1929 if (Parser.getTok().is(AsmToken::Dollar))
1930 return MatchOperand_NoMatch;
1931 SMLoc S = Parser.getTok().getLoc();
1932 if (getParser().parseExpression(IdVal))
1933 return MatchOperand_ParseFail;
1934 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001935 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001936 int64_t Val = MCE->getValue();
1937 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1938 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001939 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001940 return MatchOperand_Success;
1941}
1942
Matheus Almeida779c5932013-11-18 12:32:49 +00001943MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001944MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001945 switch (getLexer().getKind()) {
1946 default:
1947 return MatchOperand_NoMatch;
1948 case AsmToken::LParen:
1949 case AsmToken::Plus:
1950 case AsmToken::Minus:
1951 case AsmToken::Integer:
1952 break;
1953 }
1954
1955 const MCExpr *Expr;
1956 SMLoc S = Parser.getTok().getLoc();
1957
1958 if (getParser().parseExpression(Expr))
1959 return MatchOperand_ParseFail;
1960
1961 int64_t Val;
1962 if (!Expr->EvaluateAsAbsolute(Val)) {
1963 Error(S, "expected immediate value");
1964 return MatchOperand_ParseFail;
1965 }
1966
1967 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1968 // and because the CPU always adds one to the immediate field, the allowed
1969 // range becomes 1..4. We'll only check the range here and will deal
1970 // with the addition/subtraction when actually decoding/encoding
1971 // the instruction.
1972 if (Val < 1 || Val > 4) {
1973 Error(S, "immediate not in range (1..4)");
1974 return MatchOperand_ParseFail;
1975 }
1976
Jack Carter3b2c96e2014-01-22 23:31:38 +00001977 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001978 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00001979 return MatchOperand_Success;
1980}
1981
Jack Carterdc1e35d2012-09-06 20:00:02 +00001982MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1983
Vladimir Medic4c299852013-11-06 11:27:05 +00001984 MCSymbolRefExpr::VariantKind VK =
1985 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1986 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1987 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1988 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1989 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1990 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1991 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1992 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1993 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1994 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1995 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1996 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1997 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1998 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1999 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2000 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2001 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2002 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002003 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2004 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2005 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2006 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2007 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2008 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002009 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2010 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002011 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002012
Matheus Almeida2852af82014-04-22 10:15:54 +00002013 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002014
Jack Carterdc1e35d2012-09-06 20:00:02 +00002015 return VK;
2016}
Jack Cartera63b16a2012-09-07 00:23:42 +00002017
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002018/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2019/// either this.
2020/// ::= '(', register, ')'
2021/// handle it before we iterate so we don't get tripped up by the lack of
2022/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002023bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002024 if (getLexer().is(AsmToken::LParen)) {
2025 Operands.push_back(
2026 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2027 Parser.Lex();
2028 if (ParseOperand(Operands, Name)) {
2029 SMLoc Loc = getLexer().getLoc();
2030 Parser.eatToEndOfStatement();
2031 return Error(Loc, "unexpected token in argument list");
2032 }
2033 if (Parser.getTok().isNot(AsmToken::RParen)) {
2034 SMLoc Loc = getLexer().getLoc();
2035 Parser.eatToEndOfStatement();
2036 return Error(Loc, "unexpected token, expected ')'");
2037 }
2038 Operands.push_back(
2039 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2040 Parser.Lex();
2041 }
2042 return false;
2043}
2044
2045/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2046/// either one of these.
2047/// ::= '[', register, ']'
2048/// ::= '[', integer, ']'
2049/// handle it before we iterate so we don't get tripped up by the lack of
2050/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002051bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2052 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002053 if (getLexer().is(AsmToken::LBrac)) {
2054 Operands.push_back(
2055 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2056 Parser.Lex();
2057 if (ParseOperand(Operands, Name)) {
2058 SMLoc Loc = getLexer().getLoc();
2059 Parser.eatToEndOfStatement();
2060 return Error(Loc, "unexpected token in argument list");
2061 }
2062 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2063 SMLoc Loc = getLexer().getLoc();
2064 Parser.eatToEndOfStatement();
2065 return Error(Loc, "unexpected token, expected ']'");
2066 }
2067 Operands.push_back(
2068 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2069 Parser.Lex();
2070 }
2071 return false;
2072}
2073
David Blaikie960ea3f2014-06-08 16:18:35 +00002074bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2075 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002076 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002077 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002078 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002079 Parser.eatToEndOfStatement();
2080 return Error(NameLoc, "Unknown instruction");
2081 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002082 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002083 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002084
2085 // Read the remaining operands.
2086 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2087 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002088 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002089 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002090 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002091 return Error(Loc, "unexpected token in argument list");
2092 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002093 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2094 return true;
2095 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002096
Jack Carterd0bd6422013-04-18 00:41:53 +00002097 while (getLexer().is(AsmToken::Comma)) {
2098 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002099 // Parse and remember the operand.
2100 if (ParseOperand(Operands, Name)) {
2101 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002102 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002103 return Error(Loc, "unexpected token in argument list");
2104 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002105 // Parse bracket and parenthesis suffixes before we iterate
2106 if (getLexer().is(AsmToken::LBrac)) {
2107 if (ParseBracketSuffix(Name, Operands))
2108 return true;
2109 } else if (getLexer().is(AsmToken::LParen) &&
2110 ParseParenSuffix(Name, Operands))
2111 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002112 }
2113 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002114 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2115 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002116 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002117 return Error(Loc, "unexpected token in argument list");
2118 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002119 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002120 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002121}
2122
Jack Carter0b744b32012-10-04 02:29:46 +00002123bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002124 SMLoc Loc = getLexer().getLoc();
2125 Parser.eatToEndOfStatement();
2126 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002127}
2128
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002129bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2130 return Error(Loc, ErrorMsg);
2131}
2132
Jack Carter0b744b32012-10-04 02:29:46 +00002133bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002134 // Line should look like: ".set noat".
2135 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002136 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002137 // eat noat
2138 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002139 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002140 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2141 reportParseError("unexpected token in statement");
2142 return false;
2143 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002144 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002145 return false;
2146}
Jack Carterd0bd6422013-04-18 00:41:53 +00002147
Jack Carter0b744b32012-10-04 02:29:46 +00002148bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002149 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002150 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002151 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002152 getParser().Lex();
2153 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002154 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002155 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002156 return false;
2157 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002158 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002159 if (getLexer().isNot(AsmToken::Dollar)) {
2160 reportParseError("unexpected token in statement");
2161 return false;
2162 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002163 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002164 const AsmToken &Reg = Parser.getTok();
2165 if (Reg.is(AsmToken::Identifier)) {
2166 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2167 } else if (Reg.is(AsmToken::Integer)) {
2168 AtRegNo = Reg.getIntVal();
2169 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002170 reportParseError("unexpected token in statement");
2171 return false;
2172 }
Jack Carter1ac53222013-02-20 23:11:17 +00002173
Daniel Sanders71a89d922014-03-25 13:01:06 +00002174 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002175 reportParseError("unexpected token in statement");
2176 return false;
2177 }
2178
2179 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002180 reportParseError("unexpected token in statement");
2181 return false;
2182 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002183 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002184
2185 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2186 reportParseError("unexpected token in statement");
2187 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002188 }
2189 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002190 return false;
2191 } else {
2192 reportParseError("unexpected token in statement");
2193 return false;
2194 }
2195}
2196
2197bool MipsAsmParser::parseSetReorderDirective() {
2198 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002199 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002200 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2201 reportParseError("unexpected token in statement");
2202 return false;
2203 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002204 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002205 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002206 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002207 return false;
2208}
2209
2210bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002211 Parser.Lex();
2212 // If this is not the end of the statement, report an error.
2213 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2214 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002215 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002216 }
2217 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002218 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002219 Parser.Lex(); // Consume the EndOfStatement.
2220 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002221}
2222
2223bool MipsAsmParser::parseSetMacroDirective() {
2224 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002225 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002226 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2227 reportParseError("unexpected token in statement");
2228 return false;
2229 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002230 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002231 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002232 return false;
2233}
2234
2235bool MipsAsmParser::parseSetNoMacroDirective() {
2236 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002237 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002238 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2239 reportParseError("`noreorder' must be set before `nomacro'");
2240 return false;
2241 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002242 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002243 reportParseError("`noreorder' must be set before `nomacro'");
2244 return false;
2245 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002246 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002247 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002248 return false;
2249}
Jack Carterd76b2372013-03-21 21:44:16 +00002250
Jack Carter39536722014-01-22 23:08:42 +00002251bool MipsAsmParser::parseSetNoMips16Directive() {
2252 Parser.Lex();
2253 // If this is not the end of the statement, report an error.
2254 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2255 reportParseError("unexpected token in statement");
2256 return false;
2257 }
2258 // For now do nothing.
2259 Parser.Lex(); // Consume the EndOfStatement.
2260 return false;
2261}
2262
Jack Carterd76b2372013-03-21 21:44:16 +00002263bool MipsAsmParser::parseSetAssignment() {
2264 StringRef Name;
2265 const MCExpr *Value;
2266
2267 if (Parser.parseIdentifier(Name))
2268 reportParseError("expected identifier after .set");
2269
2270 if (getLexer().isNot(AsmToken::Comma))
2271 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002272 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002273
Jack Carter3b2c96e2014-01-22 23:31:38 +00002274 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002275 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002276
Jack Carterd0bd6422013-04-18 00:41:53 +00002277 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002278 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002279 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002280 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002281 Sym = getContext().GetOrCreateSymbol(Name);
2282 Sym->setVariableValue(Value);
2283
2284 return false;
2285}
Jack Carterd0bd6422013-04-18 00:41:53 +00002286
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002287bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2288 Parser.Lex();
2289 if (getLexer().isNot(AsmToken::EndOfStatement))
2290 return reportParseError("unexpected token in .set directive");
2291
Matheus Almeida2852af82014-04-22 10:15:54 +00002292 switch (Feature) {
2293 default:
2294 llvm_unreachable("Unimplemented feature");
2295 case Mips::FeatureDSP:
2296 setFeatureBits(Mips::FeatureDSP, "dsp");
2297 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002298 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002299 case Mips::FeatureMicroMips:
2300 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002301 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002302 case Mips::FeatureMips16:
2303 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002304 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002305 case Mips::FeatureMips32r2:
2306 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2307 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002308 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002309 case Mips::FeatureMips64:
2310 setFeatureBits(Mips::FeatureMips64, "mips64");
2311 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002312 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002313 case Mips::FeatureMips64r2:
2314 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2315 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002316 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002317 }
2318 return false;
2319}
2320
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002321bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2322 if (!getLexer().is(AsmToken::Dollar))
2323 return false;
2324
2325 Parser.Lex();
2326
2327 const AsmToken &Reg = Parser.getTok();
2328 if (Reg.is(AsmToken::Identifier)) {
2329 RegNum = matchCPURegisterName(Reg.getIdentifier());
2330 } else if (Reg.is(AsmToken::Integer)) {
2331 RegNum = Reg.getIntVal();
2332 } else {
2333 return false;
2334 }
2335
2336 Parser.Lex();
2337 return true;
2338}
2339
2340bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2341 if (getLexer().isNot(AsmToken::Comma)) {
2342 SMLoc Loc = getLexer().getLoc();
2343 Parser.eatToEndOfStatement();
2344 return Error(Loc, ErrorStr);
2345 }
2346
Matheus Almeida2852af82014-04-22 10:15:54 +00002347 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002348 return true;
2349}
2350
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002351bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2352 if (Options.isReorder())
2353 Warning(Loc, ".cpload in reorder section");
2354
2355 // FIXME: Warn if cpload is used in Mips16 mode.
2356
David Blaikie960ea3f2014-06-08 16:18:35 +00002357 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002358 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2359 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2360 reportParseError("expected register containing function address");
2361 return false;
2362 }
2363
David Blaikie960ea3f2014-06-08 16:18:35 +00002364 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2365 if (!RegOpnd.isGPRAsmReg()) {
2366 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002367 return false;
2368 }
2369
David Blaikie960ea3f2014-06-08 16:18:35 +00002370 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002371 return false;
2372}
2373
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002374bool MipsAsmParser::parseDirectiveCPSetup() {
2375 unsigned FuncReg;
2376 unsigned Save;
2377 bool SaveIsReg = true;
2378
2379 if (!parseRegister(FuncReg))
2380 return reportParseError("expected register containing function address");
2381 FuncReg = getGPR(FuncReg);
2382
2383 if (!eatComma("expected comma parsing directive"))
2384 return true;
2385
2386 if (!parseRegister(Save)) {
2387 const AsmToken &Tok = Parser.getTok();
2388 if (Tok.is(AsmToken::Integer)) {
2389 Save = Tok.getIntVal();
2390 SaveIsReg = false;
2391 Parser.Lex();
2392 } else
2393 return reportParseError("expected save register or stack offset");
2394 } else
2395 Save = getGPR(Save);
2396
2397 if (!eatComma("expected comma parsing directive"))
2398 return true;
2399
2400 StringRef Name;
2401 if (Parser.parseIdentifier(Name))
2402 reportParseError("expected identifier");
2403 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002404
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002405 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002406 return false;
2407}
2408
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002409bool MipsAsmParser::parseDirectiveNaN() {
2410 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2411 const AsmToken &Tok = Parser.getTok();
2412
2413 if (Tok.getString() == "2008") {
2414 Parser.Lex();
2415 getTargetStreamer().emitDirectiveNaN2008();
2416 return false;
2417 } else if (Tok.getString() == "legacy") {
2418 Parser.Lex();
2419 getTargetStreamer().emitDirectiveNaNLegacy();
2420 return false;
2421 }
2422 }
2423 // If we don't recognize the option passed to the .nan
2424 // directive (e.g. no option or unknown option), emit an error.
2425 reportParseError("invalid option in .nan directive");
2426 return false;
2427}
2428
Jack Carter0b744b32012-10-04 02:29:46 +00002429bool MipsAsmParser::parseDirectiveSet() {
2430
Jack Carterd0bd6422013-04-18 00:41:53 +00002431 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002432 const AsmToken &Tok = Parser.getTok();
2433
2434 if (Tok.getString() == "noat") {
2435 return parseSetNoAtDirective();
2436 } else if (Tok.getString() == "at") {
2437 return parseSetAtDirective();
2438 } else if (Tok.getString() == "reorder") {
2439 return parseSetReorderDirective();
2440 } else if (Tok.getString() == "noreorder") {
2441 return parseSetNoReorderDirective();
2442 } else if (Tok.getString() == "macro") {
2443 return parseSetMacroDirective();
2444 } else if (Tok.getString() == "nomacro") {
2445 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002446 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002447 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002448 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002449 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002450 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002451 getTargetStreamer().emitDirectiveSetNoMicroMips();
2452 Parser.eatToEndOfStatement();
2453 return false;
2454 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002455 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002456 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002457 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002458 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002459 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002460 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002461 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002462 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002463 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002464 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002465 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002466 parseSetAssignment();
2467 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002468 }
Jack Carter07c818d2013-01-25 01:31:34 +00002469
Jack Carter0b744b32012-10-04 02:29:46 +00002470 return true;
2471}
2472
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002473/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002474/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002475bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002476 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2477 for (;;) {
2478 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002479 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002480 return true;
2481
2482 getParser().getStreamer().EmitValue(Value, Size);
2483
2484 if (getLexer().is(AsmToken::EndOfStatement))
2485 break;
2486
2487 // FIXME: Improve diagnostic.
2488 if (getLexer().isNot(AsmToken::Comma))
2489 return Error(L, "unexpected token in directive");
2490 Parser.Lex();
2491 }
2492 }
2493
2494 Parser.Lex();
2495 return false;
2496}
2497
Vladimir Medic4c299852013-11-06 11:27:05 +00002498/// parseDirectiveGpWord
2499/// ::= .gpword local_sym
2500bool MipsAsmParser::parseDirectiveGpWord() {
2501 const MCExpr *Value;
2502 // EmitGPRel32Value requires an expression, so we are using base class
2503 // method to evaluate the expression.
2504 if (getParser().parseExpression(Value))
2505 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002506 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002507
Vladimir Medice10c1122013-11-13 13:18:04 +00002508 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002509 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002510 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002511 return false;
2512}
2513
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002514/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002515/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002516bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002517 const MCExpr *Value;
2518 // EmitGPRel64Value requires an expression, so we are using base class
2519 // method to evaluate the expression.
2520 if (getParser().parseExpression(Value))
2521 return true;
2522 getParser().getStreamer().EmitGPRel64Value(Value);
2523
2524 if (getLexer().isNot(AsmToken::EndOfStatement))
2525 return Error(getLexer().getLoc(), "unexpected token in directive");
2526 Parser.Lex(); // Eat EndOfStatement token.
2527 return false;
2528}
2529
Jack Carter0cd3c192014-01-06 23:27:31 +00002530bool MipsAsmParser::parseDirectiveOption() {
2531 // Get the option token.
2532 AsmToken Tok = Parser.getTok();
2533 // At the moment only identifiers are supported.
2534 if (Tok.isNot(AsmToken::Identifier)) {
2535 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2536 Parser.eatToEndOfStatement();
2537 return false;
2538 }
2539
2540 StringRef Option = Tok.getIdentifier();
2541
2542 if (Option == "pic0") {
2543 getTargetStreamer().emitDirectiveOptionPic0();
2544 Parser.Lex();
2545 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2546 Error(Parser.getTok().getLoc(),
2547 "unexpected token in .option pic0 directive");
2548 Parser.eatToEndOfStatement();
2549 }
2550 return false;
2551 }
2552
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002553 if (Option == "pic2") {
2554 getTargetStreamer().emitDirectiveOptionPic2();
2555 Parser.Lex();
2556 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2557 Error(Parser.getTok().getLoc(),
2558 "unexpected token in .option pic2 directive");
2559 Parser.eatToEndOfStatement();
2560 }
2561 return false;
2562 }
2563
Jack Carter0cd3c192014-01-06 23:27:31 +00002564 // Unknown option.
2565 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2566 Parser.eatToEndOfStatement();
2567 return false;
2568}
2569
Jack Carter0b744b32012-10-04 02:29:46 +00002570bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002571 StringRef IDVal = DirectiveID.getString();
2572
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002573 if (IDVal == ".cpload")
2574 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002575 if (IDVal == ".dword") {
2576 parseDataDirective(8, DirectiveID.getLoc());
2577 return false;
2578 }
2579
Jack Carterd0bd6422013-04-18 00:41:53 +00002580 if (IDVal == ".ent") {
2581 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002582 Parser.Lex();
2583 return false;
2584 }
2585
Jack Carter07c818d2013-01-25 01:31:34 +00002586 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002587 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002588 Parser.Lex();
2589 return false;
2590 }
2591
Jack Carter07c818d2013-01-25 01:31:34 +00002592 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002593 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002594 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002595 return false;
2596 }
2597
Jack Carter07c818d2013-01-25 01:31:34 +00002598 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002599 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002600 }
2601
Jack Carter07c818d2013-01-25 01:31:34 +00002602 if (IDVal == ".fmask") {
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 == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002609 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002610 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002611 return false;
2612 }
2613
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002614 if (IDVal == ".nan")
2615 return parseDirectiveNaN();
2616
Jack Carter07c818d2013-01-25 01:31:34 +00002617 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002618 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002619 return false;
2620 }
2621
Rafael Espindolab59fb732014-03-28 18:50:26 +00002622 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002623 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002624 return false;
2625 }
2626
Jack Carter07c818d2013-01-25 01:31:34 +00002627 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002628 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002629 return false;
2630 }
2631
Jack Carter0cd3c192014-01-06 23:27:31 +00002632 if (IDVal == ".option")
2633 return parseDirectiveOption();
2634
2635 if (IDVal == ".abicalls") {
2636 getTargetStreamer().emitDirectiveAbiCalls();
2637 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2638 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2639 // Clear line
2640 Parser.eatToEndOfStatement();
2641 }
2642 return false;
2643 }
2644
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002645 if (IDVal == ".cpsetup")
2646 return parseDirectiveCPSetup();
2647
Rafael Espindola870c4e92012-01-11 03:56:41 +00002648 return true;
2649}
2650
Rafael Espindola870c4e92012-01-11 03:56:41 +00002651extern "C" void LLVMInitializeMipsAsmParser() {
2652 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2653 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2654 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2655 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2656}
Jack Carterb4dbc172012-09-05 23:34:03 +00002657
2658#define GET_REGISTER_MATCHER
2659#define GET_MATCHER_IMPLEMENTATION
2660#include "MipsGenAsmMatcher.inc"