blob: dc9ed2feeb9c04d50b9b9f8d4e0fd8a8398d84f5 [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
Matheus Almeida3813d572014-06-19 14:39:14 +0000119 // Expands assembly pseudo instructions.
120 // Returns false on success, true otherwise.
121 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000122 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000123
124 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000125 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000126
127 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000128 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000129
130 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000131 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000132
Jack Carter9e65aa32013-03-22 00:05:30 +0000133 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000134 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
135 bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000136 bool reportParseError(StringRef ErrorMsg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000137 bool reportParseError(SMLoc Loc, StringRef ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000138
Jack Carterb5cf5902013-04-17 00:18:04 +0000139 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000140 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000141
Vladimir Medic4c299852013-11-06 11:27:05 +0000142 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000143
144 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000145 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000146 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000147 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000148 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000149 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000150 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000151
152 bool parseSetAtDirective();
153 bool parseSetNoAtDirective();
154 bool parseSetMacroDirective();
155 bool parseSetNoMacroDirective();
156 bool parseSetReorderDirective();
157 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000158 bool parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +0000159
Jack Carterd76b2372013-03-21 21:44:16 +0000160 bool parseSetAssignment();
161
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000162 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000163 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000164 bool parseDirectiveGpDWord();
Jack Carter07c818d2013-01-25 01:31:34 +0000165
Jack Carterdc1e35d2012-09-06 20:00:02 +0000166 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000167
Daniel Sanders5e94e682014-03-27 16:42:17 +0000168 bool isGP64() const {
169 return (STI.getFeatureBits() & Mips::FeatureGP64Bit) != 0;
Jack Carterb4dbc172012-09-05 23:34:03 +0000170 }
171
Jack Cartera63b16a2012-09-07 00:23:42 +0000172 bool isFP64() const {
173 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
174 }
175
Daniel Sandersa4b0c742014-03-26 11:39:07 +0000176 bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
Vladimir Medic4c299852013-11-06 11:27:05 +0000177 bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000178
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000179 bool isMicroMips() const {
180 return STI.getFeatureBits() & Mips::FeatureMicroMips;
181 }
182
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000183 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
184 bool hasMips32() const { return STI.getFeatureBits() & Mips::FeatureMips32; }
Daniel Sandersa84989a2014-06-16 13:25:35 +0000185 bool hasMips32r6() const {
186 return STI.getFeatureBits() & Mips::FeatureMips32r6;
187 }
188 bool hasMips64r6() const {
189 return STI.getFeatureBits() & Mips::FeatureMips64r6;
190 }
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000191
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000192 bool eatComma(StringRef ErrorStr);
193
Jack Carter1ac53222013-02-20 23:11:17 +0000194 int matchCPURegisterName(StringRef Symbol);
195
Jack Carter873c7242013-01-12 01:03:14 +0000196 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000197
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000198 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000199
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000200 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000201
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000202 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000203
Jack Carter5dc8ac92013-09-25 23:50:44 +0000204 int matchMSA128RegisterName(StringRef Name);
205
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000206 int matchMSA128CtrlRegisterName(StringRef Name);
207
Jack Carterd0bd6422013-04-18 00:41:53 +0000208 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000209
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000210 unsigned getGPR(int RegNo);
211
Matheus Almeida7de68e72014-06-18 14:46:05 +0000212 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000213
214 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000215 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000216
217 // Helper function that checks if the value of a vector index is within the
218 // boundaries of accepted values for each RegisterKind
219 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
220 bool validateMSAIndex(int Val, int RegKind);
221
Vladimir Medic615b26e2014-03-04 09:54:09 +0000222 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
223 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000224 setAvailableFeatures(
225 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000226 }
227 }
228
229 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
230 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000231 setAvailableFeatures(
232 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000233 }
234 }
235
Rafael Espindola870c4e92012-01-11 03:56:41 +0000236public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000237 enum MipsMatchResultTy {
238 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
239#define GET_OPERAND_DIAGNOSTIC_TYPES
240#include "MipsGenAsmMatcher.inc"
241#undef GET_OPERAND_DIAGNOSTIC_TYPES
242
243 };
244
Joey Gouly0e76fa72013-09-12 10:28:05 +0000245 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000246 const MCInstrInfo &MII,
247 const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000248 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000249 // Initialize the set of available features.
250 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000251
252 // Assert exactly one ABI was chosen.
253 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
254 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
255 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
256 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000257 }
258
Jack Carterb4dbc172012-09-05 23:34:03 +0000259 MCAsmParser &getParser() const { return Parser; }
260 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000261
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000262 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
263 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
264
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000265 /// Warn if RegNo is the current assembler temporary.
266 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000267};
268}
269
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000270namespace {
271
272/// MipsOperand - Instances of this class represent a parsed Mips machine
273/// instruction.
274class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000275public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000276 /// Broad categories of register classes
277 /// The exact class is finalized by the render method.
278 enum RegKind {
279 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
280 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
281 /// isFP64())
282 RegKind_FCC = 4, /// FCC
283 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
284 RegKind_MSACtrl = 16, /// MSA control registers
285 RegKind_COP2 = 32, /// COP2
286 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
287 /// context).
288 RegKind_CCR = 128, /// CCR
289 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000290 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000291
292 /// Potentially any (e.g. $1)
293 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
294 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000295 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000296 };
297
298private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000299 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000300 k_Immediate, /// An immediate (possibly involving symbol references)
301 k_Memory, /// Base + Offset Memory Address
302 k_PhysRegister, /// A physical register from the Mips namespace
303 k_RegisterIndex, /// A register index in one or more RegKind.
304 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000305 } Kind;
306
David Blaikie960ea3f2014-06-08 16:18:35 +0000307public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000308 MipsOperand(KindTy K, MipsAsmParser &Parser)
309 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
310
David Blaikie960ea3f2014-06-08 16:18:35 +0000311private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000312 /// For diagnostics, and checking the assembler temporary
313 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000314
Eric Christopher8996c5d2013-03-15 00:42:55 +0000315 struct Token {
316 const char *Data;
317 unsigned Length;
318 };
319
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000320 struct PhysRegOp {
321 unsigned Num; /// Register Number
322 };
323
324 struct RegIdxOp {
325 unsigned Index; /// Index into the register class
326 RegKind Kind; /// Bitfield of the kinds it could possibly be
327 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000328 };
329
330 struct ImmOp {
331 const MCExpr *Val;
332 };
333
334 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000335 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000336 const MCExpr *Off;
337 };
338
Jack Carterb4dbc172012-09-05 23:34:03 +0000339 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000340 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000341 struct PhysRegOp PhysReg;
342 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000343 struct ImmOp Imm;
344 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000345 };
346
347 SMLoc StartLoc, EndLoc;
348
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000349 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000350 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
351 const MCRegisterInfo *RegInfo,
352 SMLoc S, SMLoc E,
353 MipsAsmParser &Parser) {
354 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000355 Op->RegIdx.Index = Index;
356 Op->RegIdx.RegInfo = RegInfo;
357 Op->RegIdx.Kind = RegKind;
358 Op->StartLoc = S;
359 Op->EndLoc = E;
360 return Op;
361 }
362
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000363public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000364 /// Coerce the register to GPR32 and return the real register for the current
365 /// target.
366 unsigned getGPR32Reg() const {
367 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
368 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
369 unsigned ClassID = Mips::GPR32RegClassID;
370 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000371 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000372
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000373 /// Coerce the register to GPR64 and return the real register for the current
374 /// target.
375 unsigned getGPR64Reg() const {
376 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
377 unsigned ClassID = Mips::GPR64RegClassID;
378 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000379 }
380
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000381private:
382 /// Coerce the register to AFGR64 and return the real register for the current
383 /// target.
384 unsigned getAFGR64Reg() const {
385 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
386 if (RegIdx.Index % 2 != 0)
387 AsmParser.Warning(StartLoc, "Float register should be even.");
388 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
389 .getRegister(RegIdx.Index / 2);
390 }
391
392 /// Coerce the register to FGR64 and return the real register for the current
393 /// target.
394 unsigned getFGR64Reg() const {
395 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
396 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
397 .getRegister(RegIdx.Index);
398 }
399
400 /// Coerce the register to FGR32 and return the real register for the current
401 /// target.
402 unsigned getFGR32Reg() const {
403 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
404 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
405 .getRegister(RegIdx.Index);
406 }
407
408 /// Coerce the register to FGRH32 and return the real register for the current
409 /// target.
410 unsigned getFGRH32Reg() const {
411 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
412 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
413 .getRegister(RegIdx.Index);
414 }
415
416 /// Coerce the register to FCC and return the real register for the current
417 /// target.
418 unsigned getFCCReg() const {
419 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
420 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
421 .getRegister(RegIdx.Index);
422 }
423
424 /// Coerce the register to MSA128 and return the real register for the current
425 /// target.
426 unsigned getMSA128Reg() const {
427 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
428 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
429 // identical
430 unsigned ClassID = Mips::MSA128BRegClassID;
431 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
432 }
433
434 /// Coerce the register to MSACtrl and return the real register for the
435 /// current target.
436 unsigned getMSACtrlReg() const {
437 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
438 unsigned ClassID = Mips::MSACtrlRegClassID;
439 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
440 }
441
442 /// Coerce the register to COP2 and return the real register for the
443 /// current target.
444 unsigned getCOP2Reg() const {
445 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
446 unsigned ClassID = Mips::COP2RegClassID;
447 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
448 }
449
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000450 /// Coerce the register to COP3 and return the real register for the
451 /// current target.
452 unsigned getCOP3Reg() const {
453 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
454 unsigned ClassID = Mips::COP3RegClassID;
455 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
456 }
457
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000458 /// Coerce the register to ACC64DSP and return the real register for the
459 /// current target.
460 unsigned getACC64DSPReg() const {
461 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
462 unsigned ClassID = Mips::ACC64DSPRegClassID;
463 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
464 }
465
466 /// Coerce the register to HI32DSP and return the real register for the
467 /// current target.
468 unsigned getHI32DSPReg() const {
469 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
470 unsigned ClassID = Mips::HI32DSPRegClassID;
471 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
472 }
473
474 /// Coerce the register to LO32DSP and return the real register for the
475 /// current target.
476 unsigned getLO32DSPReg() const {
477 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
478 unsigned ClassID = Mips::LO32DSPRegClassID;
479 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
480 }
481
482 /// Coerce the register to CCR and return the real register for the
483 /// current target.
484 unsigned getCCRReg() const {
485 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
486 unsigned ClassID = Mips::CCRRegClassID;
487 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
488 }
489
490 /// Coerce the register to HWRegs and return the real register for the
491 /// current target.
492 unsigned getHWRegsReg() const {
493 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
494 unsigned ClassID = Mips::HWRegsRegClassID;
495 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
496 }
497
498public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000499 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000500 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000501 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000502 Inst.addOperand(MCOperand::CreateImm(0));
503 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
504 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
505 else
506 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000507 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000508
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000509 void addRegOperands(MCInst &Inst, unsigned N) const {
510 llvm_unreachable("Use a custom parser instead");
511 }
512
Daniel Sanders21bce302014-04-01 12:35:23 +0000513 /// Render the operand to an MCInst as a GPR32
514 /// Asserts if the wrong number of operands are requested, or the operand
515 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000516 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
517 assert(N == 1 && "Invalid number of operands!");
518 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
519 }
520
Daniel Sanders21bce302014-04-01 12:35:23 +0000521 /// Render the operand to an MCInst as a GPR64
522 /// Asserts if the wrong number of operands are requested, or the operand
523 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000524 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
525 assert(N == 1 && "Invalid number of operands!");
526 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
527 }
528
529 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
530 assert(N == 1 && "Invalid number of operands!");
531 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
532 }
533
534 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
535 assert(N == 1 && "Invalid number of operands!");
536 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
537 }
538
539 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
540 assert(N == 1 && "Invalid number of operands!");
541 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
542 }
543
544 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
545 assert(N == 1 && "Invalid number of operands!");
546 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
547 }
548
549 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
550 assert(N == 1 && "Invalid number of operands!");
551 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
552 }
553
554 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
555 assert(N == 1 && "Invalid number of operands!");
556 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
557 }
558
559 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
560 assert(N == 1 && "Invalid number of operands!");
561 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
562 }
563
564 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
565 assert(N == 1 && "Invalid number of operands!");
566 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
567 }
568
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000569 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
570 assert(N == 1 && "Invalid number of operands!");
571 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
572 }
573
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000574 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
575 assert(N == 1 && "Invalid number of operands!");
576 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
577 }
578
579 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
580 assert(N == 1 && "Invalid number of operands!");
581 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
582 }
583
584 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
585 assert(N == 1 && "Invalid number of operands!");
586 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
587 }
588
589 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
590 assert(N == 1 && "Invalid number of operands!");
591 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
592 }
593
594 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
595 assert(N == 1 && "Invalid number of operands!");
596 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
597 }
598
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000599 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000600 assert(N == 1 && "Invalid number of operands!");
601 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000602 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000603 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000604
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000605 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000606 assert(N == 2 && "Invalid number of operands!");
607
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000609
610 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000611 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000612 }
613
Craig Topper56c590a2014-04-29 07:58:02 +0000614 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000615 // As a special case until we sort out the definition of div/divu, pretend
616 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
617 if (isGPRAsmReg() && RegIdx.Index == 0)
618 return true;
619
620 return Kind == k_PhysRegister;
621 }
622 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000623 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000624 bool isConstantImm() const {
625 return isImm() && dyn_cast<MCConstantExpr>(getImm());
626 }
Craig Topper56c590a2014-04-29 07:58:02 +0000627 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000628 // Note: It's not possible to pretend that other operand kinds are tokens.
629 // The matcher emitter checks tokens first.
630 return Kind == k_Token;
631 }
Craig Topper56c590a2014-04-29 07:58:02 +0000632 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000633 bool isConstantMemOff() const {
634 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
635 }
636 template <unsigned Bits> bool isMemWithSimmOffset() const {
637 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
638 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000639 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000640 bool isLSAImm() const {
641 if (!isConstantImm())
642 return false;
643 int64_t Val = getConstantImm();
644 return 1 <= Val && Val <= 4;
645 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000646
647 StringRef getToken() const {
648 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000649 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000650 }
651
Craig Topper56c590a2014-04-29 07:58:02 +0000652 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000653 // As a special case until we sort out the definition of div/divu, pretend
654 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
655 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
656 RegIdx.Kind & RegKind_GPR)
657 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000658
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000659 assert(Kind == k_PhysRegister && "Invalid access!");
660 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000661 }
662
Jack Carterb4dbc172012-09-05 23:34:03 +0000663 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000665 return Imm.Val;
666 }
667
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000668 int64_t getConstantImm() const {
669 const MCExpr *Val = getImm();
670 return static_cast<const MCConstantExpr *>(Val)->getValue();
671 }
672
673 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000674 assert((Kind == k_Memory) && "Invalid access!");
675 return Mem.Base;
676 }
677
678 const MCExpr *getMemOff() const {
679 assert((Kind == k_Memory) && "Invalid access!");
680 return Mem.Off;
681 }
682
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000683 int64_t getConstantMemOff() const {
684 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
685 }
686
David Blaikie960ea3f2014-06-08 16:18:35 +0000687 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
688 MipsAsmParser &Parser) {
689 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000690 Op->Tok.Data = Str.data();
691 Op->Tok.Length = Str.size();
692 Op->StartLoc = S;
693 Op->EndLoc = S;
694 return Op;
695 }
696
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000697 /// Create a numeric register (e.g. $1). The exact register remains
698 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000699 static std::unique_ptr<MipsOperand>
700 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
701 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000702 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
703 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000704 }
705
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000706 /// Create a register that is definitely a GPR.
707 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000708 static std::unique_ptr<MipsOperand>
709 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
710 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000711 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000712 }
713
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000714 /// Create a register that is definitely a FGR.
715 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000716 static std::unique_ptr<MipsOperand>
717 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
718 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000719 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
720 }
721
722 /// Create a register that is definitely an FCC.
723 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000724 static std::unique_ptr<MipsOperand>
725 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
726 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000727 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
728 }
729
730 /// Create a register that is definitely an ACC.
731 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000732 static std::unique_ptr<MipsOperand>
733 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
734 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000735 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
736 }
737
738 /// Create a register that is definitely an MSA128.
739 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000740 static std::unique_ptr<MipsOperand>
741 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
742 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
744 }
745
746 /// Create a register that is definitely an MSACtrl.
747 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000748 static std::unique_ptr<MipsOperand>
749 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
750 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
752 }
753
David Blaikie960ea3f2014-06-08 16:18:35 +0000754 static std::unique_ptr<MipsOperand>
755 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
756 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000757 Op->Imm.Val = Val;
758 Op->StartLoc = S;
759 Op->EndLoc = E;
760 return Op;
761 }
762
David Blaikie960ea3f2014-06-08 16:18:35 +0000763 static std::unique_ptr<MipsOperand>
764 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
765 SMLoc E, MipsAsmParser &Parser) {
766 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
767 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000768 Op->Mem.Off = Off;
769 Op->StartLoc = S;
770 Op->EndLoc = E;
771 return Op;
772 }
773
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 bool isGPRAsmReg() const {
775 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000776 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000777 bool isFGRAsmReg() const {
778 // AFGR64 is $0-$15 but we handle this in getAFGR64()
779 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000780 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 bool isHWRegsAsmReg() const {
782 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000783 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000784 bool isCCRAsmReg() const {
785 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000786 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000787 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000788 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
789 return false;
790 if (!AsmParser.hasEightFccRegisters())
791 return RegIdx.Index == 0;
792 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000793 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 bool isACCAsmReg() const {
795 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000796 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000797 bool isCOP2AsmReg() const {
798 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000799 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000800 bool isCOP3AsmReg() const {
801 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
802 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000803 bool isMSA128AsmReg() const {
804 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000805 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000806 bool isMSACtrlAsmReg() const {
807 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000808 }
809
Jack Carterb4dbc172012-09-05 23:34:03 +0000810 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000811 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000812 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000813 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000814
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000815 virtual ~MipsOperand() {
816 switch (Kind) {
817 case k_Immediate:
818 break;
819 case k_Memory:
820 delete Mem.Base;
821 break;
822 case k_PhysRegister:
823 case k_RegisterIndex:
824 case k_Token:
825 break;
826 }
827 }
828
Craig Topper56c590a2014-04-29 07:58:02 +0000829 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 switch (Kind) {
831 case k_Immediate:
832 OS << "Imm<";
833 Imm.Val->print(OS);
834 OS << ">";
835 break;
836 case k_Memory:
837 OS << "Mem<";
838 Mem.Base->print(OS);
839 OS << ", ";
840 Mem.Off->print(OS);
841 OS << ">";
842 break;
843 case k_PhysRegister:
844 OS << "PhysReg<" << PhysReg.Num << ">";
845 break;
846 case k_RegisterIndex:
847 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
848 break;
849 case k_Token:
850 OS << Tok.Data;
851 break;
852 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000853 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000854}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000855} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000856
Jack Carter9e65aa32013-03-22 00:05:30 +0000857namespace llvm {
858extern const MCInstrDesc MipsInsts[];
859}
860static const MCInstrDesc &getInstDesc(unsigned Opcode) {
861 return MipsInsts[Opcode];
862}
863
864bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000865 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000866 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000867
Jack Carter9e65aa32013-03-22 00:05:30 +0000868 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000869
870 if (MCID.isBranch() || MCID.isCall()) {
871 const unsigned Opcode = Inst.getOpcode();
872 MCOperand Offset;
873
874 switch (Opcode) {
875 default:
876 break;
877 case Mips::BEQ:
878 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000879 case Mips::BEQ_MM:
880 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000881 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000882 Offset = Inst.getOperand(2);
883 if (!Offset.isImm())
884 break; // We'll deal with this situation later on when applying fixups.
885 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
886 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000887 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000888 return Error(IDLoc, "branch to misaligned address");
889 break;
890 case Mips::BGEZ:
891 case Mips::BGTZ:
892 case Mips::BLEZ:
893 case Mips::BLTZ:
894 case Mips::BGEZAL:
895 case Mips::BLTZAL:
896 case Mips::BC1F:
897 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000898 case Mips::BGEZ_MM:
899 case Mips::BGTZ_MM:
900 case Mips::BLEZ_MM:
901 case Mips::BLTZ_MM:
902 case Mips::BGEZAL_MM:
903 case Mips::BLTZAL_MM:
904 case Mips::BC1F_MM:
905 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000906 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000907 Offset = Inst.getOperand(1);
908 if (!Offset.isImm())
909 break; // We'll deal with this situation later on when applying fixups.
910 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
911 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000912 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000913 return Error(IDLoc, "branch to misaligned address");
914 break;
915 }
916 }
917
Daniel Sandersa84989a2014-06-16 13:25:35 +0000918 // SSNOP is deprecated on MIPS32r6/MIPS64r6
919 // We still accept it but it is a normal nop.
920 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
921 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
922 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
923 "nop instruction");
924 }
925
Jack Carterc15c1d22013-04-25 23:31:35 +0000926 if (MCID.hasDelaySlot() && Options.isReorder()) {
927 // If this instruction has a delay slot and .set reorder is active,
928 // emit a NOP after it.
929 Instructions.push_back(Inst);
930 MCInst NopInst;
931 NopInst.setOpcode(Mips::SLL);
932 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
933 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
934 NopInst.addOperand(MCOperand::CreateImm(0));
935 Instructions.push_back(NopInst);
936 return false;
937 }
938
Jack Carter9e65aa32013-03-22 00:05:30 +0000939 if (MCID.mayLoad() || MCID.mayStore()) {
940 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000941 // reference or immediate we may have to expand instructions.
942 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000943 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000944 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
945 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000946 MCOperand &Op = Inst.getOperand(i);
947 if (Op.isImm()) {
948 int MemOffset = Op.getImm();
949 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000950 // Offset can't exceed 16bit value.
951 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000952 return false;
953 }
954 } else if (Op.isExpr()) {
955 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000956 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000957 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000958 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000959 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000960 // Expand symbol.
961 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000962 return false;
963 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000964 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000965 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000966 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000967 }
968 }
969 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000970 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000971 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000972
973 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +0000974 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000975 else
976 Instructions.push_back(Inst);
977
978 return false;
979}
980
Jack Carter30a59822012-10-04 04:03:53 +0000981bool MipsAsmParser::needsExpansion(MCInst &Inst) {
982
Jack Carterd0bd6422013-04-18 00:41:53 +0000983 switch (Inst.getOpcode()) {
984 case Mips::LoadImm32Reg:
985 case Mips::LoadAddr32Imm:
986 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +0000987 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +0000988 return true;
989 default:
990 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000991 }
992}
Jack Carter92995f12012-10-06 00:53:28 +0000993
Matheus Almeida3813d572014-06-19 14:39:14 +0000994bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000995 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000996 switch (Inst.getOpcode()) {
Matheus Almeida3813d572014-06-19 14:39:14 +0000997 default: assert(0 && "unimplemented expansion");
998 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000999 case Mips::LoadImm32Reg:
1000 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001001 case Mips::LoadImm64Reg:
1002 if (!isGP64()) {
1003 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1004 return true;
1005 }
1006 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001007 case Mips::LoadAddr32Imm:
1008 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1009 case Mips::LoadAddr32Reg:
1010 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1011 }
Jack Carter30a59822012-10-04 04:03:53 +00001012}
Jack Carter92995f12012-10-06 00:53:28 +00001013
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001014namespace {
1015template <int Shift, bool PerformShift>
1016void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1017 SmallVectorImpl<MCInst> &Instructions) {
1018 MCInst tmpInst;
1019 if (PerformShift) {
1020 tmpInst.setOpcode(Mips::DSLL);
1021 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1022 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1023 tmpInst.addOperand(MCOperand::CreateImm(16));
1024 tmpInst.setLoc(IDLoc);
1025 Instructions.push_back(tmpInst);
1026 tmpInst.clear();
1027 }
1028 tmpInst.setOpcode(Mips::ORi);
1029 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1030 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1031 tmpInst.addOperand(
1032 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)));
1033 tmpInst.setLoc(IDLoc);
1034 Instructions.push_back(tmpInst);
1035}
1036}
1037
Matheus Almeida3813d572014-06-19 14:39:14 +00001038bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001039 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001040 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001041 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001042 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001043 const MCOperand &RegOp = Inst.getOperand(0);
1044 assert(RegOp.isReg() && "expected register operand kind");
1045
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001046 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001047 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001048 // FIXME: gas has a special case for values that are 000...1111, which
1049 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001050 if (0 <= ImmValue && ImmValue <= 65535) {
1051 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001052 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001053 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001054 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001055 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001056 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001057 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001058 } else if (ImmValue < 0 && ImmValue >= -32768) {
1059 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001060 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001061 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001062 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001063 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001064 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001065 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001066 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1067 // For any value of j that is representable as a 32-bit integer, create
1068 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001069 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001070 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001071 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001072 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1073 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001074 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001075 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1076 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
1077 if (!isGP64()) {
1078 Error (IDLoc, "instruction requires a CPU feature not currently enabled");
1079 return true;
1080 }
1081
1082 // <------- lo32 ------>
1083 // <------- hi32 ------>
1084 // <- hi16 -> <- lo16 ->
1085 // _________________________________
1086 // | | | |
1087 // | 16-bytes | 16-bytes | 16-bytes |
1088 // |__________|__________|__________|
1089 //
1090 // For any value of j that is representable as a 48-bit integer, create
1091 // a sequence of:
1092 // li d,j => lui d,hi16(j)
1093 // ori d,d,hi16(lo32(j))
1094 // dsll d,d,16
1095 // ori d,d,lo16(lo32(j))
1096 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001097 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001098 tmpInst.addOperand(
1099 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001100 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001101 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1102 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1103 } else {
1104 if (!isGP64()) {
1105 Error (IDLoc, "instruction requires a CPU feature not currently enabled");
1106 return true;
1107 }
1108
1109 // <------- hi32 ------> <------- lo32 ------>
1110 // <- hi16 -> <- lo16 ->
1111 // ___________________________________________
1112 // | | | | |
1113 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1114 // |__________|__________|__________|__________|
1115 //
1116 // For any value of j that isn't representable as a 48-bit integer.
1117 // li d,j => lui d,hi16(j)
1118 // ori d,d,lo16(hi32(j))
1119 // dsll d,d,16
1120 // ori d,d,hi16(lo32(j))
1121 // dsll d,d,16
1122 // ori d,d,lo16(lo32(j))
1123 tmpInst.setOpcode(Mips::LUi);
1124 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1125 tmpInst.addOperand(
1126 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1127 Instructions.push_back(tmpInst);
1128 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1129 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1130 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001131 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001132 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001133}
Jack Carter92995f12012-10-06 00:53:28 +00001134
Matheus Almeida3813d572014-06-19 14:39:14 +00001135bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001136MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1137 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001138 MCInst tmpInst;
1139 const MCOperand &ImmOp = Inst.getOperand(2);
1140 assert(ImmOp.isImm() && "expected immediate operand kind");
1141 const MCOperand &SrcRegOp = Inst.getOperand(1);
1142 assert(SrcRegOp.isReg() && "expected register operand kind");
1143 const MCOperand &DstRegOp = Inst.getOperand(0);
1144 assert(DstRegOp.isReg() && "expected register operand kind");
1145 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001146 if (-32768 <= ImmValue && ImmValue <= 65535) {
1147 // For -32768 <= j <= 65535.
1148 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001149 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001150 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1151 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1152 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1153 Instructions.push_back(tmpInst);
1154 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001155 // For any other value of j that is representable as a 32-bit integer.
1156 // la d,j(s) => lui d,hi16(j)
1157 // ori d,d,lo16(j)
1158 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001159 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001160 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1161 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1162 Instructions.push_back(tmpInst);
1163 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001164 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001165 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1166 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1167 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1168 Instructions.push_back(tmpInst);
1169 tmpInst.clear();
1170 tmpInst.setOpcode(Mips::ADDu);
1171 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1172 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1173 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1174 Instructions.push_back(tmpInst);
1175 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001176 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001177}
1178
Matheus Almeida3813d572014-06-19 14:39:14 +00001179bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001180MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1181 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001182 MCInst tmpInst;
1183 const MCOperand &ImmOp = Inst.getOperand(1);
1184 assert(ImmOp.isImm() && "expected immediate operand kind");
1185 const MCOperand &RegOp = Inst.getOperand(0);
1186 assert(RegOp.isReg() && "expected register operand kind");
1187 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001188 if (-32768 <= ImmValue && ImmValue <= 65535) {
1189 // For -32768 <= j <= 65535.
1190 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001191 tmpInst.setOpcode(Mips::ADDiu);
1192 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001193 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001194 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1195 Instructions.push_back(tmpInst);
1196 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001197 // For any other value of j that is representable as a 32-bit integer.
1198 // la d,j => lui d,hi16(j)
1199 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001200 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001201 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1202 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1203 Instructions.push_back(tmpInst);
1204 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001205 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001206 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1207 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1208 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1209 Instructions.push_back(tmpInst);
1210 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001211 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001212}
1213
Jack Carter9e65aa32013-03-22 00:05:30 +00001214void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001215 SmallVectorImpl<MCInst> &Instructions,
1216 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001217 const MCSymbolRefExpr *SR;
1218 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001219 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001220 const MCExpr *ExprOffset;
1221 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001222 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001223 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1224 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001225 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001226 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1227 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001228 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001229 if (isImmOpnd) {
1230 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1231 ImmOffset = Inst.getOperand(2).getImm();
1232 LoOffset = ImmOffset & 0x0000ffff;
1233 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001234 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001235 if (LoOffset & 0x8000)
1236 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001237 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001238 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001239 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001240 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001241 // These are some of the types of expansions we perform here:
1242 // 1) lw $8, sym => lui $8, %hi(sym)
1243 // lw $8, %lo(sym)($8)
1244 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1245 // add $8, $8, $9
1246 // lw $8, %lo(offset)($9)
1247 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1248 // add $at, $at, $8
1249 // lw $8, %lo(offset)($at)
1250 // 4) sw $8, sym => lui $at, %hi(sym)
1251 // sw $8, %lo(sym)($at)
1252 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1253 // add $at, $at, $8
1254 // sw $8, %lo(offset)($at)
1255 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1256 // ldc1 $f0, %lo(sym)($at)
1257 //
1258 // For load instructions we can use the destination register as a temporary
1259 // if base and dst are different (examples 1 and 2) and if the base register
1260 // is general purpose otherwise we must use $at (example 6) and error if it's
1261 // not available. For stores we must use $at (examples 4 and 5) because we
1262 // must not clobber the source register setting up the offset.
1263 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1264 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1265 unsigned RegClassIDOp0 =
1266 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1267 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1268 (RegClassIDOp0 == Mips::GPR64RegClassID);
1269 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001270 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001271 else {
1272 int AT = getATReg(IDLoc);
1273 // At this point we need AT to perform the expansions and we exit if it is
1274 // not available.
1275 if (!AT)
1276 return;
1277 TmpRegNum =
1278 getReg((isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
1279 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001280
Jack Carter9e65aa32013-03-22 00:05:30 +00001281 TempInst.setOpcode(Mips::LUi);
1282 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1283 if (isImmOpnd)
1284 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1285 else {
1286 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001287 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001288 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1289 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1290 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001291 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001292 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001293 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001294 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001295 }
1296 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001297 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001298 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001299 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001300 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001301 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001302 TempInst.setOpcode(Mips::ADDu);
1303 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1304 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1305 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1306 Instructions.push_back(TempInst);
1307 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001308 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001309 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001310 TempInst.setOpcode(Inst.getOpcode());
1311 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1312 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1313 if (isImmOpnd)
1314 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1315 else {
1316 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001317 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1318 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1319 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001320 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001321 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001322 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001323 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001324 }
1325 }
1326 Instructions.push_back(TempInst);
1327 TempInst.clear();
1328}
1329
Matheus Almeida595fcab2014-06-11 15:05:56 +00001330unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1331 // As described by the Mips32r2 spec, the registers Rd and Rs for
1332 // jalr.hb must be different.
1333 unsigned Opcode = Inst.getOpcode();
1334
1335 if (Opcode == Mips::JALR_HB &&
1336 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1337 return Match_RequiresDifferentSrcAndDst;
1338
1339 return Match_Success;
1340}
1341
David Blaikie960ea3f2014-06-08 16:18:35 +00001342bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1343 OperandVector &Operands,
1344 MCStreamer &Out,
1345 unsigned &ErrorInfo,
1346 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001347
Jack Carterb4dbc172012-09-05 23:34:03 +00001348 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001349 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001350 unsigned MatchResult =
1351 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001352
1353 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001354 default:
1355 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001356 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001357 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001358 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001359 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001360 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001361 return false;
1362 }
1363 case Match_MissingFeature:
1364 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1365 return true;
1366 case Match_InvalidOperand: {
1367 SMLoc ErrorLoc = IDLoc;
1368 if (ErrorInfo != ~0U) {
1369 if (ErrorInfo >= Operands.size())
1370 return Error(IDLoc, "too few operands for instruction");
1371
David Blaikie960ea3f2014-06-08 16:18:35 +00001372 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001373 if (ErrorLoc == SMLoc())
1374 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001375 }
1376
1377 return Error(ErrorLoc, "invalid operand for instruction");
1378 }
1379 case Match_MnemonicFail:
1380 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001381 case Match_RequiresDifferentSrcAndDst:
1382 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001383 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001384 return true;
1385}
1386
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001387void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1388 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1389 if (RegIndex == 1)
1390 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001391 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001392 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1393 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001394 }
1395}
1396
Jack Carter1ac53222013-02-20 23:11:17 +00001397int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001398 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001399
Vladimir Medic4c299852013-11-06 11:27:05 +00001400 CC = StringSwitch<unsigned>(Name)
1401 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001402 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001403 .Case("a0", 4)
1404 .Case("a1", 5)
1405 .Case("a2", 6)
1406 .Case("a3", 7)
1407 .Case("v0", 2)
1408 .Case("v1", 3)
1409 .Case("s0", 16)
1410 .Case("s1", 17)
1411 .Case("s2", 18)
1412 .Case("s3", 19)
1413 .Case("s4", 20)
1414 .Case("s5", 21)
1415 .Case("s6", 22)
1416 .Case("s7", 23)
1417 .Case("k0", 26)
1418 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001419 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001420 .Case("sp", 29)
1421 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001422 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001423 .Case("ra", 31)
1424 .Case("t0", 8)
1425 .Case("t1", 9)
1426 .Case("t2", 10)
1427 .Case("t3", 11)
1428 .Case("t4", 12)
1429 .Case("t5", 13)
1430 .Case("t6", 14)
1431 .Case("t7", 15)
1432 .Case("t8", 24)
1433 .Case("t9", 25)
1434 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001435
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001436 if (isN32() || isN64()) {
1437 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1438 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1439 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1440 if (8 <= CC && CC <= 11)
1441 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001442
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001443 if (CC == -1)
1444 CC = StringSwitch<unsigned>(Name)
1445 .Case("a4", 8)
1446 .Case("a5", 9)
1447 .Case("a6", 10)
1448 .Case("a7", 11)
1449 .Case("kt0", 26)
1450 .Case("kt1", 27)
1451 .Default(-1);
1452 }
Jack Carter1ac53222013-02-20 23:11:17 +00001453
1454 return CC;
1455}
Jack Carterd0bd6422013-04-18 00:41:53 +00001456
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001457int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001458
Jack Cartera63b16a2012-09-07 00:23:42 +00001459 if (Name[0] == 'f') {
1460 StringRef NumString = Name.substr(1);
1461 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001462 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001463 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001464 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001465 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001466 return IntVal;
1467 }
1468 return -1;
1469}
Jack Cartera63b16a2012-09-07 00:23:42 +00001470
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001471int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1472
1473 if (Name.startswith("fcc")) {
1474 StringRef NumString = Name.substr(3);
1475 unsigned IntVal;
1476 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001477 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001478 if (IntVal > 7) // There are only 8 fcc registers.
1479 return -1;
1480 return IntVal;
1481 }
1482 return -1;
1483}
1484
1485int MipsAsmParser::matchACRegisterName(StringRef Name) {
1486
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001487 if (Name.startswith("ac")) {
1488 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001489 unsigned IntVal;
1490 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001491 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001492 if (IntVal > 3) // There are only 3 acc registers.
1493 return -1;
1494 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001495 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001496 return -1;
1497}
Jack Carterd0bd6422013-04-18 00:41:53 +00001498
Jack Carter5dc8ac92013-09-25 23:50:44 +00001499int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1500 unsigned IntVal;
1501
1502 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1503 return -1;
1504
1505 if (IntVal > 31)
1506 return -1;
1507
1508 return IntVal;
1509}
1510
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001511int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1512 int CC;
1513
1514 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001515 .Case("msair", 0)
1516 .Case("msacsr", 1)
1517 .Case("msaaccess", 2)
1518 .Case("msasave", 3)
1519 .Case("msamodify", 4)
1520 .Case("msarequest", 5)
1521 .Case("msamap", 6)
1522 .Case("msaunmap", 7)
1523 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001524
1525 return CC;
1526}
1527
Jack Carter0b744b32012-10-04 02:29:46 +00001528bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1529 if (Reg > 31)
1530 return false;
1531
1532 aTReg = Reg;
1533 return true;
1534}
1535
Matheus Almeida7de68e72014-06-18 14:46:05 +00001536int MipsAsmParser::getATReg(SMLoc Loc) {
Daniel Sandersd89b1362014-03-24 16:48:01 +00001537 int AT = Options.getATRegNum();
1538 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001539 reportParseError(Loc,
1540 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001541 return AT;
1542}
Jack Carter0b744b32012-10-04 02:29:46 +00001543
Jack Carterd0bd6422013-04-18 00:41:53 +00001544unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001545 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001546}
1547
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001548unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001549 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1550 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001551}
1552
Jack Carter873c7242013-01-12 01:03:14 +00001553int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001554 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001555 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001556 return -1;
1557
Jack Carter873c7242013-01-12 01:03:14 +00001558 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001559}
1560
David Blaikie960ea3f2014-06-08 16:18:35 +00001561bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001562 DEBUG(dbgs() << "ParseOperand\n");
1563
Jack Carter30a59822012-10-04 04:03:53 +00001564 // Check if the current operand has a custom associated parser, if so, try to
1565 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001566 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1567 if (ResTy == MatchOperand_Success)
1568 return false;
1569 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1570 // there was a match, but an error occurred, in which case, just return that
1571 // the operand parsing failed.
1572 if (ResTy == MatchOperand_ParseFail)
1573 return true;
1574
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001575 DEBUG(dbgs() << ".. Generic Parser\n");
1576
Jack Carterb4dbc172012-09-05 23:34:03 +00001577 switch (getLexer().getKind()) {
1578 default:
1579 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1580 return true;
1581 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001582 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001583 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001584
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001585 // Almost all registers have been parsed by custom parsers. There is only
1586 // one exception to this. $zero (and it's alias $0) will reach this point
1587 // for div, divu, and similar instructions because it is not an operand
1588 // to the instruction definition but an explicit register. Special case
1589 // this situation for now.
1590 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001591 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001592
Jack Carterd0bd6422013-04-18 00:41:53 +00001593 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001594 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001595 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001596 return true;
1597
Jack Carter873c7242013-01-12 01:03:14 +00001598 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001599 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001600 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001601 const MCExpr *Res =
1602 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001603
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001604 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001605 return false;
1606 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001607 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001608 case AsmToken::LParen:
1609 case AsmToken::Minus:
1610 case AsmToken::Plus:
1611 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001612 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001613 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001614 DEBUG(dbgs() << ".. generic integer\n");
1615 OperandMatchResultTy ResTy = ParseImm(Operands);
1616 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001617 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001618 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001619 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001620 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001621 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001622 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001623 return true;
1624
Jack Carter873c7242013-01-12 01:03:14 +00001625 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1626
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001627 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001628 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001629 } // case AsmToken::Percent
1630 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001631 return true;
1632}
1633
Vladimir Medic4c299852013-11-06 11:27:05 +00001634const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001635 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001636 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001637 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001638 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001639 // It's a constant, evaluate reloc value.
1640 int16_t Val;
1641 switch (getVariantKind(RelocStr)) {
1642 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1643 // Get the 1st 16-bits.
1644 Val = MCE->getValue() & 0xffff;
1645 break;
1646 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1647 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1648 // 16 bits being negative.
1649 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1650 break;
1651 case MCSymbolRefExpr::VK_Mips_HIGHER:
1652 // Get the 3rd 16-bits.
1653 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1654 break;
1655 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1656 // Get the 4th 16-bits.
1657 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1658 break;
1659 default:
1660 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001661 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001662 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001663 }
1664
Jack Carterb5cf5902013-04-17 00:18:04 +00001665 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001666 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001667 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001668 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001669 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001670 return Res;
1671 }
1672
1673 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001674 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1675
Sasa Stankovic06c47802014-04-03 10:37:45 +00001676 // Try to create target expression.
1677 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1678 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001679
Jack Carterd0bd6422013-04-18 00:41:53 +00001680 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1681 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001682 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1683 return Res;
1684 }
1685
1686 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001687 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1688 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1689 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001690 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001691 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001692 return Expr;
1693}
1694
1695bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1696
1697 switch (Expr->getKind()) {
1698 case MCExpr::Constant:
1699 return true;
1700 case MCExpr::SymbolRef:
1701 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1702 case MCExpr::Binary:
1703 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1704 if (!isEvaluated(BE->getLHS()))
1705 return false;
1706 return isEvaluated(BE->getRHS());
1707 }
1708 case MCExpr::Unary:
1709 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001710 case MCExpr::Target:
1711 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001712 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001713 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001714}
Jack Carterd0bd6422013-04-18 00:41:53 +00001715
Jack Carterb5cf5902013-04-17 00:18:04 +00001716bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001717 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001718 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001719 if (Tok.isNot(AsmToken::Identifier))
1720 return true;
1721
1722 std::string Str = Tok.getIdentifier().str();
1723
Jack Carterd0bd6422013-04-18 00:41:53 +00001724 Parser.Lex(); // Eat the identifier.
1725 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001726 const MCExpr *IdVal;
1727 SMLoc EndLoc;
1728
1729 if (getLexer().getKind() == AsmToken::LParen) {
1730 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001731 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001732 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001733 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001734 const AsmToken &nextTok = Parser.getTok();
1735 if (nextTok.isNot(AsmToken::Identifier))
1736 return true;
1737 Str += "(%";
1738 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001739 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001740 if (getLexer().getKind() != AsmToken::LParen)
1741 return true;
1742 } else
1743 break;
1744 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001746 return true;
1747
1748 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001749 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001750
1751 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001752 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001753
Jack Carterd0bd6422013-04-18 00:41:53 +00001754 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001755 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001756}
1757
Jack Carterb4dbc172012-09-05 23:34:03 +00001758bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1759 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001760 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001761 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1762 if (ResTy == MatchOperand_Success) {
1763 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001764 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001765 StartLoc = Operand.getStartLoc();
1766 EndLoc = Operand.getEndLoc();
1767
1768 // AFAIK, we only support numeric registers and named GPR's in CFI
1769 // directives.
1770 // Don't worry about eating tokens before failing. Using an unrecognised
1771 // register is a parse error.
1772 if (Operand.isGPRAsmReg()) {
1773 // Resolve to GPR32 or GPR64 appropriately.
1774 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1775 }
1776
1777 return (RegNo == (unsigned)-1);
1778 }
1779
1780 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001781 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001782}
1783
Jack Carterb5cf5902013-04-17 00:18:04 +00001784bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001785 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001786 bool Result = true;
1787
1788 while (getLexer().getKind() == AsmToken::LParen)
1789 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001790
Jack Carterd0bd6422013-04-18 00:41:53 +00001791 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001792 default:
1793 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001794 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001795 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001796 case AsmToken::Integer:
1797 case AsmToken::Minus:
1798 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001799 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001800 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001801 else
1802 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001803 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001804 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001805 break;
Jack Carter873c7242013-01-12 01:03:14 +00001806 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001807 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001808 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001809 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001810}
1811
David Blaikie960ea3f2014-06-08 16:18:35 +00001812MipsAsmParser::OperandMatchResultTy
1813MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001814 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001815 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001816 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001817 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001818 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001819 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001820 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001821
Jack Carterb5cf5902013-04-17 00:18:04 +00001822 if (getLexer().getKind() == AsmToken::LParen) {
1823 Parser.Lex();
1824 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001825 }
1826
Jack Carterb5cf5902013-04-17 00:18:04 +00001827 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001828 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001829 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001830
Jack Carterd0bd6422013-04-18 00:41:53 +00001831 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001832 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001833 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1834 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001835 SMLoc E =
1836 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001837 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001838 return MatchOperand_Success;
1839 }
1840 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001841 SMLoc E =
1842 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001843
Jack Carterd0bd6422013-04-18 00:41:53 +00001844 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001845 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001846 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1847 S, E, *this);
1848 Operands.push_back(
1849 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001850 return MatchOperand_Success;
1851 }
1852 Error(Parser.getTok().getLoc(), "'(' expected");
1853 return MatchOperand_ParseFail;
1854 }
1855
Jack Carterd0bd6422013-04-18 00:41:53 +00001856 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001857 }
1858
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001859 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001860 if (Res != MatchOperand_Success)
1861 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001862
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001863 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001864 Error(Parser.getTok().getLoc(), "')' expected");
1865 return MatchOperand_ParseFail;
1866 }
1867
Jack Carter873c7242013-01-12 01:03:14 +00001868 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1869
Jack Carterd0bd6422013-04-18 00:41:53 +00001870 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001871
Craig Topper062a2ba2014-04-25 05:30:21 +00001872 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001873 IdVal = MCConstantExpr::Create(0, getContext());
1874
Jack Carterd0bd6422013-04-18 00:41:53 +00001875 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001876 std::unique_ptr<MipsOperand> op(
1877 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001878 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001879 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001880 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001881 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001882 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1883 int64_t Imm;
1884 if (IdVal->EvaluateAsAbsolute(Imm))
1885 IdVal = MCConstantExpr::Create(Imm, getContext());
1886 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1887 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1888 getContext());
1889 }
1890
David Blaikie960ea3f2014-06-08 16:18:35 +00001891 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001892 return MatchOperand_Success;
1893}
1894
David Blaikie960ea3f2014-06-08 16:18:35 +00001895bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001896
Jack Carterd76b2372013-03-21 21:44:16 +00001897 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1898 if (Sym) {
1899 SMLoc S = Parser.getTok().getLoc();
1900 const MCExpr *Expr;
1901 if (Sym->isVariable())
1902 Expr = Sym->getVariableValue();
1903 else
1904 return false;
1905 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001906 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001907 const StringRef DefSymbol = Ref->getSymbol().getName();
1908 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001909 OperandMatchResultTy ResTy =
1910 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001911 if (ResTy == MatchOperand_Success) {
1912 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001913 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001914 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001915 llvm_unreachable("Should never ParseFail");
1916 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001917 }
1918 } else if (Expr->getKind() == MCExpr::Constant) {
1919 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001920 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001921 Operands.push_back(
1922 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001923 return true;
1924 }
1925 }
1926 return false;
1927}
Jack Carterd0bd6422013-04-18 00:41:53 +00001928
Jack Carter873c7242013-01-12 01:03:14 +00001929MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001930MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1931 StringRef Identifier,
1932 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001933 int Index = matchCPURegisterName(Identifier);
1934 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001935 Operands.push_back(MipsOperand::CreateGPRReg(
1936 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1937 return MatchOperand_Success;
1938 }
1939
1940 Index = matchFPURegisterName(Identifier);
1941 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001942 Operands.push_back(MipsOperand::CreateFGRReg(
1943 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1944 return MatchOperand_Success;
1945 }
1946
1947 Index = matchFCCRegisterName(Identifier);
1948 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001949 Operands.push_back(MipsOperand::CreateFCCReg(
1950 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1951 return MatchOperand_Success;
1952 }
1953
1954 Index = matchACRegisterName(Identifier);
1955 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001956 Operands.push_back(MipsOperand::CreateACCReg(
1957 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1958 return MatchOperand_Success;
1959 }
1960
1961 Index = matchMSA128RegisterName(Identifier);
1962 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001963 Operands.push_back(MipsOperand::CreateMSA128Reg(
1964 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1965 return MatchOperand_Success;
1966 }
1967
1968 Index = matchMSA128CtrlRegisterName(Identifier);
1969 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001970 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1971 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1972 return MatchOperand_Success;
1973 }
1974
1975 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001976}
1977
1978MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001979MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001980 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001981
1982 if (Token.is(AsmToken::Identifier)) {
1983 DEBUG(dbgs() << ".. identifier\n");
1984 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001985 OperandMatchResultTy ResTy =
1986 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001987 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001988 } else if (Token.is(AsmToken::Integer)) {
1989 DEBUG(dbgs() << ".. integer\n");
1990 Operands.push_back(MipsOperand::CreateNumericReg(
1991 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1992 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001993 return MatchOperand_Success;
1994 }
1995
1996 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1997
1998 return MatchOperand_NoMatch;
1999}
2000
David Blaikie960ea3f2014-06-08 16:18:35 +00002001MipsAsmParser::OperandMatchResultTy
2002MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002003 DEBUG(dbgs() << "ParseAnyRegister\n");
2004
2005 auto Token = Parser.getTok();
2006
2007 SMLoc S = Token.getLoc();
2008
2009 if (Token.isNot(AsmToken::Dollar)) {
2010 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2011 if (Token.is(AsmToken::Identifier)) {
2012 if (searchSymbolAlias(Operands))
2013 return MatchOperand_Success;
2014 }
2015 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2016 return MatchOperand_NoMatch;
2017 }
2018 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002019
Daniel Sanders21bce302014-04-01 12:35:23 +00002020 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002021 if (ResTy == MatchOperand_Success) {
2022 Parser.Lex(); // $
2023 Parser.Lex(); // identifier
2024 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002025 return ResTy;
2026}
2027
2028MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002029MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002030 switch (getLexer().getKind()) {
2031 default:
2032 return MatchOperand_NoMatch;
2033 case AsmToken::LParen:
2034 case AsmToken::Minus:
2035 case AsmToken::Plus:
2036 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002037 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002038 case AsmToken::String:
2039 break;
2040 }
2041
2042 const MCExpr *IdVal;
2043 SMLoc S = Parser.getTok().getLoc();
2044 if (getParser().parseExpression(IdVal))
2045 return MatchOperand_ParseFail;
2046
2047 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2048 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2049 return MatchOperand_Success;
2050}
2051
David Blaikie960ea3f2014-06-08 16:18:35 +00002052MipsAsmParser::OperandMatchResultTy
2053MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002054 DEBUG(dbgs() << "ParseJumpTarget\n");
2055
2056 SMLoc S = getLexer().getLoc();
2057
2058 // Integers and expressions are acceptable
2059 OperandMatchResultTy ResTy = ParseImm(Operands);
2060 if (ResTy != MatchOperand_NoMatch)
2061 return ResTy;
2062
Daniel Sanders315386c2014-04-01 10:40:14 +00002063 // Registers are a valid target and have priority over symbols.
2064 ResTy = ParseAnyRegister(Operands);
2065 if (ResTy != MatchOperand_NoMatch)
2066 return ResTy;
2067
Daniel Sandersffd84362014-04-01 10:41:48 +00002068 const MCExpr *Expr = nullptr;
2069 if (Parser.parseExpression(Expr)) {
2070 // We have no way of knowing if a symbol was consumed so we must ParseFail
2071 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002072 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002073 Operands.push_back(
2074 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002075 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002076}
2077
Vladimir Medic2b953d02013-10-01 09:48:56 +00002078MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002079MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002080 const MCExpr *IdVal;
2081 // If the first token is '$' we may have register operand.
2082 if (Parser.getTok().is(AsmToken::Dollar))
2083 return MatchOperand_NoMatch;
2084 SMLoc S = Parser.getTok().getLoc();
2085 if (getParser().parseExpression(IdVal))
2086 return MatchOperand_ParseFail;
2087 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002088 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002089 int64_t Val = MCE->getValue();
2090 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2091 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002092 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002093 return MatchOperand_Success;
2094}
2095
Matheus Almeida779c5932013-11-18 12:32:49 +00002096MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002097MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002098 switch (getLexer().getKind()) {
2099 default:
2100 return MatchOperand_NoMatch;
2101 case AsmToken::LParen:
2102 case AsmToken::Plus:
2103 case AsmToken::Minus:
2104 case AsmToken::Integer:
2105 break;
2106 }
2107
2108 const MCExpr *Expr;
2109 SMLoc S = Parser.getTok().getLoc();
2110
2111 if (getParser().parseExpression(Expr))
2112 return MatchOperand_ParseFail;
2113
2114 int64_t Val;
2115 if (!Expr->EvaluateAsAbsolute(Val)) {
2116 Error(S, "expected immediate value");
2117 return MatchOperand_ParseFail;
2118 }
2119
2120 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2121 // and because the CPU always adds one to the immediate field, the allowed
2122 // range becomes 1..4. We'll only check the range here and will deal
2123 // with the addition/subtraction when actually decoding/encoding
2124 // the instruction.
2125 if (Val < 1 || Val > 4) {
2126 Error(S, "immediate not in range (1..4)");
2127 return MatchOperand_ParseFail;
2128 }
2129
Jack Carter3b2c96e2014-01-22 23:31:38 +00002130 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002131 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002132 return MatchOperand_Success;
2133}
2134
Jack Carterdc1e35d2012-09-06 20:00:02 +00002135MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2136
Vladimir Medic4c299852013-11-06 11:27:05 +00002137 MCSymbolRefExpr::VariantKind VK =
2138 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2139 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2140 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2141 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2142 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2143 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2144 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2145 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2146 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2147 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2148 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2149 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2150 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2151 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2152 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2153 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2154 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2155 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002156 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2157 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2158 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2159 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2160 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2161 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002162 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2163 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002164 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002165
Matheus Almeida2852af82014-04-22 10:15:54 +00002166 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002167
Jack Carterdc1e35d2012-09-06 20:00:02 +00002168 return VK;
2169}
Jack Cartera63b16a2012-09-07 00:23:42 +00002170
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002171/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2172/// either this.
2173/// ::= '(', register, ')'
2174/// handle it before we iterate so we don't get tripped up by the lack of
2175/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002176bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002177 if (getLexer().is(AsmToken::LParen)) {
2178 Operands.push_back(
2179 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2180 Parser.Lex();
2181 if (ParseOperand(Operands, Name)) {
2182 SMLoc Loc = getLexer().getLoc();
2183 Parser.eatToEndOfStatement();
2184 return Error(Loc, "unexpected token in argument list");
2185 }
2186 if (Parser.getTok().isNot(AsmToken::RParen)) {
2187 SMLoc Loc = getLexer().getLoc();
2188 Parser.eatToEndOfStatement();
2189 return Error(Loc, "unexpected token, expected ')'");
2190 }
2191 Operands.push_back(
2192 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2193 Parser.Lex();
2194 }
2195 return false;
2196}
2197
2198/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2199/// either one of these.
2200/// ::= '[', register, ']'
2201/// ::= '[', integer, ']'
2202/// handle it before we iterate so we don't get tripped up by the lack of
2203/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002204bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2205 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002206 if (getLexer().is(AsmToken::LBrac)) {
2207 Operands.push_back(
2208 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2209 Parser.Lex();
2210 if (ParseOperand(Operands, Name)) {
2211 SMLoc Loc = getLexer().getLoc();
2212 Parser.eatToEndOfStatement();
2213 return Error(Loc, "unexpected token in argument list");
2214 }
2215 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2216 SMLoc Loc = getLexer().getLoc();
2217 Parser.eatToEndOfStatement();
2218 return Error(Loc, "unexpected token, expected ']'");
2219 }
2220 Operands.push_back(
2221 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2222 Parser.Lex();
2223 }
2224 return false;
2225}
2226
David Blaikie960ea3f2014-06-08 16:18:35 +00002227bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2228 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002229 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002230 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002231 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002232 Parser.eatToEndOfStatement();
2233 return Error(NameLoc, "Unknown instruction");
2234 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002235 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002236 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002237
2238 // Read the remaining operands.
2239 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2240 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002241 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002242 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002243 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002244 return Error(Loc, "unexpected token in argument list");
2245 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002246 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2247 return true;
2248 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002249
Jack Carterd0bd6422013-04-18 00:41:53 +00002250 while (getLexer().is(AsmToken::Comma)) {
2251 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002252 // Parse and remember the operand.
2253 if (ParseOperand(Operands, Name)) {
2254 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002255 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002256 return Error(Loc, "unexpected token in argument list");
2257 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002258 // Parse bracket and parenthesis suffixes before we iterate
2259 if (getLexer().is(AsmToken::LBrac)) {
2260 if (ParseBracketSuffix(Name, Operands))
2261 return true;
2262 } else if (getLexer().is(AsmToken::LParen) &&
2263 ParseParenSuffix(Name, Operands))
2264 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002265 }
2266 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002267 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2268 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002269 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002270 return Error(Loc, "unexpected token in argument list");
2271 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002272 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002273 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002274}
2275
Jack Carter0b744b32012-10-04 02:29:46 +00002276bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002277 SMLoc Loc = getLexer().getLoc();
2278 Parser.eatToEndOfStatement();
2279 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002280}
2281
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002282bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2283 return Error(Loc, ErrorMsg);
2284}
2285
Jack Carter0b744b32012-10-04 02:29:46 +00002286bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002287 // Line should look like: ".set noat".
2288 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002289 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002290 // eat noat
2291 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002292 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002293 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2294 reportParseError("unexpected token in statement");
2295 return false;
2296 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002297 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002298 return false;
2299}
Jack Carterd0bd6422013-04-18 00:41:53 +00002300
Jack Carter0b744b32012-10-04 02:29:46 +00002301bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002302 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002303 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002304 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002305 getParser().Lex();
2306 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002307 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002308 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002309 return false;
2310 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002311 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002312 if (getLexer().isNot(AsmToken::Dollar)) {
2313 reportParseError("unexpected token in statement");
2314 return false;
2315 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002316 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002317 const AsmToken &Reg = Parser.getTok();
2318 if (Reg.is(AsmToken::Identifier)) {
2319 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2320 } else if (Reg.is(AsmToken::Integer)) {
2321 AtRegNo = Reg.getIntVal();
2322 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002323 reportParseError("unexpected token in statement");
2324 return false;
2325 }
Jack Carter1ac53222013-02-20 23:11:17 +00002326
Daniel Sanders71a89d922014-03-25 13:01:06 +00002327 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002328 reportParseError("unexpected token in statement");
2329 return false;
2330 }
2331
2332 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002333 reportParseError("unexpected token in statement");
2334 return false;
2335 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002336 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002337
2338 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2339 reportParseError("unexpected token in statement");
2340 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002341 }
2342 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002343 return false;
2344 } else {
2345 reportParseError("unexpected token in statement");
2346 return false;
2347 }
2348}
2349
2350bool MipsAsmParser::parseSetReorderDirective() {
2351 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002352 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002353 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2354 reportParseError("unexpected token in statement");
2355 return false;
2356 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002357 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002358 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002359 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002360 return false;
2361}
2362
2363bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002364 Parser.Lex();
2365 // If this is not the end of the statement, report an error.
2366 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2367 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002368 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002369 }
2370 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002371 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002372 Parser.Lex(); // Consume the EndOfStatement.
2373 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002374}
2375
2376bool MipsAsmParser::parseSetMacroDirective() {
2377 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002378 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002379 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2380 reportParseError("unexpected token in statement");
2381 return false;
2382 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002383 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002384 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002385 return false;
2386}
2387
2388bool MipsAsmParser::parseSetNoMacroDirective() {
2389 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002390 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002391 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2392 reportParseError("`noreorder' must be set before `nomacro'");
2393 return false;
2394 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002395 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002396 reportParseError("`noreorder' must be set before `nomacro'");
2397 return false;
2398 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002399 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002400 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002401 return false;
2402}
Jack Carterd76b2372013-03-21 21:44:16 +00002403
Jack Carter39536722014-01-22 23:08:42 +00002404bool MipsAsmParser::parseSetNoMips16Directive() {
2405 Parser.Lex();
2406 // If this is not the end of the statement, report an error.
2407 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2408 reportParseError("unexpected token in statement");
2409 return false;
2410 }
2411 // For now do nothing.
2412 Parser.Lex(); // Consume the EndOfStatement.
2413 return false;
2414}
2415
Jack Carterd76b2372013-03-21 21:44:16 +00002416bool MipsAsmParser::parseSetAssignment() {
2417 StringRef Name;
2418 const MCExpr *Value;
2419
2420 if (Parser.parseIdentifier(Name))
2421 reportParseError("expected identifier after .set");
2422
2423 if (getLexer().isNot(AsmToken::Comma))
2424 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002425 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002426
Jack Carter3b2c96e2014-01-22 23:31:38 +00002427 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002428 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002429
Jack Carterd0bd6422013-04-18 00:41:53 +00002430 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002431 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002432 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002433 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002434 Sym = getContext().GetOrCreateSymbol(Name);
2435 Sym->setVariableValue(Value);
2436
2437 return false;
2438}
Jack Carterd0bd6422013-04-18 00:41:53 +00002439
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002440bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2441 Parser.Lex();
2442 if (getLexer().isNot(AsmToken::EndOfStatement))
2443 return reportParseError("unexpected token in .set directive");
2444
Matheus Almeida2852af82014-04-22 10:15:54 +00002445 switch (Feature) {
2446 default:
2447 llvm_unreachable("Unimplemented feature");
2448 case Mips::FeatureDSP:
2449 setFeatureBits(Mips::FeatureDSP, "dsp");
2450 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002451 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002452 case Mips::FeatureMicroMips:
2453 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002454 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002455 case Mips::FeatureMips16:
2456 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002457 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002458 case Mips::FeatureMips32r2:
2459 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2460 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002461 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002462 case Mips::FeatureMips64:
2463 setFeatureBits(Mips::FeatureMips64, "mips64");
2464 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002465 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002466 case Mips::FeatureMips64r2:
2467 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2468 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002469 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002470 }
2471 return false;
2472}
2473
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002474bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2475 if (getLexer().isNot(AsmToken::Comma)) {
2476 SMLoc Loc = getLexer().getLoc();
2477 Parser.eatToEndOfStatement();
2478 return Error(Loc, ErrorStr);
2479 }
2480
Matheus Almeida2852af82014-04-22 10:15:54 +00002481 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002482 return true;
2483}
2484
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002485bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2486 if (Options.isReorder())
2487 Warning(Loc, ".cpload in reorder section");
2488
2489 // FIXME: Warn if cpload is used in Mips16 mode.
2490
David Blaikie960ea3f2014-06-08 16:18:35 +00002491 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002492 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2493 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2494 reportParseError("expected register containing function address");
2495 return false;
2496 }
2497
David Blaikie960ea3f2014-06-08 16:18:35 +00002498 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2499 if (!RegOpnd.isGPRAsmReg()) {
2500 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002501 return false;
2502 }
2503
David Blaikie960ea3f2014-06-08 16:18:35 +00002504 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002505 return false;
2506}
2507
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002508bool MipsAsmParser::parseDirectiveCPSetup() {
2509 unsigned FuncReg;
2510 unsigned Save;
2511 bool SaveIsReg = true;
2512
Matheus Almeida7e815762014-06-18 13:08:59 +00002513 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2514 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2515 if (ResTy == MatchOperand_NoMatch) {
2516 reportParseError("expected register containing function address");
2517 Parser.eatToEndOfStatement();
2518 return false;
2519 }
2520
2521 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2522 if (!FuncRegOpnd.isGPRAsmReg()) {
2523 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2524 Parser.eatToEndOfStatement();
2525 return false;
2526 }
2527
2528 FuncReg = FuncRegOpnd.getGPR32Reg();
2529 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002530
2531 if (!eatComma("expected comma parsing directive"))
2532 return true;
2533
Matheus Almeida7e815762014-06-18 13:08:59 +00002534 ResTy = ParseAnyRegister(TmpReg);
2535 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002536 const AsmToken &Tok = Parser.getTok();
2537 if (Tok.is(AsmToken::Integer)) {
2538 Save = Tok.getIntVal();
2539 SaveIsReg = false;
2540 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002541 } else {
2542 reportParseError("expected save register or stack offset");
2543 Parser.eatToEndOfStatement();
2544 return false;
2545 }
2546 } else {
2547 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2548 if (!SaveOpnd.isGPRAsmReg()) {
2549 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2550 Parser.eatToEndOfStatement();
2551 return false;
2552 }
2553 Save = SaveOpnd.getGPR32Reg();
2554 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002555
2556 if (!eatComma("expected comma parsing directive"))
2557 return true;
2558
2559 StringRef Name;
2560 if (Parser.parseIdentifier(Name))
2561 reportParseError("expected identifier");
2562 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002563
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002564 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002565 return false;
2566}
2567
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002568bool MipsAsmParser::parseDirectiveNaN() {
2569 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2570 const AsmToken &Tok = Parser.getTok();
2571
2572 if (Tok.getString() == "2008") {
2573 Parser.Lex();
2574 getTargetStreamer().emitDirectiveNaN2008();
2575 return false;
2576 } else if (Tok.getString() == "legacy") {
2577 Parser.Lex();
2578 getTargetStreamer().emitDirectiveNaNLegacy();
2579 return false;
2580 }
2581 }
2582 // If we don't recognize the option passed to the .nan
2583 // directive (e.g. no option or unknown option), emit an error.
2584 reportParseError("invalid option in .nan directive");
2585 return false;
2586}
2587
Jack Carter0b744b32012-10-04 02:29:46 +00002588bool MipsAsmParser::parseDirectiveSet() {
2589
Jack Carterd0bd6422013-04-18 00:41:53 +00002590 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002591 const AsmToken &Tok = Parser.getTok();
2592
2593 if (Tok.getString() == "noat") {
2594 return parseSetNoAtDirective();
2595 } else if (Tok.getString() == "at") {
2596 return parseSetAtDirective();
2597 } else if (Tok.getString() == "reorder") {
2598 return parseSetReorderDirective();
2599 } else if (Tok.getString() == "noreorder") {
2600 return parseSetNoReorderDirective();
2601 } else if (Tok.getString() == "macro") {
2602 return parseSetMacroDirective();
2603 } else if (Tok.getString() == "nomacro") {
2604 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002605 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002606 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002607 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002608 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002609 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002610 getTargetStreamer().emitDirectiveSetNoMicroMips();
2611 Parser.eatToEndOfStatement();
2612 return false;
2613 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002614 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002615 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002616 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002617 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002618 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002619 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002620 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002621 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002622 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002623 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002624 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002625 parseSetAssignment();
2626 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002627 }
Jack Carter07c818d2013-01-25 01:31:34 +00002628
Jack Carter0b744b32012-10-04 02:29:46 +00002629 return true;
2630}
2631
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002632/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002633/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002634bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002635 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2636 for (;;) {
2637 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002638 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002639 return true;
2640
2641 getParser().getStreamer().EmitValue(Value, Size);
2642
2643 if (getLexer().is(AsmToken::EndOfStatement))
2644 break;
2645
2646 // FIXME: Improve diagnostic.
2647 if (getLexer().isNot(AsmToken::Comma))
2648 return Error(L, "unexpected token in directive");
2649 Parser.Lex();
2650 }
2651 }
2652
2653 Parser.Lex();
2654 return false;
2655}
2656
Vladimir Medic4c299852013-11-06 11:27:05 +00002657/// parseDirectiveGpWord
2658/// ::= .gpword local_sym
2659bool MipsAsmParser::parseDirectiveGpWord() {
2660 const MCExpr *Value;
2661 // EmitGPRel32Value requires an expression, so we are using base class
2662 // method to evaluate the expression.
2663 if (getParser().parseExpression(Value))
2664 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002665 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002666
Vladimir Medice10c1122013-11-13 13:18:04 +00002667 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002668 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002669 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002670 return false;
2671}
2672
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002673/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002674/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002675bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002676 const MCExpr *Value;
2677 // EmitGPRel64Value requires an expression, so we are using base class
2678 // method to evaluate the expression.
2679 if (getParser().parseExpression(Value))
2680 return true;
2681 getParser().getStreamer().EmitGPRel64Value(Value);
2682
2683 if (getLexer().isNot(AsmToken::EndOfStatement))
2684 return Error(getLexer().getLoc(), "unexpected token in directive");
2685 Parser.Lex(); // Eat EndOfStatement token.
2686 return false;
2687}
2688
Jack Carter0cd3c192014-01-06 23:27:31 +00002689bool MipsAsmParser::parseDirectiveOption() {
2690 // Get the option token.
2691 AsmToken Tok = Parser.getTok();
2692 // At the moment only identifiers are supported.
2693 if (Tok.isNot(AsmToken::Identifier)) {
2694 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2695 Parser.eatToEndOfStatement();
2696 return false;
2697 }
2698
2699 StringRef Option = Tok.getIdentifier();
2700
2701 if (Option == "pic0") {
2702 getTargetStreamer().emitDirectiveOptionPic0();
2703 Parser.Lex();
2704 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2705 Error(Parser.getTok().getLoc(),
2706 "unexpected token in .option pic0 directive");
2707 Parser.eatToEndOfStatement();
2708 }
2709 return false;
2710 }
2711
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002712 if (Option == "pic2") {
2713 getTargetStreamer().emitDirectiveOptionPic2();
2714 Parser.Lex();
2715 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2716 Error(Parser.getTok().getLoc(),
2717 "unexpected token in .option pic2 directive");
2718 Parser.eatToEndOfStatement();
2719 }
2720 return false;
2721 }
2722
Jack Carter0cd3c192014-01-06 23:27:31 +00002723 // Unknown option.
2724 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2725 Parser.eatToEndOfStatement();
2726 return false;
2727}
2728
Jack Carter0b744b32012-10-04 02:29:46 +00002729bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002730 StringRef IDVal = DirectiveID.getString();
2731
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002732 if (IDVal == ".cpload")
2733 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002734 if (IDVal == ".dword") {
2735 parseDataDirective(8, DirectiveID.getLoc());
2736 return false;
2737 }
2738
Jack Carterd0bd6422013-04-18 00:41:53 +00002739 if (IDVal == ".ent") {
2740 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002741 Parser.Lex();
2742 return false;
2743 }
2744
Jack Carter07c818d2013-01-25 01:31:34 +00002745 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002746 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002747 Parser.Lex();
2748 return false;
2749 }
2750
Jack Carter07c818d2013-01-25 01:31:34 +00002751 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002752 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002753 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002754 return false;
2755 }
2756
Jack Carter07c818d2013-01-25 01:31:34 +00002757 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002758 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002759 }
2760
Jack Carter07c818d2013-01-25 01:31:34 +00002761 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002762 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002763 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002764 return false;
2765 }
2766
Jack Carter07c818d2013-01-25 01:31:34 +00002767 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002768 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002769 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002770 return false;
2771 }
2772
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002773 if (IDVal == ".nan")
2774 return parseDirectiveNaN();
2775
Jack Carter07c818d2013-01-25 01:31:34 +00002776 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002777 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002778 return false;
2779 }
2780
Rafael Espindolab59fb732014-03-28 18:50:26 +00002781 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002782 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002783 return false;
2784 }
2785
Jack Carter07c818d2013-01-25 01:31:34 +00002786 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002787 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002788 return false;
2789 }
2790
Jack Carter0cd3c192014-01-06 23:27:31 +00002791 if (IDVal == ".option")
2792 return parseDirectiveOption();
2793
2794 if (IDVal == ".abicalls") {
2795 getTargetStreamer().emitDirectiveAbiCalls();
2796 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2797 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2798 // Clear line
2799 Parser.eatToEndOfStatement();
2800 }
2801 return false;
2802 }
2803
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002804 if (IDVal == ".cpsetup")
2805 return parseDirectiveCPSetup();
2806
Rafael Espindola870c4e92012-01-11 03:56:41 +00002807 return true;
2808}
2809
Rafael Espindola870c4e92012-01-11 03:56:41 +00002810extern "C" void LLVMInitializeMipsAsmParser() {
2811 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2812 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2813 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2814 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2815}
Jack Carterb4dbc172012-09-05 23:34:03 +00002816
2817#define GET_REGISTER_MATCHER
2818#define GET_MATCHER_IMPLEMENTATION
2819#include "MipsGenAsmMatcher.inc"