blob: d65ae11c03e72c09aaffbd6d935e21538f0c19b7 [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
NAKAMURA Takumibd524ef2014-04-15 14:06:27 +00001561 delete &Operand;
1562
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001563 return (RegNo == (unsigned)-1);
1564 }
1565
1566 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001567 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001568}
1569
Jack Carterb5cf5902013-04-17 00:18:04 +00001570bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001571 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001572 bool Result = true;
1573
1574 while (getLexer().getKind() == AsmToken::LParen)
1575 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001576
Jack Carterd0bd6422013-04-18 00:41:53 +00001577 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001578 default:
1579 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001580 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001581 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001582 case AsmToken::Integer:
1583 case AsmToken::Minus:
1584 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001585 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001586 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001587 else
1588 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001589 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001590 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001591 break;
Jack Carter873c7242013-01-12 01:03:14 +00001592 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001593 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001594 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001595 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001596}
1597
Jack Carterb4dbc172012-09-05 23:34:03 +00001598MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Vladimir Medic4c299852013-11-06 11:27:05 +00001599 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001600 DEBUG(dbgs() << "parseMemOperand\n");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001601 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001602 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001603 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001604 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001605 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001606 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001607
Jack Carterb5cf5902013-04-17 00:18:04 +00001608 if (getLexer().getKind() == AsmToken::LParen) {
1609 Parser.Lex();
1610 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001611 }
1612
Jack Carterb5cf5902013-04-17 00:18:04 +00001613 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001614 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001615 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001616
Jack Carterd0bd6422013-04-18 00:41:53 +00001617 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001618 if (Tok.isNot(AsmToken::LParen)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001619 MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
Jack Carterb5cf5902013-04-17 00:18:04 +00001620 if (Mnemonic->getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001621 SMLoc E =
1622 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001623 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001624 return MatchOperand_Success;
1625 }
1626 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001627 SMLoc E =
1628 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001629
Jack Carterd0bd6422013-04-18 00:41:53 +00001630 // Zero register assumed, add a memory operand with ZERO as its base.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631 MipsOperand *Base = MipsOperand::CreateGPRReg(
1632 0, getContext().getRegisterInfo(), S, E, *this);
1633 Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001634 return MatchOperand_Success;
1635 }
1636 Error(Parser.getTok().getLoc(), "'(' expected");
1637 return MatchOperand_ParseFail;
1638 }
1639
Jack Carterd0bd6422013-04-18 00:41:53 +00001640 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001641 }
1642
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001643 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001644 if (Res != MatchOperand_Success)
1645 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001646
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001647 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001648 Error(Parser.getTok().getLoc(), "')' expected");
1649 return MatchOperand_ParseFail;
1650 }
1651
Jack Carter873c7242013-01-12 01:03:14 +00001652 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1653
Jack Carterd0bd6422013-04-18 00:41:53 +00001654 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001655
1656 if (IdVal == 0)
1657 IdVal = MCConstantExpr::Create(0, getContext());
1658
Jack Carterd0bd6422013-04-18 00:41:53 +00001659 // Replace the register operand with the memory operand.
Vladimir Medic4c299852013-11-06 11:27:05 +00001660 MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
Jack Carterd0bd6422013-04-18 00:41:53 +00001661 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001662 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001663 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001664 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1665 int64_t Imm;
1666 if (IdVal->EvaluateAsAbsolute(Imm))
1667 IdVal = MCConstantExpr::Create(Imm, getContext());
1668 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1669 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1670 getContext());
1671 }
1672
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001673 Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001674 return MatchOperand_Success;
1675}
1676
Daniel Sanderse34a1202014-03-31 18:51:43 +00001677bool MipsAsmParser::searchSymbolAlias(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001678 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001679
Jack Carterd76b2372013-03-21 21:44:16 +00001680 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1681 if (Sym) {
1682 SMLoc S = Parser.getTok().getLoc();
1683 const MCExpr *Expr;
1684 if (Sym->isVariable())
1685 Expr = Sym->getVariableValue();
1686 else
1687 return false;
1688 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001689 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001690 const StringRef DefSymbol = Ref->getSymbol().getName();
1691 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001692 OperandMatchResultTy ResTy =
1693 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001694 if (ResTy == MatchOperand_Success) {
1695 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001696 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001697 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001698 llvm_unreachable("Should never ParseFail");
1699 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001700 }
1701 } else if (Expr->getKind() == MCExpr::Constant) {
1702 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001703 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
1704 MipsOperand *op =
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001705 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this);
Jack Carterd76b2372013-03-21 21:44:16 +00001706 Operands.push_back(op);
1707 return true;
1708 }
1709 }
1710 return false;
1711}
Jack Carterd0bd6422013-04-18 00:41:53 +00001712
Jack Carter873c7242013-01-12 01:03:14 +00001713MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001714MipsAsmParser::MatchAnyRegisterNameWithoutDollar(
1715 SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
1716 SMLoc S) {
1717 int Index = matchCPURegisterName(Identifier);
1718 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001719 Operands.push_back(MipsOperand::CreateGPRReg(
1720 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1721 return MatchOperand_Success;
1722 }
1723
1724 Index = matchFPURegisterName(Identifier);
1725 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001726 Operands.push_back(MipsOperand::CreateFGRReg(
1727 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1728 return MatchOperand_Success;
1729 }
1730
1731 Index = matchFCCRegisterName(Identifier);
1732 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001733 Operands.push_back(MipsOperand::CreateFCCReg(
1734 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1735 return MatchOperand_Success;
1736 }
1737
1738 Index = matchACRegisterName(Identifier);
1739 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001740 Operands.push_back(MipsOperand::CreateACCReg(
1741 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1742 return MatchOperand_Success;
1743 }
1744
1745 Index = matchMSA128RegisterName(Identifier);
1746 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001747 Operands.push_back(MipsOperand::CreateMSA128Reg(
1748 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1749 return MatchOperand_Success;
1750 }
1751
1752 Index = matchMSA128CtrlRegisterName(Identifier);
1753 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001754 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1755 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1756 return MatchOperand_Success;
1757 }
1758
1759 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001760}
1761
1762MipsAsmParser::OperandMatchResultTy
Daniel Sanders21bce302014-04-01 12:35:23 +00001763MipsAsmParser::MatchAnyRegisterWithoutDollar(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001764 SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001765 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001766
1767 if (Token.is(AsmToken::Identifier)) {
1768 DEBUG(dbgs() << ".. identifier\n");
1769 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001770 OperandMatchResultTy ResTy =
1771 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001772 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001773 } else if (Token.is(AsmToken::Integer)) {
1774 DEBUG(dbgs() << ".. integer\n");
1775 Operands.push_back(MipsOperand::CreateNumericReg(
1776 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1777 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001778 return MatchOperand_Success;
1779 }
1780
1781 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1782
1783 return MatchOperand_NoMatch;
1784}
1785
1786MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
1787 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1788 DEBUG(dbgs() << "ParseAnyRegister\n");
1789
1790 auto Token = Parser.getTok();
1791
1792 SMLoc S = Token.getLoc();
1793
1794 if (Token.isNot(AsmToken::Dollar)) {
1795 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1796 if (Token.is(AsmToken::Identifier)) {
1797 if (searchSymbolAlias(Operands))
1798 return MatchOperand_Success;
1799 }
1800 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1801 return MatchOperand_NoMatch;
1802 }
1803 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001804
Daniel Sanders21bce302014-04-01 12:35:23 +00001805 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001806 if (ResTy == MatchOperand_Success) {
1807 Parser.Lex(); // $
1808 Parser.Lex(); // identifier
1809 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001810 return ResTy;
1811}
1812
1813MipsAsmParser::OperandMatchResultTy
1814MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1815 switch (getLexer().getKind()) {
1816 default:
1817 return MatchOperand_NoMatch;
1818 case AsmToken::LParen:
1819 case AsmToken::Minus:
1820 case AsmToken::Plus:
1821 case AsmToken::Integer:
1822 case AsmToken::String:
1823 break;
1824 }
1825
1826 const MCExpr *IdVal;
1827 SMLoc S = Parser.getTok().getLoc();
1828 if (getParser().parseExpression(IdVal))
1829 return MatchOperand_ParseFail;
1830
1831 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1832 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1833 return MatchOperand_Success;
1834}
1835
1836MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
1837 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1838 DEBUG(dbgs() << "ParseJumpTarget\n");
1839
1840 SMLoc S = getLexer().getLoc();
1841
1842 // Integers and expressions are acceptable
1843 OperandMatchResultTy ResTy = ParseImm(Operands);
1844 if (ResTy != MatchOperand_NoMatch)
1845 return ResTy;
1846
Daniel Sanders315386c2014-04-01 10:40:14 +00001847 // Registers are a valid target and have priority over symbols.
1848 ResTy = ParseAnyRegister(Operands);
1849 if (ResTy != MatchOperand_NoMatch)
1850 return ResTy;
1851
Daniel Sandersffd84362014-04-01 10:41:48 +00001852 const MCExpr *Expr = nullptr;
1853 if (Parser.parseExpression(Expr)) {
1854 // We have no way of knowing if a symbol was consumed so we must ParseFail
1855 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001856 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001857 Operands.push_back(
1858 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001859 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001860}
1861
Vladimir Medic2b953d02013-10-01 09:48:56 +00001862MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001863MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001864 const MCExpr *IdVal;
1865 // If the first token is '$' we may have register operand.
1866 if (Parser.getTok().is(AsmToken::Dollar))
1867 return MatchOperand_NoMatch;
1868 SMLoc S = Parser.getTok().getLoc();
1869 if (getParser().parseExpression(IdVal))
1870 return MatchOperand_ParseFail;
1871 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001872 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001873 int64_t Val = MCE->getValue();
1874 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1875 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001876 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001877 return MatchOperand_Success;
1878}
1879
Matheus Almeida779c5932013-11-18 12:32:49 +00001880MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001881MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001882 switch (getLexer().getKind()) {
1883 default:
1884 return MatchOperand_NoMatch;
1885 case AsmToken::LParen:
1886 case AsmToken::Plus:
1887 case AsmToken::Minus:
1888 case AsmToken::Integer:
1889 break;
1890 }
1891
1892 const MCExpr *Expr;
1893 SMLoc S = Parser.getTok().getLoc();
1894
1895 if (getParser().parseExpression(Expr))
1896 return MatchOperand_ParseFail;
1897
1898 int64_t Val;
1899 if (!Expr->EvaluateAsAbsolute(Val)) {
1900 Error(S, "expected immediate value");
1901 return MatchOperand_ParseFail;
1902 }
1903
1904 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1905 // and because the CPU always adds one to the immediate field, the allowed
1906 // range becomes 1..4. We'll only check the range here and will deal
1907 // with the addition/subtraction when actually decoding/encoding
1908 // the instruction.
1909 if (Val < 1 || Val > 4) {
1910 Error(S, "immediate not in range (1..4)");
1911 return MatchOperand_ParseFail;
1912 }
1913
Jack Carter3b2c96e2014-01-22 23:31:38 +00001914 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001915 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00001916 return MatchOperand_Success;
1917}
1918
Jack Carterdc1e35d2012-09-06 20:00:02 +00001919MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1920
Vladimir Medic4c299852013-11-06 11:27:05 +00001921 MCSymbolRefExpr::VariantKind VK =
1922 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1923 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1924 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1925 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1926 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1927 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1928 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1929 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1930 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1931 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1932 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1933 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1934 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1935 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1936 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1937 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1938 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1939 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00001940 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
1941 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
1942 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
1943 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
1944 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
1945 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Vladimir Medic4c299852013-11-06 11:27:05 +00001946 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001947
Daniel Sandersa567da52014-03-31 15:15:02 +00001948 assert (VK != MCSymbolRefExpr::VK_None);
1949
Jack Carterdc1e35d2012-09-06 20:00:02 +00001950 return VK;
1951}
Jack Cartera63b16a2012-09-07 00:23:42 +00001952
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001953/// Sometimes (i.e. load/stores) the operand may be followed immediately by
1954/// either this.
1955/// ::= '(', register, ')'
1956/// handle it before we iterate so we don't get tripped up by the lack of
1957/// a comma.
1958bool MipsAsmParser::ParseParenSuffix(
1959 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1960 if (getLexer().is(AsmToken::LParen)) {
1961 Operands.push_back(
1962 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
1963 Parser.Lex();
1964 if (ParseOperand(Operands, Name)) {
1965 SMLoc Loc = getLexer().getLoc();
1966 Parser.eatToEndOfStatement();
1967 return Error(Loc, "unexpected token in argument list");
1968 }
1969 if (Parser.getTok().isNot(AsmToken::RParen)) {
1970 SMLoc Loc = getLexer().getLoc();
1971 Parser.eatToEndOfStatement();
1972 return Error(Loc, "unexpected token, expected ')'");
1973 }
1974 Operands.push_back(
1975 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
1976 Parser.Lex();
1977 }
1978 return false;
1979}
1980
1981/// Sometimes (i.e. in MSA) the operand may be followed immediately by
1982/// either one of these.
1983/// ::= '[', register, ']'
1984/// ::= '[', integer, ']'
1985/// handle it before we iterate so we don't get tripped up by the lack of
1986/// a comma.
1987bool MipsAsmParser::ParseBracketSuffix(
1988 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1989 if (getLexer().is(AsmToken::LBrac)) {
1990 Operands.push_back(
1991 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
1992 Parser.Lex();
1993 if (ParseOperand(Operands, Name)) {
1994 SMLoc Loc = getLexer().getLoc();
1995 Parser.eatToEndOfStatement();
1996 return Error(Loc, "unexpected token in argument list");
1997 }
1998 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1999 SMLoc Loc = getLexer().getLoc();
2000 Parser.eatToEndOfStatement();
2001 return Error(Loc, "unexpected token, expected ']'");
2002 }
2003 Operands.push_back(
2004 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2005 Parser.Lex();
2006 }
2007 return false;
2008}
2009
Vladimir Medic4c299852013-11-06 11:27:05 +00002010bool MipsAsmParser::ParseInstruction(
2011 ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
2012 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002013 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002014 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002015 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002016 Parser.eatToEndOfStatement();
2017 return Error(NameLoc, "Unknown instruction");
2018 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002019 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002020 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002021
2022 // Read the remaining operands.
2023 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2024 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002025 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002026 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002027 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002028 return Error(Loc, "unexpected token in argument list");
2029 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002030 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2031 return true;
2032 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002033
Jack Carterd0bd6422013-04-18 00:41:53 +00002034 while (getLexer().is(AsmToken::Comma)) {
2035 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002036 // Parse and remember the operand.
2037 if (ParseOperand(Operands, Name)) {
2038 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002039 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002040 return Error(Loc, "unexpected token in argument list");
2041 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002042 // Parse bracket and parenthesis suffixes before we iterate
2043 if (getLexer().is(AsmToken::LBrac)) {
2044 if (ParseBracketSuffix(Name, Operands))
2045 return true;
2046 } else if (getLexer().is(AsmToken::LParen) &&
2047 ParseParenSuffix(Name, Operands))
2048 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002049 }
2050 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002051 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2052 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002053 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002054 return Error(Loc, "unexpected token in argument list");
2055 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002056 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002057 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002058}
2059
Jack Carter0b744b32012-10-04 02:29:46 +00002060bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002061 SMLoc Loc = getLexer().getLoc();
2062 Parser.eatToEndOfStatement();
2063 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002064}
2065
2066bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002067 // Line should look like: ".set noat".
2068 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002069 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002070 // eat noat
2071 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002072 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002073 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2074 reportParseError("unexpected token in statement");
2075 return false;
2076 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002077 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002078 return false;
2079}
Jack Carterd0bd6422013-04-18 00:41:53 +00002080
Jack Carter0b744b32012-10-04 02:29:46 +00002081bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002082 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002083 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002084 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002085 getParser().Lex();
2086 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002087 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002088 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002089 return false;
2090 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002091 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002092 if (getLexer().isNot(AsmToken::Dollar)) {
2093 reportParseError("unexpected token in statement");
2094 return false;
2095 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002096 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002097 const AsmToken &Reg = Parser.getTok();
2098 if (Reg.is(AsmToken::Identifier)) {
2099 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2100 } else if (Reg.is(AsmToken::Integer)) {
2101 AtRegNo = Reg.getIntVal();
2102 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002103 reportParseError("unexpected token in statement");
2104 return false;
2105 }
Jack Carter1ac53222013-02-20 23:11:17 +00002106
Daniel Sanders71a89d922014-03-25 13:01:06 +00002107 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002108 reportParseError("unexpected token in statement");
2109 return false;
2110 }
2111
2112 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002113 reportParseError("unexpected token in statement");
2114 return false;
2115 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002117
2118 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2119 reportParseError("unexpected token in statement");
2120 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002121 }
2122 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002123 return false;
2124 } else {
2125 reportParseError("unexpected token in statement");
2126 return false;
2127 }
2128}
2129
2130bool MipsAsmParser::parseSetReorderDirective() {
2131 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002132 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002133 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2134 reportParseError("unexpected token in statement");
2135 return false;
2136 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002137 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002138 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002139 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002140 return false;
2141}
2142
2143bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002144 Parser.Lex();
2145 // If this is not the end of the statement, report an error.
2146 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2147 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002148 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002149 }
2150 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002151 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002152 Parser.Lex(); // Consume the EndOfStatement.
2153 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002154}
2155
2156bool MipsAsmParser::parseSetMacroDirective() {
2157 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002158 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002159 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2160 reportParseError("unexpected token in statement");
2161 return false;
2162 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002163 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002164 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002165 return false;
2166}
2167
2168bool MipsAsmParser::parseSetNoMacroDirective() {
2169 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002170 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002171 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2172 reportParseError("`noreorder' must be set before `nomacro'");
2173 return false;
2174 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002175 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002176 reportParseError("`noreorder' must be set before `nomacro'");
2177 return false;
2178 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002179 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002180 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002181 return false;
2182}
Jack Carterd76b2372013-03-21 21:44:16 +00002183
Jack Carter39536722014-01-22 23:08:42 +00002184bool MipsAsmParser::parseSetNoMips16Directive() {
2185 Parser.Lex();
2186 // If this is not the end of the statement, report an error.
2187 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2188 reportParseError("unexpected token in statement");
2189 return false;
2190 }
2191 // For now do nothing.
2192 Parser.Lex(); // Consume the EndOfStatement.
2193 return false;
2194}
2195
Jack Carterd76b2372013-03-21 21:44:16 +00002196bool MipsAsmParser::parseSetAssignment() {
2197 StringRef Name;
2198 const MCExpr *Value;
2199
2200 if (Parser.parseIdentifier(Name))
2201 reportParseError("expected identifier after .set");
2202
2203 if (getLexer().isNot(AsmToken::Comma))
2204 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002205 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002206
Jack Carter3b2c96e2014-01-22 23:31:38 +00002207 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002208 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002209
Jack Carterd0bd6422013-04-18 00:41:53 +00002210 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002211 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002212 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002213 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002214 Sym = getContext().GetOrCreateSymbol(Name);
2215 Sym->setVariableValue(Value);
2216
2217 return false;
2218}
Jack Carterd0bd6422013-04-18 00:41:53 +00002219
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002220bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2221 Parser.Lex();
2222 if (getLexer().isNot(AsmToken::EndOfStatement))
2223 return reportParseError("unexpected token in .set directive");
2224
2225 switch(Feature) {
2226 default: llvm_unreachable("Unimplemented feature");
2227 case Mips::FeatureDSP:
2228 setFeatureBits(Mips::FeatureDSP, "dsp");
2229 getTargetStreamer().emitDirectiveSetDsp();
2230 break;
2231 case Mips::FeatureMicroMips:
2232 getTargetStreamer().emitDirectiveSetMicroMips();
2233 break;
2234 case Mips::FeatureMips16:
2235 getTargetStreamer().emitDirectiveSetMips16();
2236 break;
2237 case Mips::FeatureMips32r2:
2238 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2239 getTargetStreamer().emitDirectiveSetMips32R2();
2240 break;
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002241 case Mips::FeatureMips64:
2242 setFeatureBits(Mips::FeatureMips64, "mips64");
2243 getTargetStreamer().emitDirectiveSetMips64();
2244 break;
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002245 case Mips::FeatureMips64r2:
2246 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2247 getTargetStreamer().emitDirectiveSetMips64R2();
2248 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002249 }
2250 return false;
2251}
2252
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002253bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2254 if (!getLexer().is(AsmToken::Dollar))
2255 return false;
2256
2257 Parser.Lex();
2258
2259 const AsmToken &Reg = Parser.getTok();
2260 if (Reg.is(AsmToken::Identifier)) {
2261 RegNum = matchCPURegisterName(Reg.getIdentifier());
2262 } else if (Reg.is(AsmToken::Integer)) {
2263 RegNum = Reg.getIntVal();
2264 } else {
2265 return false;
2266 }
2267
2268 Parser.Lex();
2269 return true;
2270}
2271
2272bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2273 if (getLexer().isNot(AsmToken::Comma)) {
2274 SMLoc Loc = getLexer().getLoc();
2275 Parser.eatToEndOfStatement();
2276 return Error(Loc, ErrorStr);
2277 }
2278
2279 Parser.Lex(); // Eat the comma.
2280 return true;
2281}
2282
2283bool MipsAsmParser::parseDirectiveCPSetup() {
2284 unsigned FuncReg;
2285 unsigned Save;
2286 bool SaveIsReg = true;
2287
2288 if (!parseRegister(FuncReg))
2289 return reportParseError("expected register containing function address");
2290 FuncReg = getGPR(FuncReg);
2291
2292 if (!eatComma("expected comma parsing directive"))
2293 return true;
2294
2295 if (!parseRegister(Save)) {
2296 const AsmToken &Tok = Parser.getTok();
2297 if (Tok.is(AsmToken::Integer)) {
2298 Save = Tok.getIntVal();
2299 SaveIsReg = false;
2300 Parser.Lex();
2301 } else
2302 return reportParseError("expected save register or stack offset");
2303 } else
2304 Save = getGPR(Save);
2305
2306 if (!eatComma("expected comma parsing directive"))
2307 return true;
2308
2309 StringRef Name;
2310 if (Parser.parseIdentifier(Name))
2311 reportParseError("expected identifier");
2312 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
2313 unsigned GPReg = getGPR(matchCPURegisterName("gp"));
2314
2315 // FIXME: The code below this point should be in the TargetStreamers.
2316 // Only N32 and N64 emit anything for .cpsetup
2317 // FIXME: We should only emit something for PIC mode too.
2318 if (!isN32() && !isN64())
2319 return false;
2320
2321 MCStreamer &TS = getStreamer();
2322 MCInst Inst;
2323 // Either store the old $gp in a register or on the stack
2324 if (SaveIsReg) {
2325 // move $save, $gpreg
2326 Inst.setOpcode(Mips::DADDu);
2327 Inst.addOperand(MCOperand::CreateReg(Save));
2328 Inst.addOperand(MCOperand::CreateReg(GPReg));
2329 Inst.addOperand(MCOperand::CreateReg(getGPR(0)));
2330 } else {
2331 // sd $gpreg, offset($sp)
2332 Inst.setOpcode(Mips::SD);
2333 Inst.addOperand(MCOperand::CreateReg(GPReg));
2334 Inst.addOperand(MCOperand::CreateReg(getGPR(matchCPURegisterName("sp"))));
2335 Inst.addOperand(MCOperand::CreateImm(Save));
2336 }
2337 TS.EmitInstruction(Inst, STI);
2338 Inst.clear();
2339
2340 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2341 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI,
2342 getContext());
2343 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2344 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO,
2345 getContext());
2346 // lui $gp, %hi(%neg(%gp_rel(funcSym)))
2347 Inst.setOpcode(Mips::LUi);
2348 Inst.addOperand(MCOperand::CreateReg(GPReg));
2349 Inst.addOperand(MCOperand::CreateExpr(HiExpr));
2350 TS.EmitInstruction(Inst, STI);
2351 Inst.clear();
2352
2353 // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
2354 Inst.setOpcode(Mips::ADDiu);
2355 Inst.addOperand(MCOperand::CreateReg(GPReg));
2356 Inst.addOperand(MCOperand::CreateReg(GPReg));
2357 Inst.addOperand(MCOperand::CreateExpr(LoExpr));
2358 TS.EmitInstruction(Inst, STI);
2359 Inst.clear();
2360
2361 // daddu $gp, $gp, $funcreg
2362 Inst.setOpcode(Mips::DADDu);
2363 Inst.addOperand(MCOperand::CreateReg(GPReg));
2364 Inst.addOperand(MCOperand::CreateReg(GPReg));
2365 Inst.addOperand(MCOperand::CreateReg(FuncReg));
2366 TS.EmitInstruction(Inst, STI);
2367 return false;
2368}
2369
Jack Carter0b744b32012-10-04 02:29:46 +00002370bool MipsAsmParser::parseDirectiveSet() {
2371
Jack Carterd0bd6422013-04-18 00:41:53 +00002372 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002373 const AsmToken &Tok = Parser.getTok();
2374
2375 if (Tok.getString() == "noat") {
2376 return parseSetNoAtDirective();
2377 } else if (Tok.getString() == "at") {
2378 return parseSetAtDirective();
2379 } else if (Tok.getString() == "reorder") {
2380 return parseSetReorderDirective();
2381 } else if (Tok.getString() == "noreorder") {
2382 return parseSetNoReorderDirective();
2383 } else if (Tok.getString() == "macro") {
2384 return parseSetMacroDirective();
2385 } else if (Tok.getString() == "nomacro") {
2386 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002387 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002388 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002389 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002390 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002391 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002392 getTargetStreamer().emitDirectiveSetNoMicroMips();
2393 Parser.eatToEndOfStatement();
2394 return false;
2395 } else if (Tok.getString() == "micromips") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002396 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002397 } else if (Tok.getString() == "mips32r2") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002398 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002399 } else if (Tok.getString() == "mips64") {
2400 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002401 } else if (Tok.getString() == "mips64r2") {
2402 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002403 } else if (Tok.getString() == "dsp") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002404 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002405 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002406 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002407 parseSetAssignment();
2408 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002409 }
Jack Carter07c818d2013-01-25 01:31:34 +00002410
Jack Carter0b744b32012-10-04 02:29:46 +00002411 return true;
2412}
2413
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002414/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002415/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002416bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002417 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2418 for (;;) {
2419 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002420 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002421 return true;
2422
2423 getParser().getStreamer().EmitValue(Value, Size);
2424
2425 if (getLexer().is(AsmToken::EndOfStatement))
2426 break;
2427
2428 // FIXME: Improve diagnostic.
2429 if (getLexer().isNot(AsmToken::Comma))
2430 return Error(L, "unexpected token in directive");
2431 Parser.Lex();
2432 }
2433 }
2434
2435 Parser.Lex();
2436 return false;
2437}
2438
Vladimir Medic4c299852013-11-06 11:27:05 +00002439/// parseDirectiveGpWord
2440/// ::= .gpword local_sym
2441bool MipsAsmParser::parseDirectiveGpWord() {
2442 const MCExpr *Value;
2443 // EmitGPRel32Value requires an expression, so we are using base class
2444 // method to evaluate the expression.
2445 if (getParser().parseExpression(Value))
2446 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002447 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002448
Vladimir Medice10c1122013-11-13 13:18:04 +00002449 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002450 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002451 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002452 return false;
2453}
2454
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002455/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002456/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002457bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002458 const MCExpr *Value;
2459 // EmitGPRel64Value requires an expression, so we are using base class
2460 // method to evaluate the expression.
2461 if (getParser().parseExpression(Value))
2462 return true;
2463 getParser().getStreamer().EmitGPRel64Value(Value);
2464
2465 if (getLexer().isNot(AsmToken::EndOfStatement))
2466 return Error(getLexer().getLoc(), "unexpected token in directive");
2467 Parser.Lex(); // Eat EndOfStatement token.
2468 return false;
2469}
2470
Jack Carter0cd3c192014-01-06 23:27:31 +00002471bool MipsAsmParser::parseDirectiveOption() {
2472 // Get the option token.
2473 AsmToken Tok = Parser.getTok();
2474 // At the moment only identifiers are supported.
2475 if (Tok.isNot(AsmToken::Identifier)) {
2476 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2477 Parser.eatToEndOfStatement();
2478 return false;
2479 }
2480
2481 StringRef Option = Tok.getIdentifier();
2482
2483 if (Option == "pic0") {
2484 getTargetStreamer().emitDirectiveOptionPic0();
2485 Parser.Lex();
2486 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2487 Error(Parser.getTok().getLoc(),
2488 "unexpected token in .option pic0 directive");
2489 Parser.eatToEndOfStatement();
2490 }
2491 return false;
2492 }
2493
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002494 if (Option == "pic2") {
2495 getTargetStreamer().emitDirectiveOptionPic2();
2496 Parser.Lex();
2497 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2498 Error(Parser.getTok().getLoc(),
2499 "unexpected token in .option pic2 directive");
2500 Parser.eatToEndOfStatement();
2501 }
2502 return false;
2503 }
2504
Jack Carter0cd3c192014-01-06 23:27:31 +00002505 // Unknown option.
2506 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2507 Parser.eatToEndOfStatement();
2508 return false;
2509}
2510
Jack Carter0b744b32012-10-04 02:29:46 +00002511bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002512 StringRef IDVal = DirectiveID.getString();
2513
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002514 if (IDVal == ".dword") {
2515 parseDataDirective(8, DirectiveID.getLoc());
2516 return false;
2517 }
2518
Jack Carterd0bd6422013-04-18 00:41:53 +00002519 if (IDVal == ".ent") {
2520 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002521 Parser.Lex();
2522 return false;
2523 }
2524
Jack Carter07c818d2013-01-25 01:31:34 +00002525 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002526 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002527 Parser.Lex();
2528 return false;
2529 }
2530
Jack Carter07c818d2013-01-25 01:31:34 +00002531 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002532 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002533 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002534 return false;
2535 }
2536
Jack Carter07c818d2013-01-25 01:31:34 +00002537 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002538 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002539 }
2540
Jack Carter07c818d2013-01-25 01:31:34 +00002541 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002542 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002543 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002544 return false;
2545 }
2546
Jack Carter07c818d2013-01-25 01:31:34 +00002547 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002548 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002549 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002550 return false;
2551 }
2552
Jack Carter07c818d2013-01-25 01:31:34 +00002553 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002554 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002555 return false;
2556 }
2557
Rafael Espindolab59fb732014-03-28 18:50:26 +00002558 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002559 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002560 return false;
2561 }
2562
Jack Carter07c818d2013-01-25 01:31:34 +00002563 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002564 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002565 return false;
2566 }
2567
Jack Carter0cd3c192014-01-06 23:27:31 +00002568 if (IDVal == ".option")
2569 return parseDirectiveOption();
2570
2571 if (IDVal == ".abicalls") {
2572 getTargetStreamer().emitDirectiveAbiCalls();
2573 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2574 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2575 // Clear line
2576 Parser.eatToEndOfStatement();
2577 }
2578 return false;
2579 }
2580
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002581 if (IDVal == ".cpsetup")
2582 return parseDirectiveCPSetup();
2583
Rafael Espindola870c4e92012-01-11 03:56:41 +00002584 return true;
2585}
2586
Rafael Espindola870c4e92012-01-11 03:56:41 +00002587extern "C" void LLVMInitializeMipsAsmParser() {
2588 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2589 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2590 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2591 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2592}
Jack Carterb4dbc172012-09-05 23:34:03 +00002593
2594#define GET_REGISTER_MATCHER
2595#define GET_MATCHER_IMPLEMENTATION
2596#include "MipsGenAsmMatcher.inc"