blob: 74b15bf815e542cdb722926e744c5458693686a3 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000019#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000020#include "llvm/MC/MCParser/MCAsmLexer.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000025#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000026#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000027#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000028#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000029
30using namespace llvm;
31
Chandler Carruthe96dd892014-04-21 22:55:11 +000032#define DEBUG_TYPE "mips-asm-parser"
33
Joey Gouly0e76fa72013-09-12 10:28:05 +000034namespace llvm {
35class MCInstrInfo;
36}
37
Rafael Espindola870c4e92012-01-11 03:56:41 +000038namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000039class MipsAssemblerOptions {
40public:
Vladimir Medic4c299852013-11-06 11:27:05 +000041 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000042
Vladimir Medic4c299852013-11-06 11:27:05 +000043 unsigned getATRegNum() { return aTReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000044 bool setATReg(unsigned Reg);
45
Vladimir Medic4c299852013-11-06 11:27:05 +000046 bool isReorder() { return reorder; }
47 void setReorder() { reorder = true; }
48 void setNoreorder() { reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000049
Vladimir Medic4c299852013-11-06 11:27:05 +000050 bool isMacro() { return macro; }
51 void setMacro() { macro = true; }
52 void setNomacro() { macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000053
54private:
55 unsigned aTReg;
56 bool reorder;
57 bool macro;
58};
59}
60
61namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000062class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000063 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000064 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000065 return static_cast<MipsTargetStreamer &>(TS);
66 }
67
Jack Carterb4dbc172012-09-05 23:34:03 +000068 MCSubtargetInfo &STI;
69 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000070 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000071
Akira Hatanaka7605630c2012-08-17 20:16:42 +000072#define GET_ASSEMBLER_HEADER
73#include "MipsGenAsmMatcher.inc"
74
Chad Rosier49963552012-10-13 00:26:04 +000075 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +000076 OperandVector &Operands, MCStreamer &Out,
77 unsigned &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +000078 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000079
Daniel Sandersb50ccf82014-04-01 10:35:28 +000080 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +000081 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000082
David Blaikie960ea3f2014-06-08 16:18:35 +000083 bool ParseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +000084
David Blaikie960ea3f2014-06-08 16:18:35 +000085 bool ParseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +000086
David Blaikie960ea3f2014-06-08 16:18:35 +000087 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
88 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000089
Craig Topper56c590a2014-04-29 07:58:02 +000090 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000091
David Blaikie960ea3f2014-06-08 16:18:35 +000092 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000093
94 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +000095 MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
96 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000097
Jack Carter873c7242013-01-12 01:03:14 +000098 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +000099 MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000100
David Blaikie960ea3f2014-06-08 16:18:35 +0000101 MipsAsmParser::OperandMatchResultTy ParseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000102
David Blaikie960ea3f2014-06-08 16:18:35 +0000103 MipsAsmParser::OperandMatchResultTy ParseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000104
David Blaikie960ea3f2014-06-08 16:18:35 +0000105 MipsAsmParser::OperandMatchResultTy ParseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000106
David Blaikie960ea3f2014-06-08 16:18:35 +0000107 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000108
David Blaikie960ea3f2014-06-08 16:18:35 +0000109 MipsAsmParser::OperandMatchResultTy ParseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000110
David Blaikie960ea3f2014-06-08 16:18:35 +0000111 bool searchSymbolAlias(OperandVector &Operands);
112
113 bool ParseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000114
Jack Carter30a59822012-10-04 04:03:53 +0000115 bool needsExpansion(MCInst &Inst);
116
117 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000118 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000119 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000120 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000121 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
122 SmallVectorImpl<MCInst> &Instructions);
123 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
124 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000125 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000126 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
127 bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000128 bool reportParseError(StringRef ErrorMsg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000129 bool reportParseError(SMLoc Loc, StringRef ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000130
Jack Carterb5cf5902013-04-17 00:18:04 +0000131 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000132 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000133
Vladimir Medic4c299852013-11-06 11:27:05 +0000134 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000135
136 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000137 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000138 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000139 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000140 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000141 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000142 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000143
144 bool parseSetAtDirective();
145 bool parseSetNoAtDirective();
146 bool parseSetMacroDirective();
147 bool parseSetNoMacroDirective();
148 bool parseSetReorderDirective();
149 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000150 bool parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +0000151
Jack Carterd76b2372013-03-21 21:44:16 +0000152 bool parseSetAssignment();
153
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000154 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000155 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000156 bool parseDirectiveGpDWord();
Jack Carter07c818d2013-01-25 01:31:34 +0000157
Jack Carterdc1e35d2012-09-06 20:00:02 +0000158 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000159
Daniel Sanders5e94e682014-03-27 16:42:17 +0000160 bool isGP64() const {
161 return (STI.getFeatureBits() & Mips::FeatureGP64Bit) != 0;
Jack Carterb4dbc172012-09-05 23:34:03 +0000162 }
163
Jack Cartera63b16a2012-09-07 00:23:42 +0000164 bool isFP64() const {
165 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
166 }
167
Daniel Sandersa4b0c742014-03-26 11:39:07 +0000168 bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
Vladimir Medic4c299852013-11-06 11:27:05 +0000169 bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000170
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000171 bool isMicroMips() const {
172 return STI.getFeatureBits() & Mips::FeatureMicroMips;
173 }
174
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000175 bool parseRegister(unsigned &RegNum);
176
177 bool eatComma(StringRef ErrorStr);
178
Jack Carter1ac53222013-02-20 23:11:17 +0000179 int matchCPURegisterName(StringRef Symbol);
180
Jack Carter873c7242013-01-12 01:03:14 +0000181 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000182
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000183 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000184
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000185 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000186
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000187 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000188
Jack Carter5dc8ac92013-09-25 23:50:44 +0000189 int matchMSA128RegisterName(StringRef Name);
190
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000191 int matchMSA128CtrlRegisterName(StringRef Name);
192
Jack Carterd0bd6422013-04-18 00:41:53 +0000193 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000194
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000195 unsigned getGPR(int RegNo);
196
Jack Carter1ac53222013-02-20 23:11:17 +0000197 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000198
199 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000200 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000201
202 // Helper function that checks if the value of a vector index is within the
203 // boundaries of accepted values for each RegisterKind
204 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
205 bool validateMSAIndex(int Val, int RegKind);
206
Vladimir Medic615b26e2014-03-04 09:54:09 +0000207 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
208 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000209 setAvailableFeatures(
210 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000211 }
212 }
213
214 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
215 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000216 setAvailableFeatures(
217 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000218 }
219 }
220
Rafael Espindola870c4e92012-01-11 03:56:41 +0000221public:
Joey Gouly0e76fa72013-09-12 10:28:05 +0000222 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000223 const MCInstrInfo &MII,
224 const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000225 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000226 // Initialize the set of available features.
227 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000228
229 // Assert exactly one ABI was chosen.
230 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
231 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
232 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
233 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000234 }
235
Jack Carterb4dbc172012-09-05 23:34:03 +0000236 MCAsmParser &getParser() const { return Parser; }
237 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000238
239 /// Warn if RegNo is the current assembler temporary.
240 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000241};
242}
243
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000244namespace {
245
246/// MipsOperand - Instances of this class represent a parsed Mips machine
247/// instruction.
248class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000249public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000250 /// Broad categories of register classes
251 /// The exact class is finalized by the render method.
252 enum RegKind {
253 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
254 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
255 /// isFP64())
256 RegKind_FCC = 4, /// FCC
257 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
258 RegKind_MSACtrl = 16, /// MSA control registers
259 RegKind_COP2 = 32, /// COP2
260 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
261 /// context).
262 RegKind_CCR = 128, /// CCR
263 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000264 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000265
266 /// Potentially any (e.g. $1)
267 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
268 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000269 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000270 };
271
272private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000273 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000274 k_Immediate, /// An immediate (possibly involving symbol references)
275 k_Memory, /// Base + Offset Memory Address
276 k_PhysRegister, /// A physical register from the Mips namespace
277 k_RegisterIndex, /// A register index in one or more RegKind.
278 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000279 } Kind;
280
David Blaikie960ea3f2014-06-08 16:18:35 +0000281public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000282 MipsOperand(KindTy K, MipsAsmParser &Parser)
283 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
284
David Blaikie960ea3f2014-06-08 16:18:35 +0000285private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000286 /// For diagnostics, and checking the assembler temporary
287 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000288
Eric Christopher8996c5d2013-03-15 00:42:55 +0000289 struct Token {
290 const char *Data;
291 unsigned Length;
292 };
293
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000294 struct PhysRegOp {
295 unsigned Num; /// Register Number
296 };
297
298 struct RegIdxOp {
299 unsigned Index; /// Index into the register class
300 RegKind Kind; /// Bitfield of the kinds it could possibly be
301 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000302 };
303
304 struct ImmOp {
305 const MCExpr *Val;
306 };
307
308 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000309 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000310 const MCExpr *Off;
311 };
312
Jack Carterb4dbc172012-09-05 23:34:03 +0000313 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000314 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000315 struct PhysRegOp PhysReg;
316 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000317 struct ImmOp Imm;
318 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000319 };
320
321 SMLoc StartLoc, EndLoc;
322
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000323 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000324 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
325 const MCRegisterInfo *RegInfo,
326 SMLoc S, SMLoc E,
327 MipsAsmParser &Parser) {
328 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000329 Op->RegIdx.Index = Index;
330 Op->RegIdx.RegInfo = RegInfo;
331 Op->RegIdx.Kind = RegKind;
332 Op->StartLoc = S;
333 Op->EndLoc = E;
334 return Op;
335 }
336
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000337public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000338 /// Coerce the register to GPR32 and return the real register for the current
339 /// target.
340 unsigned getGPR32Reg() const {
341 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
342 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
343 unsigned ClassID = Mips::GPR32RegClassID;
344 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000345 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000346
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000347 /// Coerce the register to GPR64 and return the real register for the current
348 /// target.
349 unsigned getGPR64Reg() const {
350 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
351 unsigned ClassID = Mips::GPR64RegClassID;
352 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000353 }
354
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000355private:
356 /// Coerce the register to AFGR64 and return the real register for the current
357 /// target.
358 unsigned getAFGR64Reg() const {
359 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
360 if (RegIdx.Index % 2 != 0)
361 AsmParser.Warning(StartLoc, "Float register should be even.");
362 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
363 .getRegister(RegIdx.Index / 2);
364 }
365
366 /// Coerce the register to FGR64 and return the real register for the current
367 /// target.
368 unsigned getFGR64Reg() const {
369 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
370 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
371 .getRegister(RegIdx.Index);
372 }
373
374 /// Coerce the register to FGR32 and return the real register for the current
375 /// target.
376 unsigned getFGR32Reg() const {
377 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
378 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
379 .getRegister(RegIdx.Index);
380 }
381
382 /// Coerce the register to FGRH32 and return the real register for the current
383 /// target.
384 unsigned getFGRH32Reg() const {
385 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
386 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
387 .getRegister(RegIdx.Index);
388 }
389
390 /// Coerce the register to FCC and return the real register for the current
391 /// target.
392 unsigned getFCCReg() const {
393 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
394 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
395 .getRegister(RegIdx.Index);
396 }
397
398 /// Coerce the register to MSA128 and return the real register for the current
399 /// target.
400 unsigned getMSA128Reg() const {
401 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
402 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
403 // identical
404 unsigned ClassID = Mips::MSA128BRegClassID;
405 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
406 }
407
408 /// Coerce the register to MSACtrl and return the real register for the
409 /// current target.
410 unsigned getMSACtrlReg() const {
411 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
412 unsigned ClassID = Mips::MSACtrlRegClassID;
413 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
414 }
415
416 /// Coerce the register to COP2 and return the real register for the
417 /// current target.
418 unsigned getCOP2Reg() const {
419 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
420 unsigned ClassID = Mips::COP2RegClassID;
421 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
422 }
423
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000424 /// Coerce the register to COP3 and return the real register for the
425 /// current target.
426 unsigned getCOP3Reg() const {
427 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
428 unsigned ClassID = Mips::COP3RegClassID;
429 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
430 }
431
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000432 /// Coerce the register to ACC64DSP and return the real register for the
433 /// current target.
434 unsigned getACC64DSPReg() const {
435 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
436 unsigned ClassID = Mips::ACC64DSPRegClassID;
437 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
438 }
439
440 /// Coerce the register to HI32DSP and return the real register for the
441 /// current target.
442 unsigned getHI32DSPReg() const {
443 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
444 unsigned ClassID = Mips::HI32DSPRegClassID;
445 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
446 }
447
448 /// Coerce the register to LO32DSP and return the real register for the
449 /// current target.
450 unsigned getLO32DSPReg() const {
451 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
452 unsigned ClassID = Mips::LO32DSPRegClassID;
453 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
454 }
455
456 /// Coerce the register to CCR and return the real register for the
457 /// current target.
458 unsigned getCCRReg() const {
459 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
460 unsigned ClassID = Mips::CCRRegClassID;
461 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
462 }
463
464 /// Coerce the register to HWRegs and return the real register for the
465 /// current target.
466 unsigned getHWRegsReg() const {
467 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
468 unsigned ClassID = Mips::HWRegsRegClassID;
469 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
470 }
471
472public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000473 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000474 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000475 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000476 Inst.addOperand(MCOperand::CreateImm(0));
477 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
478 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
479 else
480 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000481 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000482
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000483 void addRegOperands(MCInst &Inst, unsigned N) const {
484 llvm_unreachable("Use a custom parser instead");
485 }
486
Daniel Sanders21bce302014-04-01 12:35:23 +0000487 /// Render the operand to an MCInst as a GPR32
488 /// Asserts if the wrong number of operands are requested, or the operand
489 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000490 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
491 assert(N == 1 && "Invalid number of operands!");
492 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
493 }
494
Daniel Sanders21bce302014-04-01 12:35:23 +0000495 /// Render the operand to an MCInst as a GPR64
496 /// Asserts if the wrong number of operands are requested, or the operand
497 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000498 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
499 assert(N == 1 && "Invalid number of operands!");
500 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
501 }
502
503 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
504 assert(N == 1 && "Invalid number of operands!");
505 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
506 }
507
508 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
509 assert(N == 1 && "Invalid number of operands!");
510 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
511 }
512
513 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
514 assert(N == 1 && "Invalid number of operands!");
515 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
516 }
517
518 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
519 assert(N == 1 && "Invalid number of operands!");
520 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
521 }
522
523 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
524 assert(N == 1 && "Invalid number of operands!");
525 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
526 }
527
528 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
529 assert(N == 1 && "Invalid number of operands!");
530 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
531 }
532
533 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
534 assert(N == 1 && "Invalid number of operands!");
535 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
536 }
537
538 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
539 assert(N == 1 && "Invalid number of operands!");
540 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
541 }
542
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000543 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
544 assert(N == 1 && "Invalid number of operands!");
545 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
546 }
547
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000548 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
549 assert(N == 1 && "Invalid number of operands!");
550 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
551 }
552
553 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
554 assert(N == 1 && "Invalid number of operands!");
555 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
556 }
557
558 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
559 assert(N == 1 && "Invalid number of operands!");
560 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
561 }
562
563 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
564 assert(N == 1 && "Invalid number of operands!");
565 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
566 }
567
568 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
569 assert(N == 1 && "Invalid number of operands!");
570 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
571 }
572
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000573 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000574 assert(N == 1 && "Invalid number of operands!");
575 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000576 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000577 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000578
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000579 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000580 assert(N == 2 && "Invalid number of operands!");
581
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000582 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000583
584 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000585 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000586 }
587
Craig Topper56c590a2014-04-29 07:58:02 +0000588 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000589 // As a special case until we sort out the definition of div/divu, pretend
590 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
591 if (isGPRAsmReg() && RegIdx.Index == 0)
592 return true;
593
594 return Kind == k_PhysRegister;
595 }
596 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000597 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 bool isConstantImm() const {
599 return isImm() && dyn_cast<MCConstantExpr>(getImm());
600 }
Craig Topper56c590a2014-04-29 07:58:02 +0000601 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 // Note: It's not possible to pretend that other operand kinds are tokens.
603 // The matcher emitter checks tokens first.
604 return Kind == k_Token;
605 }
Craig Topper56c590a2014-04-29 07:58:02 +0000606 bool isMem() const override { return Kind == k_Memory; }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000607 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 bool isLSAImm() const {
609 if (!isConstantImm())
610 return false;
611 int64_t Val = getConstantImm();
612 return 1 <= Val && Val <= 4;
613 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000614
615 StringRef getToken() const {
616 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000617 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000618 }
619
Craig Topper56c590a2014-04-29 07:58:02 +0000620 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000621 // As a special case until we sort out the definition of div/divu, pretend
622 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
623 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
624 RegIdx.Kind & RegKind_GPR)
625 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000626
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000627 assert(Kind == k_PhysRegister && "Invalid access!");
628 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000629 }
630
Jack Carterb4dbc172012-09-05 23:34:03 +0000631 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000632 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000633 return Imm.Val;
634 }
635
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000636 int64_t getConstantImm() const {
637 const MCExpr *Val = getImm();
638 return static_cast<const MCConstantExpr *>(Val)->getValue();
639 }
640
641 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000642 assert((Kind == k_Memory) && "Invalid access!");
643 return Mem.Base;
644 }
645
646 const MCExpr *getMemOff() const {
647 assert((Kind == k_Memory) && "Invalid access!");
648 return Mem.Off;
649 }
650
David Blaikie960ea3f2014-06-08 16:18:35 +0000651 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
652 MipsAsmParser &Parser) {
653 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000654 Op->Tok.Data = Str.data();
655 Op->Tok.Length = Str.size();
656 Op->StartLoc = S;
657 Op->EndLoc = S;
658 return Op;
659 }
660
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000661 /// Create a numeric register (e.g. $1). The exact register remains
662 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000663 static std::unique_ptr<MipsOperand>
664 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
665 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000666 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
667 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000668 }
669
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000670 /// Create a register that is definitely a GPR.
671 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000672 static std::unique_ptr<MipsOperand>
673 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
674 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000675 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000676 }
677
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000678 /// Create a register that is definitely a FGR.
679 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000680 static std::unique_ptr<MipsOperand>
681 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
682 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000683 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
684 }
685
686 /// Create a register that is definitely an FCC.
687 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000688 static std::unique_ptr<MipsOperand>
689 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
690 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000691 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
692 }
693
694 /// Create a register that is definitely an ACC.
695 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000696 static std::unique_ptr<MipsOperand>
697 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
698 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000699 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
700 }
701
702 /// Create a register that is definitely an MSA128.
703 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000704 static std::unique_ptr<MipsOperand>
705 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
706 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
708 }
709
710 /// Create a register that is definitely an MSACtrl.
711 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000712 static std::unique_ptr<MipsOperand>
713 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
714 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
716 }
717
David Blaikie960ea3f2014-06-08 16:18:35 +0000718 static std::unique_ptr<MipsOperand>
719 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
720 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000721 Op->Imm.Val = Val;
722 Op->StartLoc = S;
723 Op->EndLoc = E;
724 return Op;
725 }
726
David Blaikie960ea3f2014-06-08 16:18:35 +0000727 static std::unique_ptr<MipsOperand>
728 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
729 SMLoc E, MipsAsmParser &Parser) {
730 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
731 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000732 Op->Mem.Off = Off;
733 Op->StartLoc = S;
734 Op->EndLoc = E;
735 return Op;
736 }
737
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 bool isGPRAsmReg() const {
739 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000740 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 bool isFGRAsmReg() const {
742 // AFGR64 is $0-$15 but we handle this in getAFGR64()
743 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000744 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000745 bool isHWRegsAsmReg() const {
746 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000747 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000748 bool isCCRAsmReg() const {
749 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000750 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 bool isFCCAsmReg() const {
752 return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000753 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000754 bool isACCAsmReg() const {
755 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000756 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000757 bool isCOP2AsmReg() const {
758 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000759 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000760 bool isCOP3AsmReg() const {
761 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
762 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000763 bool isMSA128AsmReg() const {
764 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000765 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000766 bool isMSACtrlAsmReg() const {
767 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000768 }
769
Jack Carterb4dbc172012-09-05 23:34:03 +0000770 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000771 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000772 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000773 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000774
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000775 virtual ~MipsOperand() {
776 switch (Kind) {
777 case k_Immediate:
778 break;
779 case k_Memory:
780 delete Mem.Base;
781 break;
782 case k_PhysRegister:
783 case k_RegisterIndex:
784 case k_Token:
785 break;
786 }
787 }
788
Craig Topper56c590a2014-04-29 07:58:02 +0000789 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000790 switch (Kind) {
791 case k_Immediate:
792 OS << "Imm<";
793 Imm.Val->print(OS);
794 OS << ">";
795 break;
796 case k_Memory:
797 OS << "Mem<";
798 Mem.Base->print(OS);
799 OS << ", ";
800 Mem.Off->print(OS);
801 OS << ">";
802 break;
803 case k_PhysRegister:
804 OS << "PhysReg<" << PhysReg.Num << ">";
805 break;
806 case k_RegisterIndex:
807 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
808 break;
809 case k_Token:
810 OS << Tok.Data;
811 break;
812 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000813 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000814}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000815} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000816
Jack Carter9e65aa32013-03-22 00:05:30 +0000817namespace llvm {
818extern const MCInstrDesc MipsInsts[];
819}
820static const MCInstrDesc &getInstDesc(unsigned Opcode) {
821 return MipsInsts[Opcode];
822}
823
824bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000825 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000826 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000827
Jack Carter9e65aa32013-03-22 00:05:30 +0000828 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000829
830 if (MCID.isBranch() || MCID.isCall()) {
831 const unsigned Opcode = Inst.getOpcode();
832 MCOperand Offset;
833
834 switch (Opcode) {
835 default:
836 break;
837 case Mips::BEQ:
838 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000839 case Mips::BEQ_MM:
840 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000841 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000842 Offset = Inst.getOperand(2);
843 if (!Offset.isImm())
844 break; // We'll deal with this situation later on when applying fixups.
845 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
846 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000847 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000848 return Error(IDLoc, "branch to misaligned address");
849 break;
850 case Mips::BGEZ:
851 case Mips::BGTZ:
852 case Mips::BLEZ:
853 case Mips::BLTZ:
854 case Mips::BGEZAL:
855 case Mips::BLTZAL:
856 case Mips::BC1F:
857 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 case Mips::BGEZ_MM:
859 case Mips::BGTZ_MM:
860 case Mips::BLEZ_MM:
861 case Mips::BLTZ_MM:
862 case Mips::BGEZAL_MM:
863 case Mips::BLTZAL_MM:
864 case Mips::BC1F_MM:
865 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000866 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000867 Offset = Inst.getOperand(1);
868 if (!Offset.isImm())
869 break; // We'll deal with this situation later on when applying fixups.
870 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
871 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000872 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000873 return Error(IDLoc, "branch to misaligned address");
874 break;
875 }
876 }
877
Jack Carterc15c1d22013-04-25 23:31:35 +0000878 if (MCID.hasDelaySlot() && Options.isReorder()) {
879 // If this instruction has a delay slot and .set reorder is active,
880 // emit a NOP after it.
881 Instructions.push_back(Inst);
882 MCInst NopInst;
883 NopInst.setOpcode(Mips::SLL);
884 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
885 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
886 NopInst.addOperand(MCOperand::CreateImm(0));
887 Instructions.push_back(NopInst);
888 return false;
889 }
890
Jack Carter9e65aa32013-03-22 00:05:30 +0000891 if (MCID.mayLoad() || MCID.mayStore()) {
892 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000893 // reference or immediate we may have to expand instructions.
894 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000895 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000896 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
897 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000898 MCOperand &Op = Inst.getOperand(i);
899 if (Op.isImm()) {
900 int MemOffset = Op.getImm();
901 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000902 // Offset can't exceed 16bit value.
903 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000904 return false;
905 }
906 } else if (Op.isExpr()) {
907 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000908 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000909 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000910 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000911 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000912 // Expand symbol.
913 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000914 return false;
915 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000916 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000917 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000918 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000919 }
920 }
921 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000922 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000923 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000924
925 if (needsExpansion(Inst))
926 expandInstruction(Inst, IDLoc, Instructions);
927 else
928 Instructions.push_back(Inst);
929
930 return false;
931}
932
Jack Carter30a59822012-10-04 04:03:53 +0000933bool MipsAsmParser::needsExpansion(MCInst &Inst) {
934
Jack Carterd0bd6422013-04-18 00:41:53 +0000935 switch (Inst.getOpcode()) {
936 case Mips::LoadImm32Reg:
937 case Mips::LoadAddr32Imm:
938 case Mips::LoadAddr32Reg:
939 return true;
940 default:
941 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000942 }
943}
Jack Carter92995f12012-10-06 00:53:28 +0000944
Jack Carter30a59822012-10-04 04:03:53 +0000945void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000946 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000947 switch (Inst.getOpcode()) {
948 case Mips::LoadImm32Reg:
949 return expandLoadImm(Inst, IDLoc, Instructions);
950 case Mips::LoadAddr32Imm:
951 return expandLoadAddressImm(Inst, IDLoc, Instructions);
952 case Mips::LoadAddr32Reg:
953 return expandLoadAddressReg(Inst, IDLoc, Instructions);
954 }
Jack Carter30a59822012-10-04 04:03:53 +0000955}
Jack Carter92995f12012-10-06 00:53:28 +0000956
Jack Carter30a59822012-10-04 04:03:53 +0000957void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000958 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000959 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000960 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000961 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000962 const MCOperand &RegOp = Inst.getOperand(0);
963 assert(RegOp.isReg() && "expected register operand kind");
964
965 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000966 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000967 if (0 <= ImmValue && ImmValue <= 65535) {
968 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000969 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000970 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000971 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000972 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000973 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000974 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000975 } else if (ImmValue < 0 && ImmValue >= -32768) {
976 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000977 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000978 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000979 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000980 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000981 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000982 Instructions.push_back(tmpInst);
983 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000984 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000985 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000986 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000987 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000988 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
989 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000990 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000991 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000992 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000993 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
994 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
995 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
996 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000997 Instructions.push_back(tmpInst);
998 }
999}
Jack Carter92995f12012-10-06 00:53:28 +00001000
Vladimir Medic4c299852013-11-06 11:27:05 +00001001void
1002MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1003 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001004 MCInst tmpInst;
1005 const MCOperand &ImmOp = Inst.getOperand(2);
1006 assert(ImmOp.isImm() && "expected immediate operand kind");
1007 const MCOperand &SrcRegOp = Inst.getOperand(1);
1008 assert(SrcRegOp.isReg() && "expected register operand kind");
1009 const MCOperand &DstRegOp = Inst.getOperand(0);
1010 assert(DstRegOp.isReg() && "expected register operand kind");
1011 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001012 if (-32768 <= ImmValue && ImmValue <= 65535) {
1013 // For -32768 <= j <= 65535.
1014 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001015 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001016 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1017 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1018 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1019 Instructions.push_back(tmpInst);
1020 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001021 // For any other value of j that is representable as a 32-bit integer.
1022 // la d,j(s) => lui d,hi16(j)
1023 // ori d,d,lo16(j)
1024 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001025 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001026 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1027 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1028 Instructions.push_back(tmpInst);
1029 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001030 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001031 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1032 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1033 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1034 Instructions.push_back(tmpInst);
1035 tmpInst.clear();
1036 tmpInst.setOpcode(Mips::ADDu);
1037 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1038 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1039 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1040 Instructions.push_back(tmpInst);
1041 }
1042}
1043
Vladimir Medic4c299852013-11-06 11:27:05 +00001044void
1045MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1046 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001047 MCInst tmpInst;
1048 const MCOperand &ImmOp = Inst.getOperand(1);
1049 assert(ImmOp.isImm() && "expected immediate operand kind");
1050 const MCOperand &RegOp = Inst.getOperand(0);
1051 assert(RegOp.isReg() && "expected register operand kind");
1052 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001053 if (-32768 <= ImmValue && ImmValue <= 65535) {
1054 // For -32768 <= j <= 65535.
1055 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001056 tmpInst.setOpcode(Mips::ADDiu);
1057 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001058 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001059 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1060 Instructions.push_back(tmpInst);
1061 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001062 // For any other value of j that is representable as a 32-bit integer.
1063 // la d,j => lui d,hi16(j)
1064 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001065 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001066 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1067 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1068 Instructions.push_back(tmpInst);
1069 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001070 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001071 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1072 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1073 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1074 Instructions.push_back(tmpInst);
1075 }
1076}
1077
Jack Carter9e65aa32013-03-22 00:05:30 +00001078void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001079 SmallVectorImpl<MCInst> &Instructions,
1080 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001081 const MCSymbolRefExpr *SR;
1082 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001083 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001084 const MCExpr *ExprOffset;
1085 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +00001086 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001087 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001089 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1090 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001091 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001092 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1093 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001094 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001095 if (isImmOpnd) {
1096 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1097 ImmOffset = Inst.getOperand(2).getImm();
1098 LoOffset = ImmOffset & 0x0000ffff;
1099 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001100 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001101 if (LoOffset & 0x8000)
1102 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001103 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001104 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001105 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001106 TempInst.setLoc(IDLoc);
1107 // 1st instruction in expansion is LUi. For load instruction we can use
1108 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001109 // but for stores we must use $at.
1110 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +00001111 TempInst.setOpcode(Mips::LUi);
1112 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1113 if (isImmOpnd)
1114 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1115 else {
1116 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001117 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001118 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1119 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1120 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001121 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001122 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001123 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001124 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001125 }
1126 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001127 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001128 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001129 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001130 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001131 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001132 TempInst.setOpcode(Mips::ADDu);
1133 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1134 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1135 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1136 Instructions.push_back(TempInst);
1137 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001138 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001139 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001140 TempInst.setOpcode(Inst.getOpcode());
1141 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1142 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1143 if (isImmOpnd)
1144 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1145 else {
1146 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001147 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1148 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1149 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001150 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001151 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001152 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001153 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001154 }
1155 }
1156 Instructions.push_back(TempInst);
1157 TempInst.clear();
1158}
1159
David Blaikie960ea3f2014-06-08 16:18:35 +00001160bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1161 OperandVector &Operands,
1162 MCStreamer &Out,
1163 unsigned &ErrorInfo,
1164 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001165 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001166 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001167 unsigned MatchResult =
1168 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001169
1170 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001171 default:
1172 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001173 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001174 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001175 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001176 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001177 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001178 return false;
1179 }
1180 case Match_MissingFeature:
1181 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1182 return true;
1183 case Match_InvalidOperand: {
1184 SMLoc ErrorLoc = IDLoc;
1185 if (ErrorInfo != ~0U) {
1186 if (ErrorInfo >= Operands.size())
1187 return Error(IDLoc, "too few operands for instruction");
1188
David Blaikie960ea3f2014-06-08 16:18:35 +00001189 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001190 if (ErrorLoc == SMLoc())
1191 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001192 }
1193
1194 return Error(ErrorLoc, "invalid operand for instruction");
1195 }
1196 case Match_MnemonicFail:
1197 return Error(IDLoc, "invalid instruction");
1198 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001199 return true;
1200}
1201
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001202void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1203 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1204 if (RegIndex == 1)
1205 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001206 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001207 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1208 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001209 }
1210}
1211
Jack Carter1ac53222013-02-20 23:11:17 +00001212int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001213 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001214
Vladimir Medic4c299852013-11-06 11:27:05 +00001215 CC = StringSwitch<unsigned>(Name)
1216 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001217 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001218 .Case("a0", 4)
1219 .Case("a1", 5)
1220 .Case("a2", 6)
1221 .Case("a3", 7)
1222 .Case("v0", 2)
1223 .Case("v1", 3)
1224 .Case("s0", 16)
1225 .Case("s1", 17)
1226 .Case("s2", 18)
1227 .Case("s3", 19)
1228 .Case("s4", 20)
1229 .Case("s5", 21)
1230 .Case("s6", 22)
1231 .Case("s7", 23)
1232 .Case("k0", 26)
1233 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001234 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001235 .Case("sp", 29)
1236 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001237 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001238 .Case("ra", 31)
1239 .Case("t0", 8)
1240 .Case("t1", 9)
1241 .Case("t2", 10)
1242 .Case("t3", 11)
1243 .Case("t4", 12)
1244 .Case("t5", 13)
1245 .Case("t6", 14)
1246 .Case("t7", 15)
1247 .Case("t8", 24)
1248 .Case("t9", 25)
1249 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001250
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001251 if (isN32() || isN64()) {
1252 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1253 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1254 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1255 if (8 <= CC && CC <= 11)
1256 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001257
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001258 if (CC == -1)
1259 CC = StringSwitch<unsigned>(Name)
1260 .Case("a4", 8)
1261 .Case("a5", 9)
1262 .Case("a6", 10)
1263 .Case("a7", 11)
1264 .Case("kt0", 26)
1265 .Case("kt1", 27)
1266 .Default(-1);
1267 }
Jack Carter1ac53222013-02-20 23:11:17 +00001268
1269 return CC;
1270}
Jack Carterd0bd6422013-04-18 00:41:53 +00001271
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001272int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001273
Jack Cartera63b16a2012-09-07 00:23:42 +00001274 if (Name[0] == 'f') {
1275 StringRef NumString = Name.substr(1);
1276 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001277 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001278 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001279 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001280 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001281 return IntVal;
1282 }
1283 return -1;
1284}
Jack Cartera63b16a2012-09-07 00:23:42 +00001285
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001286int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1287
1288 if (Name.startswith("fcc")) {
1289 StringRef NumString = Name.substr(3);
1290 unsigned IntVal;
1291 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001292 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001293 if (IntVal > 7) // There are only 8 fcc registers.
1294 return -1;
1295 return IntVal;
1296 }
1297 return -1;
1298}
1299
1300int MipsAsmParser::matchACRegisterName(StringRef Name) {
1301
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001302 if (Name.startswith("ac")) {
1303 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001304 unsigned IntVal;
1305 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001306 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001307 if (IntVal > 3) // There are only 3 acc registers.
1308 return -1;
1309 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001310 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001311 return -1;
1312}
Jack Carterd0bd6422013-04-18 00:41:53 +00001313
Jack Carter5dc8ac92013-09-25 23:50:44 +00001314int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1315 unsigned IntVal;
1316
1317 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1318 return -1;
1319
1320 if (IntVal > 31)
1321 return -1;
1322
1323 return IntVal;
1324}
1325
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001326int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1327 int CC;
1328
1329 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001330 .Case("msair", 0)
1331 .Case("msacsr", 1)
1332 .Case("msaaccess", 2)
1333 .Case("msasave", 3)
1334 .Case("msamodify", 4)
1335 .Case("msarequest", 5)
1336 .Case("msamap", 6)
1337 .Case("msaunmap", 7)
1338 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001339
1340 return CC;
1341}
1342
Jack Carter0b744b32012-10-04 02:29:46 +00001343bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1344 if (Reg > 31)
1345 return false;
1346
1347 aTReg = Reg;
1348 return true;
1349}
1350
Daniel Sandersd89b1362014-03-24 16:48:01 +00001351int MipsAsmParser::getATReg() {
1352 int AT = Options.getATRegNum();
1353 if (AT == 0)
1354 TokError("Pseudo instruction requires $at, which is not available");
1355 return AT;
1356}
Jack Carter0b744b32012-10-04 02:29:46 +00001357
Jack Carterd0bd6422013-04-18 00:41:53 +00001358unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001359 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001360}
1361
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001362unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001363 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1364 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001365}
1366
Jack Carter873c7242013-01-12 01:03:14 +00001367int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001368 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001369 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001370 return -1;
1371
Jack Carter873c7242013-01-12 01:03:14 +00001372 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001373}
1374
David Blaikie960ea3f2014-06-08 16:18:35 +00001375bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001376 DEBUG(dbgs() << "ParseOperand\n");
1377
Jack Carter30a59822012-10-04 04:03:53 +00001378 // Check if the current operand has a custom associated parser, if so, try to
1379 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001380 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1381 if (ResTy == MatchOperand_Success)
1382 return false;
1383 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1384 // there was a match, but an error occurred, in which case, just return that
1385 // the operand parsing failed.
1386 if (ResTy == MatchOperand_ParseFail)
1387 return true;
1388
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001389 DEBUG(dbgs() << ".. Generic Parser\n");
1390
Jack Carterb4dbc172012-09-05 23:34:03 +00001391 switch (getLexer().getKind()) {
1392 default:
1393 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1394 return true;
1395 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001396 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001397 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001398
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001399 // Almost all registers have been parsed by custom parsers. There is only
1400 // one exception to this. $zero (and it's alias $0) will reach this point
1401 // for div, divu, and similar instructions because it is not an operand
1402 // to the instruction definition but an explicit register. Special case
1403 // this situation for now.
1404 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001405 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001406
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001408 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001409 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001410 return true;
1411
Jack Carter873c7242013-01-12 01:03:14 +00001412 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001413 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001414 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001415 const MCExpr *Res =
1416 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001417
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001418 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001419 return false;
1420 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001421 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001422 case AsmToken::LParen:
1423 case AsmToken::Minus:
1424 case AsmToken::Plus:
1425 case AsmToken::Integer:
1426 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001427 DEBUG(dbgs() << ".. generic integer\n");
1428 OperandMatchResultTy ResTy = ParseImm(Operands);
1429 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001430 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001431 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001432 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001433 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001434 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001435 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001436 return true;
1437
Jack Carter873c7242013-01-12 01:03:14 +00001438 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1439
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001440 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001441 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001442 } // case AsmToken::Percent
1443 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001444 return true;
1445}
1446
Vladimir Medic4c299852013-11-06 11:27:05 +00001447const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001448 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001449 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001450 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001451 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001452 // It's a constant, evaluate reloc value.
1453 int16_t Val;
1454 switch (getVariantKind(RelocStr)) {
1455 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1456 // Get the 1st 16-bits.
1457 Val = MCE->getValue() & 0xffff;
1458 break;
1459 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1460 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1461 // 16 bits being negative.
1462 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1463 break;
1464 case MCSymbolRefExpr::VK_Mips_HIGHER:
1465 // Get the 3rd 16-bits.
1466 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1467 break;
1468 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1469 // Get the 4th 16-bits.
1470 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1471 break;
1472 default:
1473 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001474 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001475 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001476 }
1477
Jack Carterb5cf5902013-04-17 00:18:04 +00001478 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001479 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001480 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001481 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001482 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001483 return Res;
1484 }
1485
1486 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001487 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1488
Sasa Stankovic06c47802014-04-03 10:37:45 +00001489 // Try to create target expression.
1490 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1491 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001492
Jack Carterd0bd6422013-04-18 00:41:53 +00001493 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1494 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001495 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1496 return Res;
1497 }
1498
1499 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001500 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1501 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1502 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001503 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001504 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001505 return Expr;
1506}
1507
1508bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1509
1510 switch (Expr->getKind()) {
1511 case MCExpr::Constant:
1512 return true;
1513 case MCExpr::SymbolRef:
1514 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1515 case MCExpr::Binary:
1516 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1517 if (!isEvaluated(BE->getLHS()))
1518 return false;
1519 return isEvaluated(BE->getRHS());
1520 }
1521 case MCExpr::Unary:
1522 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001523 case MCExpr::Target:
1524 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001525 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001526 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001527}
Jack Carterd0bd6422013-04-18 00:41:53 +00001528
Jack Carterb5cf5902013-04-17 00:18:04 +00001529bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001530 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001531 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001532 if (Tok.isNot(AsmToken::Identifier))
1533 return true;
1534
1535 std::string Str = Tok.getIdentifier().str();
1536
Jack Carterd0bd6422013-04-18 00:41:53 +00001537 Parser.Lex(); // Eat the identifier.
1538 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001539 const MCExpr *IdVal;
1540 SMLoc EndLoc;
1541
1542 if (getLexer().getKind() == AsmToken::LParen) {
1543 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001544 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001545 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001546 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001547 const AsmToken &nextTok = Parser.getTok();
1548 if (nextTok.isNot(AsmToken::Identifier))
1549 return true;
1550 Str += "(%";
1551 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001552 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001553 if (getLexer().getKind() != AsmToken::LParen)
1554 return true;
1555 } else
1556 break;
1557 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001558 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001559 return true;
1560
1561 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001562 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001563
1564 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001565 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001566
Jack Carterd0bd6422013-04-18 00:41:53 +00001567 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001568 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001569}
1570
Jack Carterb4dbc172012-09-05 23:34:03 +00001571bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1572 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001573 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001574 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1575 if (ResTy == MatchOperand_Success) {
1576 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001577 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001578 StartLoc = Operand.getStartLoc();
1579 EndLoc = Operand.getEndLoc();
1580
1581 // AFAIK, we only support numeric registers and named GPR's in CFI
1582 // directives.
1583 // Don't worry about eating tokens before failing. Using an unrecognised
1584 // register is a parse error.
1585 if (Operand.isGPRAsmReg()) {
1586 // Resolve to GPR32 or GPR64 appropriately.
1587 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1588 }
1589
1590 return (RegNo == (unsigned)-1);
1591 }
1592
1593 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001594 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001595}
1596
Jack Carterb5cf5902013-04-17 00:18:04 +00001597bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001598 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001599 bool Result = true;
1600
1601 while (getLexer().getKind() == AsmToken::LParen)
1602 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001603
Jack Carterd0bd6422013-04-18 00:41:53 +00001604 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001605 default:
1606 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001607 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001608 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001609 case AsmToken::Integer:
1610 case AsmToken::Minus:
1611 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001612 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001613 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001614 else
1615 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001617 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 break;
Jack Carter873c7242013-01-12 01:03:14 +00001619 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001620 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001621 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001622 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001623}
1624
David Blaikie960ea3f2014-06-08 16:18:35 +00001625MipsAsmParser::OperandMatchResultTy
1626MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001627 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001628 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001629 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001630 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001631 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001632 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001633 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001634
Jack Carterb5cf5902013-04-17 00:18:04 +00001635 if (getLexer().getKind() == AsmToken::LParen) {
1636 Parser.Lex();
1637 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001638 }
1639
Jack Carterb5cf5902013-04-17 00:18:04 +00001640 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001641 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001642 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001643
Jack Carterd0bd6422013-04-18 00:41:53 +00001644 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001645 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001646 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1647 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001648 SMLoc E =
1649 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001650 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001651 return MatchOperand_Success;
1652 }
1653 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001654 SMLoc E =
1655 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001656
Jack Carterd0bd6422013-04-18 00:41:53 +00001657 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001658 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001659 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1660 S, E, *this);
1661 Operands.push_back(
1662 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001663 return MatchOperand_Success;
1664 }
1665 Error(Parser.getTok().getLoc(), "'(' expected");
1666 return MatchOperand_ParseFail;
1667 }
1668
Jack Carterd0bd6422013-04-18 00:41:53 +00001669 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001670 }
1671
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001672 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001673 if (Res != MatchOperand_Success)
1674 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001675
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001676 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001677 Error(Parser.getTok().getLoc(), "')' expected");
1678 return MatchOperand_ParseFail;
1679 }
1680
Jack Carter873c7242013-01-12 01:03:14 +00001681 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1682
Jack Carterd0bd6422013-04-18 00:41:53 +00001683 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001684
Craig Topper062a2ba2014-04-25 05:30:21 +00001685 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001686 IdVal = MCConstantExpr::Create(0, getContext());
1687
Jack Carterd0bd6422013-04-18 00:41:53 +00001688 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001689 std::unique_ptr<MipsOperand> op(
1690 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001691 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001692 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001693 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001694 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001695 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1696 int64_t Imm;
1697 if (IdVal->EvaluateAsAbsolute(Imm))
1698 IdVal = MCConstantExpr::Create(Imm, getContext());
1699 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1700 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1701 getContext());
1702 }
1703
David Blaikie960ea3f2014-06-08 16:18:35 +00001704 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001705 return MatchOperand_Success;
1706}
1707
David Blaikie960ea3f2014-06-08 16:18:35 +00001708bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001709
Jack Carterd76b2372013-03-21 21:44:16 +00001710 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1711 if (Sym) {
1712 SMLoc S = Parser.getTok().getLoc();
1713 const MCExpr *Expr;
1714 if (Sym->isVariable())
1715 Expr = Sym->getVariableValue();
1716 else
1717 return false;
1718 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001719 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001720 const StringRef DefSymbol = Ref->getSymbol().getName();
1721 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001722 OperandMatchResultTy ResTy =
1723 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001724 if (ResTy == MatchOperand_Success) {
1725 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001726 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001727 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001728 llvm_unreachable("Should never ParseFail");
1729 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001730 }
1731 } else if (Expr->getKind() == MCExpr::Constant) {
1732 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001733 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001734 Operands.push_back(
1735 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001736 return true;
1737 }
1738 }
1739 return false;
1740}
Jack Carterd0bd6422013-04-18 00:41:53 +00001741
Jack Carter873c7242013-01-12 01:03:14 +00001742MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001743MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1744 StringRef Identifier,
1745 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001746 int Index = matchCPURegisterName(Identifier);
1747 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001748 Operands.push_back(MipsOperand::CreateGPRReg(
1749 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1750 return MatchOperand_Success;
1751 }
1752
1753 Index = matchFPURegisterName(Identifier);
1754 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001755 Operands.push_back(MipsOperand::CreateFGRReg(
1756 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1757 return MatchOperand_Success;
1758 }
1759
1760 Index = matchFCCRegisterName(Identifier);
1761 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001762 Operands.push_back(MipsOperand::CreateFCCReg(
1763 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1764 return MatchOperand_Success;
1765 }
1766
1767 Index = matchACRegisterName(Identifier);
1768 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001769 Operands.push_back(MipsOperand::CreateACCReg(
1770 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1771 return MatchOperand_Success;
1772 }
1773
1774 Index = matchMSA128RegisterName(Identifier);
1775 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001776 Operands.push_back(MipsOperand::CreateMSA128Reg(
1777 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1778 return MatchOperand_Success;
1779 }
1780
1781 Index = matchMSA128CtrlRegisterName(Identifier);
1782 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001783 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1784 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1785 return MatchOperand_Success;
1786 }
1787
1788 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001789}
1790
1791MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001792MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001793 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001794
1795 if (Token.is(AsmToken::Identifier)) {
1796 DEBUG(dbgs() << ".. identifier\n");
1797 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001798 OperandMatchResultTy ResTy =
1799 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001800 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001801 } else if (Token.is(AsmToken::Integer)) {
1802 DEBUG(dbgs() << ".. integer\n");
1803 Operands.push_back(MipsOperand::CreateNumericReg(
1804 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1805 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001806 return MatchOperand_Success;
1807 }
1808
1809 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1810
1811 return MatchOperand_NoMatch;
1812}
1813
David Blaikie960ea3f2014-06-08 16:18:35 +00001814MipsAsmParser::OperandMatchResultTy
1815MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001816 DEBUG(dbgs() << "ParseAnyRegister\n");
1817
1818 auto Token = Parser.getTok();
1819
1820 SMLoc S = Token.getLoc();
1821
1822 if (Token.isNot(AsmToken::Dollar)) {
1823 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1824 if (Token.is(AsmToken::Identifier)) {
1825 if (searchSymbolAlias(Operands))
1826 return MatchOperand_Success;
1827 }
1828 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1829 return MatchOperand_NoMatch;
1830 }
1831 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001832
Daniel Sanders21bce302014-04-01 12:35:23 +00001833 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001834 if (ResTy == MatchOperand_Success) {
1835 Parser.Lex(); // $
1836 Parser.Lex(); // identifier
1837 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001838 return ResTy;
1839}
1840
1841MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001842MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001843 switch (getLexer().getKind()) {
1844 default:
1845 return MatchOperand_NoMatch;
1846 case AsmToken::LParen:
1847 case AsmToken::Minus:
1848 case AsmToken::Plus:
1849 case AsmToken::Integer:
1850 case AsmToken::String:
1851 break;
1852 }
1853
1854 const MCExpr *IdVal;
1855 SMLoc S = Parser.getTok().getLoc();
1856 if (getParser().parseExpression(IdVal))
1857 return MatchOperand_ParseFail;
1858
1859 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1860 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1861 return MatchOperand_Success;
1862}
1863
David Blaikie960ea3f2014-06-08 16:18:35 +00001864MipsAsmParser::OperandMatchResultTy
1865MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001866 DEBUG(dbgs() << "ParseJumpTarget\n");
1867
1868 SMLoc S = getLexer().getLoc();
1869
1870 // Integers and expressions are acceptable
1871 OperandMatchResultTy ResTy = ParseImm(Operands);
1872 if (ResTy != MatchOperand_NoMatch)
1873 return ResTy;
1874
Daniel Sanders315386c2014-04-01 10:40:14 +00001875 // Registers are a valid target and have priority over symbols.
1876 ResTy = ParseAnyRegister(Operands);
1877 if (ResTy != MatchOperand_NoMatch)
1878 return ResTy;
1879
Daniel Sandersffd84362014-04-01 10:41:48 +00001880 const MCExpr *Expr = nullptr;
1881 if (Parser.parseExpression(Expr)) {
1882 // We have no way of knowing if a symbol was consumed so we must ParseFail
1883 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001884 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001885 Operands.push_back(
1886 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001887 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001888}
1889
Vladimir Medic2b953d02013-10-01 09:48:56 +00001890MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001891MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001892 const MCExpr *IdVal;
1893 // If the first token is '$' we may have register operand.
1894 if (Parser.getTok().is(AsmToken::Dollar))
1895 return MatchOperand_NoMatch;
1896 SMLoc S = Parser.getTok().getLoc();
1897 if (getParser().parseExpression(IdVal))
1898 return MatchOperand_ParseFail;
1899 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001900 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001901 int64_t Val = MCE->getValue();
1902 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1903 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001904 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001905 return MatchOperand_Success;
1906}
1907
Matheus Almeida779c5932013-11-18 12:32:49 +00001908MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001909MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001910 switch (getLexer().getKind()) {
1911 default:
1912 return MatchOperand_NoMatch;
1913 case AsmToken::LParen:
1914 case AsmToken::Plus:
1915 case AsmToken::Minus:
1916 case AsmToken::Integer:
1917 break;
1918 }
1919
1920 const MCExpr *Expr;
1921 SMLoc S = Parser.getTok().getLoc();
1922
1923 if (getParser().parseExpression(Expr))
1924 return MatchOperand_ParseFail;
1925
1926 int64_t Val;
1927 if (!Expr->EvaluateAsAbsolute(Val)) {
1928 Error(S, "expected immediate value");
1929 return MatchOperand_ParseFail;
1930 }
1931
1932 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1933 // and because the CPU always adds one to the immediate field, the allowed
1934 // range becomes 1..4. We'll only check the range here and will deal
1935 // with the addition/subtraction when actually decoding/encoding
1936 // the instruction.
1937 if (Val < 1 || Val > 4) {
1938 Error(S, "immediate not in range (1..4)");
1939 return MatchOperand_ParseFail;
1940 }
1941
Jack Carter3b2c96e2014-01-22 23:31:38 +00001942 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001943 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00001944 return MatchOperand_Success;
1945}
1946
Jack Carterdc1e35d2012-09-06 20:00:02 +00001947MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1948
Vladimir Medic4c299852013-11-06 11:27:05 +00001949 MCSymbolRefExpr::VariantKind VK =
1950 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1951 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1952 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1953 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1954 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1955 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1956 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1957 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1958 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1959 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1960 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1961 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1962 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1963 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1964 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1965 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1966 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1967 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00001968 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
1969 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
1970 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
1971 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
1972 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
1973 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00001974 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
1975 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00001976 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001977
Matheus Almeida2852af82014-04-22 10:15:54 +00001978 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00001979
Jack Carterdc1e35d2012-09-06 20:00:02 +00001980 return VK;
1981}
Jack Cartera63b16a2012-09-07 00:23:42 +00001982
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001983/// Sometimes (i.e. load/stores) the operand may be followed immediately by
1984/// either this.
1985/// ::= '(', register, ')'
1986/// handle it before we iterate so we don't get tripped up by the lack of
1987/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00001988bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001989 if (getLexer().is(AsmToken::LParen)) {
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::RParen)) {
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
2010/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2011/// either one of these.
2012/// ::= '[', register, ']'
2013/// ::= '[', integer, ']'
2014/// handle it before we iterate so we don't get tripped up by the lack of
2015/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002016bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2017 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002018 if (getLexer().is(AsmToken::LBrac)) {
2019 Operands.push_back(
2020 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2021 Parser.Lex();
2022 if (ParseOperand(Operands, Name)) {
2023 SMLoc Loc = getLexer().getLoc();
2024 Parser.eatToEndOfStatement();
2025 return Error(Loc, "unexpected token in argument list");
2026 }
2027 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2028 SMLoc Loc = getLexer().getLoc();
2029 Parser.eatToEndOfStatement();
2030 return Error(Loc, "unexpected token, expected ']'");
2031 }
2032 Operands.push_back(
2033 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2034 Parser.Lex();
2035 }
2036 return false;
2037}
2038
David Blaikie960ea3f2014-06-08 16:18:35 +00002039bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2040 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002041 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002042 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002043 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002044 Parser.eatToEndOfStatement();
2045 return Error(NameLoc, "Unknown instruction");
2046 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002047 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002048 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002049
2050 // Read the remaining operands.
2051 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2052 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002053 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002054 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002055 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002056 return Error(Loc, "unexpected token in argument list");
2057 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002058 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2059 return true;
2060 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002061
Jack Carterd0bd6422013-04-18 00:41:53 +00002062 while (getLexer().is(AsmToken::Comma)) {
2063 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002064 // Parse and remember the operand.
2065 if (ParseOperand(Operands, Name)) {
2066 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002067 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002068 return Error(Loc, "unexpected token in argument list");
2069 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002070 // Parse bracket and parenthesis suffixes before we iterate
2071 if (getLexer().is(AsmToken::LBrac)) {
2072 if (ParseBracketSuffix(Name, Operands))
2073 return true;
2074 } else if (getLexer().is(AsmToken::LParen) &&
2075 ParseParenSuffix(Name, Operands))
2076 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002077 }
2078 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002079 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2080 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002081 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002082 return Error(Loc, "unexpected token in argument list");
2083 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002084 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002085 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002086}
2087
Jack Carter0b744b32012-10-04 02:29:46 +00002088bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002089 SMLoc Loc = getLexer().getLoc();
2090 Parser.eatToEndOfStatement();
2091 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002092}
2093
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002094bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2095 return Error(Loc, ErrorMsg);
2096}
2097
Jack Carter0b744b32012-10-04 02:29:46 +00002098bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002099 // Line should look like: ".set noat".
2100 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002101 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002102 // eat noat
2103 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002105 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2106 reportParseError("unexpected token in statement");
2107 return false;
2108 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002109 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002110 return false;
2111}
Jack Carterd0bd6422013-04-18 00:41:53 +00002112
Jack Carter0b744b32012-10-04 02:29:46 +00002113bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002114 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002115 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002116 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002117 getParser().Lex();
2118 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002119 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002120 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002121 return false;
2122 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002123 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002124 if (getLexer().isNot(AsmToken::Dollar)) {
2125 reportParseError("unexpected token in statement");
2126 return false;
2127 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002128 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002129 const AsmToken &Reg = Parser.getTok();
2130 if (Reg.is(AsmToken::Identifier)) {
2131 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2132 } else if (Reg.is(AsmToken::Integer)) {
2133 AtRegNo = Reg.getIntVal();
2134 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002135 reportParseError("unexpected token in statement");
2136 return false;
2137 }
Jack Carter1ac53222013-02-20 23:11:17 +00002138
Daniel Sanders71a89d922014-03-25 13:01:06 +00002139 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002140 reportParseError("unexpected token in statement");
2141 return false;
2142 }
2143
2144 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002145 reportParseError("unexpected token in statement");
2146 return false;
2147 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002148 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002149
2150 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2151 reportParseError("unexpected token in statement");
2152 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002153 }
2154 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002155 return false;
2156 } else {
2157 reportParseError("unexpected token in statement");
2158 return false;
2159 }
2160}
2161
2162bool MipsAsmParser::parseSetReorderDirective() {
2163 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002164 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002165 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2166 reportParseError("unexpected token in statement");
2167 return false;
2168 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002169 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002170 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002171 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002172 return false;
2173}
2174
2175bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002176 Parser.Lex();
2177 // If this is not the end of the statement, report an error.
2178 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2179 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002180 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002181 }
2182 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002183 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002184 Parser.Lex(); // Consume the EndOfStatement.
2185 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002186}
2187
2188bool MipsAsmParser::parseSetMacroDirective() {
2189 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002190 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002191 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2192 reportParseError("unexpected token in statement");
2193 return false;
2194 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002195 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002196 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002197 return false;
2198}
2199
2200bool MipsAsmParser::parseSetNoMacroDirective() {
2201 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002202 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002203 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2204 reportParseError("`noreorder' must be set before `nomacro'");
2205 return false;
2206 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002207 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002208 reportParseError("`noreorder' must be set before `nomacro'");
2209 return false;
2210 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002211 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002212 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002213 return false;
2214}
Jack Carterd76b2372013-03-21 21:44:16 +00002215
Jack Carter39536722014-01-22 23:08:42 +00002216bool MipsAsmParser::parseSetNoMips16Directive() {
2217 Parser.Lex();
2218 // If this is not the end of the statement, report an error.
2219 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2220 reportParseError("unexpected token in statement");
2221 return false;
2222 }
2223 // For now do nothing.
2224 Parser.Lex(); // Consume the EndOfStatement.
2225 return false;
2226}
2227
Jack Carterd76b2372013-03-21 21:44:16 +00002228bool MipsAsmParser::parseSetAssignment() {
2229 StringRef Name;
2230 const MCExpr *Value;
2231
2232 if (Parser.parseIdentifier(Name))
2233 reportParseError("expected identifier after .set");
2234
2235 if (getLexer().isNot(AsmToken::Comma))
2236 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002237 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002238
Jack Carter3b2c96e2014-01-22 23:31:38 +00002239 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002240 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002241
Jack Carterd0bd6422013-04-18 00:41:53 +00002242 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002243 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002244 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002245 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002246 Sym = getContext().GetOrCreateSymbol(Name);
2247 Sym->setVariableValue(Value);
2248
2249 return false;
2250}
Jack Carterd0bd6422013-04-18 00:41:53 +00002251
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002252bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2253 Parser.Lex();
2254 if (getLexer().isNot(AsmToken::EndOfStatement))
2255 return reportParseError("unexpected token in .set directive");
2256
Matheus Almeida2852af82014-04-22 10:15:54 +00002257 switch (Feature) {
2258 default:
2259 llvm_unreachable("Unimplemented feature");
2260 case Mips::FeatureDSP:
2261 setFeatureBits(Mips::FeatureDSP, "dsp");
2262 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002263 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002264 case Mips::FeatureMicroMips:
2265 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002266 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002267 case Mips::FeatureMips16:
2268 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002269 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002270 case Mips::FeatureMips32r2:
2271 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2272 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002273 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002274 case Mips::FeatureMips64:
2275 setFeatureBits(Mips::FeatureMips64, "mips64");
2276 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002277 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002278 case Mips::FeatureMips64r2:
2279 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2280 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002281 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002282 }
2283 return false;
2284}
2285
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002286bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2287 if (!getLexer().is(AsmToken::Dollar))
2288 return false;
2289
2290 Parser.Lex();
2291
2292 const AsmToken &Reg = Parser.getTok();
2293 if (Reg.is(AsmToken::Identifier)) {
2294 RegNum = matchCPURegisterName(Reg.getIdentifier());
2295 } else if (Reg.is(AsmToken::Integer)) {
2296 RegNum = Reg.getIntVal();
2297 } else {
2298 return false;
2299 }
2300
2301 Parser.Lex();
2302 return true;
2303}
2304
2305bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2306 if (getLexer().isNot(AsmToken::Comma)) {
2307 SMLoc Loc = getLexer().getLoc();
2308 Parser.eatToEndOfStatement();
2309 return Error(Loc, ErrorStr);
2310 }
2311
Matheus Almeida2852af82014-04-22 10:15:54 +00002312 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002313 return true;
2314}
2315
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002316bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2317 if (Options.isReorder())
2318 Warning(Loc, ".cpload in reorder section");
2319
2320 // FIXME: Warn if cpload is used in Mips16 mode.
2321
David Blaikie960ea3f2014-06-08 16:18:35 +00002322 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002323 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2324 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2325 reportParseError("expected register containing function address");
2326 return false;
2327 }
2328
David Blaikie960ea3f2014-06-08 16:18:35 +00002329 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2330 if (!RegOpnd.isGPRAsmReg()) {
2331 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002332 return false;
2333 }
2334
David Blaikie960ea3f2014-06-08 16:18:35 +00002335 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002336 return false;
2337}
2338
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002339bool MipsAsmParser::parseDirectiveCPSetup() {
2340 unsigned FuncReg;
2341 unsigned Save;
2342 bool SaveIsReg = true;
2343
2344 if (!parseRegister(FuncReg))
2345 return reportParseError("expected register containing function address");
2346 FuncReg = getGPR(FuncReg);
2347
2348 if (!eatComma("expected comma parsing directive"))
2349 return true;
2350
2351 if (!parseRegister(Save)) {
2352 const AsmToken &Tok = Parser.getTok();
2353 if (Tok.is(AsmToken::Integer)) {
2354 Save = Tok.getIntVal();
2355 SaveIsReg = false;
2356 Parser.Lex();
2357 } else
2358 return reportParseError("expected save register or stack offset");
2359 } else
2360 Save = getGPR(Save);
2361
2362 if (!eatComma("expected comma parsing directive"))
2363 return true;
2364
2365 StringRef Name;
2366 if (Parser.parseIdentifier(Name))
2367 reportParseError("expected identifier");
2368 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002369
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002370 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002371 return false;
2372}
2373
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002374bool MipsAsmParser::parseDirectiveNaN() {
2375 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2376 const AsmToken &Tok = Parser.getTok();
2377
2378 if (Tok.getString() == "2008") {
2379 Parser.Lex();
2380 getTargetStreamer().emitDirectiveNaN2008();
2381 return false;
2382 } else if (Tok.getString() == "legacy") {
2383 Parser.Lex();
2384 getTargetStreamer().emitDirectiveNaNLegacy();
2385 return false;
2386 }
2387 }
2388 // If we don't recognize the option passed to the .nan
2389 // directive (e.g. no option or unknown option), emit an error.
2390 reportParseError("invalid option in .nan directive");
2391 return false;
2392}
2393
Jack Carter0b744b32012-10-04 02:29:46 +00002394bool MipsAsmParser::parseDirectiveSet() {
2395
Jack Carterd0bd6422013-04-18 00:41:53 +00002396 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002397 const AsmToken &Tok = Parser.getTok();
2398
2399 if (Tok.getString() == "noat") {
2400 return parseSetNoAtDirective();
2401 } else if (Tok.getString() == "at") {
2402 return parseSetAtDirective();
2403 } else if (Tok.getString() == "reorder") {
2404 return parseSetReorderDirective();
2405 } else if (Tok.getString() == "noreorder") {
2406 return parseSetNoReorderDirective();
2407 } else if (Tok.getString() == "macro") {
2408 return parseSetMacroDirective();
2409 } else if (Tok.getString() == "nomacro") {
2410 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002411 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002412 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002413 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002414 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002415 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002416 getTargetStreamer().emitDirectiveSetNoMicroMips();
2417 Parser.eatToEndOfStatement();
2418 return false;
2419 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002420 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002421 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002422 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002423 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002424 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002425 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002426 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002427 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002428 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002429 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002430 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002431 parseSetAssignment();
2432 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002433 }
Jack Carter07c818d2013-01-25 01:31:34 +00002434
Jack Carter0b744b32012-10-04 02:29:46 +00002435 return true;
2436}
2437
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002438/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002439/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002440bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002441 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2442 for (;;) {
2443 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002444 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002445 return true;
2446
2447 getParser().getStreamer().EmitValue(Value, Size);
2448
2449 if (getLexer().is(AsmToken::EndOfStatement))
2450 break;
2451
2452 // FIXME: Improve diagnostic.
2453 if (getLexer().isNot(AsmToken::Comma))
2454 return Error(L, "unexpected token in directive");
2455 Parser.Lex();
2456 }
2457 }
2458
2459 Parser.Lex();
2460 return false;
2461}
2462
Vladimir Medic4c299852013-11-06 11:27:05 +00002463/// parseDirectiveGpWord
2464/// ::= .gpword local_sym
2465bool MipsAsmParser::parseDirectiveGpWord() {
2466 const MCExpr *Value;
2467 // EmitGPRel32Value requires an expression, so we are using base class
2468 // method to evaluate the expression.
2469 if (getParser().parseExpression(Value))
2470 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002471 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002472
Vladimir Medice10c1122013-11-13 13:18:04 +00002473 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002474 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002475 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002476 return false;
2477}
2478
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002479/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002480/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002481bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002482 const MCExpr *Value;
2483 // EmitGPRel64Value requires an expression, so we are using base class
2484 // method to evaluate the expression.
2485 if (getParser().parseExpression(Value))
2486 return true;
2487 getParser().getStreamer().EmitGPRel64Value(Value);
2488
2489 if (getLexer().isNot(AsmToken::EndOfStatement))
2490 return Error(getLexer().getLoc(), "unexpected token in directive");
2491 Parser.Lex(); // Eat EndOfStatement token.
2492 return false;
2493}
2494
Jack Carter0cd3c192014-01-06 23:27:31 +00002495bool MipsAsmParser::parseDirectiveOption() {
2496 // Get the option token.
2497 AsmToken Tok = Parser.getTok();
2498 // At the moment only identifiers are supported.
2499 if (Tok.isNot(AsmToken::Identifier)) {
2500 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2501 Parser.eatToEndOfStatement();
2502 return false;
2503 }
2504
2505 StringRef Option = Tok.getIdentifier();
2506
2507 if (Option == "pic0") {
2508 getTargetStreamer().emitDirectiveOptionPic0();
2509 Parser.Lex();
2510 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2511 Error(Parser.getTok().getLoc(),
2512 "unexpected token in .option pic0 directive");
2513 Parser.eatToEndOfStatement();
2514 }
2515 return false;
2516 }
2517
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002518 if (Option == "pic2") {
2519 getTargetStreamer().emitDirectiveOptionPic2();
2520 Parser.Lex();
2521 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2522 Error(Parser.getTok().getLoc(),
2523 "unexpected token in .option pic2 directive");
2524 Parser.eatToEndOfStatement();
2525 }
2526 return false;
2527 }
2528
Jack Carter0cd3c192014-01-06 23:27:31 +00002529 // Unknown option.
2530 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2531 Parser.eatToEndOfStatement();
2532 return false;
2533}
2534
Jack Carter0b744b32012-10-04 02:29:46 +00002535bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002536 StringRef IDVal = DirectiveID.getString();
2537
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002538 if (IDVal == ".cpload")
2539 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002540 if (IDVal == ".dword") {
2541 parseDataDirective(8, DirectiveID.getLoc());
2542 return false;
2543 }
2544
Jack Carterd0bd6422013-04-18 00:41:53 +00002545 if (IDVal == ".ent") {
2546 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002547 Parser.Lex();
2548 return false;
2549 }
2550
Jack Carter07c818d2013-01-25 01:31:34 +00002551 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002552 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002553 Parser.Lex();
2554 return false;
2555 }
2556
Jack Carter07c818d2013-01-25 01:31:34 +00002557 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002558 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002559 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002560 return false;
2561 }
2562
Jack Carter07c818d2013-01-25 01:31:34 +00002563 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002564 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002565 }
2566
Jack Carter07c818d2013-01-25 01:31:34 +00002567 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002568 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002569 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002570 return false;
2571 }
2572
Jack Carter07c818d2013-01-25 01:31:34 +00002573 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002574 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002575 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002576 return false;
2577 }
2578
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002579 if (IDVal == ".nan")
2580 return parseDirectiveNaN();
2581
Jack Carter07c818d2013-01-25 01:31:34 +00002582 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002583 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002584 return false;
2585 }
2586
Rafael Espindolab59fb732014-03-28 18:50:26 +00002587 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002588 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002589 return false;
2590 }
2591
Jack Carter07c818d2013-01-25 01:31:34 +00002592 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002593 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002594 return false;
2595 }
2596
Jack Carter0cd3c192014-01-06 23:27:31 +00002597 if (IDVal == ".option")
2598 return parseDirectiveOption();
2599
2600 if (IDVal == ".abicalls") {
2601 getTargetStreamer().emitDirectiveAbiCalls();
2602 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2603 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2604 // Clear line
2605 Parser.eatToEndOfStatement();
2606 }
2607 return false;
2608 }
2609
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002610 if (IDVal == ".cpsetup")
2611 return parseDirectiveCPSetup();
2612
Rafael Espindola870c4e92012-01-11 03:56:41 +00002613 return true;
2614}
2615
Rafael Espindola870c4e92012-01-11 03:56:41 +00002616extern "C" void LLVMInitializeMipsAsmParser() {
2617 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2618 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2619 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2620 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2621}
Jack Carterb4dbc172012-09-05 23:34:03 +00002622
2623#define GET_REGISTER_MATCHER
2624#define GET_MATCHER_IMPLEMENTATION
2625#include "MipsGenAsmMatcher.inc"