blob: 736c910e45af62a9a3d74abc3348fafbd16c7e09 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000019#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000020#include "llvm/MC/MCParser/MCAsmLexer.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000025#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000026#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000027#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000028#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000029
30using namespace llvm;
31
Joey Gouly0e76fa72013-09-12 10:28:05 +000032namespace llvm {
33class MCInstrInfo;
34}
35
Rafael Espindola870c4e92012-01-11 03:56:41 +000036namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000037class MipsAssemblerOptions {
38public:
Vladimir Medic4c299852013-11-06 11:27:05 +000039 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000040
Vladimir Medic4c299852013-11-06 11:27:05 +000041 unsigned getATRegNum() { return aTReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000042 bool setATReg(unsigned Reg);
43
Vladimir Medic4c299852013-11-06 11:27:05 +000044 bool isReorder() { return reorder; }
45 void setReorder() { reorder = true; }
46 void setNoreorder() { reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000047
Vladimir Medic4c299852013-11-06 11:27:05 +000048 bool isMacro() { return macro; }
49 void setMacro() { macro = true; }
50 void setNomacro() { macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000051
52private:
53 unsigned aTReg;
54 bool reorder;
55 bool macro;
56};
57}
58
59namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000060class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000061 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000062 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000063 return static_cast<MipsTargetStreamer &>(TS);
64 }
65
Jack Carterb4dbc172012-09-05 23:34:03 +000066 MCSubtargetInfo &STI;
67 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000068 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000069
Akira Hatanaka7605630c2012-08-17 20:16:42 +000070#define GET_ASSEMBLER_HEADER
71#include "MipsGenAsmMatcher.inc"
72
Chad Rosier49963552012-10-13 00:26:04 +000073 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Vladimir Medic4c299852013-11-06 11:27:05 +000074 SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000075 MCStreamer &Out, unsigned &ErrorInfo,
76 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000077
Daniel Sandersb50ccf82014-04-01 10:35:28 +000078 /// Parse a register as used in CFI directives
Rafael Espindola870c4e92012-01-11 03:56:41 +000079 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
80
Daniel Sandersb50ccf82014-04-01 10:35:28 +000081 bool ParseParenSuffix(StringRef Name,
82 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
83
84 bool ParseBracketSuffix(StringRef Name,
85 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
86
Chad Rosierf0e87202012-10-25 20:41:34 +000087 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
88 SMLoc NameLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +000089 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000090
91 bool ParseDirective(AsmToken DirectiveID);
92
Jack Carterb4dbc172012-09-05 23:34:03 +000093 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +000094 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +000095
Daniel Sandersb50ccf82014-04-01 10:35:28 +000096 MipsAsmParser::OperandMatchResultTy MatchAnyRegisterNameWithoutDollar(
97 SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
98 SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000099
100 MipsAsmParser::OperandMatchResultTy
Daniel Sanders21bce302014-04-01 12:35:23 +0000101 MatchAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000102 SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000103
Jack Carter873c7242013-01-12 01:03:14 +0000104 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000105 ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000106
107 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000108 ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000109
110 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000111 ParseJumpTarget(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000112
113 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000114 parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000115
Matheus Almeida779c5932013-11-18 12:32:49 +0000116 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000117 ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000118
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000119 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000120
Vladimir Medic4c299852013-11-06 11:27:05 +0000121 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
Jack Carterb4dbc172012-09-05 23:34:03 +0000122 StringRef Mnemonic);
123
Jack Carter30a59822012-10-04 04:03:53 +0000124 bool needsExpansion(MCInst &Inst);
125
126 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000127 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000128 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000129 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000130 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
131 SmallVectorImpl<MCInst> &Instructions);
132 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
133 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000134 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000135 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
136 bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000137 bool reportParseError(StringRef ErrorMsg);
138
Jack Carterb5cf5902013-04-17 00:18:04 +0000139 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000140 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000141
Vladimir Medic4c299852013-11-06 11:27:05 +0000142 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000143
144 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000145 bool parseSetFeature(uint64_t Feature);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000146 bool parseDirectiveCPSetup();
Jack Carter0b744b32012-10-04 02:29:46 +0000147 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000148 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000149
150 bool parseSetAtDirective();
151 bool parseSetNoAtDirective();
152 bool parseSetMacroDirective();
153 bool parseSetNoMacroDirective();
154 bool parseSetReorderDirective();
155 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000156 bool parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +0000157
Jack Carterd76b2372013-03-21 21:44:16 +0000158 bool parseSetAssignment();
159
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000160 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000161 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000162 bool parseDirectiveGpDWord();
Jack Carter07c818d2013-01-25 01:31:34 +0000163
Jack Carterdc1e35d2012-09-06 20:00:02 +0000164 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000165
Daniel Sanders5e94e682014-03-27 16:42:17 +0000166 bool isGP64() const {
167 return (STI.getFeatureBits() & Mips::FeatureGP64Bit) != 0;
Jack Carterb4dbc172012-09-05 23:34:03 +0000168 }
169
Jack Cartera63b16a2012-09-07 00:23:42 +0000170 bool isFP64() const {
171 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
172 }
173
Daniel Sandersa4b0c742014-03-26 11:39:07 +0000174 bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
Vladimir Medic4c299852013-11-06 11:27:05 +0000175 bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000176
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000177 bool isMicroMips() const {
178 return STI.getFeatureBits() & Mips::FeatureMicroMips;
179 }
180
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000181 bool parseRegister(unsigned &RegNum);
182
183 bool eatComma(StringRef ErrorStr);
184
Jack Carter1ac53222013-02-20 23:11:17 +0000185 int matchCPURegisterName(StringRef Symbol);
186
Jack Carter873c7242013-01-12 01:03:14 +0000187 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000188
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000189 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000190
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000191 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000192
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000193 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000194
Jack Carter5dc8ac92013-09-25 23:50:44 +0000195 int matchMSA128RegisterName(StringRef Name);
196
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000197 int matchMSA128CtrlRegisterName(StringRef Name);
198
Jack Carterd0bd6422013-04-18 00:41:53 +0000199 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000200
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000201 unsigned getGPR(int RegNo);
202
Jack Carter1ac53222013-02-20 23:11:17 +0000203 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000204
205 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000206 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000207
208 // Helper function that checks if the value of a vector index is within the
209 // boundaries of accepted values for each RegisterKind
210 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
211 bool validateMSAIndex(int Val, int RegKind);
212
Vladimir Medic615b26e2014-03-04 09:54:09 +0000213 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
214 if (!(STI.getFeatureBits() & Feature)) {
215 setAvailableFeatures(ComputeAvailableFeatures(
216 STI.ToggleFeature(FeatureString)));
217 }
218 }
219
220 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
221 if (STI.getFeatureBits() & Feature) {
222 setAvailableFeatures(ComputeAvailableFeatures(
223 STI.ToggleFeature(FeatureString)));
224 }
225 }
226
Rafael Espindola870c4e92012-01-11 03:56:41 +0000227public:
Joey Gouly0e76fa72013-09-12 10:28:05 +0000228 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
229 const MCInstrInfo &MII)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000230 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000231 // Initialize the set of available features.
232 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000233
234 // Assert exactly one ABI was chosen.
235 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
236 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
237 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
238 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000239 }
240
Jack Carterb4dbc172012-09-05 23:34:03 +0000241 MCAsmParser &getParser() const { return Parser; }
242 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000243
244 /// Warn if RegNo is the current assembler temporary.
245 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000246};
247}
248
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000249namespace {
250
251/// MipsOperand - Instances of this class represent a parsed Mips machine
252/// instruction.
253class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000254public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000255 /// Broad categories of register classes
256 /// The exact class is finalized by the render method.
257 enum RegKind {
258 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
259 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
260 /// isFP64())
261 RegKind_FCC = 4, /// FCC
262 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
263 RegKind_MSACtrl = 16, /// MSA control registers
264 RegKind_COP2 = 32, /// COP2
265 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
266 /// context).
267 RegKind_CCR = 128, /// CCR
268 RegKind_HWRegs = 256, /// HWRegs
269
270 /// Potentially any (e.g. $1)
271 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
272 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
273 RegKind_CCR | RegKind_HWRegs
Jack Carter873c7242013-01-12 01:03:14 +0000274 };
275
276private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000277 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000278 k_Immediate, /// An immediate (possibly involving symbol references)
279 k_Memory, /// Base + Offset Memory Address
280 k_PhysRegister, /// A physical register from the Mips namespace
281 k_RegisterIndex, /// A register index in one or more RegKind.
282 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000283 } Kind;
284
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000285 MipsOperand(KindTy K, MipsAsmParser &Parser)
286 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
287
288 /// For diagnostics, and checking the assembler temporary
289 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000290
Eric Christopher8996c5d2013-03-15 00:42:55 +0000291 struct Token {
292 const char *Data;
293 unsigned Length;
294 };
295
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000296 struct PhysRegOp {
297 unsigned Num; /// Register Number
298 };
299
300 struct RegIdxOp {
301 unsigned Index; /// Index into the register class
302 RegKind Kind; /// Bitfield of the kinds it could possibly be
303 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000304 };
305
306 struct ImmOp {
307 const MCExpr *Val;
308 };
309
310 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000311 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000312 const MCExpr *Off;
313 };
314
Jack Carterb4dbc172012-09-05 23:34:03 +0000315 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000316 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000317 struct PhysRegOp PhysReg;
318 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000319 struct ImmOp Imm;
320 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000321 };
322
323 SMLoc StartLoc, EndLoc;
324
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000325 /// Internal constructor for register kinds
326 static MipsOperand *CreateReg(unsigned Index, RegKind RegKind,
327 const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
328 MipsAsmParser &Parser) {
329 MipsOperand *Op = new MipsOperand(k_RegisterIndex, Parser);
330 Op->RegIdx.Index = Index;
331 Op->RegIdx.RegInfo = RegInfo;
332 Op->RegIdx.Kind = RegKind;
333 Op->StartLoc = S;
334 Op->EndLoc = E;
335 return Op;
336 }
337
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000338public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000339 /// Coerce the register to GPR32 and return the real register for the current
340 /// target.
341 unsigned getGPR32Reg() const {
342 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
343 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
344 unsigned ClassID = Mips::GPR32RegClassID;
345 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000346 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000347
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000348 /// Coerce the register to GPR64 and return the real register for the current
349 /// target.
350 unsigned getGPR64Reg() const {
351 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
352 unsigned ClassID = Mips::GPR64RegClassID;
353 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000354 }
355
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000356private:
357 /// Coerce the register to AFGR64 and return the real register for the current
358 /// target.
359 unsigned getAFGR64Reg() const {
360 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
361 if (RegIdx.Index % 2 != 0)
362 AsmParser.Warning(StartLoc, "Float register should be even.");
363 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
364 .getRegister(RegIdx.Index / 2);
365 }
366
367 /// Coerce the register to FGR64 and return the real register for the current
368 /// target.
369 unsigned getFGR64Reg() const {
370 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
371 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
372 .getRegister(RegIdx.Index);
373 }
374
375 /// Coerce the register to FGR32 and return the real register for the current
376 /// target.
377 unsigned getFGR32Reg() const {
378 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
379 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
380 .getRegister(RegIdx.Index);
381 }
382
383 /// Coerce the register to FGRH32 and return the real register for the current
384 /// target.
385 unsigned getFGRH32Reg() const {
386 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
387 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
388 .getRegister(RegIdx.Index);
389 }
390
391 /// Coerce the register to FCC and return the real register for the current
392 /// target.
393 unsigned getFCCReg() const {
394 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
395 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
396 .getRegister(RegIdx.Index);
397 }
398
399 /// Coerce the register to MSA128 and return the real register for the current
400 /// target.
401 unsigned getMSA128Reg() const {
402 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
403 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
404 // identical
405 unsigned ClassID = Mips::MSA128BRegClassID;
406 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
407 }
408
409 /// Coerce the register to MSACtrl and return the real register for the
410 /// current target.
411 unsigned getMSACtrlReg() const {
412 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
413 unsigned ClassID = Mips::MSACtrlRegClassID;
414 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
415 }
416
417 /// Coerce the register to COP2 and return the real register for the
418 /// current target.
419 unsigned getCOP2Reg() const {
420 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
421 unsigned ClassID = Mips::COP2RegClassID;
422 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
423 }
424
425 /// Coerce the register to ACC64DSP and return the real register for the
426 /// current target.
427 unsigned getACC64DSPReg() const {
428 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
429 unsigned ClassID = Mips::ACC64DSPRegClassID;
430 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
431 }
432
433 /// Coerce the register to HI32DSP and return the real register for the
434 /// current target.
435 unsigned getHI32DSPReg() const {
436 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
437 unsigned ClassID = Mips::HI32DSPRegClassID;
438 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
439 }
440
441 /// Coerce the register to LO32DSP and return the real register for the
442 /// current target.
443 unsigned getLO32DSPReg() const {
444 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
445 unsigned ClassID = Mips::LO32DSPRegClassID;
446 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
447 }
448
449 /// Coerce the register to CCR and return the real register for the
450 /// current target.
451 unsigned getCCRReg() const {
452 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
453 unsigned ClassID = Mips::CCRRegClassID;
454 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
455 }
456
457 /// Coerce the register to HWRegs and return the real register for the
458 /// current target.
459 unsigned getHWRegsReg() const {
460 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
461 unsigned ClassID = Mips::HWRegsRegClassID;
462 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
463 }
464
465public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000466 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000467 // Add as immediate when possible. Null MCExpr = 0.
468 if (Expr == 0)
469 Inst.addOperand(MCOperand::CreateImm(0));
470 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
471 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
472 else
473 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000474 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000475
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000476 void addRegOperands(MCInst &Inst, unsigned N) const {
477 llvm_unreachable("Use a custom parser instead");
478 }
479
Daniel Sanders21bce302014-04-01 12:35:23 +0000480 /// Render the operand to an MCInst as a GPR32
481 /// Asserts if the wrong number of operands are requested, or the operand
482 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000483 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
484 assert(N == 1 && "Invalid number of operands!");
485 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
486 }
487
Daniel Sanders21bce302014-04-01 12:35:23 +0000488 /// Render the operand to an MCInst as a GPR64
489 /// Asserts if the wrong number of operands are requested, or the operand
490 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000491 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
492 assert(N == 1 && "Invalid number of operands!");
493 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
494 }
495
496 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
497 assert(N == 1 && "Invalid number of operands!");
498 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
499 }
500
501 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
502 assert(N == 1 && "Invalid number of operands!");
503 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
504 }
505
506 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
507 assert(N == 1 && "Invalid number of operands!");
508 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
509 }
510
511 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
512 assert(N == 1 && "Invalid number of operands!");
513 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
514 }
515
516 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
517 assert(N == 1 && "Invalid number of operands!");
518 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
519 }
520
521 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
522 assert(N == 1 && "Invalid number of operands!");
523 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
524 }
525
526 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
527 assert(N == 1 && "Invalid number of operands!");
528 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
529 }
530
531 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
532 assert(N == 1 && "Invalid number of operands!");
533 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
534 }
535
536 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
537 assert(N == 1 && "Invalid number of operands!");
538 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
539 }
540
541 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
542 assert(N == 1 && "Invalid number of operands!");
543 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
544 }
545
546 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
547 assert(N == 1 && "Invalid number of operands!");
548 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
549 }
550
551 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
552 assert(N == 1 && "Invalid number of operands!");
553 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
554 }
555
556 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
557 assert(N == 1 && "Invalid number of operands!");
558 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
559 }
560
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000561 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000562 assert(N == 1 && "Invalid number of operands!");
563 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000564 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000565 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000566
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000567 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000568 assert(N == 2 && "Invalid number of operands!");
569
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000570 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000571
572 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000573 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000574 }
575
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 bool isReg() const {
577 // As a special case until we sort out the definition of div/divu, pretend
578 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
579 if (isGPRAsmReg() && RegIdx.Index == 0)
580 return true;
581
582 return Kind == k_PhysRegister;
583 }
584 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000585 bool isImm() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 bool isConstantImm() const {
587 return isImm() && dyn_cast<MCConstantExpr>(getImm());
588 }
589 bool isToken() const {
590 // Note: It's not possible to pretend that other operand kinds are tokens.
591 // The matcher emitter checks tokens first.
592 return Kind == k_Token;
593 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000594 bool isMem() const { return Kind == k_Memory; }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000595 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000596 bool isLSAImm() const {
597 if (!isConstantImm())
598 return false;
599 int64_t Val = getConstantImm();
600 return 1 <= Val && Val <= 4;
601 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000602
603 StringRef getToken() const {
604 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000605 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000606 }
607
608 unsigned getReg() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000609 // As a special case until we sort out the definition of div/divu, pretend
610 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
611 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
612 RegIdx.Kind & RegKind_GPR)
613 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000614
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000615 assert(Kind == k_PhysRegister && "Invalid access!");
616 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000617 }
618
Jack Carterb4dbc172012-09-05 23:34:03 +0000619 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000620 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000621 return Imm.Val;
622 }
623
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000624 int64_t getConstantImm() const {
625 const MCExpr *Val = getImm();
626 return static_cast<const MCConstantExpr *>(Val)->getValue();
627 }
628
629 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000630 assert((Kind == k_Memory) && "Invalid access!");
631 return Mem.Base;
632 }
633
634 const MCExpr *getMemOff() const {
635 assert((Kind == k_Memory) && "Invalid access!");
636 return Mem.Off;
637 }
638
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000639 static MipsOperand *CreateToken(StringRef Str, SMLoc S,
640 MipsAsmParser &Parser) {
641 MipsOperand *Op = new MipsOperand(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000642 Op->Tok.Data = Str.data();
643 Op->Tok.Length = Str.size();
644 Op->StartLoc = S;
645 Op->EndLoc = S;
646 return Op;
647 }
648
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 /// Create a numeric register (e.g. $1). The exact register remains
650 /// unresolved until an instruction successfully matches
651 static MipsOperand *CreateNumericReg(unsigned Index,
652 const MCRegisterInfo *RegInfo, SMLoc S,
653 SMLoc E, MipsAsmParser &Parser) {
654 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
655 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000656 }
657
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000658 /// Create a register that is definitely a GPR.
659 /// This is typically only used for named registers such as $gp.
660 static MipsOperand *CreateGPRReg(unsigned Index,
661 const MCRegisterInfo *RegInfo, SMLoc S,
662 SMLoc E, MipsAsmParser &Parser) {
663 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000664 }
665
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000666 /// Create a register that is definitely a FGR.
667 /// This is typically only used for named registers such as $f0.
668 static MipsOperand *CreateFGRReg(unsigned Index,
669 const MCRegisterInfo *RegInfo, SMLoc S,
670 SMLoc E, MipsAsmParser &Parser) {
671 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
672 }
673
674 /// Create a register that is definitely an FCC.
675 /// This is typically only used for named registers such as $fcc0.
676 static MipsOperand *CreateFCCReg(unsigned Index,
677 const MCRegisterInfo *RegInfo, SMLoc S,
678 SMLoc E, MipsAsmParser &Parser) {
679 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
680 }
681
682 /// Create a register that is definitely an ACC.
683 /// This is typically only used for named registers such as $ac0.
684 static MipsOperand *CreateACCReg(unsigned Index,
685 const MCRegisterInfo *RegInfo, SMLoc S,
686 SMLoc E, MipsAsmParser &Parser) {
687 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
688 }
689
690 /// Create a register that is definitely an MSA128.
691 /// This is typically only used for named registers such as $w0.
692 static MipsOperand *CreateMSA128Reg(unsigned Index,
693 const MCRegisterInfo *RegInfo, SMLoc S,
694 SMLoc E, MipsAsmParser &Parser) {
695 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
696 }
697
698 /// Create a register that is definitely an MSACtrl.
699 /// This is typically only used for named registers such as $msaaccess.
700 static MipsOperand *CreateMSACtrlReg(unsigned Index,
701 const MCRegisterInfo *RegInfo, SMLoc S,
702 SMLoc E, MipsAsmParser &Parser) {
703 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
704 }
705
706 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E,
707 MipsAsmParser &Parser) {
708 MipsOperand *Op = new MipsOperand(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000709 Op->Imm.Val = Val;
710 Op->StartLoc = S;
711 Op->EndLoc = E;
712 return Op;
713 }
714
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S,
716 SMLoc E, MipsAsmParser &Parser) {
717 MipsOperand *Op = new MipsOperand(k_Memory, Parser);
Jack Carterdc1e35d2012-09-06 20:00:02 +0000718 Op->Mem.Base = Base;
719 Op->Mem.Off = Off;
720 Op->StartLoc = S;
721 Op->EndLoc = E;
722 return Op;
723 }
724
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000725 bool isGPRAsmReg() const {
726 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000727 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 bool isFGRAsmReg() const {
729 // AFGR64 is $0-$15 but we handle this in getAFGR64()
730 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000731 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 bool isHWRegsAsmReg() const {
733 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000734 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000735 bool isCCRAsmReg() const {
736 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000737 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 bool isFCCAsmReg() const {
739 return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000740 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 bool isACCAsmReg() const {
742 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000743 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 bool isCOP2AsmReg() const {
745 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000746 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 bool isMSA128AsmReg() const {
748 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000749 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 bool isMSACtrlAsmReg() const {
751 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000752 }
753
Jack Carterb4dbc172012-09-05 23:34:03 +0000754 /// getStartLoc - Get the location of the first token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000755 SMLoc getStartLoc() const { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000756 /// getEndLoc - Get the location of the last token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000757 SMLoc getEndLoc() const { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000758
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000759 virtual void print(raw_ostream &OS) const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 switch (Kind) {
761 case k_Immediate:
762 OS << "Imm<";
763 Imm.Val->print(OS);
764 OS << ">";
765 break;
766 case k_Memory:
767 OS << "Mem<";
768 Mem.Base->print(OS);
769 OS << ", ";
770 Mem.Off->print(OS);
771 OS << ">";
772 break;
773 case k_PhysRegister:
774 OS << "PhysReg<" << PhysReg.Num << ">";
775 break;
776 case k_RegisterIndex:
777 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
778 break;
779 case k_Token:
780 OS << Tok.Data;
781 break;
782 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000783 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000784}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000785} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000786
Jack Carter9e65aa32013-03-22 00:05:30 +0000787namespace llvm {
788extern const MCInstrDesc MipsInsts[];
789}
790static const MCInstrDesc &getInstDesc(unsigned Opcode) {
791 return MipsInsts[Opcode];
792}
793
794bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000795 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000796 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000797
Jack Carter9e65aa32013-03-22 00:05:30 +0000798 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000799
800 if (MCID.isBranch() || MCID.isCall()) {
801 const unsigned Opcode = Inst.getOpcode();
802 MCOperand Offset;
803
804 switch (Opcode) {
805 default:
806 break;
807 case Mips::BEQ:
808 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 case Mips::BEQ_MM:
810 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000811 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000812 Offset = Inst.getOperand(2);
813 if (!Offset.isImm())
814 break; // We'll deal with this situation later on when applying fixups.
815 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
816 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000817 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000818 return Error(IDLoc, "branch to misaligned address");
819 break;
820 case Mips::BGEZ:
821 case Mips::BGTZ:
822 case Mips::BLEZ:
823 case Mips::BLTZ:
824 case Mips::BGEZAL:
825 case Mips::BLTZAL:
826 case Mips::BC1F:
827 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 case Mips::BGEZ_MM:
829 case Mips::BGTZ_MM:
830 case Mips::BLEZ_MM:
831 case Mips::BLTZ_MM:
832 case Mips::BGEZAL_MM:
833 case Mips::BLTZAL_MM:
834 case Mips::BC1F_MM:
835 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000836 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000837 Offset = Inst.getOperand(1);
838 if (!Offset.isImm())
839 break; // We'll deal with this situation later on when applying fixups.
840 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
841 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000842 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000843 return Error(IDLoc, "branch to misaligned address");
844 break;
845 }
846 }
847
Jack Carterc15c1d22013-04-25 23:31:35 +0000848 if (MCID.hasDelaySlot() && Options.isReorder()) {
849 // If this instruction has a delay slot and .set reorder is active,
850 // emit a NOP after it.
851 Instructions.push_back(Inst);
852 MCInst NopInst;
853 NopInst.setOpcode(Mips::SLL);
854 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
855 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
856 NopInst.addOperand(MCOperand::CreateImm(0));
857 Instructions.push_back(NopInst);
858 return false;
859 }
860
Jack Carter9e65aa32013-03-22 00:05:30 +0000861 if (MCID.mayLoad() || MCID.mayStore()) {
862 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000863 // reference or immediate we may have to expand instructions.
864 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000865 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000866 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
867 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000868 MCOperand &Op = Inst.getOperand(i);
869 if (Op.isImm()) {
870 int MemOffset = Op.getImm();
871 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000872 // Offset can't exceed 16bit value.
873 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000874 return false;
875 }
876 } else if (Op.isExpr()) {
877 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000878 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000879 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000880 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000881 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000882 // Expand symbol.
883 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000884 return false;
885 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000886 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000887 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000888 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000889 }
890 }
891 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000892 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000893 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000894
895 if (needsExpansion(Inst))
896 expandInstruction(Inst, IDLoc, Instructions);
897 else
898 Instructions.push_back(Inst);
899
900 return false;
901}
902
Jack Carter30a59822012-10-04 04:03:53 +0000903bool MipsAsmParser::needsExpansion(MCInst &Inst) {
904
Jack Carterd0bd6422013-04-18 00:41:53 +0000905 switch (Inst.getOpcode()) {
906 case Mips::LoadImm32Reg:
907 case Mips::LoadAddr32Imm:
908 case Mips::LoadAddr32Reg:
Daniel Sandersa771fef2014-03-24 14:05:39 +0000909 case Mips::SUBi:
910 case Mips::SUBiu:
911 case Mips::DSUBi:
912 case Mips::DSUBiu:
Jack Carterd0bd6422013-04-18 00:41:53 +0000913 return true;
914 default:
915 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000916 }
917}
Jack Carter92995f12012-10-06 00:53:28 +0000918
Jack Carter30a59822012-10-04 04:03:53 +0000919void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000920 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000921 switch (Inst.getOpcode()) {
922 case Mips::LoadImm32Reg:
923 return expandLoadImm(Inst, IDLoc, Instructions);
924 case Mips::LoadAddr32Imm:
925 return expandLoadAddressImm(Inst, IDLoc, Instructions);
926 case Mips::LoadAddr32Reg:
927 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Daniel Sandersa771fef2014-03-24 14:05:39 +0000928 case Mips::SUBi:
929 Instructions.push_back(MCInstBuilder(Mips::ADDi)
930 .addReg(Inst.getOperand(0).getReg())
931 .addReg(Inst.getOperand(1).getReg())
932 .addImm(-Inst.getOperand(2).getImm()));
933 return;
934 case Mips::SUBiu:
935 Instructions.push_back(MCInstBuilder(Mips::ADDiu)
936 .addReg(Inst.getOperand(0).getReg())
937 .addReg(Inst.getOperand(1).getReg())
938 .addImm(-Inst.getOperand(2).getImm()));
939 return;
940 case Mips::DSUBi:
941 Instructions.push_back(MCInstBuilder(Mips::DADDi)
942 .addReg(Inst.getOperand(0).getReg())
943 .addReg(Inst.getOperand(1).getReg())
944 .addImm(-Inst.getOperand(2).getImm()));
945 return;
946 case Mips::DSUBiu:
947 Instructions.push_back(MCInstBuilder(Mips::DADDiu)
948 .addReg(Inst.getOperand(0).getReg())
949 .addReg(Inst.getOperand(1).getReg())
950 .addImm(-Inst.getOperand(2).getImm()));
951 return;
Jack Carterd0bd6422013-04-18 00:41:53 +0000952 }
Jack Carter30a59822012-10-04 04:03:53 +0000953}
Jack Carter92995f12012-10-06 00:53:28 +0000954
Jack Carter30a59822012-10-04 04:03:53 +0000955void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000956 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000957 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000958 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000959 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000960 const MCOperand &RegOp = Inst.getOperand(0);
961 assert(RegOp.isReg() && "expected register operand kind");
962
963 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000964 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000965 if (0 <= ImmValue && ImmValue <= 65535) {
966 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000967 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000968 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000969 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000970 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000971 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000972 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000973 } else if (ImmValue < 0 && ImmValue >= -32768) {
974 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000975 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000976 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000977 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000978 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000979 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000980 Instructions.push_back(tmpInst);
981 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000982 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000983 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000984 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000985 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000986 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
987 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000988 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000989 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000990 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000991 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
992 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
993 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
994 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000995 Instructions.push_back(tmpInst);
996 }
997}
Jack Carter92995f12012-10-06 00:53:28 +0000998
Vladimir Medic4c299852013-11-06 11:27:05 +0000999void
1000MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1001 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001002 MCInst tmpInst;
1003 const MCOperand &ImmOp = Inst.getOperand(2);
1004 assert(ImmOp.isImm() && "expected immediate operand kind");
1005 const MCOperand &SrcRegOp = Inst.getOperand(1);
1006 assert(SrcRegOp.isReg() && "expected register operand kind");
1007 const MCOperand &DstRegOp = Inst.getOperand(0);
1008 assert(DstRegOp.isReg() && "expected register operand kind");
1009 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001010 if (-32768 <= ImmValue && ImmValue <= 65535) {
1011 // For -32768 <= j <= 65535.
1012 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001013 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001014 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1015 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1016 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1017 Instructions.push_back(tmpInst);
1018 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001019 // For any other value of j that is representable as a 32-bit integer.
1020 // la d,j(s) => lui d,hi16(j)
1021 // ori d,d,lo16(j)
1022 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001023 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001024 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1025 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1026 Instructions.push_back(tmpInst);
1027 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001028 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001029 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1030 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1031 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1032 Instructions.push_back(tmpInst);
1033 tmpInst.clear();
1034 tmpInst.setOpcode(Mips::ADDu);
1035 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1036 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1037 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1038 Instructions.push_back(tmpInst);
1039 }
1040}
1041
Vladimir Medic4c299852013-11-06 11:27:05 +00001042void
1043MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1044 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001045 MCInst tmpInst;
1046 const MCOperand &ImmOp = Inst.getOperand(1);
1047 assert(ImmOp.isImm() && "expected immediate operand kind");
1048 const MCOperand &RegOp = Inst.getOperand(0);
1049 assert(RegOp.isReg() && "expected register operand kind");
1050 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001051 if (-32768 <= ImmValue && ImmValue <= 65535) {
1052 // For -32768 <= j <= 65535.
1053 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001054 tmpInst.setOpcode(Mips::ADDiu);
1055 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001056 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001057 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1058 Instructions.push_back(tmpInst);
1059 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001060 // For any other value of j that is representable as a 32-bit integer.
1061 // la d,j => lui d,hi16(j)
1062 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001063 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001064 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1065 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1066 Instructions.push_back(tmpInst);
1067 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001068 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001069 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1070 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1071 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1072 Instructions.push_back(tmpInst);
1073 }
1074}
1075
Jack Carter9e65aa32013-03-22 00:05:30 +00001076void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001077 SmallVectorImpl<MCInst> &Instructions,
1078 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001079 const MCSymbolRefExpr *SR;
1080 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001081 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001082 const MCExpr *ExprOffset;
1083 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +00001084 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001085 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +00001086 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001087 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1088 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001089 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001090 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1091 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001092 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001093 if (isImmOpnd) {
1094 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1095 ImmOffset = Inst.getOperand(2).getImm();
1096 LoOffset = ImmOffset & 0x0000ffff;
1097 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001098 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001099 if (LoOffset & 0x8000)
1100 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001101 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001102 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001103 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001104 TempInst.setLoc(IDLoc);
1105 // 1st instruction in expansion is LUi. For load instruction we can use
1106 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001107 // but for stores we must use $at.
1108 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +00001109 TempInst.setOpcode(Mips::LUi);
1110 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1111 if (isImmOpnd)
1112 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1113 else {
1114 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001115 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1117 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1118 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001119 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001120 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001121 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001122 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001123 }
1124 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001125 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001126 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001127 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001128 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001129 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001130 TempInst.setOpcode(Mips::ADDu);
1131 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1132 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1133 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1134 Instructions.push_back(TempInst);
1135 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001136 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001137 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001138 TempInst.setOpcode(Inst.getOpcode());
1139 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1140 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1141 if (isImmOpnd)
1142 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1143 else {
1144 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001145 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1146 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1147 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001148 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001149 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001150 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001151 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001152 }
1153 }
1154 Instructions.push_back(TempInst);
1155 TempInst.clear();
1156}
1157
Vladimir Medic4c299852013-11-06 11:27:05 +00001158bool MipsAsmParser::MatchAndEmitInstruction(
1159 SMLoc IDLoc, unsigned &Opcode,
1160 SmallVectorImpl<MCParsedAsmOperand *> &Operands, MCStreamer &Out,
1161 unsigned &ErrorInfo, bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001162 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001163 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001164 unsigned MatchResult =
1165 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001166
1167 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001168 default:
1169 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001170 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001171 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001172 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001173 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001174 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001175 return false;
1176 }
1177 case Match_MissingFeature:
1178 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1179 return true;
1180 case Match_InvalidOperand: {
1181 SMLoc ErrorLoc = IDLoc;
1182 if (ErrorInfo != ~0U) {
1183 if (ErrorInfo >= Operands.size())
1184 return Error(IDLoc, "too few operands for instruction");
1185
Vladimir Medic4c299852013-11-06 11:27:05 +00001186 ErrorLoc = ((MipsOperand *)Operands[ErrorInfo])->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001187 if (ErrorLoc == SMLoc())
1188 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001189 }
1190
1191 return Error(ErrorLoc, "invalid operand for instruction");
1192 }
1193 case Match_MnemonicFail:
1194 return Error(IDLoc, "invalid instruction");
1195 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001196 return true;
1197}
1198
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001199void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1200 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1201 if (RegIndex == 1)
1202 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001203 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001204 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1205 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001206 }
1207}
1208
Jack Carter1ac53222013-02-20 23:11:17 +00001209int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001210 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001211
Vladimir Medic4c299852013-11-06 11:27:05 +00001212 CC = StringSwitch<unsigned>(Name)
1213 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001214 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001215 .Case("a0", 4)
1216 .Case("a1", 5)
1217 .Case("a2", 6)
1218 .Case("a3", 7)
1219 .Case("v0", 2)
1220 .Case("v1", 3)
1221 .Case("s0", 16)
1222 .Case("s1", 17)
1223 .Case("s2", 18)
1224 .Case("s3", 19)
1225 .Case("s4", 20)
1226 .Case("s5", 21)
1227 .Case("s6", 22)
1228 .Case("s7", 23)
1229 .Case("k0", 26)
1230 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001231 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001232 .Case("sp", 29)
1233 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001234 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001235 .Case("ra", 31)
1236 .Case("t0", 8)
1237 .Case("t1", 9)
1238 .Case("t2", 10)
1239 .Case("t3", 11)
1240 .Case("t4", 12)
1241 .Case("t5", 13)
1242 .Case("t6", 14)
1243 .Case("t7", 15)
1244 .Case("t8", 24)
1245 .Case("t9", 25)
1246 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001247
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001248 if (isN32() || isN64()) {
1249 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1250 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1251 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1252 if (8 <= CC && CC <= 11)
1253 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001254
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001255 if (CC == -1)
1256 CC = StringSwitch<unsigned>(Name)
1257 .Case("a4", 8)
1258 .Case("a5", 9)
1259 .Case("a6", 10)
1260 .Case("a7", 11)
1261 .Case("kt0", 26)
1262 .Case("kt1", 27)
1263 .Default(-1);
1264 }
Jack Carter1ac53222013-02-20 23:11:17 +00001265
1266 return CC;
1267}
Jack Carterd0bd6422013-04-18 00:41:53 +00001268
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001269int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001270
Jack Cartera63b16a2012-09-07 00:23:42 +00001271 if (Name[0] == 'f') {
1272 StringRef NumString = Name.substr(1);
1273 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001274 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001275 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001276 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001277 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001278 return IntVal;
1279 }
1280 return -1;
1281}
Jack Cartera63b16a2012-09-07 00:23:42 +00001282
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001283int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1284
1285 if (Name.startswith("fcc")) {
1286 StringRef NumString = Name.substr(3);
1287 unsigned IntVal;
1288 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001289 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001290 if (IntVal > 7) // There are only 8 fcc registers.
1291 return -1;
1292 return IntVal;
1293 }
1294 return -1;
1295}
1296
1297int MipsAsmParser::matchACRegisterName(StringRef Name) {
1298
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001299 if (Name.startswith("ac")) {
1300 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001301 unsigned IntVal;
1302 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001303 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001304 if (IntVal > 3) // There are only 3 acc registers.
1305 return -1;
1306 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001307 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001308 return -1;
1309}
Jack Carterd0bd6422013-04-18 00:41:53 +00001310
Jack Carter5dc8ac92013-09-25 23:50:44 +00001311int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1312 unsigned IntVal;
1313
1314 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1315 return -1;
1316
1317 if (IntVal > 31)
1318 return -1;
1319
1320 return IntVal;
1321}
1322
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001323int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1324 int CC;
1325
1326 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001327 .Case("msair", 0)
1328 .Case("msacsr", 1)
1329 .Case("msaaccess", 2)
1330 .Case("msasave", 3)
1331 .Case("msamodify", 4)
1332 .Case("msarequest", 5)
1333 .Case("msamap", 6)
1334 .Case("msaunmap", 7)
1335 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001336
1337 return CC;
1338}
1339
Jack Carter0b744b32012-10-04 02:29:46 +00001340bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1341 if (Reg > 31)
1342 return false;
1343
1344 aTReg = Reg;
1345 return true;
1346}
1347
Daniel Sandersd89b1362014-03-24 16:48:01 +00001348int MipsAsmParser::getATReg() {
1349 int AT = Options.getATRegNum();
1350 if (AT == 0)
1351 TokError("Pseudo instruction requires $at, which is not available");
1352 return AT;
1353}
Jack Carter0b744b32012-10-04 02:29:46 +00001354
Jack Carterd0bd6422013-04-18 00:41:53 +00001355unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001356 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001357}
1358
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001359unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001360 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1361 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001362}
1363
Jack Carter873c7242013-01-12 01:03:14 +00001364int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001365 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001366 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001367 return -1;
1368
Jack Carter873c7242013-01-12 01:03:14 +00001369 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001370}
1371
Vladimir Medic4c299852013-11-06 11:27:05 +00001372bool
1373MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1374 StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001375 DEBUG(dbgs() << "ParseOperand\n");
1376
Jack Carter30a59822012-10-04 04:03:53 +00001377 // Check if the current operand has a custom associated parser, if so, try to
1378 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001379 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1380 if (ResTy == MatchOperand_Success)
1381 return false;
1382 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1383 // there was a match, but an error occurred, in which case, just return that
1384 // the operand parsing failed.
1385 if (ResTy == MatchOperand_ParseFail)
1386 return true;
1387
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001388 DEBUG(dbgs() << ".. Generic Parser\n");
1389
Jack Carterb4dbc172012-09-05 23:34:03 +00001390 switch (getLexer().getKind()) {
1391 default:
1392 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1393 return true;
1394 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001395 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001396 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001397
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001398 // Almost all registers have been parsed by custom parsers. There is only
1399 // one exception to this. $zero (and it's alias $0) will reach this point
1400 // for div, divu, and similar instructions because it is not an operand
1401 // to the instruction definition but an explicit register. Special case
1402 // this situation for now.
1403 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001404 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001405
Jack Carterd0bd6422013-04-18 00:41:53 +00001406 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001407 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001408 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001409 return true;
1410
Jack Carter873c7242013-01-12 01:03:14 +00001411 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001412 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001413 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001414 const MCExpr *Res =
1415 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001416
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001417 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001418 return false;
1419 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001420 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001421 case AsmToken::LParen:
1422 case AsmToken::Minus:
1423 case AsmToken::Plus:
1424 case AsmToken::Integer:
1425 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001426 DEBUG(dbgs() << ".. generic integer\n");
1427 OperandMatchResultTy ResTy = ParseImm(Operands);
1428 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001429 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001430 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001431 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001432 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001433 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001434 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001435 return true;
1436
Jack Carter873c7242013-01-12 01:03:14 +00001437 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1438
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001439 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001440 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001441 } // case AsmToken::Percent
1442 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001443 return true;
1444}
1445
Vladimir Medic4c299852013-11-06 11:27:05 +00001446const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001447 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001448 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001449 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001450 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001451 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001452 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001453 short Val = MCE->getValue();
1454 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001455 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001456 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001457 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001458 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001459 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001460 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001461 if (LoSign)
1462 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001463 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001464 } else {
1465 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001466 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001467 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001468 }
1469
Jack Carterb5cf5902013-04-17 00:18:04 +00001470 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001471 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001472 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001473 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001474 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001475 return Res;
1476 }
1477
1478 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001479 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1480
1481 // Check for %hi(sym1-sym2) and %lo(sym1-sym2) expressions.
1482 if (isa<MCSymbolRefExpr>(BE->getLHS()) && isa<MCSymbolRefExpr>(BE->getRHS())
1483 && (VK == MCSymbolRefExpr::VK_Mips_ABS_HI
1484 || VK == MCSymbolRefExpr::VK_Mips_ABS_LO)) {
1485 // Create target expression for %hi(sym1-sym2) and %lo(sym1-sym2).
1486 if (VK == MCSymbolRefExpr::VK_Mips_ABS_HI)
1487 return MipsMCExpr::CreateHi(Expr, getContext());
1488 return MipsMCExpr::CreateLo(Expr, getContext());
1489 }
1490
Jack Carterd0bd6422013-04-18 00:41:53 +00001491 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1492 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001493 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1494 return Res;
1495 }
1496
1497 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001498 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1499 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1500 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001501 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001502 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001503 return Expr;
1504}
1505
1506bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1507
1508 switch (Expr->getKind()) {
1509 case MCExpr::Constant:
1510 return true;
1511 case MCExpr::SymbolRef:
1512 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1513 case MCExpr::Binary:
1514 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1515 if (!isEvaluated(BE->getLHS()))
1516 return false;
1517 return isEvaluated(BE->getRHS());
1518 }
1519 case MCExpr::Unary:
1520 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001521 case MCExpr::Target:
1522 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001523 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001524 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001525}
Jack Carterd0bd6422013-04-18 00:41:53 +00001526
Jack Carterb5cf5902013-04-17 00:18:04 +00001527bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001528 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001529 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001530 if (Tok.isNot(AsmToken::Identifier))
1531 return true;
1532
1533 std::string Str = Tok.getIdentifier().str();
1534
Jack Carterd0bd6422013-04-18 00:41:53 +00001535 Parser.Lex(); // Eat the identifier.
1536 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001537 const MCExpr *IdVal;
1538 SMLoc EndLoc;
1539
1540 if (getLexer().getKind() == AsmToken::LParen) {
1541 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001542 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001543 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001544 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001545 const AsmToken &nextTok = Parser.getTok();
1546 if (nextTok.isNot(AsmToken::Identifier))
1547 return true;
1548 Str += "(%";
1549 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001550 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001551 if (getLexer().getKind() != AsmToken::LParen)
1552 return true;
1553 } else
1554 break;
1555 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001556 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001557 return true;
1558
1559 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001560 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001561
1562 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001563 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001564
Jack Carterd0bd6422013-04-18 00:41:53 +00001565 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001566 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001567}
1568
Jack Carterb4dbc172012-09-05 23:34:03 +00001569bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1570 SMLoc &EndLoc) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001571 SmallVector<MCParsedAsmOperand *, 1> Operands;
1572 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1573 if (ResTy == MatchOperand_Success) {
1574 assert(Operands.size() == 1);
1575 MipsOperand &Operand = *static_cast<MipsOperand *>(Operands.front());
1576 StartLoc = Operand.getStartLoc();
1577 EndLoc = Operand.getEndLoc();
1578
1579 // AFAIK, we only support numeric registers and named GPR's in CFI
1580 // directives.
1581 // Don't worry about eating tokens before failing. Using an unrecognised
1582 // register is a parse error.
1583 if (Operand.isGPRAsmReg()) {
1584 // Resolve to GPR32 or GPR64 appropriately.
1585 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1586 }
1587
1588 return (RegNo == (unsigned)-1);
1589 }
1590
1591 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001592 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001593}
1594
Jack Carterb5cf5902013-04-17 00:18:04 +00001595bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001596 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001597 bool Result = true;
1598
1599 while (getLexer().getKind() == AsmToken::LParen)
1600 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001601
Jack Carterd0bd6422013-04-18 00:41:53 +00001602 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001603 default:
1604 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001605 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001606 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001607 case AsmToken::Integer:
1608 case AsmToken::Minus:
1609 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001610 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001611 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001612 else
1613 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001614 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001615 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 break;
Jack Carter873c7242013-01-12 01:03:14 +00001617 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001618 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001619 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001620 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001621}
1622
Jack Carterb4dbc172012-09-05 23:34:03 +00001623MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Vladimir Medic4c299852013-11-06 11:27:05 +00001624 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001625 DEBUG(dbgs() << "parseMemOperand\n");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001626 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001627 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001628 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001629 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001630 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001631 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001632
Jack Carterb5cf5902013-04-17 00:18:04 +00001633 if (getLexer().getKind() == AsmToken::LParen) {
1634 Parser.Lex();
1635 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001636 }
1637
Jack Carterb5cf5902013-04-17 00:18:04 +00001638 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001639 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001640 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001641
Jack Carterd0bd6422013-04-18 00:41:53 +00001642 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001643 if (Tok.isNot(AsmToken::LParen)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001644 MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
Jack Carterb5cf5902013-04-17 00:18:04 +00001645 if (Mnemonic->getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001646 SMLoc E =
1647 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001648 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001649 return MatchOperand_Success;
1650 }
1651 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001652 SMLoc E =
1653 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001654
Jack Carterd0bd6422013-04-18 00:41:53 +00001655 // Zero register assumed, add a memory operand with ZERO as its base.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001656 MipsOperand *Base = MipsOperand::CreateGPRReg(
1657 0, getContext().getRegisterInfo(), S, E, *this);
1658 Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001659 return MatchOperand_Success;
1660 }
1661 Error(Parser.getTok().getLoc(), "'(' expected");
1662 return MatchOperand_ParseFail;
1663 }
1664
Jack Carterd0bd6422013-04-18 00:41:53 +00001665 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001666 }
1667
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001668 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001669 if (Res != MatchOperand_Success)
1670 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001671
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001672 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001673 Error(Parser.getTok().getLoc(), "')' expected");
1674 return MatchOperand_ParseFail;
1675 }
1676
Jack Carter873c7242013-01-12 01:03:14 +00001677 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1678
Jack Carterd0bd6422013-04-18 00:41:53 +00001679 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001680
1681 if (IdVal == 0)
1682 IdVal = MCConstantExpr::Create(0, getContext());
1683
Jack Carterd0bd6422013-04-18 00:41:53 +00001684 // Replace the register operand with the memory operand.
Vladimir Medic4c299852013-11-06 11:27:05 +00001685 MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
Jack Carterd0bd6422013-04-18 00:41:53 +00001686 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001687 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001688 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001689 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1690 int64_t Imm;
1691 if (IdVal->EvaluateAsAbsolute(Imm))
1692 IdVal = MCConstantExpr::Create(Imm, getContext());
1693 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1694 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1695 getContext());
1696 }
1697
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001698 Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001699 return MatchOperand_Success;
1700}
1701
Daniel Sanderse34a1202014-03-31 18:51:43 +00001702bool MipsAsmParser::searchSymbolAlias(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001703 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001704
Jack Carterd76b2372013-03-21 21:44:16 +00001705 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1706 if (Sym) {
1707 SMLoc S = Parser.getTok().getLoc();
1708 const MCExpr *Expr;
1709 if (Sym->isVariable())
1710 Expr = Sym->getVariableValue();
1711 else
1712 return false;
1713 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001714 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001715 const StringRef DefSymbol = Ref->getSymbol().getName();
1716 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001717 OperandMatchResultTy ResTy =
1718 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001719 if (ResTy == MatchOperand_Success) {
1720 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001721 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001722 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001723 llvm_unreachable("Should never ParseFail");
1724 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001725 }
1726 } else if (Expr->getKind() == MCExpr::Constant) {
1727 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001728 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
1729 MipsOperand *op =
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001730 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this);
Jack Carterd76b2372013-03-21 21:44:16 +00001731 Operands.push_back(op);
1732 return true;
1733 }
1734 }
1735 return false;
1736}
Jack Carterd0bd6422013-04-18 00:41:53 +00001737
Jack Carter873c7242013-01-12 01:03:14 +00001738MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001739MipsAsmParser::MatchAnyRegisterNameWithoutDollar(
1740 SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
1741 SMLoc S) {
1742 int Index = matchCPURegisterName(Identifier);
1743 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001744 Operands.push_back(MipsOperand::CreateGPRReg(
1745 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1746 return MatchOperand_Success;
1747 }
1748
1749 Index = matchFPURegisterName(Identifier);
1750 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001751 Operands.push_back(MipsOperand::CreateFGRReg(
1752 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1753 return MatchOperand_Success;
1754 }
1755
1756 Index = matchFCCRegisterName(Identifier);
1757 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001758 Operands.push_back(MipsOperand::CreateFCCReg(
1759 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1760 return MatchOperand_Success;
1761 }
1762
1763 Index = matchACRegisterName(Identifier);
1764 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001765 Operands.push_back(MipsOperand::CreateACCReg(
1766 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1767 return MatchOperand_Success;
1768 }
1769
1770 Index = matchMSA128RegisterName(Identifier);
1771 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001772 Operands.push_back(MipsOperand::CreateMSA128Reg(
1773 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1774 return MatchOperand_Success;
1775 }
1776
1777 Index = matchMSA128CtrlRegisterName(Identifier);
1778 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001779 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1780 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1781 return MatchOperand_Success;
1782 }
1783
1784 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001785}
1786
1787MipsAsmParser::OperandMatchResultTy
Daniel Sanders21bce302014-04-01 12:35:23 +00001788MipsAsmParser::MatchAnyRegisterWithoutDollar(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001789 SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001790 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001791
1792 if (Token.is(AsmToken::Identifier)) {
1793 DEBUG(dbgs() << ".. identifier\n");
1794 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001795 OperandMatchResultTy ResTy =
1796 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001797 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001798 } else if (Token.is(AsmToken::Integer)) {
1799 DEBUG(dbgs() << ".. integer\n");
1800 Operands.push_back(MipsOperand::CreateNumericReg(
1801 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1802 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001803 return MatchOperand_Success;
1804 }
1805
1806 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1807
1808 return MatchOperand_NoMatch;
1809}
1810
1811MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
1812 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1813 DEBUG(dbgs() << "ParseAnyRegister\n");
1814
1815 auto Token = Parser.getTok();
1816
1817 SMLoc S = Token.getLoc();
1818
1819 if (Token.isNot(AsmToken::Dollar)) {
1820 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1821 if (Token.is(AsmToken::Identifier)) {
1822 if (searchSymbolAlias(Operands))
1823 return MatchOperand_Success;
1824 }
1825 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1826 return MatchOperand_NoMatch;
1827 }
1828 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001829
Daniel Sanders21bce302014-04-01 12:35:23 +00001830 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001831 if (ResTy == MatchOperand_Success) {
1832 Parser.Lex(); // $
1833 Parser.Lex(); // identifier
1834 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001835 return ResTy;
1836}
1837
1838MipsAsmParser::OperandMatchResultTy
1839MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1840 switch (getLexer().getKind()) {
1841 default:
1842 return MatchOperand_NoMatch;
1843 case AsmToken::LParen:
1844 case AsmToken::Minus:
1845 case AsmToken::Plus:
1846 case AsmToken::Integer:
1847 case AsmToken::String:
1848 break;
1849 }
1850
1851 const MCExpr *IdVal;
1852 SMLoc S = Parser.getTok().getLoc();
1853 if (getParser().parseExpression(IdVal))
1854 return MatchOperand_ParseFail;
1855
1856 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1857 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1858 return MatchOperand_Success;
1859}
1860
1861MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
1862 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1863 DEBUG(dbgs() << "ParseJumpTarget\n");
1864
1865 SMLoc S = getLexer().getLoc();
1866
1867 // Integers and expressions are acceptable
1868 OperandMatchResultTy ResTy = ParseImm(Operands);
1869 if (ResTy != MatchOperand_NoMatch)
1870 return ResTy;
1871
Daniel Sanders315386c2014-04-01 10:40:14 +00001872 // Registers are a valid target and have priority over symbols.
1873 ResTy = ParseAnyRegister(Operands);
1874 if (ResTy != MatchOperand_NoMatch)
1875 return ResTy;
1876
Daniel Sandersffd84362014-04-01 10:41:48 +00001877 const MCExpr *Expr = nullptr;
1878 if (Parser.parseExpression(Expr)) {
1879 // We have no way of knowing if a symbol was consumed so we must ParseFail
1880 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001881 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001882 Operands.push_back(
1883 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001884 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001885}
1886
Vladimir Medic2b953d02013-10-01 09:48:56 +00001887MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001888MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001889 const MCExpr *IdVal;
1890 // If the first token is '$' we may have register operand.
1891 if (Parser.getTok().is(AsmToken::Dollar))
1892 return MatchOperand_NoMatch;
1893 SMLoc S = Parser.getTok().getLoc();
1894 if (getParser().parseExpression(IdVal))
1895 return MatchOperand_ParseFail;
1896 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001897 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001898 int64_t Val = MCE->getValue();
1899 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1900 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001901 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001902 return MatchOperand_Success;
1903}
1904
Matheus Almeida779c5932013-11-18 12:32:49 +00001905MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001906MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001907 switch (getLexer().getKind()) {
1908 default:
1909 return MatchOperand_NoMatch;
1910 case AsmToken::LParen:
1911 case AsmToken::Plus:
1912 case AsmToken::Minus:
1913 case AsmToken::Integer:
1914 break;
1915 }
1916
1917 const MCExpr *Expr;
1918 SMLoc S = Parser.getTok().getLoc();
1919
1920 if (getParser().parseExpression(Expr))
1921 return MatchOperand_ParseFail;
1922
1923 int64_t Val;
1924 if (!Expr->EvaluateAsAbsolute(Val)) {
1925 Error(S, "expected immediate value");
1926 return MatchOperand_ParseFail;
1927 }
1928
1929 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1930 // and because the CPU always adds one to the immediate field, the allowed
1931 // range becomes 1..4. We'll only check the range here and will deal
1932 // with the addition/subtraction when actually decoding/encoding
1933 // the instruction.
1934 if (Val < 1 || Val > 4) {
1935 Error(S, "immediate not in range (1..4)");
1936 return MatchOperand_ParseFail;
1937 }
1938
Jack Carter3b2c96e2014-01-22 23:31:38 +00001939 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001940 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00001941 return MatchOperand_Success;
1942}
1943
Jack Carterdc1e35d2012-09-06 20:00:02 +00001944MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1945
Vladimir Medic4c299852013-11-06 11:27:05 +00001946 MCSymbolRefExpr::VariantKind VK =
1947 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1948 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1949 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1950 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1951 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1952 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1953 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1954 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1955 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1956 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1957 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1958 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1959 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1960 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1961 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1962 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1963 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1964 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00001965 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
1966 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
1967 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
1968 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
1969 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
1970 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Vladimir Medic4c299852013-11-06 11:27:05 +00001971 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001972
Daniel Sandersa567da52014-03-31 15:15:02 +00001973 assert (VK != MCSymbolRefExpr::VK_None);
1974
Jack Carterdc1e35d2012-09-06 20:00:02 +00001975 return VK;
1976}
Jack Cartera63b16a2012-09-07 00:23:42 +00001977
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001978/// Sometimes (i.e. load/stores) the operand may be followed immediately by
1979/// either this.
1980/// ::= '(', register, ')'
1981/// handle it before we iterate so we don't get tripped up by the lack of
1982/// a comma.
1983bool MipsAsmParser::ParseParenSuffix(
1984 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1985 if (getLexer().is(AsmToken::LParen)) {
1986 Operands.push_back(
1987 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
1988 Parser.Lex();
1989 if (ParseOperand(Operands, Name)) {
1990 SMLoc Loc = getLexer().getLoc();
1991 Parser.eatToEndOfStatement();
1992 return Error(Loc, "unexpected token in argument list");
1993 }
1994 if (Parser.getTok().isNot(AsmToken::RParen)) {
1995 SMLoc Loc = getLexer().getLoc();
1996 Parser.eatToEndOfStatement();
1997 return Error(Loc, "unexpected token, expected ')'");
1998 }
1999 Operands.push_back(
2000 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2001 Parser.Lex();
2002 }
2003 return false;
2004}
2005
2006/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2007/// either one of these.
2008/// ::= '[', register, ']'
2009/// ::= '[', integer, ']'
2010/// handle it before we iterate so we don't get tripped up by the lack of
2011/// a comma.
2012bool MipsAsmParser::ParseBracketSuffix(
2013 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2014 if (getLexer().is(AsmToken::LBrac)) {
2015 Operands.push_back(
2016 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2017 Parser.Lex();
2018 if (ParseOperand(Operands, Name)) {
2019 SMLoc Loc = getLexer().getLoc();
2020 Parser.eatToEndOfStatement();
2021 return Error(Loc, "unexpected token in argument list");
2022 }
2023 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2024 SMLoc Loc = getLexer().getLoc();
2025 Parser.eatToEndOfStatement();
2026 return Error(Loc, "unexpected token, expected ']'");
2027 }
2028 Operands.push_back(
2029 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2030 Parser.Lex();
2031 }
2032 return false;
2033}
2034
Vladimir Medic4c299852013-11-06 11:27:05 +00002035bool MipsAsmParser::ParseInstruction(
2036 ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
2037 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002038 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002039 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002040 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002041 Parser.eatToEndOfStatement();
2042 return Error(NameLoc, "Unknown instruction");
2043 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002044 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002045 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002046
2047 // Read the remaining operands.
2048 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2049 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002050 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002051 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002052 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002053 return Error(Loc, "unexpected token in argument list");
2054 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002055 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2056 return true;
2057 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002058
Jack Carterd0bd6422013-04-18 00:41:53 +00002059 while (getLexer().is(AsmToken::Comma)) {
2060 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002061 // Parse and remember the operand.
2062 if (ParseOperand(Operands, Name)) {
2063 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002064 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002065 return Error(Loc, "unexpected token in argument list");
2066 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002067 // Parse bracket and parenthesis suffixes before we iterate
2068 if (getLexer().is(AsmToken::LBrac)) {
2069 if (ParseBracketSuffix(Name, Operands))
2070 return true;
2071 } else if (getLexer().is(AsmToken::LParen) &&
2072 ParseParenSuffix(Name, Operands))
2073 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002074 }
2075 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002076 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2077 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002078 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002079 return Error(Loc, "unexpected token in argument list");
2080 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002081 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002082 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002083}
2084
Jack Carter0b744b32012-10-04 02:29:46 +00002085bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002086 SMLoc Loc = getLexer().getLoc();
2087 Parser.eatToEndOfStatement();
2088 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002089}
2090
2091bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002092 // Line should look like: ".set noat".
2093 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002094 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002095 // eat noat
2096 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002097 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002098 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2099 reportParseError("unexpected token in statement");
2100 return false;
2101 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002102 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002103 return false;
2104}
Jack Carterd0bd6422013-04-18 00:41:53 +00002105
Jack Carter0b744b32012-10-04 02:29:46 +00002106bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002108 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002109 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002110 getParser().Lex();
2111 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002112 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002114 return false;
2115 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002117 if (getLexer().isNot(AsmToken::Dollar)) {
2118 reportParseError("unexpected token in statement");
2119 return false;
2120 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002121 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002122 const AsmToken &Reg = Parser.getTok();
2123 if (Reg.is(AsmToken::Identifier)) {
2124 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2125 } else if (Reg.is(AsmToken::Integer)) {
2126 AtRegNo = Reg.getIntVal();
2127 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002128 reportParseError("unexpected token in statement");
2129 return false;
2130 }
Jack Carter1ac53222013-02-20 23:11:17 +00002131
Daniel Sanders71a89d922014-03-25 13:01:06 +00002132 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002133 reportParseError("unexpected token in statement");
2134 return false;
2135 }
2136
2137 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002138 reportParseError("unexpected token in statement");
2139 return false;
2140 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002141 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002142
2143 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2144 reportParseError("unexpected token in statement");
2145 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002146 }
2147 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002148 return false;
2149 } else {
2150 reportParseError("unexpected token in statement");
2151 return false;
2152 }
2153}
2154
2155bool MipsAsmParser::parseSetReorderDirective() {
2156 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002157 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002158 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2159 reportParseError("unexpected token in statement");
2160 return false;
2161 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002162 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002163 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002164 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002165 return false;
2166}
2167
2168bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002169 Parser.Lex();
2170 // If this is not the end of the statement, report an error.
2171 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2172 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002173 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002174 }
2175 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002176 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002177 Parser.Lex(); // Consume the EndOfStatement.
2178 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002179}
2180
2181bool MipsAsmParser::parseSetMacroDirective() {
2182 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002183 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002184 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2185 reportParseError("unexpected token in statement");
2186 return false;
2187 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002188 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002189 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002190 return false;
2191}
2192
2193bool MipsAsmParser::parseSetNoMacroDirective() {
2194 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002195 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002196 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2197 reportParseError("`noreorder' must be set before `nomacro'");
2198 return false;
2199 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002200 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002201 reportParseError("`noreorder' must be set before `nomacro'");
2202 return false;
2203 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002204 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002205 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002206 return false;
2207}
Jack Carterd76b2372013-03-21 21:44:16 +00002208
Jack Carter39536722014-01-22 23:08:42 +00002209bool MipsAsmParser::parseSetNoMips16Directive() {
2210 Parser.Lex();
2211 // If this is not the end of the statement, report an error.
2212 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2213 reportParseError("unexpected token in statement");
2214 return false;
2215 }
2216 // For now do nothing.
2217 Parser.Lex(); // Consume the EndOfStatement.
2218 return false;
2219}
2220
Jack Carterd76b2372013-03-21 21:44:16 +00002221bool MipsAsmParser::parseSetAssignment() {
2222 StringRef Name;
2223 const MCExpr *Value;
2224
2225 if (Parser.parseIdentifier(Name))
2226 reportParseError("expected identifier after .set");
2227
2228 if (getLexer().isNot(AsmToken::Comma))
2229 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002230 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002231
Jack Carter3b2c96e2014-01-22 23:31:38 +00002232 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002233 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002234
Jack Carterd0bd6422013-04-18 00:41:53 +00002235 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002236 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002237 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002238 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002239 Sym = getContext().GetOrCreateSymbol(Name);
2240 Sym->setVariableValue(Value);
2241
2242 return false;
2243}
Jack Carterd0bd6422013-04-18 00:41:53 +00002244
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002245bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2246 Parser.Lex();
2247 if (getLexer().isNot(AsmToken::EndOfStatement))
2248 return reportParseError("unexpected token in .set directive");
2249
2250 switch(Feature) {
2251 default: llvm_unreachable("Unimplemented feature");
2252 case Mips::FeatureDSP:
2253 setFeatureBits(Mips::FeatureDSP, "dsp");
2254 getTargetStreamer().emitDirectiveSetDsp();
2255 break;
2256 case Mips::FeatureMicroMips:
2257 getTargetStreamer().emitDirectiveSetMicroMips();
2258 break;
2259 case Mips::FeatureMips16:
2260 getTargetStreamer().emitDirectiveSetMips16();
2261 break;
2262 case Mips::FeatureMips32r2:
2263 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2264 getTargetStreamer().emitDirectiveSetMips32R2();
2265 break;
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002266 case Mips::FeatureMips64:
2267 setFeatureBits(Mips::FeatureMips64, "mips64");
2268 getTargetStreamer().emitDirectiveSetMips64();
2269 break;
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002270 case Mips::FeatureMips64r2:
2271 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2272 getTargetStreamer().emitDirectiveSetMips64R2();
2273 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002274 }
2275 return false;
2276}
2277
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002278bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2279 if (!getLexer().is(AsmToken::Dollar))
2280 return false;
2281
2282 Parser.Lex();
2283
2284 const AsmToken &Reg = Parser.getTok();
2285 if (Reg.is(AsmToken::Identifier)) {
2286 RegNum = matchCPURegisterName(Reg.getIdentifier());
2287 } else if (Reg.is(AsmToken::Integer)) {
2288 RegNum = Reg.getIntVal();
2289 } else {
2290 return false;
2291 }
2292
2293 Parser.Lex();
2294 return true;
2295}
2296
2297bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2298 if (getLexer().isNot(AsmToken::Comma)) {
2299 SMLoc Loc = getLexer().getLoc();
2300 Parser.eatToEndOfStatement();
2301 return Error(Loc, ErrorStr);
2302 }
2303
2304 Parser.Lex(); // Eat the comma.
2305 return true;
2306}
2307
2308bool MipsAsmParser::parseDirectiveCPSetup() {
2309 unsigned FuncReg;
2310 unsigned Save;
2311 bool SaveIsReg = true;
2312
2313 if (!parseRegister(FuncReg))
2314 return reportParseError("expected register containing function address");
2315 FuncReg = getGPR(FuncReg);
2316
2317 if (!eatComma("expected comma parsing directive"))
2318 return true;
2319
2320 if (!parseRegister(Save)) {
2321 const AsmToken &Tok = Parser.getTok();
2322 if (Tok.is(AsmToken::Integer)) {
2323 Save = Tok.getIntVal();
2324 SaveIsReg = false;
2325 Parser.Lex();
2326 } else
2327 return reportParseError("expected save register or stack offset");
2328 } else
2329 Save = getGPR(Save);
2330
2331 if (!eatComma("expected comma parsing directive"))
2332 return true;
2333
2334 StringRef Name;
2335 if (Parser.parseIdentifier(Name))
2336 reportParseError("expected identifier");
2337 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
2338 unsigned GPReg = getGPR(matchCPURegisterName("gp"));
2339
2340 // FIXME: The code below this point should be in the TargetStreamers.
2341 // Only N32 and N64 emit anything for .cpsetup
2342 // FIXME: We should only emit something for PIC mode too.
2343 if (!isN32() && !isN64())
2344 return false;
2345
2346 MCStreamer &TS = getStreamer();
2347 MCInst Inst;
2348 // Either store the old $gp in a register or on the stack
2349 if (SaveIsReg) {
2350 // move $save, $gpreg
2351 Inst.setOpcode(Mips::DADDu);
2352 Inst.addOperand(MCOperand::CreateReg(Save));
2353 Inst.addOperand(MCOperand::CreateReg(GPReg));
2354 Inst.addOperand(MCOperand::CreateReg(getGPR(0)));
2355 } else {
2356 // sd $gpreg, offset($sp)
2357 Inst.setOpcode(Mips::SD);
2358 Inst.addOperand(MCOperand::CreateReg(GPReg));
2359 Inst.addOperand(MCOperand::CreateReg(getGPR(matchCPURegisterName("sp"))));
2360 Inst.addOperand(MCOperand::CreateImm(Save));
2361 }
2362 TS.EmitInstruction(Inst, STI);
2363 Inst.clear();
2364
2365 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2366 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI,
2367 getContext());
2368 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2369 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO,
2370 getContext());
2371 // lui $gp, %hi(%neg(%gp_rel(funcSym)))
2372 Inst.setOpcode(Mips::LUi);
2373 Inst.addOperand(MCOperand::CreateReg(GPReg));
2374 Inst.addOperand(MCOperand::CreateExpr(HiExpr));
2375 TS.EmitInstruction(Inst, STI);
2376 Inst.clear();
2377
2378 // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
2379 Inst.setOpcode(Mips::ADDiu);
2380 Inst.addOperand(MCOperand::CreateReg(GPReg));
2381 Inst.addOperand(MCOperand::CreateReg(GPReg));
2382 Inst.addOperand(MCOperand::CreateExpr(LoExpr));
2383 TS.EmitInstruction(Inst, STI);
2384 Inst.clear();
2385
2386 // daddu $gp, $gp, $funcreg
2387 Inst.setOpcode(Mips::DADDu);
2388 Inst.addOperand(MCOperand::CreateReg(GPReg));
2389 Inst.addOperand(MCOperand::CreateReg(GPReg));
2390 Inst.addOperand(MCOperand::CreateReg(FuncReg));
2391 TS.EmitInstruction(Inst, STI);
2392 return false;
2393}
2394
Jack Carter0b744b32012-10-04 02:29:46 +00002395bool MipsAsmParser::parseDirectiveSet() {
2396
Jack Carterd0bd6422013-04-18 00:41:53 +00002397 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002398 const AsmToken &Tok = Parser.getTok();
2399
2400 if (Tok.getString() == "noat") {
2401 return parseSetNoAtDirective();
2402 } else if (Tok.getString() == "at") {
2403 return parseSetAtDirective();
2404 } else if (Tok.getString() == "reorder") {
2405 return parseSetReorderDirective();
2406 } else if (Tok.getString() == "noreorder") {
2407 return parseSetNoReorderDirective();
2408 } else if (Tok.getString() == "macro") {
2409 return parseSetMacroDirective();
2410 } else if (Tok.getString() == "nomacro") {
2411 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002412 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002413 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002414 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002415 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002416 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002417 getTargetStreamer().emitDirectiveSetNoMicroMips();
2418 Parser.eatToEndOfStatement();
2419 return false;
2420 } else if (Tok.getString() == "micromips") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002421 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002422 } else if (Tok.getString() == "mips32r2") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002423 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002424 } else if (Tok.getString() == "mips64") {
2425 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002426 } else if (Tok.getString() == "mips64r2") {
2427 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002428 } else if (Tok.getString() == "dsp") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002429 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002430 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002431 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002432 parseSetAssignment();
2433 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002434 }
Jack Carter07c818d2013-01-25 01:31:34 +00002435
Jack Carter0b744b32012-10-04 02:29:46 +00002436 return true;
2437}
2438
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002439/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002440/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002441bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002442 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2443 for (;;) {
2444 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002445 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002446 return true;
2447
2448 getParser().getStreamer().EmitValue(Value, Size);
2449
2450 if (getLexer().is(AsmToken::EndOfStatement))
2451 break;
2452
2453 // FIXME: Improve diagnostic.
2454 if (getLexer().isNot(AsmToken::Comma))
2455 return Error(L, "unexpected token in directive");
2456 Parser.Lex();
2457 }
2458 }
2459
2460 Parser.Lex();
2461 return false;
2462}
2463
Vladimir Medic4c299852013-11-06 11:27:05 +00002464/// parseDirectiveGpWord
2465/// ::= .gpword local_sym
2466bool MipsAsmParser::parseDirectiveGpWord() {
2467 const MCExpr *Value;
2468 // EmitGPRel32Value requires an expression, so we are using base class
2469 // method to evaluate the expression.
2470 if (getParser().parseExpression(Value))
2471 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002472 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002473
Vladimir Medice10c1122013-11-13 13:18:04 +00002474 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002475 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002476 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002477 return false;
2478}
2479
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002480/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002481/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002482bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002483 const MCExpr *Value;
2484 // EmitGPRel64Value requires an expression, so we are using base class
2485 // method to evaluate the expression.
2486 if (getParser().parseExpression(Value))
2487 return true;
2488 getParser().getStreamer().EmitGPRel64Value(Value);
2489
2490 if (getLexer().isNot(AsmToken::EndOfStatement))
2491 return Error(getLexer().getLoc(), "unexpected token in directive");
2492 Parser.Lex(); // Eat EndOfStatement token.
2493 return false;
2494}
2495
Jack Carter0cd3c192014-01-06 23:27:31 +00002496bool MipsAsmParser::parseDirectiveOption() {
2497 // Get the option token.
2498 AsmToken Tok = Parser.getTok();
2499 // At the moment only identifiers are supported.
2500 if (Tok.isNot(AsmToken::Identifier)) {
2501 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2502 Parser.eatToEndOfStatement();
2503 return false;
2504 }
2505
2506 StringRef Option = Tok.getIdentifier();
2507
2508 if (Option == "pic0") {
2509 getTargetStreamer().emitDirectiveOptionPic0();
2510 Parser.Lex();
2511 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2512 Error(Parser.getTok().getLoc(),
2513 "unexpected token in .option pic0 directive");
2514 Parser.eatToEndOfStatement();
2515 }
2516 return false;
2517 }
2518
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002519 if (Option == "pic2") {
2520 getTargetStreamer().emitDirectiveOptionPic2();
2521 Parser.Lex();
2522 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2523 Error(Parser.getTok().getLoc(),
2524 "unexpected token in .option pic2 directive");
2525 Parser.eatToEndOfStatement();
2526 }
2527 return false;
2528 }
2529
Jack Carter0cd3c192014-01-06 23:27:31 +00002530 // Unknown option.
2531 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2532 Parser.eatToEndOfStatement();
2533 return false;
2534}
2535
Jack Carter0b744b32012-10-04 02:29:46 +00002536bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002537 StringRef IDVal = DirectiveID.getString();
2538
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002539 if (IDVal == ".dword") {
2540 parseDataDirective(8, DirectiveID.getLoc());
2541 return false;
2542 }
2543
Jack Carterd0bd6422013-04-18 00:41:53 +00002544 if (IDVal == ".ent") {
2545 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002546 Parser.Lex();
2547 return false;
2548 }
2549
Jack Carter07c818d2013-01-25 01:31:34 +00002550 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002551 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002552 Parser.Lex();
2553 return false;
2554 }
2555
Jack Carter07c818d2013-01-25 01:31:34 +00002556 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002557 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002558 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002559 return false;
2560 }
2561
Jack Carter07c818d2013-01-25 01:31:34 +00002562 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002563 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002564 }
2565
Jack Carter07c818d2013-01-25 01:31:34 +00002566 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002568 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002569 return false;
2570 }
2571
Jack Carter07c818d2013-01-25 01:31:34 +00002572 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002573 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002574 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002575 return false;
2576 }
2577
Jack Carter07c818d2013-01-25 01:31:34 +00002578 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002579 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002580 return false;
2581 }
2582
Rafael Espindolab59fb732014-03-28 18:50:26 +00002583 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002584 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002585 return false;
2586 }
2587
Jack Carter07c818d2013-01-25 01:31:34 +00002588 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002589 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002590 return false;
2591 }
2592
Jack Carter0cd3c192014-01-06 23:27:31 +00002593 if (IDVal == ".option")
2594 return parseDirectiveOption();
2595
2596 if (IDVal == ".abicalls") {
2597 getTargetStreamer().emitDirectiveAbiCalls();
2598 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2599 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2600 // Clear line
2601 Parser.eatToEndOfStatement();
2602 }
2603 return false;
2604 }
2605
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002606 if (IDVal == ".cpsetup")
2607 return parseDirectiveCPSetup();
2608
Rafael Espindola870c4e92012-01-11 03:56:41 +00002609 return true;
2610}
2611
Rafael Espindola870c4e92012-01-11 03:56:41 +00002612extern "C" void LLVMInitializeMipsAsmParser() {
2613 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2614 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2615 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2616 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2617}
Jack Carterb4dbc172012-09-05 23:34:03 +00002618
2619#define GET_REGISTER_MATCHER
2620#define GET_MATCHER_IMPLEMENTATION
2621#include "MipsGenAsmMatcher.inc"