blob: 85c5a70ed909e17e34a324030208cfcf681daa3a [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
Joey Gouly0e76fa72013-09-12 10:28:05 +000032namespace llvm {
33class MCInstrInfo;
34}
35
Rafael Espindola870c4e92012-01-11 03:56:41 +000036namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000037class MipsAssemblerOptions {
38public:
Vladimir Medic4c299852013-11-06 11:27:05 +000039 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000040
Vladimir Medic4c299852013-11-06 11:27:05 +000041 unsigned getATRegNum() { return aTReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000042 bool setATReg(unsigned Reg);
43
Vladimir Medic4c299852013-11-06 11:27:05 +000044 bool isReorder() { return reorder; }
45 void setReorder() { reorder = true; }
46 void setNoreorder() { reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000047
Vladimir Medic4c299852013-11-06 11:27:05 +000048 bool isMacro() { return macro; }
49 void setMacro() { macro = true; }
50 void setNomacro() { macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000051
52private:
53 unsigned aTReg;
54 bool reorder;
55 bool macro;
56};
57}
58
59namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000060class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000061 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000062 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000063 return static_cast<MipsTargetStreamer &>(TS);
64 }
65
Jack Carterb4dbc172012-09-05 23:34:03 +000066 MCSubtargetInfo &STI;
67 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000068 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000069
Akira Hatanaka7605630c2012-08-17 20:16:42 +000070#define GET_ASSEMBLER_HEADER
71#include "MipsGenAsmMatcher.inc"
72
Chad Rosier49963552012-10-13 00:26:04 +000073 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Vladimir Medic4c299852013-11-06 11:27:05 +000074 SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000075 MCStreamer &Out, unsigned &ErrorInfo,
76 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000077
Daniel Sandersb50ccf82014-04-01 10:35:28 +000078 /// Parse a register as used in CFI directives
Rafael Espindola870c4e92012-01-11 03:56:41 +000079 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
80
Daniel Sandersb50ccf82014-04-01 10:35:28 +000081 bool ParseParenSuffix(StringRef Name,
82 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
83
84 bool ParseBracketSuffix(StringRef Name,
85 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
86
Chad Rosierf0e87202012-10-25 20:41:34 +000087 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
88 SMLoc NameLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +000089 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000090
91 bool ParseDirective(AsmToken DirectiveID);
92
Jack Carterb4dbc172012-09-05 23:34:03 +000093 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +000094 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +000095
Daniel Sandersb50ccf82014-04-01 10:35:28 +000096 MipsAsmParser::OperandMatchResultTy MatchAnyRegisterNameWithoutDollar(
97 SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
98 SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000099
100 MipsAsmParser::OperandMatchResultTy
Daniel Sanders21bce302014-04-01 12:35:23 +0000101 MatchAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000102 SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000103
Jack Carter873c7242013-01-12 01:03:14 +0000104 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000105 ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000106
107 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000108 ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000109
110 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000111 ParseJumpTarget(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000112
113 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000114 parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000115
Matheus Almeida779c5932013-11-18 12:32:49 +0000116 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000117 ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000118
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000119 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000120
Vladimir Medic4c299852013-11-06 11:27:05 +0000121 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
Jack Carterb4dbc172012-09-05 23:34:03 +0000122 StringRef Mnemonic);
123
Jack Carter30a59822012-10-04 04:03:53 +0000124 bool needsExpansion(MCInst &Inst);
125
126 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000127 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000128 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000129 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000130 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
131 SmallVectorImpl<MCInst> &Instructions);
132 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
133 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000134 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000135 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
136 bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000137 bool reportParseError(StringRef ErrorMsg);
138
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);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000146 bool parseDirectiveCPSetup();
Jack Carter0b744b32012-10-04 02:29:46 +0000147 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000148 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000149
150 bool parseSetAtDirective();
151 bool parseSetNoAtDirective();
152 bool parseSetMacroDirective();
153 bool parseSetNoMacroDirective();
154 bool parseSetReorderDirective();
155 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000156 bool parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +0000157
Jack Carterd76b2372013-03-21 21:44:16 +0000158 bool parseSetAssignment();
159
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000160 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000161 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000162 bool parseDirectiveGpDWord();
Jack Carter07c818d2013-01-25 01:31:34 +0000163
Jack Carterdc1e35d2012-09-06 20:00:02 +0000164 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000165
Daniel Sanders5e94e682014-03-27 16:42:17 +0000166 bool isGP64() const {
167 return (STI.getFeatureBits() & Mips::FeatureGP64Bit) != 0;
Jack Carterb4dbc172012-09-05 23:34:03 +0000168 }
169
Jack Cartera63b16a2012-09-07 00:23:42 +0000170 bool isFP64() const {
171 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
172 }
173
Daniel Sandersa4b0c742014-03-26 11:39:07 +0000174 bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
Vladimir Medic4c299852013-11-06 11:27:05 +0000175 bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000176
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000177 bool isMicroMips() const {
178 return STI.getFeatureBits() & Mips::FeatureMicroMips;
179 }
180
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000181 bool parseRegister(unsigned &RegNum);
182
183 bool eatComma(StringRef ErrorStr);
184
Jack Carter1ac53222013-02-20 23:11:17 +0000185 int matchCPURegisterName(StringRef Symbol);
186
Jack Carter873c7242013-01-12 01:03:14 +0000187 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000188
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000189 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000190
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000191 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000192
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000193 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000194
Jack Carter5dc8ac92013-09-25 23:50:44 +0000195 int matchMSA128RegisterName(StringRef Name);
196
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000197 int matchMSA128CtrlRegisterName(StringRef Name);
198
Jack Carterd0bd6422013-04-18 00:41:53 +0000199 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000200
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000201 unsigned getGPR(int RegNo);
202
Jack Carter1ac53222013-02-20 23:11:17 +0000203 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000204
205 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000206 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000207
208 // Helper function that checks if the value of a vector index is within the
209 // boundaries of accepted values for each RegisterKind
210 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
211 bool validateMSAIndex(int Val, int RegKind);
212
Vladimir Medic615b26e2014-03-04 09:54:09 +0000213 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
214 if (!(STI.getFeatureBits() & Feature)) {
215 setAvailableFeatures(ComputeAvailableFeatures(
216 STI.ToggleFeature(FeatureString)));
217 }
218 }
219
220 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
221 if (STI.getFeatureBits() & Feature) {
222 setAvailableFeatures(ComputeAvailableFeatures(
223 STI.ToggleFeature(FeatureString)));
224 }
225 }
226
Rafael Espindola870c4e92012-01-11 03:56:41 +0000227public:
Joey Gouly0e76fa72013-09-12 10:28:05 +0000228 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
229 const MCInstrInfo &MII)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000230 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000231 // Initialize the set of available features.
232 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000233
234 // Assert exactly one ABI was chosen.
235 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
236 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
237 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
238 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000239 }
240
Jack Carterb4dbc172012-09-05 23:34:03 +0000241 MCAsmParser &getParser() const { return Parser; }
242 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000243
244 /// Warn if RegNo is the current assembler temporary.
245 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000246};
247}
248
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000249namespace {
250
251/// MipsOperand - Instances of this class represent a parsed Mips machine
252/// instruction.
253class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000254public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000255 /// Broad categories of register classes
256 /// The exact class is finalized by the render method.
257 enum RegKind {
258 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
259 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
260 /// isFP64())
261 RegKind_FCC = 4, /// FCC
262 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
263 RegKind_MSACtrl = 16, /// MSA control registers
264 RegKind_COP2 = 32, /// COP2
265 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
266 /// context).
267 RegKind_CCR = 128, /// CCR
268 RegKind_HWRegs = 256, /// HWRegs
269
270 /// Potentially any (e.g. $1)
271 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
272 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
273 RegKind_CCR | RegKind_HWRegs
Jack Carter873c7242013-01-12 01:03:14 +0000274 };
275
276private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000277 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000278 k_Immediate, /// An immediate (possibly involving symbol references)
279 k_Memory, /// Base + Offset Memory Address
280 k_PhysRegister, /// A physical register from the Mips namespace
281 k_RegisterIndex, /// A register index in one or more RegKind.
282 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000283 } Kind;
284
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000285 MipsOperand(KindTy K, MipsAsmParser &Parser)
286 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
287
288 /// For diagnostics, and checking the assembler temporary
289 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000290
Eric Christopher8996c5d2013-03-15 00:42:55 +0000291 struct Token {
292 const char *Data;
293 unsigned Length;
294 };
295
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000296 struct PhysRegOp {
297 unsigned Num; /// Register Number
298 };
299
300 struct RegIdxOp {
301 unsigned Index; /// Index into the register class
302 RegKind Kind; /// Bitfield of the kinds it could possibly be
303 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000304 };
305
306 struct ImmOp {
307 const MCExpr *Val;
308 };
309
310 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000311 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000312 const MCExpr *Off;
313 };
314
Jack Carterb4dbc172012-09-05 23:34:03 +0000315 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000316 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000317 struct PhysRegOp PhysReg;
318 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000319 struct ImmOp Imm;
320 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000321 };
322
323 SMLoc StartLoc, EndLoc;
324
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000325 /// Internal constructor for register kinds
326 static MipsOperand *CreateReg(unsigned Index, RegKind RegKind,
327 const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
328 MipsAsmParser &Parser) {
329 MipsOperand *Op = new MipsOperand(k_RegisterIndex, Parser);
330 Op->RegIdx.Index = Index;
331 Op->RegIdx.RegInfo = RegInfo;
332 Op->RegIdx.Kind = RegKind;
333 Op->StartLoc = S;
334 Op->EndLoc = E;
335 return Op;
336 }
337
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000338public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000339 /// Coerce the register to GPR32 and return the real register for the current
340 /// target.
341 unsigned getGPR32Reg() const {
342 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
343 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
344 unsigned ClassID = Mips::GPR32RegClassID;
345 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000346 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000347
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000348 /// Coerce the register to GPR64 and return the real register for the current
349 /// target.
350 unsigned getGPR64Reg() const {
351 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
352 unsigned ClassID = Mips::GPR64RegClassID;
353 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000354 }
355
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000356private:
357 /// Coerce the register to AFGR64 and return the real register for the current
358 /// target.
359 unsigned getAFGR64Reg() const {
360 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
361 if (RegIdx.Index % 2 != 0)
362 AsmParser.Warning(StartLoc, "Float register should be even.");
363 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
364 .getRegister(RegIdx.Index / 2);
365 }
366
367 /// Coerce the register to FGR64 and return the real register for the current
368 /// target.
369 unsigned getFGR64Reg() const {
370 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
371 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
372 .getRegister(RegIdx.Index);
373 }
374
375 /// Coerce the register to FGR32 and return the real register for the current
376 /// target.
377 unsigned getFGR32Reg() const {
378 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
379 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
380 .getRegister(RegIdx.Index);
381 }
382
383 /// Coerce the register to FGRH32 and return the real register for the current
384 /// target.
385 unsigned getFGRH32Reg() const {
386 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
387 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
388 .getRegister(RegIdx.Index);
389 }
390
391 /// Coerce the register to FCC and return the real register for the current
392 /// target.
393 unsigned getFCCReg() const {
394 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
395 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
396 .getRegister(RegIdx.Index);
397 }
398
399 /// Coerce the register to MSA128 and return the real register for the current
400 /// target.
401 unsigned getMSA128Reg() const {
402 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
403 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
404 // identical
405 unsigned ClassID = Mips::MSA128BRegClassID;
406 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
407 }
408
409 /// Coerce the register to MSACtrl and return the real register for the
410 /// current target.
411 unsigned getMSACtrlReg() const {
412 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
413 unsigned ClassID = Mips::MSACtrlRegClassID;
414 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
415 }
416
417 /// Coerce the register to COP2 and return the real register for the
418 /// current target.
419 unsigned getCOP2Reg() const {
420 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
421 unsigned ClassID = Mips::COP2RegClassID;
422 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
423 }
424
425 /// Coerce the register to ACC64DSP and return the real register for the
426 /// current target.
427 unsigned getACC64DSPReg() const {
428 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
429 unsigned ClassID = Mips::ACC64DSPRegClassID;
430 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
431 }
432
433 /// Coerce the register to HI32DSP and return the real register for the
434 /// current target.
435 unsigned getHI32DSPReg() const {
436 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
437 unsigned ClassID = Mips::HI32DSPRegClassID;
438 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
439 }
440
441 /// Coerce the register to LO32DSP and return the real register for the
442 /// current target.
443 unsigned getLO32DSPReg() const {
444 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
445 unsigned ClassID = Mips::LO32DSPRegClassID;
446 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
447 }
448
449 /// Coerce the register to CCR and return the real register for the
450 /// current target.
451 unsigned getCCRReg() const {
452 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
453 unsigned ClassID = Mips::CCRRegClassID;
454 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
455 }
456
457 /// Coerce the register to HWRegs and return the real register for the
458 /// current target.
459 unsigned getHWRegsReg() const {
460 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
461 unsigned ClassID = Mips::HWRegsRegClassID;
462 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
463 }
464
465public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000466 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000467 // Add as immediate when possible. Null MCExpr = 0.
468 if (Expr == 0)
469 Inst.addOperand(MCOperand::CreateImm(0));
470 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
471 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
472 else
473 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000474 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000475
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000476 void addRegOperands(MCInst &Inst, unsigned N) const {
477 llvm_unreachable("Use a custom parser instead");
478 }
479
Daniel Sanders21bce302014-04-01 12:35:23 +0000480 /// Render the operand to an MCInst as a GPR32
481 /// Asserts if the wrong number of operands are requested, or the operand
482 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000483 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
484 assert(N == 1 && "Invalid number of operands!");
485 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
486 }
487
Daniel Sanders21bce302014-04-01 12:35:23 +0000488 /// Render the operand to an MCInst as a GPR64
489 /// Asserts if the wrong number of operands are requested, or the operand
490 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000491 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
492 assert(N == 1 && "Invalid number of operands!");
493 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
494 }
495
496 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
497 assert(N == 1 && "Invalid number of operands!");
498 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
499 }
500
501 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
502 assert(N == 1 && "Invalid number of operands!");
503 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
504 }
505
506 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
507 assert(N == 1 && "Invalid number of operands!");
508 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
509 }
510
511 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
512 assert(N == 1 && "Invalid number of operands!");
513 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
514 }
515
516 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
517 assert(N == 1 && "Invalid number of operands!");
518 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
519 }
520
521 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
522 assert(N == 1 && "Invalid number of operands!");
523 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
524 }
525
526 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
527 assert(N == 1 && "Invalid number of operands!");
528 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
529 }
530
531 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
532 assert(N == 1 && "Invalid number of operands!");
533 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
534 }
535
536 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
537 assert(N == 1 && "Invalid number of operands!");
538 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
539 }
540
541 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
542 assert(N == 1 && "Invalid number of operands!");
543 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
544 }
545
546 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
547 assert(N == 1 && "Invalid number of operands!");
548 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
549 }
550
551 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
552 assert(N == 1 && "Invalid number of operands!");
553 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
554 }
555
556 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
557 assert(N == 1 && "Invalid number of operands!");
558 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
559 }
560
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000561 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000562 assert(N == 1 && "Invalid number of operands!");
563 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000564 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000565 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000566
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000567 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000568 assert(N == 2 && "Invalid number of operands!");
569
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000571
572 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000573 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000574 }
575
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 bool isReg() const {
577 // As a special case until we sort out the definition of div/divu, pretend
578 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
579 if (isGPRAsmReg() && RegIdx.Index == 0)
580 return true;
581
582 return Kind == k_PhysRegister;
583 }
584 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000585 bool isImm() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 bool isConstantImm() const {
587 return isImm() && dyn_cast<MCConstantExpr>(getImm());
588 }
589 bool isToken() const {
590 // Note: It's not possible to pretend that other operand kinds are tokens.
591 // The matcher emitter checks tokens first.
592 return Kind == k_Token;
593 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000594 bool isMem() const { return Kind == k_Memory; }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000595 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000596 bool isLSAImm() const {
597 if (!isConstantImm())
598 return false;
599 int64_t Val = getConstantImm();
600 return 1 <= Val && Val <= 4;
601 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000602
603 StringRef getToken() const {
604 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000605 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000606 }
607
608 unsigned getReg() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000609 // As a special case until we sort out the definition of div/divu, pretend
610 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
611 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
612 RegIdx.Kind & RegKind_GPR)
613 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000614
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000615 assert(Kind == k_PhysRegister && "Invalid access!");
616 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000617 }
618
Jack Carterb4dbc172012-09-05 23:34:03 +0000619 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000620 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000621 return Imm.Val;
622 }
623
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000624 int64_t getConstantImm() const {
625 const MCExpr *Val = getImm();
626 return static_cast<const MCConstantExpr *>(Val)->getValue();
627 }
628
629 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000630 assert((Kind == k_Memory) && "Invalid access!");
631 return Mem.Base;
632 }
633
634 const MCExpr *getMemOff() const {
635 assert((Kind == k_Memory) && "Invalid access!");
636 return Mem.Off;
637 }
638
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000639 static MipsOperand *CreateToken(StringRef Str, SMLoc S,
640 MipsAsmParser &Parser) {
641 MipsOperand *Op = new MipsOperand(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000642 Op->Tok.Data = Str.data();
643 Op->Tok.Length = Str.size();
644 Op->StartLoc = S;
645 Op->EndLoc = S;
646 return Op;
647 }
648
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 /// Create a numeric register (e.g. $1). The exact register remains
650 /// unresolved until an instruction successfully matches
651 static MipsOperand *CreateNumericReg(unsigned Index,
652 const MCRegisterInfo *RegInfo, SMLoc S,
653 SMLoc E, MipsAsmParser &Parser) {
654 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
655 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000656 }
657
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000658 /// Create a register that is definitely a GPR.
659 /// This is typically only used for named registers such as $gp.
660 static MipsOperand *CreateGPRReg(unsigned Index,
661 const MCRegisterInfo *RegInfo, SMLoc S,
662 SMLoc E, MipsAsmParser &Parser) {
663 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000664 }
665
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000666 /// Create a register that is definitely a FGR.
667 /// This is typically only used for named registers such as $f0.
668 static MipsOperand *CreateFGRReg(unsigned Index,
669 const MCRegisterInfo *RegInfo, SMLoc S,
670 SMLoc E, MipsAsmParser &Parser) {
671 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
672 }
673
674 /// Create a register that is definitely an FCC.
675 /// This is typically only used for named registers such as $fcc0.
676 static MipsOperand *CreateFCCReg(unsigned Index,
677 const MCRegisterInfo *RegInfo, SMLoc S,
678 SMLoc E, MipsAsmParser &Parser) {
679 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
680 }
681
682 /// Create a register that is definitely an ACC.
683 /// This is typically only used for named registers such as $ac0.
684 static MipsOperand *CreateACCReg(unsigned Index,
685 const MCRegisterInfo *RegInfo, SMLoc S,
686 SMLoc E, MipsAsmParser &Parser) {
687 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
688 }
689
690 /// Create a register that is definitely an MSA128.
691 /// This is typically only used for named registers such as $w0.
692 static MipsOperand *CreateMSA128Reg(unsigned Index,
693 const MCRegisterInfo *RegInfo, SMLoc S,
694 SMLoc E, MipsAsmParser &Parser) {
695 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
696 }
697
698 /// Create a register that is definitely an MSACtrl.
699 /// This is typically only used for named registers such as $msaaccess.
700 static MipsOperand *CreateMSACtrlReg(unsigned Index,
701 const MCRegisterInfo *RegInfo, SMLoc S,
702 SMLoc E, MipsAsmParser &Parser) {
703 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
704 }
705
706 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E,
707 MipsAsmParser &Parser) {
708 MipsOperand *Op = new MipsOperand(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000709 Op->Imm.Val = Val;
710 Op->StartLoc = S;
711 Op->EndLoc = E;
712 return Op;
713 }
714
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S,
716 SMLoc E, MipsAsmParser &Parser) {
717 MipsOperand *Op = new MipsOperand(k_Memory, Parser);
Jack Carterdc1e35d2012-09-06 20:00:02 +0000718 Op->Mem.Base = Base;
719 Op->Mem.Off = Off;
720 Op->StartLoc = S;
721 Op->EndLoc = E;
722 return Op;
723 }
724
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000725 bool isGPRAsmReg() const {
726 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000727 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 bool isFGRAsmReg() const {
729 // AFGR64 is $0-$15 but we handle this in getAFGR64()
730 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000731 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 bool isHWRegsAsmReg() const {
733 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000734 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000735 bool isCCRAsmReg() const {
736 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000737 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 bool isFCCAsmReg() const {
739 return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000740 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 bool isACCAsmReg() const {
742 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000743 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 bool isCOP2AsmReg() const {
745 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000746 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 bool isMSA128AsmReg() const {
748 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000749 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 bool isMSACtrlAsmReg() const {
751 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000752 }
753
Jack Carterb4dbc172012-09-05 23:34:03 +0000754 /// getStartLoc - Get the location of the first token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000755 SMLoc getStartLoc() const { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000756 /// getEndLoc - Get the location of the last token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000757 SMLoc getEndLoc() const { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000758
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000759 virtual void print(raw_ostream &OS) const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 switch (Kind) {
761 case k_Immediate:
762 OS << "Imm<";
763 Imm.Val->print(OS);
764 OS << ">";
765 break;
766 case k_Memory:
767 OS << "Mem<";
768 Mem.Base->print(OS);
769 OS << ", ";
770 Mem.Off->print(OS);
771 OS << ">";
772 break;
773 case k_PhysRegister:
774 OS << "PhysReg<" << PhysReg.Num << ">";
775 break;
776 case k_RegisterIndex:
777 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
778 break;
779 case k_Token:
780 OS << Tok.Data;
781 break;
782 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000783 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000784}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000785} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000786
Jack Carter9e65aa32013-03-22 00:05:30 +0000787namespace llvm {
788extern const MCInstrDesc MipsInsts[];
789}
790static const MCInstrDesc &getInstDesc(unsigned Opcode) {
791 return MipsInsts[Opcode];
792}
793
794bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000795 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000796 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000797
Jack Carter9e65aa32013-03-22 00:05:30 +0000798 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000799
800 if (MCID.isBranch() || MCID.isCall()) {
801 const unsigned Opcode = Inst.getOpcode();
802 MCOperand Offset;
803
804 switch (Opcode) {
805 default:
806 break;
807 case Mips::BEQ:
808 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 case Mips::BEQ_MM:
810 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000811 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000812 Offset = Inst.getOperand(2);
813 if (!Offset.isImm())
814 break; // We'll deal with this situation later on when applying fixups.
815 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
816 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000817 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000818 return Error(IDLoc, "branch to misaligned address");
819 break;
820 case Mips::BGEZ:
821 case Mips::BGTZ:
822 case Mips::BLEZ:
823 case Mips::BLTZ:
824 case Mips::BGEZAL:
825 case Mips::BLTZAL:
826 case Mips::BC1F:
827 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 case Mips::BGEZ_MM:
829 case Mips::BGTZ_MM:
830 case Mips::BLEZ_MM:
831 case Mips::BLTZ_MM:
832 case Mips::BGEZAL_MM:
833 case Mips::BLTZAL_MM:
834 case Mips::BC1F_MM:
835 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000836 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000837 Offset = Inst.getOperand(1);
838 if (!Offset.isImm())
839 break; // We'll deal with this situation later on when applying fixups.
840 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
841 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000842 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000843 return Error(IDLoc, "branch to misaligned address");
844 break;
845 }
846 }
847
Jack Carterc15c1d22013-04-25 23:31:35 +0000848 if (MCID.hasDelaySlot() && Options.isReorder()) {
849 // If this instruction has a delay slot and .set reorder is active,
850 // emit a NOP after it.
851 Instructions.push_back(Inst);
852 MCInst NopInst;
853 NopInst.setOpcode(Mips::SLL);
854 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
855 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
856 NopInst.addOperand(MCOperand::CreateImm(0));
857 Instructions.push_back(NopInst);
858 return false;
859 }
860
Jack Carter9e65aa32013-03-22 00:05:30 +0000861 if (MCID.mayLoad() || MCID.mayStore()) {
862 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000863 // reference or immediate we may have to expand instructions.
864 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000865 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000866 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
867 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000868 MCOperand &Op = Inst.getOperand(i);
869 if (Op.isImm()) {
870 int MemOffset = Op.getImm();
871 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000872 // Offset can't exceed 16bit value.
873 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000874 return false;
875 }
876 } else if (Op.isExpr()) {
877 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000878 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000879 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000880 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000881 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000882 // Expand symbol.
883 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000884 return false;
885 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000886 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000887 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000888 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000889 }
890 }
891 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000892 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000893 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000894
895 if (needsExpansion(Inst))
896 expandInstruction(Inst, IDLoc, Instructions);
897 else
898 Instructions.push_back(Inst);
899
900 return false;
901}
902
Jack Carter30a59822012-10-04 04:03:53 +0000903bool MipsAsmParser::needsExpansion(MCInst &Inst) {
904
Jack Carterd0bd6422013-04-18 00:41:53 +0000905 switch (Inst.getOpcode()) {
906 case Mips::LoadImm32Reg:
907 case Mips::LoadAddr32Imm:
908 case Mips::LoadAddr32Reg:
909 return true;
910 default:
911 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000912 }
913}
Jack Carter92995f12012-10-06 00:53:28 +0000914
Jack Carter30a59822012-10-04 04:03:53 +0000915void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000916 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000917 switch (Inst.getOpcode()) {
918 case Mips::LoadImm32Reg:
919 return expandLoadImm(Inst, IDLoc, Instructions);
920 case Mips::LoadAddr32Imm:
921 return expandLoadAddressImm(Inst, IDLoc, Instructions);
922 case Mips::LoadAddr32Reg:
923 return expandLoadAddressReg(Inst, IDLoc, Instructions);
924 }
Jack Carter30a59822012-10-04 04:03:53 +0000925}
Jack Carter92995f12012-10-06 00:53:28 +0000926
Jack Carter30a59822012-10-04 04:03:53 +0000927void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000928 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000929 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000930 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000931 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000932 const MCOperand &RegOp = Inst.getOperand(0);
933 assert(RegOp.isReg() && "expected register operand kind");
934
935 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000936 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000937 if (0 <= ImmValue && ImmValue <= 65535) {
938 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000939 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000940 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000941 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000942 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000943 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000944 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000945 } else if (ImmValue < 0 && ImmValue >= -32768) {
946 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000947 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000948 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000949 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000950 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000951 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000952 Instructions.push_back(tmpInst);
953 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000954 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000955 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000956 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000957 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000958 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
959 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000960 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000961 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000962 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000963 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
964 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
965 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
966 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000967 Instructions.push_back(tmpInst);
968 }
969}
Jack Carter92995f12012-10-06 00:53:28 +0000970
Vladimir Medic4c299852013-11-06 11:27:05 +0000971void
972MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
973 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000974 MCInst tmpInst;
975 const MCOperand &ImmOp = Inst.getOperand(2);
976 assert(ImmOp.isImm() && "expected immediate operand kind");
977 const MCOperand &SrcRegOp = Inst.getOperand(1);
978 assert(SrcRegOp.isReg() && "expected register operand kind");
979 const MCOperand &DstRegOp = Inst.getOperand(0);
980 assert(DstRegOp.isReg() && "expected register operand kind");
981 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000982 if (-32768 <= ImmValue && ImmValue <= 65535) {
983 // For -32768 <= j <= 65535.
984 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000985 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000986 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
987 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
988 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
989 Instructions.push_back(tmpInst);
990 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000991 // For any other value of j that is representable as a 32-bit integer.
992 // la d,j(s) => lui d,hi16(j)
993 // ori d,d,lo16(j)
994 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000995 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000996 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
997 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
998 Instructions.push_back(tmpInst);
999 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001000 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001001 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1002 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1003 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1004 Instructions.push_back(tmpInst);
1005 tmpInst.clear();
1006 tmpInst.setOpcode(Mips::ADDu);
1007 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1008 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1009 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1010 Instructions.push_back(tmpInst);
1011 }
1012}
1013
Vladimir Medic4c299852013-11-06 11:27:05 +00001014void
1015MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1016 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001017 MCInst tmpInst;
1018 const MCOperand &ImmOp = Inst.getOperand(1);
1019 assert(ImmOp.isImm() && "expected immediate operand kind");
1020 const MCOperand &RegOp = Inst.getOperand(0);
1021 assert(RegOp.isReg() && "expected register operand kind");
1022 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001023 if (-32768 <= ImmValue && ImmValue <= 65535) {
1024 // For -32768 <= j <= 65535.
1025 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001026 tmpInst.setOpcode(Mips::ADDiu);
1027 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001028 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001029 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1030 Instructions.push_back(tmpInst);
1031 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001032 // For any other value of j that is representable as a 32-bit integer.
1033 // la d,j => lui d,hi16(j)
1034 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001035 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001036 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1037 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1038 Instructions.push_back(tmpInst);
1039 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001040 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001041 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1042 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1043 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1044 Instructions.push_back(tmpInst);
1045 }
1046}
1047
Jack Carter9e65aa32013-03-22 00:05:30 +00001048void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001049 SmallVectorImpl<MCInst> &Instructions,
1050 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001051 const MCSymbolRefExpr *SR;
1052 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001053 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001054 const MCExpr *ExprOffset;
1055 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +00001056 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001057 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +00001058 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001059 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1060 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001061 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001062 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1063 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001064 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001065 if (isImmOpnd) {
1066 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1067 ImmOffset = Inst.getOperand(2).getImm();
1068 LoOffset = ImmOffset & 0x0000ffff;
1069 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001070 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001071 if (LoOffset & 0x8000)
1072 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001073 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001074 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001075 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001076 TempInst.setLoc(IDLoc);
1077 // 1st instruction in expansion is LUi. For load instruction we can use
1078 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001079 // but for stores we must use $at.
1080 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +00001081 TempInst.setOpcode(Mips::LUi);
1082 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1083 if (isImmOpnd)
1084 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1085 else {
1086 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001087 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1089 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1090 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001091 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001092 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001093 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001094 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001095 }
1096 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001097 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001098 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001099 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001100 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001101 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001102 TempInst.setOpcode(Mips::ADDu);
1103 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1104 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1105 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1106 Instructions.push_back(TempInst);
1107 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001108 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001109 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001110 TempInst.setOpcode(Inst.getOpcode());
1111 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1112 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1113 if (isImmOpnd)
1114 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1115 else {
1116 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001117 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1118 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1119 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001120 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001121 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001122 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001123 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001124 }
1125 }
1126 Instructions.push_back(TempInst);
1127 TempInst.clear();
1128}
1129
Vladimir Medic4c299852013-11-06 11:27:05 +00001130bool MipsAsmParser::MatchAndEmitInstruction(
1131 SMLoc IDLoc, unsigned &Opcode,
1132 SmallVectorImpl<MCParsedAsmOperand *> &Operands, MCStreamer &Out,
1133 unsigned &ErrorInfo, bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001134 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001135 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001136 unsigned MatchResult =
1137 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001138
1139 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001140 default:
1141 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001142 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001143 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001144 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001145 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001146 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001147 return false;
1148 }
1149 case Match_MissingFeature:
1150 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1151 return true;
1152 case Match_InvalidOperand: {
1153 SMLoc ErrorLoc = IDLoc;
1154 if (ErrorInfo != ~0U) {
1155 if (ErrorInfo >= Operands.size())
1156 return Error(IDLoc, "too few operands for instruction");
1157
Vladimir Medic4c299852013-11-06 11:27:05 +00001158 ErrorLoc = ((MipsOperand *)Operands[ErrorInfo])->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001159 if (ErrorLoc == SMLoc())
1160 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001161 }
1162
1163 return Error(ErrorLoc, "invalid operand for instruction");
1164 }
1165 case Match_MnemonicFail:
1166 return Error(IDLoc, "invalid instruction");
1167 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001168 return true;
1169}
1170
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001171void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1172 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1173 if (RegIndex == 1)
1174 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001175 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001176 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1177 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001178 }
1179}
1180
Jack Carter1ac53222013-02-20 23:11:17 +00001181int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001182 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001183
Vladimir Medic4c299852013-11-06 11:27:05 +00001184 CC = StringSwitch<unsigned>(Name)
1185 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001186 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001187 .Case("a0", 4)
1188 .Case("a1", 5)
1189 .Case("a2", 6)
1190 .Case("a3", 7)
1191 .Case("v0", 2)
1192 .Case("v1", 3)
1193 .Case("s0", 16)
1194 .Case("s1", 17)
1195 .Case("s2", 18)
1196 .Case("s3", 19)
1197 .Case("s4", 20)
1198 .Case("s5", 21)
1199 .Case("s6", 22)
1200 .Case("s7", 23)
1201 .Case("k0", 26)
1202 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001203 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001204 .Case("sp", 29)
1205 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001206 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001207 .Case("ra", 31)
1208 .Case("t0", 8)
1209 .Case("t1", 9)
1210 .Case("t2", 10)
1211 .Case("t3", 11)
1212 .Case("t4", 12)
1213 .Case("t5", 13)
1214 .Case("t6", 14)
1215 .Case("t7", 15)
1216 .Case("t8", 24)
1217 .Case("t9", 25)
1218 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001219
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001220 if (isN32() || isN64()) {
1221 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1222 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1223 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1224 if (8 <= CC && CC <= 11)
1225 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001226
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001227 if (CC == -1)
1228 CC = StringSwitch<unsigned>(Name)
1229 .Case("a4", 8)
1230 .Case("a5", 9)
1231 .Case("a6", 10)
1232 .Case("a7", 11)
1233 .Case("kt0", 26)
1234 .Case("kt1", 27)
1235 .Default(-1);
1236 }
Jack Carter1ac53222013-02-20 23:11:17 +00001237
1238 return CC;
1239}
Jack Carterd0bd6422013-04-18 00:41:53 +00001240
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001241int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001242
Jack Cartera63b16a2012-09-07 00:23:42 +00001243 if (Name[0] == 'f') {
1244 StringRef NumString = Name.substr(1);
1245 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001246 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001247 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001248 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001249 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001250 return IntVal;
1251 }
1252 return -1;
1253}
Jack Cartera63b16a2012-09-07 00:23:42 +00001254
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001255int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1256
1257 if (Name.startswith("fcc")) {
1258 StringRef NumString = Name.substr(3);
1259 unsigned IntVal;
1260 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001261 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001262 if (IntVal > 7) // There are only 8 fcc registers.
1263 return -1;
1264 return IntVal;
1265 }
1266 return -1;
1267}
1268
1269int MipsAsmParser::matchACRegisterName(StringRef Name) {
1270
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001271 if (Name.startswith("ac")) {
1272 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001273 unsigned IntVal;
1274 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001275 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001276 if (IntVal > 3) // There are only 3 acc registers.
1277 return -1;
1278 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001279 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001280 return -1;
1281}
Jack Carterd0bd6422013-04-18 00:41:53 +00001282
Jack Carter5dc8ac92013-09-25 23:50:44 +00001283int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1284 unsigned IntVal;
1285
1286 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1287 return -1;
1288
1289 if (IntVal > 31)
1290 return -1;
1291
1292 return IntVal;
1293}
1294
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001295int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1296 int CC;
1297
1298 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001299 .Case("msair", 0)
1300 .Case("msacsr", 1)
1301 .Case("msaaccess", 2)
1302 .Case("msasave", 3)
1303 .Case("msamodify", 4)
1304 .Case("msarequest", 5)
1305 .Case("msamap", 6)
1306 .Case("msaunmap", 7)
1307 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001308
1309 return CC;
1310}
1311
Jack Carter0b744b32012-10-04 02:29:46 +00001312bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1313 if (Reg > 31)
1314 return false;
1315
1316 aTReg = Reg;
1317 return true;
1318}
1319
Daniel Sandersd89b1362014-03-24 16:48:01 +00001320int MipsAsmParser::getATReg() {
1321 int AT = Options.getATRegNum();
1322 if (AT == 0)
1323 TokError("Pseudo instruction requires $at, which is not available");
1324 return AT;
1325}
Jack Carter0b744b32012-10-04 02:29:46 +00001326
Jack Carterd0bd6422013-04-18 00:41:53 +00001327unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001328 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001329}
1330
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001331unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001332 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1333 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001334}
1335
Jack Carter873c7242013-01-12 01:03:14 +00001336int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001337 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001338 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001339 return -1;
1340
Jack Carter873c7242013-01-12 01:03:14 +00001341 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001342}
1343
Vladimir Medic4c299852013-11-06 11:27:05 +00001344bool
1345MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1346 StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001347 DEBUG(dbgs() << "ParseOperand\n");
1348
Jack Carter30a59822012-10-04 04:03:53 +00001349 // Check if the current operand has a custom associated parser, if so, try to
1350 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001351 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1352 if (ResTy == MatchOperand_Success)
1353 return false;
1354 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1355 // there was a match, but an error occurred, in which case, just return that
1356 // the operand parsing failed.
1357 if (ResTy == MatchOperand_ParseFail)
1358 return true;
1359
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001360 DEBUG(dbgs() << ".. Generic Parser\n");
1361
Jack Carterb4dbc172012-09-05 23:34:03 +00001362 switch (getLexer().getKind()) {
1363 default:
1364 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1365 return true;
1366 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001367 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001368 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001369
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001370 // Almost all registers have been parsed by custom parsers. There is only
1371 // one exception to this. $zero (and it's alias $0) will reach this point
1372 // for div, divu, and similar instructions because it is not an operand
1373 // to the instruction definition but an explicit register. Special case
1374 // this situation for now.
1375 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001376 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001377
Jack Carterd0bd6422013-04-18 00:41:53 +00001378 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001379 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001380 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001381 return true;
1382
Jack Carter873c7242013-01-12 01:03:14 +00001383 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001384 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001385 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001386 const MCExpr *Res =
1387 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001388
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001389 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001390 return false;
1391 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001392 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001393 case AsmToken::LParen:
1394 case AsmToken::Minus:
1395 case AsmToken::Plus:
1396 case AsmToken::Integer:
1397 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001398 DEBUG(dbgs() << ".. generic integer\n");
1399 OperandMatchResultTy ResTy = ParseImm(Operands);
1400 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001401 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001402 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001403 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001404 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001405 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001406 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001407 return true;
1408
Jack Carter873c7242013-01-12 01:03:14 +00001409 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1410
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001411 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001412 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001413 } // case AsmToken::Percent
1414 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001415 return true;
1416}
1417
Vladimir Medic4c299852013-11-06 11:27:05 +00001418const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001419 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001420 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001421 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001422 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001423 // It's a constant, evaluate reloc value.
1424 int16_t Val;
1425 switch (getVariantKind(RelocStr)) {
1426 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1427 // Get the 1st 16-bits.
1428 Val = MCE->getValue() & 0xffff;
1429 break;
1430 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1431 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1432 // 16 bits being negative.
1433 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1434 break;
1435 case MCSymbolRefExpr::VK_Mips_HIGHER:
1436 // Get the 3rd 16-bits.
1437 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1438 break;
1439 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1440 // Get the 4th 16-bits.
1441 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1442 break;
1443 default:
1444 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001445 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001446 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001447 }
1448
Jack Carterb5cf5902013-04-17 00:18:04 +00001449 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001450 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001451 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001452 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001453 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001454 return Res;
1455 }
1456
1457 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001458 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1459
Sasa Stankovic06c47802014-04-03 10:37:45 +00001460 // Try to create target expression.
1461 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1462 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001463
Jack Carterd0bd6422013-04-18 00:41:53 +00001464 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1465 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001466 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1467 return Res;
1468 }
1469
1470 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001471 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1472 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1473 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001474 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001475 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001476 return Expr;
1477}
1478
1479bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1480
1481 switch (Expr->getKind()) {
1482 case MCExpr::Constant:
1483 return true;
1484 case MCExpr::SymbolRef:
1485 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1486 case MCExpr::Binary:
1487 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1488 if (!isEvaluated(BE->getLHS()))
1489 return false;
1490 return isEvaluated(BE->getRHS());
1491 }
1492 case MCExpr::Unary:
1493 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001494 case MCExpr::Target:
1495 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001496 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001497 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001498}
Jack Carterd0bd6422013-04-18 00:41:53 +00001499
Jack Carterb5cf5902013-04-17 00:18:04 +00001500bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001501 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001502 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001503 if (Tok.isNot(AsmToken::Identifier))
1504 return true;
1505
1506 std::string Str = Tok.getIdentifier().str();
1507
Jack Carterd0bd6422013-04-18 00:41:53 +00001508 Parser.Lex(); // Eat the identifier.
1509 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001510 const MCExpr *IdVal;
1511 SMLoc EndLoc;
1512
1513 if (getLexer().getKind() == AsmToken::LParen) {
1514 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001515 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001516 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001517 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001518 const AsmToken &nextTok = Parser.getTok();
1519 if (nextTok.isNot(AsmToken::Identifier))
1520 return true;
1521 Str += "(%";
1522 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001523 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001524 if (getLexer().getKind() != AsmToken::LParen)
1525 return true;
1526 } else
1527 break;
1528 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001529 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001530 return true;
1531
1532 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001533 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001534
1535 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001536 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001537
Jack Carterd0bd6422013-04-18 00:41:53 +00001538 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001539 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001540}
1541
Jack Carterb4dbc172012-09-05 23:34:03 +00001542bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1543 SMLoc &EndLoc) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001544 SmallVector<MCParsedAsmOperand *, 1> Operands;
1545 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1546 if (ResTy == MatchOperand_Success) {
1547 assert(Operands.size() == 1);
1548 MipsOperand &Operand = *static_cast<MipsOperand *>(Operands.front());
1549 StartLoc = Operand.getStartLoc();
1550 EndLoc = Operand.getEndLoc();
1551
1552 // AFAIK, we only support numeric registers and named GPR's in CFI
1553 // directives.
1554 // Don't worry about eating tokens before failing. Using an unrecognised
1555 // register is a parse error.
1556 if (Operand.isGPRAsmReg()) {
1557 // Resolve to GPR32 or GPR64 appropriately.
1558 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1559 }
1560
1561 return (RegNo == (unsigned)-1);
1562 }
1563
1564 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001565 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001566}
1567
Jack Carterb5cf5902013-04-17 00:18:04 +00001568bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001569 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001570 bool Result = true;
1571
1572 while (getLexer().getKind() == AsmToken::LParen)
1573 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001574
Jack Carterd0bd6422013-04-18 00:41:53 +00001575 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001576 default:
1577 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001578 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001579 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001580 case AsmToken::Integer:
1581 case AsmToken::Minus:
1582 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001583 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001584 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001585 else
1586 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001587 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001588 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001589 break;
Jack Carter873c7242013-01-12 01:03:14 +00001590 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001591 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001592 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001593 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001594}
1595
Jack Carterb4dbc172012-09-05 23:34:03 +00001596MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Vladimir Medic4c299852013-11-06 11:27:05 +00001597 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001598 DEBUG(dbgs() << "parseMemOperand\n");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001599 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001600 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001601 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001602 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001604 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001605
Jack Carterb5cf5902013-04-17 00:18:04 +00001606 if (getLexer().getKind() == AsmToken::LParen) {
1607 Parser.Lex();
1608 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001609 }
1610
Jack Carterb5cf5902013-04-17 00:18:04 +00001611 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001612 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001613 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001614
Jack Carterd0bd6422013-04-18 00:41:53 +00001615 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001616 if (Tok.isNot(AsmToken::LParen)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001617 MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
Jack Carterb5cf5902013-04-17 00:18:04 +00001618 if (Mnemonic->getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001619 SMLoc E =
1620 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001621 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001622 return MatchOperand_Success;
1623 }
1624 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001625 SMLoc E =
1626 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001627
Jack Carterd0bd6422013-04-18 00:41:53 +00001628 // Zero register assumed, add a memory operand with ZERO as its base.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001629 MipsOperand *Base = MipsOperand::CreateGPRReg(
1630 0, getContext().getRegisterInfo(), S, E, *this);
1631 Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001632 return MatchOperand_Success;
1633 }
1634 Error(Parser.getTok().getLoc(), "'(' expected");
1635 return MatchOperand_ParseFail;
1636 }
1637
Jack Carterd0bd6422013-04-18 00:41:53 +00001638 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001639 }
1640
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001641 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001642 if (Res != MatchOperand_Success)
1643 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001644
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001645 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001646 Error(Parser.getTok().getLoc(), "')' expected");
1647 return MatchOperand_ParseFail;
1648 }
1649
Jack Carter873c7242013-01-12 01:03:14 +00001650 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1651
Jack Carterd0bd6422013-04-18 00:41:53 +00001652 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001653
1654 if (IdVal == 0)
1655 IdVal = MCConstantExpr::Create(0, getContext());
1656
Jack Carterd0bd6422013-04-18 00:41:53 +00001657 // Replace the register operand with the memory operand.
Vladimir Medic4c299852013-11-06 11:27:05 +00001658 MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
Jack Carterd0bd6422013-04-18 00:41:53 +00001659 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001660 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001661 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001662 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1663 int64_t Imm;
1664 if (IdVal->EvaluateAsAbsolute(Imm))
1665 IdVal = MCConstantExpr::Create(Imm, getContext());
1666 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1667 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1668 getContext());
1669 }
1670
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001671 Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001672 return MatchOperand_Success;
1673}
1674
Daniel Sanderse34a1202014-03-31 18:51:43 +00001675bool MipsAsmParser::searchSymbolAlias(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001676 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001677
Jack Carterd76b2372013-03-21 21:44:16 +00001678 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1679 if (Sym) {
1680 SMLoc S = Parser.getTok().getLoc();
1681 const MCExpr *Expr;
1682 if (Sym->isVariable())
1683 Expr = Sym->getVariableValue();
1684 else
1685 return false;
1686 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001687 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001688 const StringRef DefSymbol = Ref->getSymbol().getName();
1689 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001690 OperandMatchResultTy ResTy =
1691 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001692 if (ResTy == MatchOperand_Success) {
1693 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001694 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001695 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001696 llvm_unreachable("Should never ParseFail");
1697 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001698 }
1699 } else if (Expr->getKind() == MCExpr::Constant) {
1700 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001701 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
1702 MipsOperand *op =
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001703 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this);
Jack Carterd76b2372013-03-21 21:44:16 +00001704 Operands.push_back(op);
1705 return true;
1706 }
1707 }
1708 return false;
1709}
Jack Carterd0bd6422013-04-18 00:41:53 +00001710
Jack Carter873c7242013-01-12 01:03:14 +00001711MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001712MipsAsmParser::MatchAnyRegisterNameWithoutDollar(
1713 SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
1714 SMLoc S) {
1715 int Index = matchCPURegisterName(Identifier);
1716 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001717 Operands.push_back(MipsOperand::CreateGPRReg(
1718 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1719 return MatchOperand_Success;
1720 }
1721
1722 Index = matchFPURegisterName(Identifier);
1723 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001724 Operands.push_back(MipsOperand::CreateFGRReg(
1725 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1726 return MatchOperand_Success;
1727 }
1728
1729 Index = matchFCCRegisterName(Identifier);
1730 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001731 Operands.push_back(MipsOperand::CreateFCCReg(
1732 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1733 return MatchOperand_Success;
1734 }
1735
1736 Index = matchACRegisterName(Identifier);
1737 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001738 Operands.push_back(MipsOperand::CreateACCReg(
1739 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1740 return MatchOperand_Success;
1741 }
1742
1743 Index = matchMSA128RegisterName(Identifier);
1744 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001745 Operands.push_back(MipsOperand::CreateMSA128Reg(
1746 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1747 return MatchOperand_Success;
1748 }
1749
1750 Index = matchMSA128CtrlRegisterName(Identifier);
1751 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001752 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1753 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1754 return MatchOperand_Success;
1755 }
1756
1757 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001758}
1759
1760MipsAsmParser::OperandMatchResultTy
Daniel Sanders21bce302014-04-01 12:35:23 +00001761MipsAsmParser::MatchAnyRegisterWithoutDollar(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001762 SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001763 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001764
1765 if (Token.is(AsmToken::Identifier)) {
1766 DEBUG(dbgs() << ".. identifier\n");
1767 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001768 OperandMatchResultTy ResTy =
1769 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001770 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001771 } else if (Token.is(AsmToken::Integer)) {
1772 DEBUG(dbgs() << ".. integer\n");
1773 Operands.push_back(MipsOperand::CreateNumericReg(
1774 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1775 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001776 return MatchOperand_Success;
1777 }
1778
1779 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1780
1781 return MatchOperand_NoMatch;
1782}
1783
1784MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
1785 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1786 DEBUG(dbgs() << "ParseAnyRegister\n");
1787
1788 auto Token = Parser.getTok();
1789
1790 SMLoc S = Token.getLoc();
1791
1792 if (Token.isNot(AsmToken::Dollar)) {
1793 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1794 if (Token.is(AsmToken::Identifier)) {
1795 if (searchSymbolAlias(Operands))
1796 return MatchOperand_Success;
1797 }
1798 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1799 return MatchOperand_NoMatch;
1800 }
1801 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001802
Daniel Sanders21bce302014-04-01 12:35:23 +00001803 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001804 if (ResTy == MatchOperand_Success) {
1805 Parser.Lex(); // $
1806 Parser.Lex(); // identifier
1807 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001808 return ResTy;
1809}
1810
1811MipsAsmParser::OperandMatchResultTy
1812MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1813 switch (getLexer().getKind()) {
1814 default:
1815 return MatchOperand_NoMatch;
1816 case AsmToken::LParen:
1817 case AsmToken::Minus:
1818 case AsmToken::Plus:
1819 case AsmToken::Integer:
1820 case AsmToken::String:
1821 break;
1822 }
1823
1824 const MCExpr *IdVal;
1825 SMLoc S = Parser.getTok().getLoc();
1826 if (getParser().parseExpression(IdVal))
1827 return MatchOperand_ParseFail;
1828
1829 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1830 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1831 return MatchOperand_Success;
1832}
1833
1834MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
1835 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1836 DEBUG(dbgs() << "ParseJumpTarget\n");
1837
1838 SMLoc S = getLexer().getLoc();
1839
1840 // Integers and expressions are acceptable
1841 OperandMatchResultTy ResTy = ParseImm(Operands);
1842 if (ResTy != MatchOperand_NoMatch)
1843 return ResTy;
1844
Daniel Sanders315386c2014-04-01 10:40:14 +00001845 // Registers are a valid target and have priority over symbols.
1846 ResTy = ParseAnyRegister(Operands);
1847 if (ResTy != MatchOperand_NoMatch)
1848 return ResTy;
1849
Daniel Sandersffd84362014-04-01 10:41:48 +00001850 const MCExpr *Expr = nullptr;
1851 if (Parser.parseExpression(Expr)) {
1852 // We have no way of knowing if a symbol was consumed so we must ParseFail
1853 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001854 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001855 Operands.push_back(
1856 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001857 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001858}
1859
Vladimir Medic2b953d02013-10-01 09:48:56 +00001860MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001861MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001862 const MCExpr *IdVal;
1863 // If the first token is '$' we may have register operand.
1864 if (Parser.getTok().is(AsmToken::Dollar))
1865 return MatchOperand_NoMatch;
1866 SMLoc S = Parser.getTok().getLoc();
1867 if (getParser().parseExpression(IdVal))
1868 return MatchOperand_ParseFail;
1869 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001870 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001871 int64_t Val = MCE->getValue();
1872 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1873 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001874 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001875 return MatchOperand_Success;
1876}
1877
Matheus Almeida779c5932013-11-18 12:32:49 +00001878MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001879MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001880 switch (getLexer().getKind()) {
1881 default:
1882 return MatchOperand_NoMatch;
1883 case AsmToken::LParen:
1884 case AsmToken::Plus:
1885 case AsmToken::Minus:
1886 case AsmToken::Integer:
1887 break;
1888 }
1889
1890 const MCExpr *Expr;
1891 SMLoc S = Parser.getTok().getLoc();
1892
1893 if (getParser().parseExpression(Expr))
1894 return MatchOperand_ParseFail;
1895
1896 int64_t Val;
1897 if (!Expr->EvaluateAsAbsolute(Val)) {
1898 Error(S, "expected immediate value");
1899 return MatchOperand_ParseFail;
1900 }
1901
1902 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1903 // and because the CPU always adds one to the immediate field, the allowed
1904 // range becomes 1..4. We'll only check the range here and will deal
1905 // with the addition/subtraction when actually decoding/encoding
1906 // the instruction.
1907 if (Val < 1 || Val > 4) {
1908 Error(S, "immediate not in range (1..4)");
1909 return MatchOperand_ParseFail;
1910 }
1911
Jack Carter3b2c96e2014-01-22 23:31:38 +00001912 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001913 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00001914 return MatchOperand_Success;
1915}
1916
Jack Carterdc1e35d2012-09-06 20:00:02 +00001917MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1918
Vladimir Medic4c299852013-11-06 11:27:05 +00001919 MCSymbolRefExpr::VariantKind VK =
1920 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1921 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1922 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1923 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1924 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1925 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1926 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1927 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1928 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1929 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1930 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1931 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1932 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1933 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1934 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1935 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1936 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1937 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00001938 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
1939 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
1940 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
1941 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
1942 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
1943 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Vladimir Medic4c299852013-11-06 11:27:05 +00001944 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001945
Daniel Sandersa567da52014-03-31 15:15:02 +00001946 assert (VK != MCSymbolRefExpr::VK_None);
1947
Jack Carterdc1e35d2012-09-06 20:00:02 +00001948 return VK;
1949}
Jack Cartera63b16a2012-09-07 00:23:42 +00001950
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001951/// Sometimes (i.e. load/stores) the operand may be followed immediately by
1952/// either this.
1953/// ::= '(', register, ')'
1954/// handle it before we iterate so we don't get tripped up by the lack of
1955/// a comma.
1956bool MipsAsmParser::ParseParenSuffix(
1957 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1958 if (getLexer().is(AsmToken::LParen)) {
1959 Operands.push_back(
1960 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
1961 Parser.Lex();
1962 if (ParseOperand(Operands, Name)) {
1963 SMLoc Loc = getLexer().getLoc();
1964 Parser.eatToEndOfStatement();
1965 return Error(Loc, "unexpected token in argument list");
1966 }
1967 if (Parser.getTok().isNot(AsmToken::RParen)) {
1968 SMLoc Loc = getLexer().getLoc();
1969 Parser.eatToEndOfStatement();
1970 return Error(Loc, "unexpected token, expected ')'");
1971 }
1972 Operands.push_back(
1973 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
1974 Parser.Lex();
1975 }
1976 return false;
1977}
1978
1979/// Sometimes (i.e. in MSA) the operand may be followed immediately by
1980/// either one of these.
1981/// ::= '[', register, ']'
1982/// ::= '[', integer, ']'
1983/// handle it before we iterate so we don't get tripped up by the lack of
1984/// a comma.
1985bool MipsAsmParser::ParseBracketSuffix(
1986 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1987 if (getLexer().is(AsmToken::LBrac)) {
1988 Operands.push_back(
1989 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
1990 Parser.Lex();
1991 if (ParseOperand(Operands, Name)) {
1992 SMLoc Loc = getLexer().getLoc();
1993 Parser.eatToEndOfStatement();
1994 return Error(Loc, "unexpected token in argument list");
1995 }
1996 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1997 SMLoc Loc = getLexer().getLoc();
1998 Parser.eatToEndOfStatement();
1999 return Error(Loc, "unexpected token, expected ']'");
2000 }
2001 Operands.push_back(
2002 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2003 Parser.Lex();
2004 }
2005 return false;
2006}
2007
Vladimir Medic4c299852013-11-06 11:27:05 +00002008bool MipsAsmParser::ParseInstruction(
2009 ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
2010 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002011 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002012 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002013 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002014 Parser.eatToEndOfStatement();
2015 return Error(NameLoc, "Unknown instruction");
2016 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002017 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002018 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002019
2020 // Read the remaining operands.
2021 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2022 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002023 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002024 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002025 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002026 return Error(Loc, "unexpected token in argument list");
2027 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002028 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2029 return true;
2030 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002031
Jack Carterd0bd6422013-04-18 00:41:53 +00002032 while (getLexer().is(AsmToken::Comma)) {
2033 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002034 // Parse and remember the operand.
2035 if (ParseOperand(Operands, Name)) {
2036 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002037 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002038 return Error(Loc, "unexpected token in argument list");
2039 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002040 // Parse bracket and parenthesis suffixes before we iterate
2041 if (getLexer().is(AsmToken::LBrac)) {
2042 if (ParseBracketSuffix(Name, Operands))
2043 return true;
2044 } else if (getLexer().is(AsmToken::LParen) &&
2045 ParseParenSuffix(Name, Operands))
2046 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002047 }
2048 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2050 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002051 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002052 return Error(Loc, "unexpected token in argument list");
2053 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002054 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002055 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002056}
2057
Jack Carter0b744b32012-10-04 02:29:46 +00002058bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002059 SMLoc Loc = getLexer().getLoc();
2060 Parser.eatToEndOfStatement();
2061 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002062}
2063
2064bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002065 // Line should look like: ".set noat".
2066 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002067 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002068 // eat noat
2069 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002070 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002071 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2072 reportParseError("unexpected token in statement");
2073 return false;
2074 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002075 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002076 return false;
2077}
Jack Carterd0bd6422013-04-18 00:41:53 +00002078
Jack Carter0b744b32012-10-04 02:29:46 +00002079bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002081 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002082 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002083 getParser().Lex();
2084 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002085 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002086 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002087 return false;
2088 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002089 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002090 if (getLexer().isNot(AsmToken::Dollar)) {
2091 reportParseError("unexpected token in statement");
2092 return false;
2093 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002094 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002095 const AsmToken &Reg = Parser.getTok();
2096 if (Reg.is(AsmToken::Identifier)) {
2097 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2098 } else if (Reg.is(AsmToken::Integer)) {
2099 AtRegNo = Reg.getIntVal();
2100 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002101 reportParseError("unexpected token in statement");
2102 return false;
2103 }
Jack Carter1ac53222013-02-20 23:11:17 +00002104
Daniel Sanders71a89d922014-03-25 13:01:06 +00002105 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002106 reportParseError("unexpected token in statement");
2107 return false;
2108 }
2109
2110 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002111 reportParseError("unexpected token in statement");
2112 return false;
2113 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002114 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002115
2116 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2117 reportParseError("unexpected token in statement");
2118 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002119 }
2120 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002121 return false;
2122 } else {
2123 reportParseError("unexpected token in statement");
2124 return false;
2125 }
2126}
2127
2128bool MipsAsmParser::parseSetReorderDirective() {
2129 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002130 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002131 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2132 reportParseError("unexpected token in statement");
2133 return false;
2134 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002135 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002136 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002137 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002138 return false;
2139}
2140
2141bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002142 Parser.Lex();
2143 // If this is not the end of the statement, report an error.
2144 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2145 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002146 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002147 }
2148 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002149 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002150 Parser.Lex(); // Consume the EndOfStatement.
2151 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002152}
2153
2154bool MipsAsmParser::parseSetMacroDirective() {
2155 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002156 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002157 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2158 reportParseError("unexpected token in statement");
2159 return false;
2160 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002161 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002162 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002163 return false;
2164}
2165
2166bool MipsAsmParser::parseSetNoMacroDirective() {
2167 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002168 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002169 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2170 reportParseError("`noreorder' must be set before `nomacro'");
2171 return false;
2172 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002173 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002174 reportParseError("`noreorder' must be set before `nomacro'");
2175 return false;
2176 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002177 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002178 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002179 return false;
2180}
Jack Carterd76b2372013-03-21 21:44:16 +00002181
Jack Carter39536722014-01-22 23:08:42 +00002182bool MipsAsmParser::parseSetNoMips16Directive() {
2183 Parser.Lex();
2184 // If this is not the end of the statement, report an error.
2185 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2186 reportParseError("unexpected token in statement");
2187 return false;
2188 }
2189 // For now do nothing.
2190 Parser.Lex(); // Consume the EndOfStatement.
2191 return false;
2192}
2193
Jack Carterd76b2372013-03-21 21:44:16 +00002194bool MipsAsmParser::parseSetAssignment() {
2195 StringRef Name;
2196 const MCExpr *Value;
2197
2198 if (Parser.parseIdentifier(Name))
2199 reportParseError("expected identifier after .set");
2200
2201 if (getLexer().isNot(AsmToken::Comma))
2202 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002203 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002204
Jack Carter3b2c96e2014-01-22 23:31:38 +00002205 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002206 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002207
Jack Carterd0bd6422013-04-18 00:41:53 +00002208 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002209 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002210 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002211 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002212 Sym = getContext().GetOrCreateSymbol(Name);
2213 Sym->setVariableValue(Value);
2214
2215 return false;
2216}
Jack Carterd0bd6422013-04-18 00:41:53 +00002217
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002218bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2219 Parser.Lex();
2220 if (getLexer().isNot(AsmToken::EndOfStatement))
2221 return reportParseError("unexpected token in .set directive");
2222
2223 switch(Feature) {
2224 default: llvm_unreachable("Unimplemented feature");
2225 case Mips::FeatureDSP:
2226 setFeatureBits(Mips::FeatureDSP, "dsp");
2227 getTargetStreamer().emitDirectiveSetDsp();
2228 break;
2229 case Mips::FeatureMicroMips:
2230 getTargetStreamer().emitDirectiveSetMicroMips();
2231 break;
2232 case Mips::FeatureMips16:
2233 getTargetStreamer().emitDirectiveSetMips16();
2234 break;
2235 case Mips::FeatureMips32r2:
2236 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2237 getTargetStreamer().emitDirectiveSetMips32R2();
2238 break;
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002239 case Mips::FeatureMips64:
2240 setFeatureBits(Mips::FeatureMips64, "mips64");
2241 getTargetStreamer().emitDirectiveSetMips64();
2242 break;
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002243 case Mips::FeatureMips64r2:
2244 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2245 getTargetStreamer().emitDirectiveSetMips64R2();
2246 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002247 }
2248 return false;
2249}
2250
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002251bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2252 if (!getLexer().is(AsmToken::Dollar))
2253 return false;
2254
2255 Parser.Lex();
2256
2257 const AsmToken &Reg = Parser.getTok();
2258 if (Reg.is(AsmToken::Identifier)) {
2259 RegNum = matchCPURegisterName(Reg.getIdentifier());
2260 } else if (Reg.is(AsmToken::Integer)) {
2261 RegNum = Reg.getIntVal();
2262 } else {
2263 return false;
2264 }
2265
2266 Parser.Lex();
2267 return true;
2268}
2269
2270bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2271 if (getLexer().isNot(AsmToken::Comma)) {
2272 SMLoc Loc = getLexer().getLoc();
2273 Parser.eatToEndOfStatement();
2274 return Error(Loc, ErrorStr);
2275 }
2276
2277 Parser.Lex(); // Eat the comma.
2278 return true;
2279}
2280
2281bool MipsAsmParser::parseDirectiveCPSetup() {
2282 unsigned FuncReg;
2283 unsigned Save;
2284 bool SaveIsReg = true;
2285
2286 if (!parseRegister(FuncReg))
2287 return reportParseError("expected register containing function address");
2288 FuncReg = getGPR(FuncReg);
2289
2290 if (!eatComma("expected comma parsing directive"))
2291 return true;
2292
2293 if (!parseRegister(Save)) {
2294 const AsmToken &Tok = Parser.getTok();
2295 if (Tok.is(AsmToken::Integer)) {
2296 Save = Tok.getIntVal();
2297 SaveIsReg = false;
2298 Parser.Lex();
2299 } else
2300 return reportParseError("expected save register or stack offset");
2301 } else
2302 Save = getGPR(Save);
2303
2304 if (!eatComma("expected comma parsing directive"))
2305 return true;
2306
2307 StringRef Name;
2308 if (Parser.parseIdentifier(Name))
2309 reportParseError("expected identifier");
2310 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
2311 unsigned GPReg = getGPR(matchCPURegisterName("gp"));
2312
2313 // FIXME: The code below this point should be in the TargetStreamers.
2314 // Only N32 and N64 emit anything for .cpsetup
2315 // FIXME: We should only emit something for PIC mode too.
2316 if (!isN32() && !isN64())
2317 return false;
2318
2319 MCStreamer &TS = getStreamer();
2320 MCInst Inst;
2321 // Either store the old $gp in a register or on the stack
2322 if (SaveIsReg) {
2323 // move $save, $gpreg
2324 Inst.setOpcode(Mips::DADDu);
2325 Inst.addOperand(MCOperand::CreateReg(Save));
2326 Inst.addOperand(MCOperand::CreateReg(GPReg));
2327 Inst.addOperand(MCOperand::CreateReg(getGPR(0)));
2328 } else {
2329 // sd $gpreg, offset($sp)
2330 Inst.setOpcode(Mips::SD);
2331 Inst.addOperand(MCOperand::CreateReg(GPReg));
2332 Inst.addOperand(MCOperand::CreateReg(getGPR(matchCPURegisterName("sp"))));
2333 Inst.addOperand(MCOperand::CreateImm(Save));
2334 }
2335 TS.EmitInstruction(Inst, STI);
2336 Inst.clear();
2337
2338 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2339 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI,
2340 getContext());
2341 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2342 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO,
2343 getContext());
2344 // lui $gp, %hi(%neg(%gp_rel(funcSym)))
2345 Inst.setOpcode(Mips::LUi);
2346 Inst.addOperand(MCOperand::CreateReg(GPReg));
2347 Inst.addOperand(MCOperand::CreateExpr(HiExpr));
2348 TS.EmitInstruction(Inst, STI);
2349 Inst.clear();
2350
2351 // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
2352 Inst.setOpcode(Mips::ADDiu);
2353 Inst.addOperand(MCOperand::CreateReg(GPReg));
2354 Inst.addOperand(MCOperand::CreateReg(GPReg));
2355 Inst.addOperand(MCOperand::CreateExpr(LoExpr));
2356 TS.EmitInstruction(Inst, STI);
2357 Inst.clear();
2358
2359 // daddu $gp, $gp, $funcreg
2360 Inst.setOpcode(Mips::DADDu);
2361 Inst.addOperand(MCOperand::CreateReg(GPReg));
2362 Inst.addOperand(MCOperand::CreateReg(GPReg));
2363 Inst.addOperand(MCOperand::CreateReg(FuncReg));
2364 TS.EmitInstruction(Inst, STI);
2365 return false;
2366}
2367
Jack Carter0b744b32012-10-04 02:29:46 +00002368bool MipsAsmParser::parseDirectiveSet() {
2369
Jack Carterd0bd6422013-04-18 00:41:53 +00002370 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002371 const AsmToken &Tok = Parser.getTok();
2372
2373 if (Tok.getString() == "noat") {
2374 return parseSetNoAtDirective();
2375 } else if (Tok.getString() == "at") {
2376 return parseSetAtDirective();
2377 } else if (Tok.getString() == "reorder") {
2378 return parseSetReorderDirective();
2379 } else if (Tok.getString() == "noreorder") {
2380 return parseSetNoReorderDirective();
2381 } else if (Tok.getString() == "macro") {
2382 return parseSetMacroDirective();
2383 } else if (Tok.getString() == "nomacro") {
2384 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002385 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002386 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002387 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002388 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002389 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002390 getTargetStreamer().emitDirectiveSetNoMicroMips();
2391 Parser.eatToEndOfStatement();
2392 return false;
2393 } else if (Tok.getString() == "micromips") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002394 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002395 } else if (Tok.getString() == "mips32r2") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002396 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002397 } else if (Tok.getString() == "mips64") {
2398 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002399 } else if (Tok.getString() == "mips64r2") {
2400 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002401 } else if (Tok.getString() == "dsp") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002402 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002403 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002404 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002405 parseSetAssignment();
2406 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002407 }
Jack Carter07c818d2013-01-25 01:31:34 +00002408
Jack Carter0b744b32012-10-04 02:29:46 +00002409 return true;
2410}
2411
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002412/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002413/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002414bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002415 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2416 for (;;) {
2417 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002418 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002419 return true;
2420
2421 getParser().getStreamer().EmitValue(Value, Size);
2422
2423 if (getLexer().is(AsmToken::EndOfStatement))
2424 break;
2425
2426 // FIXME: Improve diagnostic.
2427 if (getLexer().isNot(AsmToken::Comma))
2428 return Error(L, "unexpected token in directive");
2429 Parser.Lex();
2430 }
2431 }
2432
2433 Parser.Lex();
2434 return false;
2435}
2436
Vladimir Medic4c299852013-11-06 11:27:05 +00002437/// parseDirectiveGpWord
2438/// ::= .gpword local_sym
2439bool MipsAsmParser::parseDirectiveGpWord() {
2440 const MCExpr *Value;
2441 // EmitGPRel32Value requires an expression, so we are using base class
2442 // method to evaluate the expression.
2443 if (getParser().parseExpression(Value))
2444 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002445 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002446
Vladimir Medice10c1122013-11-13 13:18:04 +00002447 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002448 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002449 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002450 return false;
2451}
2452
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002453/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002454/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002455bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002456 const MCExpr *Value;
2457 // EmitGPRel64Value requires an expression, so we are using base class
2458 // method to evaluate the expression.
2459 if (getParser().parseExpression(Value))
2460 return true;
2461 getParser().getStreamer().EmitGPRel64Value(Value);
2462
2463 if (getLexer().isNot(AsmToken::EndOfStatement))
2464 return Error(getLexer().getLoc(), "unexpected token in directive");
2465 Parser.Lex(); // Eat EndOfStatement token.
2466 return false;
2467}
2468
Jack Carter0cd3c192014-01-06 23:27:31 +00002469bool MipsAsmParser::parseDirectiveOption() {
2470 // Get the option token.
2471 AsmToken Tok = Parser.getTok();
2472 // At the moment only identifiers are supported.
2473 if (Tok.isNot(AsmToken::Identifier)) {
2474 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2475 Parser.eatToEndOfStatement();
2476 return false;
2477 }
2478
2479 StringRef Option = Tok.getIdentifier();
2480
2481 if (Option == "pic0") {
2482 getTargetStreamer().emitDirectiveOptionPic0();
2483 Parser.Lex();
2484 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2485 Error(Parser.getTok().getLoc(),
2486 "unexpected token in .option pic0 directive");
2487 Parser.eatToEndOfStatement();
2488 }
2489 return false;
2490 }
2491
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002492 if (Option == "pic2") {
2493 getTargetStreamer().emitDirectiveOptionPic2();
2494 Parser.Lex();
2495 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2496 Error(Parser.getTok().getLoc(),
2497 "unexpected token in .option pic2 directive");
2498 Parser.eatToEndOfStatement();
2499 }
2500 return false;
2501 }
2502
Jack Carter0cd3c192014-01-06 23:27:31 +00002503 // Unknown option.
2504 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2505 Parser.eatToEndOfStatement();
2506 return false;
2507}
2508
Jack Carter0b744b32012-10-04 02:29:46 +00002509bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002510 StringRef IDVal = DirectiveID.getString();
2511
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002512 if (IDVal == ".dword") {
2513 parseDataDirective(8, DirectiveID.getLoc());
2514 return false;
2515 }
2516
Jack Carterd0bd6422013-04-18 00:41:53 +00002517 if (IDVal == ".ent") {
2518 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002519 Parser.Lex();
2520 return false;
2521 }
2522
Jack Carter07c818d2013-01-25 01:31:34 +00002523 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002524 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002525 Parser.Lex();
2526 return false;
2527 }
2528
Jack Carter07c818d2013-01-25 01:31:34 +00002529 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002530 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002531 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002532 return false;
2533 }
2534
Jack Carter07c818d2013-01-25 01:31:34 +00002535 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002536 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002537 }
2538
Jack Carter07c818d2013-01-25 01:31:34 +00002539 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002540 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002541 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002542 return false;
2543 }
2544
Jack Carter07c818d2013-01-25 01:31:34 +00002545 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002546 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002547 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002548 return false;
2549 }
2550
Jack Carter07c818d2013-01-25 01:31:34 +00002551 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002552 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002553 return false;
2554 }
2555
Rafael Espindolab59fb732014-03-28 18:50:26 +00002556 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002557 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002558 return false;
2559 }
2560
Jack Carter07c818d2013-01-25 01:31:34 +00002561 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002562 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002563 return false;
2564 }
2565
Jack Carter0cd3c192014-01-06 23:27:31 +00002566 if (IDVal == ".option")
2567 return parseDirectiveOption();
2568
2569 if (IDVal == ".abicalls") {
2570 getTargetStreamer().emitDirectiveAbiCalls();
2571 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2572 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2573 // Clear line
2574 Parser.eatToEndOfStatement();
2575 }
2576 return false;
2577 }
2578
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002579 if (IDVal == ".cpsetup")
2580 return parseDirectiveCPSetup();
2581
Rafael Espindola870c4e92012-01-11 03:56:41 +00002582 return true;
2583}
2584
Rafael Espindola870c4e92012-01-11 03:56:41 +00002585extern "C" void LLVMInitializeMipsAsmParser() {
2586 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2587 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2588 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2589 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2590}
Jack Carterb4dbc172012-09-05 23:34:03 +00002591
2592#define GET_REGISTER_MATCHER
2593#define GET_MATCHER_IMPLEMENTATION
2594#include "MipsGenAsmMatcher.inc"