blob: 95e7d09ce0c7271a4aa736dda8f146276d027eb3 [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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +0000101 ParseAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
102 SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000103
Jack Carter873c7242013-01-12 01:03:14 +0000104 MipsAsmParser::OperandMatchResultTy
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000105 ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000106
107 MipsAsmParser::OperandMatchResultTy
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000108 ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000109
110 MipsAsmParser::OperandMatchResultTy
Daniel Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +0000117 ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000118
Daniel Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 {
Jack Carter873c7242013-01-12 01:03:14 +0000254public:
Daniel Sanders0c648ba2014-03-31 17:43:46 +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 {
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000278 k_Immediate,
279 k_Memory,
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000280 k_PhysRegister,
281 k_RegisterIndex,
282 k_Token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000283 } Kind;
284
Daniel Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +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 Sanders0c648ba2014-03-31 17:43:46 +0000476 void addRegOperands(MCInst &Inst, unsigned N) const {
477 llvm_unreachable("Use a custom parser instead");
478 }
479
480 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
481 assert(N == 1 && "Invalid number of operands!");
482 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
483 }
484
485 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
486 assert(N == 1 && "Invalid number of operands!");
487 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
488 }
489
490 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
491 assert(N == 1 && "Invalid number of operands!");
492 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
493 }
494
495 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
496 assert(N == 1 && "Invalid number of operands!");
497 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
498 }
499
500 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
501 assert(N == 1 && "Invalid number of operands!");
502 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
503 }
504
505 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
506 assert(N == 1 && "Invalid number of operands!");
507 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
508 }
509
510 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
511 assert(N == 1 && "Invalid number of operands!");
512 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
513 }
514
515 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
516 assert(N == 1 && "Invalid number of operands!");
517 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
518 }
519
520 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
521 assert(N == 1 && "Invalid number of operands!");
522 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
523 }
524
525 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
526 assert(N == 1 && "Invalid number of operands!");
527 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
528 }
529
530 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
531 assert(N == 1 && "Invalid number of operands!");
532 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
533 }
534
535 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
536 assert(N == 1 && "Invalid number of operands!");
537 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
538 }
539
540 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
541 assert(N == 1 && "Invalid number of operands!");
542 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
543 }
544
545 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
546 assert(N == 1 && "Invalid number of operands!");
547 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
548 }
549
550 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
551 assert(N == 1 && "Invalid number of operands!");
552 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
553 }
554
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000555 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000556 assert(N == 1 && "Invalid number of operands!");
557 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000558 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000559 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000560
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000561 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000562 assert(N == 2 && "Invalid number of operands!");
563
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000564 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000565
566 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000567 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000568 }
569
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000570 bool isReg() const {
571 // As a special case until we sort out the definition of div/divu, pretend
572 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
573 if (isGPRAsmReg() && RegIdx.Index == 0)
574 return true;
575
576 return Kind == k_PhysRegister;
577 }
578 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000579 bool isImm() const { return Kind == k_Immediate; }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000580 bool isConstantImm() const {
581 return isImm() && dyn_cast<MCConstantExpr>(getImm());
582 }
583 bool isToken() const {
584 // Note: It's not possible to pretend that other operand kinds are tokens.
585 // The matcher emitter checks tokens first.
586 return Kind == k_Token;
587 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000588 bool isMem() const { return Kind == k_Memory; }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000589 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000590 bool isLSAImm() const {
591 if (!isConstantImm())
592 return false;
593 int64_t Val = getConstantImm();
594 return 1 <= Val && Val <= 4;
595 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000596
597 StringRef getToken() const {
598 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000599 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000600 }
601
602 unsigned getReg() const {
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000603 // As a special case until we sort out the definition of div/divu, pretend
604 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
605 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
606 RegIdx.Kind & RegKind_GPR)
607 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000608
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000609 assert(Kind == k_PhysRegister && "Invalid access!");
610 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000611 }
612
Jack Carterb4dbc172012-09-05 23:34:03 +0000613 const MCExpr *getImm() const {
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000614 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000615 return Imm.Val;
616 }
617
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000618 int64_t getConstantImm() const {
619 const MCExpr *Val = getImm();
620 return static_cast<const MCConstantExpr *>(Val)->getValue();
621 }
622
623 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000624 assert((Kind == k_Memory) && "Invalid access!");
625 return Mem.Base;
626 }
627
628 const MCExpr *getMemOff() const {
629 assert((Kind == k_Memory) && "Invalid access!");
630 return Mem.Off;
631 }
632
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000633 static MipsOperand *CreateToken(StringRef Str, SMLoc S,
634 MipsAsmParser &Parser) {
635 MipsOperand *Op = new MipsOperand(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000636 Op->Tok.Data = Str.data();
637 Op->Tok.Length = Str.size();
638 Op->StartLoc = S;
639 Op->EndLoc = S;
640 return Op;
641 }
642
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000643 /// Create a numeric register (e.g. $1). The exact register remains
644 /// unresolved until an instruction successfully matches
645 static MipsOperand *CreateNumericReg(unsigned Index,
646 const MCRegisterInfo *RegInfo, SMLoc S,
647 SMLoc E, MipsAsmParser &Parser) {
648 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
649 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000650 }
651
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000652 /// Create a register that is definitely a GPR.
653 /// This is typically only used for named registers such as $gp.
654 static MipsOperand *CreateGPRReg(unsigned Index,
655 const MCRegisterInfo *RegInfo, SMLoc S,
656 SMLoc E, MipsAsmParser &Parser) {
657 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000658 }
659
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000660 /// Create a register that is definitely a FGR.
661 /// This is typically only used for named registers such as $f0.
662 static MipsOperand *CreateFGRReg(unsigned Index,
663 const MCRegisterInfo *RegInfo, SMLoc S,
664 SMLoc E, MipsAsmParser &Parser) {
665 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
666 }
667
668 /// Create a register that is definitely an FCC.
669 /// This is typically only used for named registers such as $fcc0.
670 static MipsOperand *CreateFCCReg(unsigned Index,
671 const MCRegisterInfo *RegInfo, SMLoc S,
672 SMLoc E, MipsAsmParser &Parser) {
673 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
674 }
675
676 /// Create a register that is definitely an ACC.
677 /// This is typically only used for named registers such as $ac0.
678 static MipsOperand *CreateACCReg(unsigned Index,
679 const MCRegisterInfo *RegInfo, SMLoc S,
680 SMLoc E, MipsAsmParser &Parser) {
681 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
682 }
683
684 /// Create a register that is definitely an MSA128.
685 /// This is typically only used for named registers such as $w0.
686 static MipsOperand *CreateMSA128Reg(unsigned Index,
687 const MCRegisterInfo *RegInfo, SMLoc S,
688 SMLoc E, MipsAsmParser &Parser) {
689 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
690 }
691
692 /// Create a register that is definitely an MSACtrl.
693 /// This is typically only used for named registers such as $msaaccess.
694 static MipsOperand *CreateMSACtrlReg(unsigned Index,
695 const MCRegisterInfo *RegInfo, SMLoc S,
696 SMLoc E, MipsAsmParser &Parser) {
697 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
698 }
699
700 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E,
701 MipsAsmParser &Parser) {
702 MipsOperand *Op = new MipsOperand(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000703 Op->Imm.Val = Val;
704 Op->StartLoc = S;
705 Op->EndLoc = E;
706 return Op;
707 }
708
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000709 static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S,
710 SMLoc E, MipsAsmParser &Parser) {
711 MipsOperand *Op = new MipsOperand(k_Memory, Parser);
Jack Carterdc1e35d2012-09-06 20:00:02 +0000712 Op->Mem.Base = Base;
713 Op->Mem.Off = Off;
714 Op->StartLoc = S;
715 Op->EndLoc = E;
716 return Op;
717 }
718
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000719 bool isGPRAsmReg() const {
720 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000721 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000722 bool isFGRAsmReg() const {
723 // AFGR64 is $0-$15 but we handle this in getAFGR64()
724 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000725 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000726 bool isHWRegsAsmReg() const {
727 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000728 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000729 bool isCCRAsmReg() const {
730 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000731 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000732 bool isFCCAsmReg() const {
733 return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000734 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000735 bool isACCAsmReg() const {
736 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000737 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000738 bool isCOP2AsmReg() const {
739 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000740 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000741 bool isMSA128AsmReg() const {
742 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000743 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000744 bool isMSACtrlAsmReg() const {
745 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000746 }
747
Jack Carterb4dbc172012-09-05 23:34:03 +0000748 /// getStartLoc - Get the location of the first token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000749 SMLoc getStartLoc() const { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000750 /// getEndLoc - Get the location of the last token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000751 SMLoc getEndLoc() const { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000752
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000753 virtual void print(raw_ostream &OS) const {
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000754 switch (Kind) {
755 case k_Immediate:
756 OS << "Imm<";
757 Imm.Val->print(OS);
758 OS << ">";
759 break;
760 case k_Memory:
761 OS << "Mem<";
762 Mem.Base->print(OS);
763 OS << ", ";
764 Mem.Off->print(OS);
765 OS << ">";
766 break;
767 case k_PhysRegister:
768 OS << "PhysReg<" << PhysReg.Num << ">";
769 break;
770 case k_RegisterIndex:
771 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
772 break;
773 case k_Token:
774 OS << Tok.Data;
775 break;
776 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000777 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000778}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000779} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000780
Jack Carter9e65aa32013-03-22 00:05:30 +0000781namespace llvm {
782extern const MCInstrDesc MipsInsts[];
783}
784static const MCInstrDesc &getInstDesc(unsigned Opcode) {
785 return MipsInsts[Opcode];
786}
787
788bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000789 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000790 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000791
Jack Carter9e65aa32013-03-22 00:05:30 +0000792 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000793
794 if (MCID.isBranch() || MCID.isCall()) {
795 const unsigned Opcode = Inst.getOpcode();
796 MCOperand Offset;
797
798 switch (Opcode) {
799 default:
800 break;
801 case Mips::BEQ:
802 case Mips::BNE:
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000803 case Mips::BEQ_MM:
804 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000805 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000806 Offset = Inst.getOperand(2);
807 if (!Offset.isImm())
808 break; // We'll deal with this situation later on when applying fixups.
809 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
810 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000811 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000812 return Error(IDLoc, "branch to misaligned address");
813 break;
814 case Mips::BGEZ:
815 case Mips::BGTZ:
816 case Mips::BLEZ:
817 case Mips::BLTZ:
818 case Mips::BGEZAL:
819 case Mips::BLTZAL:
820 case Mips::BC1F:
821 case Mips::BC1T:
Daniel Sanders0c648ba2014-03-31 17:43:46 +0000822 case Mips::BGEZ_MM:
823 case Mips::BGTZ_MM:
824 case Mips::BLEZ_MM:
825 case Mips::BLTZ_MM:
826 case Mips::BGEZAL_MM:
827 case Mips::BLTZAL_MM:
828 case Mips::BC1F_MM:
829 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000830 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000831 Offset = Inst.getOperand(1);
832 if (!Offset.isImm())
833 break; // We'll deal with this situation later on when applying fixups.
834 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
835 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000836 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000837 return Error(IDLoc, "branch to misaligned address");
838 break;
839 }
840 }
841
Jack Carterc15c1d22013-04-25 23:31:35 +0000842 if (MCID.hasDelaySlot() && Options.isReorder()) {
843 // If this instruction has a delay slot and .set reorder is active,
844 // emit a NOP after it.
845 Instructions.push_back(Inst);
846 MCInst NopInst;
847 NopInst.setOpcode(Mips::SLL);
848 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
849 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
850 NopInst.addOperand(MCOperand::CreateImm(0));
851 Instructions.push_back(NopInst);
852 return false;
853 }
854
Jack Carter9e65aa32013-03-22 00:05:30 +0000855 if (MCID.mayLoad() || MCID.mayStore()) {
856 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000857 // reference or immediate we may have to expand instructions.
858 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000859 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000860 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
861 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000862 MCOperand &Op = Inst.getOperand(i);
863 if (Op.isImm()) {
864 int MemOffset = Op.getImm();
865 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000866 // Offset can't exceed 16bit value.
867 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000868 return false;
869 }
870 } else if (Op.isExpr()) {
871 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000872 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000873 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000874 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000875 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000876 // Expand symbol.
877 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000878 return false;
879 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000880 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000881 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000882 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000883 }
884 }
885 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000886 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000887 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000888
889 if (needsExpansion(Inst))
890 expandInstruction(Inst, IDLoc, Instructions);
891 else
892 Instructions.push_back(Inst);
893
894 return false;
895}
896
Jack Carter30a59822012-10-04 04:03:53 +0000897bool MipsAsmParser::needsExpansion(MCInst &Inst) {
898
Jack Carterd0bd6422013-04-18 00:41:53 +0000899 switch (Inst.getOpcode()) {
900 case Mips::LoadImm32Reg:
901 case Mips::LoadAddr32Imm:
902 case Mips::LoadAddr32Reg:
Daniel Sandersa771fef2014-03-24 14:05:39 +0000903 case Mips::SUBi:
904 case Mips::SUBiu:
905 case Mips::DSUBi:
906 case Mips::DSUBiu:
Jack Carterd0bd6422013-04-18 00:41:53 +0000907 return true;
908 default:
909 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000910 }
911}
Jack Carter92995f12012-10-06 00:53:28 +0000912
Jack Carter30a59822012-10-04 04:03:53 +0000913void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000914 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000915 switch (Inst.getOpcode()) {
916 case Mips::LoadImm32Reg:
917 return expandLoadImm(Inst, IDLoc, Instructions);
918 case Mips::LoadAddr32Imm:
919 return expandLoadAddressImm(Inst, IDLoc, Instructions);
920 case Mips::LoadAddr32Reg:
921 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Daniel Sandersa771fef2014-03-24 14:05:39 +0000922 case Mips::SUBi:
923 Instructions.push_back(MCInstBuilder(Mips::ADDi)
924 .addReg(Inst.getOperand(0).getReg())
925 .addReg(Inst.getOperand(1).getReg())
926 .addImm(-Inst.getOperand(2).getImm()));
927 return;
928 case Mips::SUBiu:
929 Instructions.push_back(MCInstBuilder(Mips::ADDiu)
930 .addReg(Inst.getOperand(0).getReg())
931 .addReg(Inst.getOperand(1).getReg())
932 .addImm(-Inst.getOperand(2).getImm()));
933 return;
934 case Mips::DSUBi:
935 Instructions.push_back(MCInstBuilder(Mips::DADDi)
936 .addReg(Inst.getOperand(0).getReg())
937 .addReg(Inst.getOperand(1).getReg())
938 .addImm(-Inst.getOperand(2).getImm()));
939 return;
940 case Mips::DSUBiu:
941 Instructions.push_back(MCInstBuilder(Mips::DADDiu)
942 .addReg(Inst.getOperand(0).getReg())
943 .addReg(Inst.getOperand(1).getReg())
944 .addImm(-Inst.getOperand(2).getImm()));
945 return;
Jack Carterd0bd6422013-04-18 00:41:53 +0000946 }
Jack Carter30a59822012-10-04 04:03:53 +0000947}
Jack Carter92995f12012-10-06 00:53:28 +0000948
Jack Carter30a59822012-10-04 04:03:53 +0000949void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000950 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000951 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000952 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000953 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000954 const MCOperand &RegOp = Inst.getOperand(0);
955 assert(RegOp.isReg() && "expected register operand kind");
956
957 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000958 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000959 if (0 <= ImmValue && ImmValue <= 65535) {
960 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000961 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000962 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000963 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000964 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000965 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000966 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000967 } else if (ImmValue < 0 && ImmValue >= -32768) {
968 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000969 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000970 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000971 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000972 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000973 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000974 Instructions.push_back(tmpInst);
975 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000976 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000977 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000978 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000979 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000980 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
981 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000982 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000983 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000984 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000985 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
986 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
987 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
988 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000989 Instructions.push_back(tmpInst);
990 }
991}
Jack Carter92995f12012-10-06 00:53:28 +0000992
Vladimir Medic4c299852013-11-06 11:27:05 +0000993void
994MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
995 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000996 MCInst tmpInst;
997 const MCOperand &ImmOp = Inst.getOperand(2);
998 assert(ImmOp.isImm() && "expected immediate operand kind");
999 const MCOperand &SrcRegOp = Inst.getOperand(1);
1000 assert(SrcRegOp.isReg() && "expected register operand kind");
1001 const MCOperand &DstRegOp = Inst.getOperand(0);
1002 assert(DstRegOp.isReg() && "expected register operand kind");
1003 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001004 if (-32768 <= ImmValue && ImmValue <= 65535) {
1005 // For -32768 <= j <= 65535.
1006 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001007 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001008 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1009 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1010 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1011 Instructions.push_back(tmpInst);
1012 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001013 // For any other value of j that is representable as a 32-bit integer.
1014 // la d,j(s) => lui d,hi16(j)
1015 // ori d,d,lo16(j)
1016 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001017 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001018 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1019 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1020 Instructions.push_back(tmpInst);
1021 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001022 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001023 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1024 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1025 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1026 Instructions.push_back(tmpInst);
1027 tmpInst.clear();
1028 tmpInst.setOpcode(Mips::ADDu);
1029 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1030 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1031 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1032 Instructions.push_back(tmpInst);
1033 }
1034}
1035
Vladimir Medic4c299852013-11-06 11:27:05 +00001036void
1037MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1038 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001039 MCInst tmpInst;
1040 const MCOperand &ImmOp = Inst.getOperand(1);
1041 assert(ImmOp.isImm() && "expected immediate operand kind");
1042 const MCOperand &RegOp = Inst.getOperand(0);
1043 assert(RegOp.isReg() && "expected register operand kind");
1044 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001045 if (-32768 <= ImmValue && ImmValue <= 65535) {
1046 // For -32768 <= j <= 65535.
1047 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001048 tmpInst.setOpcode(Mips::ADDiu);
1049 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001050 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001051 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1052 Instructions.push_back(tmpInst);
1053 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001054 // For any other value of j that is representable as a 32-bit integer.
1055 // la d,j => lui d,hi16(j)
1056 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001057 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001058 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1059 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1060 Instructions.push_back(tmpInst);
1061 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001062 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001063 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1064 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1065 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1066 Instructions.push_back(tmpInst);
1067 }
1068}
1069
Jack Carter9e65aa32013-03-22 00:05:30 +00001070void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001071 SmallVectorImpl<MCInst> &Instructions,
1072 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001073 const MCSymbolRefExpr *SR;
1074 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001075 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001076 const MCExpr *ExprOffset;
1077 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +00001078 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001079 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +00001080 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001081 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1082 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001083 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001084 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1085 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001086 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001087 if (isImmOpnd) {
1088 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1089 ImmOffset = Inst.getOperand(2).getImm();
1090 LoOffset = ImmOffset & 0x0000ffff;
1091 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001092 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001093 if (LoOffset & 0x8000)
1094 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001095 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001096 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001097 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001098 TempInst.setLoc(IDLoc);
1099 // 1st instruction in expansion is LUi. For load instruction we can use
1100 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001101 // but for stores we must use $at.
1102 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +00001103 TempInst.setOpcode(Mips::LUi);
1104 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1105 if (isImmOpnd)
1106 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1107 else {
1108 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001109 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001110 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1111 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1112 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001113 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001114 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001115 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001116 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001117 }
1118 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001119 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001120 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001121 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001122 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001123 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001124 TempInst.setOpcode(Mips::ADDu);
1125 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1126 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1127 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1128 Instructions.push_back(TempInst);
1129 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001130 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001131 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001132 TempInst.setOpcode(Inst.getOpcode());
1133 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1134 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1135 if (isImmOpnd)
1136 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1137 else {
1138 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001139 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1140 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1141 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001142 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001143 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001144 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001145 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001146 }
1147 }
1148 Instructions.push_back(TempInst);
1149 TempInst.clear();
1150}
1151
Vladimir Medic4c299852013-11-06 11:27:05 +00001152bool MipsAsmParser::MatchAndEmitInstruction(
1153 SMLoc IDLoc, unsigned &Opcode,
1154 SmallVectorImpl<MCParsedAsmOperand *> &Operands, MCStreamer &Out,
1155 unsigned &ErrorInfo, bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001156 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001157 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001158 unsigned MatchResult =
1159 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001160
1161 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001162 default:
1163 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001164 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001165 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001166 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001167 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001168 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001169 return false;
1170 }
1171 case Match_MissingFeature:
1172 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1173 return true;
1174 case Match_InvalidOperand: {
1175 SMLoc ErrorLoc = IDLoc;
1176 if (ErrorInfo != ~0U) {
1177 if (ErrorInfo >= Operands.size())
1178 return Error(IDLoc, "too few operands for instruction");
1179
Vladimir Medic4c299852013-11-06 11:27:05 +00001180 ErrorLoc = ((MipsOperand *)Operands[ErrorInfo])->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001181 if (ErrorLoc == SMLoc())
1182 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001183 }
1184
1185 return Error(ErrorLoc, "invalid operand for instruction");
1186 }
1187 case Match_MnemonicFail:
1188 return Error(IDLoc, "invalid instruction");
1189 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001190 return true;
1191}
1192
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001193void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1194 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1195 if (RegIndex == 1)
1196 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001197 else
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001198 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1199 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001200 }
1201}
1202
Jack Carter1ac53222013-02-20 23:11:17 +00001203int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001204 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001205
Vladimir Medic4c299852013-11-06 11:27:05 +00001206 CC = StringSwitch<unsigned>(Name)
1207 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001208 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001209 .Case("a0", 4)
1210 .Case("a1", 5)
1211 .Case("a2", 6)
1212 .Case("a3", 7)
1213 .Case("v0", 2)
1214 .Case("v1", 3)
1215 .Case("s0", 16)
1216 .Case("s1", 17)
1217 .Case("s2", 18)
1218 .Case("s3", 19)
1219 .Case("s4", 20)
1220 .Case("s5", 21)
1221 .Case("s6", 22)
1222 .Case("s7", 23)
1223 .Case("k0", 26)
1224 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001225 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001226 .Case("sp", 29)
1227 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001228 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001229 .Case("ra", 31)
1230 .Case("t0", 8)
1231 .Case("t1", 9)
1232 .Case("t2", 10)
1233 .Case("t3", 11)
1234 .Case("t4", 12)
1235 .Case("t5", 13)
1236 .Case("t6", 14)
1237 .Case("t7", 15)
1238 .Case("t8", 24)
1239 .Case("t9", 25)
1240 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001241
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001242 if (isN32() || isN64()) {
1243 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1244 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1245 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1246 if (8 <= CC && CC <= 11)
1247 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001248
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001249 if (CC == -1)
1250 CC = StringSwitch<unsigned>(Name)
1251 .Case("a4", 8)
1252 .Case("a5", 9)
1253 .Case("a6", 10)
1254 .Case("a7", 11)
1255 .Case("kt0", 26)
1256 .Case("kt1", 27)
1257 .Default(-1);
1258 }
Jack Carter1ac53222013-02-20 23:11:17 +00001259
1260 return CC;
1261}
Jack Carterd0bd6422013-04-18 00:41:53 +00001262
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001263int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001264
Jack Cartera63b16a2012-09-07 00:23:42 +00001265 if (Name[0] == 'f') {
1266 StringRef NumString = Name.substr(1);
1267 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001268 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001269 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001270 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001271 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001272 return IntVal;
1273 }
1274 return -1;
1275}
Jack Cartera63b16a2012-09-07 00:23:42 +00001276
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001277int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1278
1279 if (Name.startswith("fcc")) {
1280 StringRef NumString = Name.substr(3);
1281 unsigned IntVal;
1282 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001283 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001284 if (IntVal > 7) // There are only 8 fcc registers.
1285 return -1;
1286 return IntVal;
1287 }
1288 return -1;
1289}
1290
1291int MipsAsmParser::matchACRegisterName(StringRef Name) {
1292
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001293 if (Name.startswith("ac")) {
1294 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001295 unsigned IntVal;
1296 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001297 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001298 if (IntVal > 3) // There are only 3 acc registers.
1299 return -1;
1300 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001301 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001302 return -1;
1303}
Jack Carterd0bd6422013-04-18 00:41:53 +00001304
Jack Carter5dc8ac92013-09-25 23:50:44 +00001305int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1306 unsigned IntVal;
1307
1308 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1309 return -1;
1310
1311 if (IntVal > 31)
1312 return -1;
1313
1314 return IntVal;
1315}
1316
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001317int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1318 int CC;
1319
1320 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001321 .Case("msair", 0)
1322 .Case("msacsr", 1)
1323 .Case("msaaccess", 2)
1324 .Case("msasave", 3)
1325 .Case("msamodify", 4)
1326 .Case("msarequest", 5)
1327 .Case("msamap", 6)
1328 .Case("msaunmap", 7)
1329 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001330
1331 return CC;
1332}
1333
Jack Carter0b744b32012-10-04 02:29:46 +00001334bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1335 if (Reg > 31)
1336 return false;
1337
1338 aTReg = Reg;
1339 return true;
1340}
1341
Daniel Sandersd89b1362014-03-24 16:48:01 +00001342int MipsAsmParser::getATReg() {
1343 int AT = Options.getATRegNum();
1344 if (AT == 0)
1345 TokError("Pseudo instruction requires $at, which is not available");
1346 return AT;
1347}
Jack Carter0b744b32012-10-04 02:29:46 +00001348
Jack Carterd0bd6422013-04-18 00:41:53 +00001349unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001350 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001351}
1352
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001353unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001354 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1355 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001356}
1357
Jack Carter873c7242013-01-12 01:03:14 +00001358int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001359 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001360 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001361 return -1;
1362
Jack Carter873c7242013-01-12 01:03:14 +00001363 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001364}
1365
Vladimir Medic4c299852013-11-06 11:27:05 +00001366bool
1367MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1368 StringRef Mnemonic) {
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001369 DEBUG(dbgs() << "ParseOperand\n");
1370
Jack Carter30a59822012-10-04 04:03:53 +00001371 // Check if the current operand has a custom associated parser, if so, try to
1372 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001373 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1374 if (ResTy == MatchOperand_Success)
1375 return false;
1376 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1377 // there was a match, but an error occurred, in which case, just return that
1378 // the operand parsing failed.
1379 if (ResTy == MatchOperand_ParseFail)
1380 return true;
1381
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001382 DEBUG(dbgs() << ".. Generic Parser\n");
1383
Jack Carterb4dbc172012-09-05 23:34:03 +00001384 switch (getLexer().getKind()) {
1385 default:
1386 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1387 return true;
1388 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001389 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001390 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001391
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001392 // Almost all registers have been parsed by custom parsers. There is only
1393 // one exception to this. $zero (and it's alias $0) will reach this point
1394 // for div, divu, and similar instructions because it is not an operand
1395 // to the instruction definition but an explicit register. Special case
1396 // this situation for now.
1397 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001398 return false;
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001399
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001401 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001402 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001403 return true;
1404
Jack Carter873c7242013-01-12 01:03:14 +00001405 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001406 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001408 const MCExpr *Res =
1409 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001410
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001411 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001412 return false;
1413 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001414 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001415 case AsmToken::LParen:
1416 case AsmToken::Minus:
1417 case AsmToken::Plus:
1418 case AsmToken::Integer:
1419 case AsmToken::String: {
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001420 DEBUG(dbgs() << ".. generic integer\n");
1421 OperandMatchResultTy ResTy = ParseImm(Operands);
1422 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001423 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001424 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001425 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001426 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001427 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001428 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001429 return true;
1430
Jack Carter873c7242013-01-12 01:03:14 +00001431 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1432
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001433 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001434 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001435 } // case AsmToken::Percent
1436 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001437 return true;
1438}
1439
Vladimir Medic4c299852013-11-06 11:27:05 +00001440const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001441 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001442 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001443 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001444 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001445 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001446 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001447 short Val = MCE->getValue();
1448 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001449 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001450 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001451 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001452 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001453 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001454 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001455 if (LoSign)
1456 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001457 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001458 } else {
1459 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001460 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001461 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001462 }
1463
Jack Carterb5cf5902013-04-17 00:18:04 +00001464 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001465 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001466 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001467 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001468 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001469 return Res;
1470 }
1471
1472 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001473 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1474
1475 // Check for %hi(sym1-sym2) and %lo(sym1-sym2) expressions.
1476 if (isa<MCSymbolRefExpr>(BE->getLHS()) && isa<MCSymbolRefExpr>(BE->getRHS())
1477 && (VK == MCSymbolRefExpr::VK_Mips_ABS_HI
1478 || VK == MCSymbolRefExpr::VK_Mips_ABS_LO)) {
1479 // Create target expression for %hi(sym1-sym2) and %lo(sym1-sym2).
1480 if (VK == MCSymbolRefExpr::VK_Mips_ABS_HI)
1481 return MipsMCExpr::CreateHi(Expr, getContext());
1482 return MipsMCExpr::CreateLo(Expr, getContext());
1483 }
1484
Jack Carterd0bd6422013-04-18 00:41:53 +00001485 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1486 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001487 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1488 return Res;
1489 }
1490
1491 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001492 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1493 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1494 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001495 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001496 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001497 return Expr;
1498}
1499
1500bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1501
1502 switch (Expr->getKind()) {
1503 case MCExpr::Constant:
1504 return true;
1505 case MCExpr::SymbolRef:
1506 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1507 case MCExpr::Binary:
1508 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1509 if (!isEvaluated(BE->getLHS()))
1510 return false;
1511 return isEvaluated(BE->getRHS());
1512 }
1513 case MCExpr::Unary:
1514 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001515 case MCExpr::Target:
1516 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001517 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001518 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001519}
Jack Carterd0bd6422013-04-18 00:41:53 +00001520
Jack Carterb5cf5902013-04-17 00:18:04 +00001521bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001522 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001523 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001524 if (Tok.isNot(AsmToken::Identifier))
1525 return true;
1526
1527 std::string Str = Tok.getIdentifier().str();
1528
Jack Carterd0bd6422013-04-18 00:41:53 +00001529 Parser.Lex(); // Eat the identifier.
1530 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001531 const MCExpr *IdVal;
1532 SMLoc EndLoc;
1533
1534 if (getLexer().getKind() == AsmToken::LParen) {
1535 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001536 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001537 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001538 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001539 const AsmToken &nextTok = Parser.getTok();
1540 if (nextTok.isNot(AsmToken::Identifier))
1541 return true;
1542 Str += "(%";
1543 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001544 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001545 if (getLexer().getKind() != AsmToken::LParen)
1546 return true;
1547 } else
1548 break;
1549 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001550 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001551 return true;
1552
1553 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001554 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001555
1556 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001557 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001558
Jack Carterd0bd6422013-04-18 00:41:53 +00001559 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001560 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001561}
1562
Jack Carterb4dbc172012-09-05 23:34:03 +00001563bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1564 SMLoc &EndLoc) {
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001565 SmallVector<MCParsedAsmOperand *, 1> Operands;
1566 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1567 if (ResTy == MatchOperand_Success) {
1568 assert(Operands.size() == 1);
1569 MipsOperand &Operand = *static_cast<MipsOperand *>(Operands.front());
1570 StartLoc = Operand.getStartLoc();
1571 EndLoc = Operand.getEndLoc();
1572
1573 // AFAIK, we only support numeric registers and named GPR's in CFI
1574 // directives.
1575 // Don't worry about eating tokens before failing. Using an unrecognised
1576 // register is a parse error.
1577 if (Operand.isGPRAsmReg()) {
1578 // Resolve to GPR32 or GPR64 appropriately.
1579 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1580 }
1581
1582 return (RegNo == (unsigned)-1);
1583 }
1584
1585 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001586 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001587}
1588
Jack Carterb5cf5902013-04-17 00:18:04 +00001589bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001590 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001591 bool Result = true;
1592
1593 while (getLexer().getKind() == AsmToken::LParen)
1594 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001595
Jack Carterd0bd6422013-04-18 00:41:53 +00001596 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001597 default:
1598 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001599 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001600 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001601 case AsmToken::Integer:
1602 case AsmToken::Minus:
1603 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001604 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001605 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001606 else
1607 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001608 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001609 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001610 break;
Jack Carter873c7242013-01-12 01:03:14 +00001611 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001612 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001613 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001614 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001615}
1616
Jack Carterb4dbc172012-09-05 23:34:03 +00001617MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Vladimir Medic4c299852013-11-06 11:27:05 +00001618 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001619 DEBUG(dbgs() << "parseMemOperand\n");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001620 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001621 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001622 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001623 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001625 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001626
Jack Carterb5cf5902013-04-17 00:18:04 +00001627 if (getLexer().getKind() == AsmToken::LParen) {
1628 Parser.Lex();
1629 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001630 }
1631
Jack Carterb5cf5902013-04-17 00:18:04 +00001632 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001633 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001634 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001635
Jack Carterd0bd6422013-04-18 00:41:53 +00001636 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001637 if (Tok.isNot(AsmToken::LParen)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001638 MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
Jack Carterb5cf5902013-04-17 00:18:04 +00001639 if (Mnemonic->getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001640 SMLoc E =
1641 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001642 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001643 return MatchOperand_Success;
1644 }
1645 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001646 SMLoc E =
1647 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001648
Jack Carterd0bd6422013-04-18 00:41:53 +00001649 // Zero register assumed, add a memory operand with ZERO as its base.
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001650 MipsOperand *Base = MipsOperand::CreateGPRReg(
1651 0, getContext().getRegisterInfo(), S, E, *this);
1652 Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001653 return MatchOperand_Success;
1654 }
1655 Error(Parser.getTok().getLoc(), "'(' expected");
1656 return MatchOperand_ParseFail;
1657 }
1658
Jack Carterd0bd6422013-04-18 00:41:53 +00001659 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001660 }
1661
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001662 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001663 if (Res != MatchOperand_Success)
1664 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001665
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001666 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001667 Error(Parser.getTok().getLoc(), "')' expected");
1668 return MatchOperand_ParseFail;
1669 }
1670
Jack Carter873c7242013-01-12 01:03:14 +00001671 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1672
Jack Carterd0bd6422013-04-18 00:41:53 +00001673 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001674
1675 if (IdVal == 0)
1676 IdVal = MCConstantExpr::Create(0, getContext());
1677
Jack Carterd0bd6422013-04-18 00:41:53 +00001678 // Replace the register operand with the memory operand.
Vladimir Medic4c299852013-11-06 11:27:05 +00001679 MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
Jack Carterd0bd6422013-04-18 00:41:53 +00001680 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001681 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001682 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001683 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1684 int64_t Imm;
1685 if (IdVal->EvaluateAsAbsolute(Imm))
1686 IdVal = MCConstantExpr::Create(Imm, getContext());
1687 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1688 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1689 getContext());
1690 }
1691
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001692 Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001693 return MatchOperand_Success;
1694}
1695
Jack Carterd0bd6422013-04-18 00:41:53 +00001696bool MipsAsmParser::searchSymbolAlias(
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001697 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Jack Carterd76b2372013-03-21 21:44:16 +00001698
1699 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1700 if (Sym) {
1701 SMLoc S = Parser.getTok().getLoc();
1702 const MCExpr *Expr;
1703 if (Sym->isVariable())
1704 Expr = Sym->getVariableValue();
1705 else
1706 return false;
1707 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001708 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001709 const StringRef DefSymbol = Ref->getSymbol().getName();
1710 if (DefSymbol.startswith("$")) {
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001711 OperandMatchResultTy ResTy =
1712 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
1713 if (ResTy == MatchOperand_Success)
Jack Carterd76b2372013-03-21 21:44:16 +00001714 return true;
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001715 else if (ResTy == MatchOperand_ParseFail)
1716 llvm_unreachable("Should never ParseFail");
1717 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001718 }
1719 } else if (Expr->getKind() == MCExpr::Constant) {
1720 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001721 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
1722 MipsOperand *op =
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001723 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this);
Jack Carterd76b2372013-03-21 21:44:16 +00001724 Operands.push_back(op);
1725 return true;
1726 }
1727 }
1728 return false;
1729}
Jack Carterd0bd6422013-04-18 00:41:53 +00001730
Jack Carter873c7242013-01-12 01:03:14 +00001731MipsAsmParser::OperandMatchResultTy
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001732MipsAsmParser::MatchAnyRegisterNameWithoutDollar(
1733 SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
1734 SMLoc S) {
1735 int Index = matchCPURegisterName(Identifier);
1736 if (Index != -1) {
1737 Parser.Lex();
1738 Operands.push_back(MipsOperand::CreateGPRReg(
1739 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1740 return MatchOperand_Success;
1741 }
1742
1743 Index = matchFPURegisterName(Identifier);
1744 if (Index != -1) {
1745 Parser.Lex();
1746 Operands.push_back(MipsOperand::CreateFGRReg(
1747 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1748 return MatchOperand_Success;
1749 }
1750
1751 Index = matchFCCRegisterName(Identifier);
1752 if (Index != -1) {
1753 Parser.Lex();
1754 Operands.push_back(MipsOperand::CreateFCCReg(
1755 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1756 return MatchOperand_Success;
1757 }
1758
1759 Index = matchACRegisterName(Identifier);
1760 if (Index != -1) {
1761 Parser.Lex();
1762 Operands.push_back(MipsOperand::CreateACCReg(
1763 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1764 return MatchOperand_Success;
1765 }
1766
1767 Index = matchMSA128RegisterName(Identifier);
1768 if (Index != -1) {
1769 Parser.Lex();
1770 Operands.push_back(MipsOperand::CreateMSA128Reg(
1771 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1772 return MatchOperand_Success;
1773 }
1774
1775 Index = matchMSA128CtrlRegisterName(Identifier);
1776 if (Index != -1) {
1777 Parser.Lex();
1778 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1779 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1780 return MatchOperand_Success;
1781 }
1782
1783 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001784}
1785
1786MipsAsmParser::OperandMatchResultTy
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001787MipsAsmParser::ParseAnyRegisterWithoutDollar(
1788 SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc S) {
1789 auto Token = Parser.getTok();
1790
1791 if (Token.is(AsmToken::Identifier)) {
1792 DEBUG(dbgs() << ".. identifier\n");
1793 StringRef Identifier = Token.getIdentifier();
1794 return MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
1795 } else if (Token.is(AsmToken::Integer)) {
1796 DEBUG(dbgs() << ".. integer\n");
1797 Operands.push_back(MipsOperand::CreateNumericReg(
1798 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1799 *this));
1800 Parser.Lex();
1801 return MatchOperand_Success;
1802 }
1803
1804 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1805
1806 return MatchOperand_NoMatch;
1807}
1808
1809MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
1810 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1811 DEBUG(dbgs() << "ParseAnyRegister\n");
1812
1813 auto Token = Parser.getTok();
1814
1815 SMLoc S = Token.getLoc();
1816
1817 if (Token.isNot(AsmToken::Dollar)) {
1818 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1819 if (Token.is(AsmToken::Identifier)) {
1820 if (searchSymbolAlias(Operands))
1821 return MatchOperand_Success;
1822 }
1823 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1824 return MatchOperand_NoMatch;
1825 }
1826 DEBUG(dbgs() << ".. $\n");
1827 Parser.Lex();
1828 Token = Parser.getTok();
1829
1830 OperandMatchResultTy ResTy = ParseAnyRegisterWithoutDollar(Operands, S);
1831 if (ResTy == MatchOperand_NoMatch)
1832 return MatchOperand_ParseFail; // We ate the $ so NoMatch isn't valid
1833 return ResTy;
1834}
1835
1836MipsAsmParser::OperandMatchResultTy
1837MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1838 switch (getLexer().getKind()) {
1839 default:
1840 return MatchOperand_NoMatch;
1841 case AsmToken::LParen:
1842 case AsmToken::Minus:
1843 case AsmToken::Plus:
1844 case AsmToken::Integer:
1845 case AsmToken::String:
1846 break;
1847 }
1848
1849 const MCExpr *IdVal;
1850 SMLoc S = Parser.getTok().getLoc();
1851 if (getParser().parseExpression(IdVal))
1852 return MatchOperand_ParseFail;
1853
1854 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1855 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1856 return MatchOperand_Success;
1857}
1858
1859MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
1860 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1861 DEBUG(dbgs() << "ParseJumpTarget\n");
1862
1863 SMLoc S = getLexer().getLoc();
1864
1865 // Integers and expressions are acceptable
1866 OperandMatchResultTy ResTy = ParseImm(Operands);
1867 if (ResTy != MatchOperand_NoMatch)
1868 return ResTy;
1869
1870 // Consume the $ if there is one. We'll add it to the symbol below.
1871 bool hasConsumedDollar = false;
1872 if (getLexer().is(AsmToken::Dollar)) {
1873 Parser.Lex();
1874 hasConsumedDollar = true;
1875
1876 // We have an unfortunate conflict between '$sym' and '$reg' so give
1877 // registers a chance before we try symbols.
1878 // The conflict is between 'bc1t $offset', and 'bc1t $fcc, $offset'.
1879 OperandMatchResultTy ResTy = ParseAnyRegisterWithoutDollar(Operands, S);
1880 if (ResTy != MatchOperand_NoMatch)
1881 return ResTy;
1882 }
1883
1884 StringRef Identifier;
1885 if (Parser.parseIdentifier(Identifier))
1886 return hasConsumedDollar ? MatchOperand_ParseFail : MatchOperand_NoMatch;
1887
1888 if (hasConsumedDollar)
1889 Identifier = StringRef("$" + Identifier.str());
1890
1891 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1892 MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
1893
1894 // Create a symbol reference.
1895 const MCExpr *Res =
1896 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
1897
1898 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
1899 return MatchOperand_Success;
1900 // // Look for the existing symbol, we should check if
1901 // // we need to assign the proper RegisterKind.
1902 // if (searchSymbolAlias(Operands))
1903 // return false;
1904
1905 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001906}
1907
Vladimir Medic2b953d02013-10-01 09:48:56 +00001908MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001909MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001910 const MCExpr *IdVal;
1911 // If the first token is '$' we may have register operand.
1912 if (Parser.getTok().is(AsmToken::Dollar))
1913 return MatchOperand_NoMatch;
1914 SMLoc S = Parser.getTok().getLoc();
1915 if (getParser().parseExpression(IdVal))
1916 return MatchOperand_ParseFail;
1917 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001918 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001919 int64_t Val = MCE->getValue();
1920 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1921 Operands.push_back(MipsOperand::CreateImm(
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001922 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001923 return MatchOperand_Success;
1924}
1925
Matheus Almeida779c5932013-11-18 12:32:49 +00001926MipsAsmParser::OperandMatchResultTy
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001927MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001928 switch (getLexer().getKind()) {
1929 default:
1930 return MatchOperand_NoMatch;
1931 case AsmToken::LParen:
1932 case AsmToken::Plus:
1933 case AsmToken::Minus:
1934 case AsmToken::Integer:
1935 break;
1936 }
1937
1938 const MCExpr *Expr;
1939 SMLoc S = Parser.getTok().getLoc();
1940
1941 if (getParser().parseExpression(Expr))
1942 return MatchOperand_ParseFail;
1943
1944 int64_t Val;
1945 if (!Expr->EvaluateAsAbsolute(Val)) {
1946 Error(S, "expected immediate value");
1947 return MatchOperand_ParseFail;
1948 }
1949
1950 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1951 // and because the CPU always adds one to the immediate field, the allowed
1952 // range becomes 1..4. We'll only check the range here and will deal
1953 // with the addition/subtraction when actually decoding/encoding
1954 // the instruction.
1955 if (Val < 1 || Val > 4) {
1956 Error(S, "immediate not in range (1..4)");
1957 return MatchOperand_ParseFail;
1958 }
1959
Jack Carter3b2c96e2014-01-22 23:31:38 +00001960 Operands.push_back(
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001961 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00001962 return MatchOperand_Success;
1963}
1964
Jack Carterdc1e35d2012-09-06 20:00:02 +00001965MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1966
Vladimir Medic4c299852013-11-06 11:27:05 +00001967 MCSymbolRefExpr::VariantKind VK =
1968 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1969 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1970 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1971 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1972 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1973 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1974 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1975 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1976 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1977 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1978 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1979 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1980 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1981 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1982 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1983 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1984 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1985 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00001986 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
1987 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
1988 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
1989 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
1990 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
1991 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Vladimir Medic4c299852013-11-06 11:27:05 +00001992 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001993
Daniel Sandersa567da52014-03-31 15:15:02 +00001994 assert (VK != MCSymbolRefExpr::VK_None);
1995
Jack Carterdc1e35d2012-09-06 20:00:02 +00001996 return VK;
1997}
Jack Cartera63b16a2012-09-07 00:23:42 +00001998
Daniel Sanders0c648ba2014-03-31 17:43:46 +00001999/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2000/// either this.
2001/// ::= '(', register, ')'
2002/// handle it before we iterate so we don't get tripped up by the lack of
2003/// a comma.
2004bool MipsAsmParser::ParseParenSuffix(
2005 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2006 if (getLexer().is(AsmToken::LParen)) {
2007 Operands.push_back(
2008 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2009 Parser.Lex();
2010 if (ParseOperand(Operands, Name)) {
2011 SMLoc Loc = getLexer().getLoc();
2012 Parser.eatToEndOfStatement();
2013 return Error(Loc, "unexpected token in argument list");
2014 }
2015 if (Parser.getTok().isNot(AsmToken::RParen)) {
2016 SMLoc Loc = getLexer().getLoc();
2017 Parser.eatToEndOfStatement();
2018 return Error(Loc, "unexpected token, expected ')'");
2019 }
2020 Operands.push_back(
2021 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2022 Parser.Lex();
2023 }
2024 return false;
2025}
2026
2027/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2028/// either one of these.
2029/// ::= '[', register, ']'
2030/// ::= '[', integer, ']'
2031/// handle it before we iterate so we don't get tripped up by the lack of
2032/// a comma.
2033bool MipsAsmParser::ParseBracketSuffix(
2034 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2035 if (getLexer().is(AsmToken::LBrac)) {
2036 Operands.push_back(
2037 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2038 Parser.Lex();
2039 if (ParseOperand(Operands, Name)) {
2040 SMLoc Loc = getLexer().getLoc();
2041 Parser.eatToEndOfStatement();
2042 return Error(Loc, "unexpected token in argument list");
2043 }
2044 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2045 SMLoc Loc = getLexer().getLoc();
2046 Parser.eatToEndOfStatement();
2047 return Error(Loc, "unexpected token, expected ']'");
2048 }
2049 Operands.push_back(
2050 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2051 Parser.Lex();
2052 }
2053 return false;
2054}
2055
Vladimir Medic4c299852013-11-06 11:27:05 +00002056bool MipsAsmParser::ParseInstruction(
2057 ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
2058 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sanders0c648ba2014-03-31 17:43:46 +00002059 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002060 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002061 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002062 Parser.eatToEndOfStatement();
2063 return Error(NameLoc, "Unknown instruction");
2064 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002065 // First operand in MCInst is instruction mnemonic.
Daniel Sanders0c648ba2014-03-31 17:43:46 +00002066 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002067
2068 // Read the remaining operands.
2069 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2070 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002071 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002072 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002073 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002074 return Error(Loc, "unexpected token in argument list");
2075 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +00002076 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2077 return true;
2078 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002079
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 while (getLexer().is(AsmToken::Comma)) {
2081 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002082 // Parse and remember the operand.
2083 if (ParseOperand(Operands, Name)) {
2084 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002085 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002086 return Error(Loc, "unexpected token in argument list");
2087 }
Daniel Sanders0c648ba2014-03-31 17:43:46 +00002088 // Parse bracket and parenthesis suffixes before we iterate
2089 if (getLexer().is(AsmToken::LBrac)) {
2090 if (ParseBracketSuffix(Name, Operands))
2091 return true;
2092 } else if (getLexer().is(AsmToken::LParen) &&
2093 ParseParenSuffix(Name, Operands))
2094 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002095 }
2096 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002097 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2098 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002099 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002100 return Error(Loc, "unexpected token in argument list");
2101 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002102 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002103 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002104}
2105
Jack Carter0b744b32012-10-04 02:29:46 +00002106bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 SMLoc Loc = getLexer().getLoc();
2108 Parser.eatToEndOfStatement();
2109 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002110}
2111
2112bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 // Line should look like: ".set noat".
2114 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002115 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002116 // eat noat
2117 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002118 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002119 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2120 reportParseError("unexpected token in statement");
2121 return false;
2122 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002123 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002124 return false;
2125}
Jack Carterd0bd6422013-04-18 00:41:53 +00002126
Jack Carter0b744b32012-10-04 02:29:46 +00002127bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002128 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002129 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002130 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002131 getParser().Lex();
2132 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002133 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002134 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002135 return false;
2136 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002137 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002138 if (getLexer().isNot(AsmToken::Dollar)) {
2139 reportParseError("unexpected token in statement");
2140 return false;
2141 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002142 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002143 const AsmToken &Reg = Parser.getTok();
2144 if (Reg.is(AsmToken::Identifier)) {
2145 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2146 } else if (Reg.is(AsmToken::Integer)) {
2147 AtRegNo = Reg.getIntVal();
2148 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002149 reportParseError("unexpected token in statement");
2150 return false;
2151 }
Jack Carter1ac53222013-02-20 23:11:17 +00002152
Daniel Sanders71a89d922014-03-25 13:01:06 +00002153 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002154 reportParseError("unexpected token in statement");
2155 return false;
2156 }
2157
2158 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002159 reportParseError("unexpected token in statement");
2160 return false;
2161 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002162 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002163
2164 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2165 reportParseError("unexpected token in statement");
2166 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002167 }
2168 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002169 return false;
2170 } else {
2171 reportParseError("unexpected token in statement");
2172 return false;
2173 }
2174}
2175
2176bool MipsAsmParser::parseSetReorderDirective() {
2177 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002178 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002179 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2180 reportParseError("unexpected token in statement");
2181 return false;
2182 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002183 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002184 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002185 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002186 return false;
2187}
2188
2189bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002190 Parser.Lex();
2191 // If this is not the end of the statement, report an error.
2192 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2193 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002194 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002195 }
2196 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002197 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002198 Parser.Lex(); // Consume the EndOfStatement.
2199 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002200}
2201
2202bool MipsAsmParser::parseSetMacroDirective() {
2203 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002204 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002205 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2206 reportParseError("unexpected token in statement");
2207 return false;
2208 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002209 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002210 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002211 return false;
2212}
2213
2214bool MipsAsmParser::parseSetNoMacroDirective() {
2215 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002216 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002217 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2218 reportParseError("`noreorder' must be set before `nomacro'");
2219 return false;
2220 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002221 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002222 reportParseError("`noreorder' must be set before `nomacro'");
2223 return false;
2224 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002225 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002226 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002227 return false;
2228}
Jack Carterd76b2372013-03-21 21:44:16 +00002229
Jack Carter39536722014-01-22 23:08:42 +00002230bool MipsAsmParser::parseSetNoMips16Directive() {
2231 Parser.Lex();
2232 // If this is not the end of the statement, report an error.
2233 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2234 reportParseError("unexpected token in statement");
2235 return false;
2236 }
2237 // For now do nothing.
2238 Parser.Lex(); // Consume the EndOfStatement.
2239 return false;
2240}
2241
Jack Carterd76b2372013-03-21 21:44:16 +00002242bool MipsAsmParser::parseSetAssignment() {
2243 StringRef Name;
2244 const MCExpr *Value;
2245
2246 if (Parser.parseIdentifier(Name))
2247 reportParseError("expected identifier after .set");
2248
2249 if (getLexer().isNot(AsmToken::Comma))
2250 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002251 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002252
Jack Carter3b2c96e2014-01-22 23:31:38 +00002253 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002254 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002255
Jack Carterd0bd6422013-04-18 00:41:53 +00002256 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002257 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002258 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002259 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002260 Sym = getContext().GetOrCreateSymbol(Name);
2261 Sym->setVariableValue(Value);
2262
2263 return false;
2264}
Jack Carterd0bd6422013-04-18 00:41:53 +00002265
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002266bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2267 Parser.Lex();
2268 if (getLexer().isNot(AsmToken::EndOfStatement))
2269 return reportParseError("unexpected token in .set directive");
2270
2271 switch(Feature) {
2272 default: llvm_unreachable("Unimplemented feature");
2273 case Mips::FeatureDSP:
2274 setFeatureBits(Mips::FeatureDSP, "dsp");
2275 getTargetStreamer().emitDirectiveSetDsp();
2276 break;
2277 case Mips::FeatureMicroMips:
2278 getTargetStreamer().emitDirectiveSetMicroMips();
2279 break;
2280 case Mips::FeatureMips16:
2281 getTargetStreamer().emitDirectiveSetMips16();
2282 break;
2283 case Mips::FeatureMips32r2:
2284 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2285 getTargetStreamer().emitDirectiveSetMips32R2();
2286 break;
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002287 case Mips::FeatureMips64:
2288 setFeatureBits(Mips::FeatureMips64, "mips64");
2289 getTargetStreamer().emitDirectiveSetMips64();
2290 break;
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002291 case Mips::FeatureMips64r2:
2292 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2293 getTargetStreamer().emitDirectiveSetMips64R2();
2294 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002295 }
2296 return false;
2297}
2298
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002299bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2300 if (!getLexer().is(AsmToken::Dollar))
2301 return false;
2302
2303 Parser.Lex();
2304
2305 const AsmToken &Reg = Parser.getTok();
2306 if (Reg.is(AsmToken::Identifier)) {
2307 RegNum = matchCPURegisterName(Reg.getIdentifier());
2308 } else if (Reg.is(AsmToken::Integer)) {
2309 RegNum = Reg.getIntVal();
2310 } else {
2311 return false;
2312 }
2313
2314 Parser.Lex();
2315 return true;
2316}
2317
2318bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2319 if (getLexer().isNot(AsmToken::Comma)) {
2320 SMLoc Loc = getLexer().getLoc();
2321 Parser.eatToEndOfStatement();
2322 return Error(Loc, ErrorStr);
2323 }
2324
2325 Parser.Lex(); // Eat the comma.
2326 return true;
2327}
2328
2329bool MipsAsmParser::parseDirectiveCPSetup() {
2330 unsigned FuncReg;
2331 unsigned Save;
2332 bool SaveIsReg = true;
2333
2334 if (!parseRegister(FuncReg))
2335 return reportParseError("expected register containing function address");
2336 FuncReg = getGPR(FuncReg);
2337
2338 if (!eatComma("expected comma parsing directive"))
2339 return true;
2340
2341 if (!parseRegister(Save)) {
2342 const AsmToken &Tok = Parser.getTok();
2343 if (Tok.is(AsmToken::Integer)) {
2344 Save = Tok.getIntVal();
2345 SaveIsReg = false;
2346 Parser.Lex();
2347 } else
2348 return reportParseError("expected save register or stack offset");
2349 } else
2350 Save = getGPR(Save);
2351
2352 if (!eatComma("expected comma parsing directive"))
2353 return true;
2354
2355 StringRef Name;
2356 if (Parser.parseIdentifier(Name))
2357 reportParseError("expected identifier");
2358 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
2359 unsigned GPReg = getGPR(matchCPURegisterName("gp"));
2360
2361 // FIXME: The code below this point should be in the TargetStreamers.
2362 // Only N32 and N64 emit anything for .cpsetup
2363 // FIXME: We should only emit something for PIC mode too.
2364 if (!isN32() && !isN64())
2365 return false;
2366
2367 MCStreamer &TS = getStreamer();
2368 MCInst Inst;
2369 // Either store the old $gp in a register or on the stack
2370 if (SaveIsReg) {
2371 // move $save, $gpreg
2372 Inst.setOpcode(Mips::DADDu);
2373 Inst.addOperand(MCOperand::CreateReg(Save));
2374 Inst.addOperand(MCOperand::CreateReg(GPReg));
2375 Inst.addOperand(MCOperand::CreateReg(getGPR(0)));
2376 } else {
2377 // sd $gpreg, offset($sp)
2378 Inst.setOpcode(Mips::SD);
2379 Inst.addOperand(MCOperand::CreateReg(GPReg));
2380 Inst.addOperand(MCOperand::CreateReg(getGPR(matchCPURegisterName("sp"))));
2381 Inst.addOperand(MCOperand::CreateImm(Save));
2382 }
2383 TS.EmitInstruction(Inst, STI);
2384 Inst.clear();
2385
2386 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2387 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI,
2388 getContext());
2389 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2390 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO,
2391 getContext());
2392 // lui $gp, %hi(%neg(%gp_rel(funcSym)))
2393 Inst.setOpcode(Mips::LUi);
2394 Inst.addOperand(MCOperand::CreateReg(GPReg));
2395 Inst.addOperand(MCOperand::CreateExpr(HiExpr));
2396 TS.EmitInstruction(Inst, STI);
2397 Inst.clear();
2398
2399 // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
2400 Inst.setOpcode(Mips::ADDiu);
2401 Inst.addOperand(MCOperand::CreateReg(GPReg));
2402 Inst.addOperand(MCOperand::CreateReg(GPReg));
2403 Inst.addOperand(MCOperand::CreateExpr(LoExpr));
2404 TS.EmitInstruction(Inst, STI);
2405 Inst.clear();
2406
2407 // daddu $gp, $gp, $funcreg
2408 Inst.setOpcode(Mips::DADDu);
2409 Inst.addOperand(MCOperand::CreateReg(GPReg));
2410 Inst.addOperand(MCOperand::CreateReg(GPReg));
2411 Inst.addOperand(MCOperand::CreateReg(FuncReg));
2412 TS.EmitInstruction(Inst, STI);
2413 return false;
2414}
2415
Jack Carter0b744b32012-10-04 02:29:46 +00002416bool MipsAsmParser::parseDirectiveSet() {
2417
Jack Carterd0bd6422013-04-18 00:41:53 +00002418 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002419 const AsmToken &Tok = Parser.getTok();
2420
2421 if (Tok.getString() == "noat") {
2422 return parseSetNoAtDirective();
2423 } else if (Tok.getString() == "at") {
2424 return parseSetAtDirective();
2425 } else if (Tok.getString() == "reorder") {
2426 return parseSetReorderDirective();
2427 } else if (Tok.getString() == "noreorder") {
2428 return parseSetNoReorderDirective();
2429 } else if (Tok.getString() == "macro") {
2430 return parseSetMacroDirective();
2431 } else if (Tok.getString() == "nomacro") {
2432 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002433 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002434 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002435 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002436 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002437 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002438 getTargetStreamer().emitDirectiveSetNoMicroMips();
2439 Parser.eatToEndOfStatement();
2440 return false;
2441 } else if (Tok.getString() == "micromips") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002442 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002443 } else if (Tok.getString() == "mips32r2") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002444 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002445 } else if (Tok.getString() == "mips64") {
2446 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002447 } else if (Tok.getString() == "mips64r2") {
2448 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002449 } else if (Tok.getString() == "dsp") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002450 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002451 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002452 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002453 parseSetAssignment();
2454 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002455 }
Jack Carter07c818d2013-01-25 01:31:34 +00002456
Jack Carter0b744b32012-10-04 02:29:46 +00002457 return true;
2458}
2459
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002460/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002461/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002462bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002463 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2464 for (;;) {
2465 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002466 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002467 return true;
2468
2469 getParser().getStreamer().EmitValue(Value, Size);
2470
2471 if (getLexer().is(AsmToken::EndOfStatement))
2472 break;
2473
2474 // FIXME: Improve diagnostic.
2475 if (getLexer().isNot(AsmToken::Comma))
2476 return Error(L, "unexpected token in directive");
2477 Parser.Lex();
2478 }
2479 }
2480
2481 Parser.Lex();
2482 return false;
2483}
2484
Vladimir Medic4c299852013-11-06 11:27:05 +00002485/// parseDirectiveGpWord
2486/// ::= .gpword local_sym
2487bool MipsAsmParser::parseDirectiveGpWord() {
2488 const MCExpr *Value;
2489 // EmitGPRel32Value requires an expression, so we are using base class
2490 // method to evaluate the expression.
2491 if (getParser().parseExpression(Value))
2492 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002493 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002494
Vladimir Medice10c1122013-11-13 13:18:04 +00002495 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002496 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002497 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002498 return false;
2499}
2500
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002501/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002502/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002503bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002504 const MCExpr *Value;
2505 // EmitGPRel64Value requires an expression, so we are using base class
2506 // method to evaluate the expression.
2507 if (getParser().parseExpression(Value))
2508 return true;
2509 getParser().getStreamer().EmitGPRel64Value(Value);
2510
2511 if (getLexer().isNot(AsmToken::EndOfStatement))
2512 return Error(getLexer().getLoc(), "unexpected token in directive");
2513 Parser.Lex(); // Eat EndOfStatement token.
2514 return false;
2515}
2516
Jack Carter0cd3c192014-01-06 23:27:31 +00002517bool MipsAsmParser::parseDirectiveOption() {
2518 // Get the option token.
2519 AsmToken Tok = Parser.getTok();
2520 // At the moment only identifiers are supported.
2521 if (Tok.isNot(AsmToken::Identifier)) {
2522 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2523 Parser.eatToEndOfStatement();
2524 return false;
2525 }
2526
2527 StringRef Option = Tok.getIdentifier();
2528
2529 if (Option == "pic0") {
2530 getTargetStreamer().emitDirectiveOptionPic0();
2531 Parser.Lex();
2532 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2533 Error(Parser.getTok().getLoc(),
2534 "unexpected token in .option pic0 directive");
2535 Parser.eatToEndOfStatement();
2536 }
2537 return false;
2538 }
2539
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002540 if (Option == "pic2") {
2541 getTargetStreamer().emitDirectiveOptionPic2();
2542 Parser.Lex();
2543 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2544 Error(Parser.getTok().getLoc(),
2545 "unexpected token in .option pic2 directive");
2546 Parser.eatToEndOfStatement();
2547 }
2548 return false;
2549 }
2550
Jack Carter0cd3c192014-01-06 23:27:31 +00002551 // Unknown option.
2552 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2553 Parser.eatToEndOfStatement();
2554 return false;
2555}
2556
Jack Carter0b744b32012-10-04 02:29:46 +00002557bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002558 StringRef IDVal = DirectiveID.getString();
2559
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002560 if (IDVal == ".dword") {
2561 parseDataDirective(8, DirectiveID.getLoc());
2562 return false;
2563 }
2564
Jack Carterd0bd6422013-04-18 00:41:53 +00002565 if (IDVal == ".ent") {
2566 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002567 Parser.Lex();
2568 return false;
2569 }
2570
Jack Carter07c818d2013-01-25 01:31:34 +00002571 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002572 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002573 Parser.Lex();
2574 return false;
2575 }
2576
Jack Carter07c818d2013-01-25 01:31:34 +00002577 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002578 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002579 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002580 return false;
2581 }
2582
Jack Carter07c818d2013-01-25 01:31:34 +00002583 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002584 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002585 }
2586
Jack Carter07c818d2013-01-25 01:31:34 +00002587 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002588 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002589 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002590 return false;
2591 }
2592
Jack Carter07c818d2013-01-25 01:31:34 +00002593 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002594 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002595 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002596 return false;
2597 }
2598
Jack Carter07c818d2013-01-25 01:31:34 +00002599 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002600 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002601 return false;
2602 }
2603
Rafael Espindolab59fb732014-03-28 18:50:26 +00002604 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002605 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002606 return false;
2607 }
2608
Jack Carter07c818d2013-01-25 01:31:34 +00002609 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002610 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002611 return false;
2612 }
2613
Jack Carter0cd3c192014-01-06 23:27:31 +00002614 if (IDVal == ".option")
2615 return parseDirectiveOption();
2616
2617 if (IDVal == ".abicalls") {
2618 getTargetStreamer().emitDirectiveAbiCalls();
2619 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2620 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2621 // Clear line
2622 Parser.eatToEndOfStatement();
2623 }
2624 return false;
2625 }
2626
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002627 if (IDVal == ".cpsetup")
2628 return parseDirectiveCPSetup();
2629
Rafael Espindola870c4e92012-01-11 03:56:41 +00002630 return true;
2631}
2632
Rafael Espindola870c4e92012-01-11 03:56:41 +00002633extern "C" void LLVMInitializeMipsAsmParser() {
2634 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2635 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2636 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2637 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2638}
Jack Carterb4dbc172012-09-05 23:34:03 +00002639
2640#define GET_REGISTER_MATCHER
2641#define GET_MATCHER_IMPLEMENTATION
2642#include "MipsGenAsmMatcher.inc"