blob: 4a6dd5e2fa2647fde5523f8f6bee91f11ceae765 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000019#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000020#include "llvm/MC/MCParser/MCAsmLexer.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000025#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000026#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000027#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000028#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000029
30using namespace llvm;
31
Chandler Carruthe96dd892014-04-21 22:55:11 +000032#define DEBUG_TYPE "mips-asm-parser"
33
Joey Gouly0e76fa72013-09-12 10:28:05 +000034namespace llvm {
35class MCInstrInfo;
36}
37
Rafael Espindola870c4e92012-01-11 03:56:41 +000038namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000039class MipsAssemblerOptions {
40public:
Vladimir Medic4c299852013-11-06 11:27:05 +000041 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000042
Vladimir Medic4c299852013-11-06 11:27:05 +000043 unsigned getATRegNum() { return aTReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000044 bool setATReg(unsigned Reg);
45
Vladimir Medic4c299852013-11-06 11:27:05 +000046 bool isReorder() { return reorder; }
47 void setReorder() { reorder = true; }
48 void setNoreorder() { reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000049
Vladimir Medic4c299852013-11-06 11:27:05 +000050 bool isMacro() { return macro; }
51 void setMacro() { macro = true; }
52 void setNomacro() { macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000053
54private:
55 unsigned aTReg;
56 bool reorder;
57 bool macro;
58};
59}
60
61namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000062class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000063 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000064 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000065 return static_cast<MipsTargetStreamer &>(TS);
66 }
67
Jack Carterb4dbc172012-09-05 23:34:03 +000068 MCSubtargetInfo &STI;
69 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000070 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000071
Akira Hatanaka7605630c2012-08-17 20:16:42 +000072#define GET_ASSEMBLER_HEADER
73#include "MipsGenAsmMatcher.inc"
74
Chad Rosier49963552012-10-13 00:26:04 +000075 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Vladimir Medic4c299852013-11-06 11:27:05 +000076 SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000077 MCStreamer &Out, unsigned &ErrorInfo,
78 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000079
Daniel Sandersb50ccf82014-04-01 10:35:28 +000080 /// Parse a register as used in CFI directives
Rafael Espindola870c4e92012-01-11 03:56:41 +000081 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
82
Daniel Sandersb50ccf82014-04-01 10:35:28 +000083 bool ParseParenSuffix(StringRef Name,
84 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
85
86 bool ParseBracketSuffix(StringRef Name,
87 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
88
Chad Rosierf0e87202012-10-25 20:41:34 +000089 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
90 SMLoc NameLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +000091 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000092
93 bool ParseDirective(AsmToken DirectiveID);
94
Jack Carterb4dbc172012-09-05 23:34:03 +000095 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +000096 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +000097
Daniel Sandersb50ccf82014-04-01 10:35:28 +000098 MipsAsmParser::OperandMatchResultTy MatchAnyRegisterNameWithoutDollar(
99 SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
100 SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000101
102 MipsAsmParser::OperandMatchResultTy
Daniel Sanders21bce302014-04-01 12:35:23 +0000103 MatchAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000104 SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000105
Jack Carter873c7242013-01-12 01:03:14 +0000106 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000107 ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000108
109 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000110 ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000111
112 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000113 ParseJumpTarget(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000114
115 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000116 parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000117
Matheus Almeida779c5932013-11-18 12:32:49 +0000118 MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000119 ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000120
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000121 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000122
Vladimir Medic4c299852013-11-06 11:27:05 +0000123 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
Jack Carterb4dbc172012-09-05 23:34:03 +0000124 StringRef Mnemonic);
125
Jack Carter30a59822012-10-04 04:03:53 +0000126 bool needsExpansion(MCInst &Inst);
127
128 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000129 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000130 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000131 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000132 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
133 SmallVectorImpl<MCInst> &Instructions);
134 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
135 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000136 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000137 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
138 bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000139 bool reportParseError(StringRef ErrorMsg);
140
Jack Carterb5cf5902013-04-17 00:18:04 +0000141 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000142 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000143
Vladimir Medic4c299852013-11-06 11:27:05 +0000144 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000145
146 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000147 bool parseSetFeature(uint64_t Feature);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000148 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000149 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000150 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000151 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000152
153 bool parseSetAtDirective();
154 bool parseSetNoAtDirective();
155 bool parseSetMacroDirective();
156 bool parseSetNoMacroDirective();
157 bool parseSetReorderDirective();
158 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000159 bool parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +0000160
Jack Carterd76b2372013-03-21 21:44:16 +0000161 bool parseSetAssignment();
162
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000163 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000164 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000165 bool parseDirectiveGpDWord();
Jack Carter07c818d2013-01-25 01:31:34 +0000166
Jack Carterdc1e35d2012-09-06 20:00:02 +0000167 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000168
Daniel Sanders5e94e682014-03-27 16:42:17 +0000169 bool isGP64() const {
170 return (STI.getFeatureBits() & Mips::FeatureGP64Bit) != 0;
Jack Carterb4dbc172012-09-05 23:34:03 +0000171 }
172
Jack Cartera63b16a2012-09-07 00:23:42 +0000173 bool isFP64() const {
174 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
175 }
176
Daniel Sandersa4b0c742014-03-26 11:39:07 +0000177 bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
Vladimir Medic4c299852013-11-06 11:27:05 +0000178 bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000179
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000180 bool isMicroMips() const {
181 return STI.getFeatureBits() & Mips::FeatureMicroMips;
182 }
183
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000184 bool parseRegister(unsigned &RegNum);
185
186 bool eatComma(StringRef ErrorStr);
187
Jack Carter1ac53222013-02-20 23:11:17 +0000188 int matchCPURegisterName(StringRef Symbol);
189
Jack Carter873c7242013-01-12 01:03:14 +0000190 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000191
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000192 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000193
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000194 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000195
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000196 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000197
Jack Carter5dc8ac92013-09-25 23:50:44 +0000198 int matchMSA128RegisterName(StringRef Name);
199
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000200 int matchMSA128CtrlRegisterName(StringRef Name);
201
Jack Carterd0bd6422013-04-18 00:41:53 +0000202 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000203
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000204 unsigned getGPR(int RegNo);
205
Jack Carter1ac53222013-02-20 23:11:17 +0000206 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000207
208 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000209 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000210
211 // Helper function that checks if the value of a vector index is within the
212 // boundaries of accepted values for each RegisterKind
213 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
214 bool validateMSAIndex(int Val, int RegKind);
215
Vladimir Medic615b26e2014-03-04 09:54:09 +0000216 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
217 if (!(STI.getFeatureBits() & Feature)) {
218 setAvailableFeatures(ComputeAvailableFeatures(
219 STI.ToggleFeature(FeatureString)));
220 }
221 }
222
223 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
224 if (STI.getFeatureBits() & Feature) {
225 setAvailableFeatures(ComputeAvailableFeatures(
226 STI.ToggleFeature(FeatureString)));
227 }
228 }
229
Rafael Espindola870c4e92012-01-11 03:56:41 +0000230public:
Joey Gouly0e76fa72013-09-12 10:28:05 +0000231 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
232 const MCInstrInfo &MII)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000233 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000234 // Initialize the set of available features.
235 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000236
237 // Assert exactly one ABI was chosen.
238 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
239 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
240 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
241 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000242 }
243
Jack Carterb4dbc172012-09-05 23:34:03 +0000244 MCAsmParser &getParser() const { return Parser; }
245 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000246
247 /// Warn if RegNo is the current assembler temporary.
248 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000249};
250}
251
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000252namespace {
253
254/// MipsOperand - Instances of this class represent a parsed Mips machine
255/// instruction.
256class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000257public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000258 /// Broad categories of register classes
259 /// The exact class is finalized by the render method.
260 enum RegKind {
261 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64())
262 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
263 /// isFP64())
264 RegKind_FCC = 4, /// FCC
265 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
266 RegKind_MSACtrl = 16, /// MSA control registers
267 RegKind_COP2 = 32, /// COP2
268 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
269 /// context).
270 RegKind_CCR = 128, /// CCR
271 RegKind_HWRegs = 256, /// HWRegs
272
273 /// Potentially any (e.g. $1)
274 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
275 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
276 RegKind_CCR | RegKind_HWRegs
Jack Carter873c7242013-01-12 01:03:14 +0000277 };
278
279private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000280 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000281 k_Immediate, /// An immediate (possibly involving symbol references)
282 k_Memory, /// Base + Offset Memory Address
283 k_PhysRegister, /// A physical register from the Mips namespace
284 k_RegisterIndex, /// A register index in one or more RegKind.
285 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000286 } Kind;
287
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000288 MipsOperand(KindTy K, MipsAsmParser &Parser)
289 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
290
291 /// For diagnostics, and checking the assembler temporary
292 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000293
Eric Christopher8996c5d2013-03-15 00:42:55 +0000294 struct Token {
295 const char *Data;
296 unsigned Length;
297 };
298
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000299 struct PhysRegOp {
300 unsigned Num; /// Register Number
301 };
302
303 struct RegIdxOp {
304 unsigned Index; /// Index into the register class
305 RegKind Kind; /// Bitfield of the kinds it could possibly be
306 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000307 };
308
309 struct ImmOp {
310 const MCExpr *Val;
311 };
312
313 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000314 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000315 const MCExpr *Off;
316 };
317
Jack Carterb4dbc172012-09-05 23:34:03 +0000318 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000319 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000320 struct PhysRegOp PhysReg;
321 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000322 struct ImmOp Imm;
323 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000324 };
325
326 SMLoc StartLoc, EndLoc;
327
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000328 /// Internal constructor for register kinds
329 static MipsOperand *CreateReg(unsigned Index, RegKind RegKind,
330 const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
331 MipsAsmParser &Parser) {
332 MipsOperand *Op = new MipsOperand(k_RegisterIndex, Parser);
333 Op->RegIdx.Index = Index;
334 Op->RegIdx.RegInfo = RegInfo;
335 Op->RegIdx.Kind = RegKind;
336 Op->StartLoc = S;
337 Op->EndLoc = E;
338 return Op;
339 }
340
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000341public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000342 /// Coerce the register to GPR32 and return the real register for the current
343 /// target.
344 unsigned getGPR32Reg() const {
345 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
346 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
347 unsigned ClassID = Mips::GPR32RegClassID;
348 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000349 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000350
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000351 /// Coerce the register to GPR64 and return the real register for the current
352 /// target.
353 unsigned getGPR64Reg() const {
354 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
355 unsigned ClassID = Mips::GPR64RegClassID;
356 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000357 }
358
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000359private:
360 /// Coerce the register to AFGR64 and return the real register for the current
361 /// target.
362 unsigned getAFGR64Reg() const {
363 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
364 if (RegIdx.Index % 2 != 0)
365 AsmParser.Warning(StartLoc, "Float register should be even.");
366 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
367 .getRegister(RegIdx.Index / 2);
368 }
369
370 /// Coerce the register to FGR64 and return the real register for the current
371 /// target.
372 unsigned getFGR64Reg() const {
373 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
374 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
375 .getRegister(RegIdx.Index);
376 }
377
378 /// Coerce the register to FGR32 and return the real register for the current
379 /// target.
380 unsigned getFGR32Reg() const {
381 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
382 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
383 .getRegister(RegIdx.Index);
384 }
385
386 /// Coerce the register to FGRH32 and return the real register for the current
387 /// target.
388 unsigned getFGRH32Reg() const {
389 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
390 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
391 .getRegister(RegIdx.Index);
392 }
393
394 /// Coerce the register to FCC and return the real register for the current
395 /// target.
396 unsigned getFCCReg() const {
397 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
398 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
399 .getRegister(RegIdx.Index);
400 }
401
402 /// Coerce the register to MSA128 and return the real register for the current
403 /// target.
404 unsigned getMSA128Reg() const {
405 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
406 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
407 // identical
408 unsigned ClassID = Mips::MSA128BRegClassID;
409 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
410 }
411
412 /// Coerce the register to MSACtrl and return the real register for the
413 /// current target.
414 unsigned getMSACtrlReg() const {
415 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
416 unsigned ClassID = Mips::MSACtrlRegClassID;
417 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
418 }
419
420 /// Coerce the register to COP2 and return the real register for the
421 /// current target.
422 unsigned getCOP2Reg() const {
423 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
424 unsigned ClassID = Mips::COP2RegClassID;
425 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
426 }
427
428 /// Coerce the register to ACC64DSP and return the real register for the
429 /// current target.
430 unsigned getACC64DSPReg() const {
431 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
432 unsigned ClassID = Mips::ACC64DSPRegClassID;
433 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
434 }
435
436 /// Coerce the register to HI32DSP and return the real register for the
437 /// current target.
438 unsigned getHI32DSPReg() const {
439 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
440 unsigned ClassID = Mips::HI32DSPRegClassID;
441 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
442 }
443
444 /// Coerce the register to LO32DSP and return the real register for the
445 /// current target.
446 unsigned getLO32DSPReg() const {
447 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
448 unsigned ClassID = Mips::LO32DSPRegClassID;
449 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
450 }
451
452 /// Coerce the register to CCR and return the real register for the
453 /// current target.
454 unsigned getCCRReg() const {
455 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
456 unsigned ClassID = Mips::CCRRegClassID;
457 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
458 }
459
460 /// Coerce the register to HWRegs and return the real register for the
461 /// current target.
462 unsigned getHWRegsReg() const {
463 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
464 unsigned ClassID = Mips::HWRegsRegClassID;
465 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
466 }
467
468public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000469 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000470 // Add as immediate when possible. Null MCExpr = 0.
471 if (Expr == 0)
472 Inst.addOperand(MCOperand::CreateImm(0));
473 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
474 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
475 else
476 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000477 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000478
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000479 void addRegOperands(MCInst &Inst, unsigned N) const {
480 llvm_unreachable("Use a custom parser instead");
481 }
482
Daniel Sanders21bce302014-04-01 12:35:23 +0000483 /// Render the operand to an MCInst as a GPR32
484 /// Asserts if the wrong number of operands are requested, or the operand
485 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000486 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
487 assert(N == 1 && "Invalid number of operands!");
488 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
489 }
490
Daniel Sanders21bce302014-04-01 12:35:23 +0000491 /// Render the operand to an MCInst as a GPR64
492 /// Asserts if the wrong number of operands are requested, or the operand
493 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000494 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
495 assert(N == 1 && "Invalid number of operands!");
496 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
497 }
498
499 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
500 assert(N == 1 && "Invalid number of operands!");
501 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
502 }
503
504 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
505 assert(N == 1 && "Invalid number of operands!");
506 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
507 }
508
509 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
510 assert(N == 1 && "Invalid number of operands!");
511 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
512 }
513
514 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
515 assert(N == 1 && "Invalid number of operands!");
516 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
517 }
518
519 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
520 assert(N == 1 && "Invalid number of operands!");
521 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
522 }
523
524 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
525 assert(N == 1 && "Invalid number of operands!");
526 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
527 }
528
529 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
530 assert(N == 1 && "Invalid number of operands!");
531 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
532 }
533
534 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
535 assert(N == 1 && "Invalid number of operands!");
536 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
537 }
538
539 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
540 assert(N == 1 && "Invalid number of operands!");
541 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
542 }
543
544 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
545 assert(N == 1 && "Invalid number of operands!");
546 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
547 }
548
549 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
550 assert(N == 1 && "Invalid number of operands!");
551 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
552 }
553
554 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
555 assert(N == 1 && "Invalid number of operands!");
556 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
557 }
558
559 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
560 assert(N == 1 && "Invalid number of operands!");
561 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
562 }
563
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000564 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000565 assert(N == 1 && "Invalid number of operands!");
566 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000567 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000568 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000569
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000570 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000571 assert(N == 2 && "Invalid number of operands!");
572
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000573 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000574
575 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000576 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000577 }
578
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000579 bool isReg() const {
580 // As a special case until we sort out the definition of div/divu, pretend
581 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
582 if (isGPRAsmReg() && RegIdx.Index == 0)
583 return true;
584
585 return Kind == k_PhysRegister;
586 }
587 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000588 bool isImm() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000589 bool isConstantImm() const {
590 return isImm() && dyn_cast<MCConstantExpr>(getImm());
591 }
592 bool isToken() const {
593 // Note: It's not possible to pretend that other operand kinds are tokens.
594 // The matcher emitter checks tokens first.
595 return Kind == k_Token;
596 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000597 bool isMem() const { return Kind == k_Memory; }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000598 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000599 bool isLSAImm() const {
600 if (!isConstantImm())
601 return false;
602 int64_t Val = getConstantImm();
603 return 1 <= Val && Val <= 4;
604 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000605
606 StringRef getToken() const {
607 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000608 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000609 }
610
611 unsigned getReg() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000612 // As a special case until we sort out the definition of div/divu, pretend
613 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
614 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
615 RegIdx.Kind & RegKind_GPR)
616 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000617
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000618 assert(Kind == k_PhysRegister && "Invalid access!");
619 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000620 }
621
Jack Carterb4dbc172012-09-05 23:34:03 +0000622 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000623 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000624 return Imm.Val;
625 }
626
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000627 int64_t getConstantImm() const {
628 const MCExpr *Val = getImm();
629 return static_cast<const MCConstantExpr *>(Val)->getValue();
630 }
631
632 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000633 assert((Kind == k_Memory) && "Invalid access!");
634 return Mem.Base;
635 }
636
637 const MCExpr *getMemOff() const {
638 assert((Kind == k_Memory) && "Invalid access!");
639 return Mem.Off;
640 }
641
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000642 static MipsOperand *CreateToken(StringRef Str, SMLoc S,
643 MipsAsmParser &Parser) {
644 MipsOperand *Op = new MipsOperand(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000645 Op->Tok.Data = Str.data();
646 Op->Tok.Length = Str.size();
647 Op->StartLoc = S;
648 Op->EndLoc = S;
649 return Op;
650 }
651
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000652 /// Create a numeric register (e.g. $1). The exact register remains
653 /// unresolved until an instruction successfully matches
654 static MipsOperand *CreateNumericReg(unsigned Index,
655 const MCRegisterInfo *RegInfo, SMLoc S,
656 SMLoc E, MipsAsmParser &Parser) {
657 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
658 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000659 }
660
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000661 /// Create a register that is definitely a GPR.
662 /// This is typically only used for named registers such as $gp.
663 static MipsOperand *CreateGPRReg(unsigned Index,
664 const MCRegisterInfo *RegInfo, SMLoc S,
665 SMLoc E, MipsAsmParser &Parser) {
666 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000667 }
668
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000669 /// Create a register that is definitely a FGR.
670 /// This is typically only used for named registers such as $f0.
671 static MipsOperand *CreateFGRReg(unsigned Index,
672 const MCRegisterInfo *RegInfo, SMLoc S,
673 SMLoc E, MipsAsmParser &Parser) {
674 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
675 }
676
677 /// Create a register that is definitely an FCC.
678 /// This is typically only used for named registers such as $fcc0.
679 static MipsOperand *CreateFCCReg(unsigned Index,
680 const MCRegisterInfo *RegInfo, SMLoc S,
681 SMLoc E, MipsAsmParser &Parser) {
682 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
683 }
684
685 /// Create a register that is definitely an ACC.
686 /// This is typically only used for named registers such as $ac0.
687 static MipsOperand *CreateACCReg(unsigned Index,
688 const MCRegisterInfo *RegInfo, SMLoc S,
689 SMLoc E, MipsAsmParser &Parser) {
690 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
691 }
692
693 /// Create a register that is definitely an MSA128.
694 /// This is typically only used for named registers such as $w0.
695 static MipsOperand *CreateMSA128Reg(unsigned Index,
696 const MCRegisterInfo *RegInfo, SMLoc S,
697 SMLoc E, MipsAsmParser &Parser) {
698 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
699 }
700
701 /// Create a register that is definitely an MSACtrl.
702 /// This is typically only used for named registers such as $msaaccess.
703 static MipsOperand *CreateMSACtrlReg(unsigned Index,
704 const MCRegisterInfo *RegInfo, SMLoc S,
705 SMLoc E, MipsAsmParser &Parser) {
706 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
707 }
708
709 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E,
710 MipsAsmParser &Parser) {
711 MipsOperand *Op = new MipsOperand(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000712 Op->Imm.Val = Val;
713 Op->StartLoc = S;
714 Op->EndLoc = E;
715 return Op;
716 }
717
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000718 static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S,
719 SMLoc E, MipsAsmParser &Parser) {
720 MipsOperand *Op = new MipsOperand(k_Memory, Parser);
Jack Carterdc1e35d2012-09-06 20:00:02 +0000721 Op->Mem.Base = Base;
722 Op->Mem.Off = Off;
723 Op->StartLoc = S;
724 Op->EndLoc = E;
725 return Op;
726 }
727
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 bool isGPRAsmReg() const {
729 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000730 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 bool isFGRAsmReg() const {
732 // AFGR64 is $0-$15 but we handle this in getAFGR64()
733 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000734 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000735 bool isHWRegsAsmReg() const {
736 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000737 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 bool isCCRAsmReg() const {
739 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000740 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 bool isFCCAsmReg() const {
742 return isRegIdx() && RegIdx.Kind & RegKind_FCC && RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000743 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 bool isACCAsmReg() const {
745 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000746 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 bool isCOP2AsmReg() const {
748 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000749 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 bool isMSA128AsmReg() const {
751 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000752 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000753 bool isMSACtrlAsmReg() const {
754 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000755 }
756
Jack Carterb4dbc172012-09-05 23:34:03 +0000757 /// getStartLoc - Get the location of the first token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000758 SMLoc getStartLoc() const { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000759 /// getEndLoc - Get the location of the last token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000760 SMLoc getEndLoc() const { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000761
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000762 virtual ~MipsOperand() {
763 switch (Kind) {
764 case k_Immediate:
765 break;
766 case k_Memory:
767 delete Mem.Base;
768 break;
769 case k_PhysRegister:
770 case k_RegisterIndex:
771 case k_Token:
772 break;
773 }
774 }
775
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000776 virtual void print(raw_ostream &OS) const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000777 switch (Kind) {
778 case k_Immediate:
779 OS << "Imm<";
780 Imm.Val->print(OS);
781 OS << ">";
782 break;
783 case k_Memory:
784 OS << "Mem<";
785 Mem.Base->print(OS);
786 OS << ", ";
787 Mem.Off->print(OS);
788 OS << ">";
789 break;
790 case k_PhysRegister:
791 OS << "PhysReg<" << PhysReg.Num << ">";
792 break;
793 case k_RegisterIndex:
794 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
795 break;
796 case k_Token:
797 OS << Tok.Data;
798 break;
799 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000800 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000801}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000802} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000803
Jack Carter9e65aa32013-03-22 00:05:30 +0000804namespace llvm {
805extern const MCInstrDesc MipsInsts[];
806}
807static const MCInstrDesc &getInstDesc(unsigned Opcode) {
808 return MipsInsts[Opcode];
809}
810
811bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000812 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000813 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000814
Jack Carter9e65aa32013-03-22 00:05:30 +0000815 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000816
817 if (MCID.isBranch() || MCID.isCall()) {
818 const unsigned Opcode = Inst.getOpcode();
819 MCOperand Offset;
820
821 switch (Opcode) {
822 default:
823 break;
824 case Mips::BEQ:
825 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 case Mips::BEQ_MM:
827 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000828 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000829 Offset = Inst.getOperand(2);
830 if (!Offset.isImm())
831 break; // We'll deal with this situation later on when applying fixups.
832 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
833 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000834 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000835 return Error(IDLoc, "branch to misaligned address");
836 break;
837 case Mips::BGEZ:
838 case Mips::BGTZ:
839 case Mips::BLEZ:
840 case Mips::BLTZ:
841 case Mips::BGEZAL:
842 case Mips::BLTZAL:
843 case Mips::BC1F:
844 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 case Mips::BGEZ_MM:
846 case Mips::BGTZ_MM:
847 case Mips::BLEZ_MM:
848 case Mips::BLTZ_MM:
849 case Mips::BGEZAL_MM:
850 case Mips::BLTZAL_MM:
851 case Mips::BC1F_MM:
852 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000853 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000854 Offset = Inst.getOperand(1);
855 if (!Offset.isImm())
856 break; // We'll deal with this situation later on when applying fixups.
857 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
858 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000859 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000860 return Error(IDLoc, "branch to misaligned address");
861 break;
862 }
863 }
864
Jack Carterc15c1d22013-04-25 23:31:35 +0000865 if (MCID.hasDelaySlot() && Options.isReorder()) {
866 // If this instruction has a delay slot and .set reorder is active,
867 // emit a NOP after it.
868 Instructions.push_back(Inst);
869 MCInst NopInst;
870 NopInst.setOpcode(Mips::SLL);
871 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
872 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
873 NopInst.addOperand(MCOperand::CreateImm(0));
874 Instructions.push_back(NopInst);
875 return false;
876 }
877
Jack Carter9e65aa32013-03-22 00:05:30 +0000878 if (MCID.mayLoad() || MCID.mayStore()) {
879 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000880 // reference or immediate we may have to expand instructions.
881 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000882 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000883 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
884 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000885 MCOperand &Op = Inst.getOperand(i);
886 if (Op.isImm()) {
887 int MemOffset = Op.getImm();
888 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000889 // Offset can't exceed 16bit value.
890 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000891 return false;
892 }
893 } else if (Op.isExpr()) {
894 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000895 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000896 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000897 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000898 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000899 // Expand symbol.
900 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000901 return false;
902 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000903 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000904 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000905 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000906 }
907 }
908 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000909 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000910 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000911
912 if (needsExpansion(Inst))
913 expandInstruction(Inst, IDLoc, Instructions);
914 else
915 Instructions.push_back(Inst);
916
917 return false;
918}
919
Jack Carter30a59822012-10-04 04:03:53 +0000920bool MipsAsmParser::needsExpansion(MCInst &Inst) {
921
Jack Carterd0bd6422013-04-18 00:41:53 +0000922 switch (Inst.getOpcode()) {
923 case Mips::LoadImm32Reg:
924 case Mips::LoadAddr32Imm:
925 case Mips::LoadAddr32Reg:
926 return true;
927 default:
928 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000929 }
930}
Jack Carter92995f12012-10-06 00:53:28 +0000931
Jack Carter30a59822012-10-04 04:03:53 +0000932void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000933 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000934 switch (Inst.getOpcode()) {
935 case Mips::LoadImm32Reg:
936 return expandLoadImm(Inst, IDLoc, Instructions);
937 case Mips::LoadAddr32Imm:
938 return expandLoadAddressImm(Inst, IDLoc, Instructions);
939 case Mips::LoadAddr32Reg:
940 return expandLoadAddressReg(Inst, IDLoc, Instructions);
941 }
Jack Carter30a59822012-10-04 04:03:53 +0000942}
Jack Carter92995f12012-10-06 00:53:28 +0000943
Jack Carter30a59822012-10-04 04:03:53 +0000944void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000945 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000946 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000947 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000948 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000949 const MCOperand &RegOp = Inst.getOperand(0);
950 assert(RegOp.isReg() && "expected register operand kind");
951
952 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000953 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000954 if (0 <= ImmValue && ImmValue <= 65535) {
955 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000956 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000957 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000958 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000959 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000960 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000961 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000962 } else if (ImmValue < 0 && ImmValue >= -32768) {
963 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000964 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000965 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000966 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000967 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000968 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000969 Instructions.push_back(tmpInst);
970 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000971 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000972 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000973 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000974 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000975 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
976 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000977 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000978 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000979 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000980 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
981 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
982 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
983 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000984 Instructions.push_back(tmpInst);
985 }
986}
Jack Carter92995f12012-10-06 00:53:28 +0000987
Vladimir Medic4c299852013-11-06 11:27:05 +0000988void
989MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
990 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000991 MCInst tmpInst;
992 const MCOperand &ImmOp = Inst.getOperand(2);
993 assert(ImmOp.isImm() && "expected immediate operand kind");
994 const MCOperand &SrcRegOp = Inst.getOperand(1);
995 assert(SrcRegOp.isReg() && "expected register operand kind");
996 const MCOperand &DstRegOp = Inst.getOperand(0);
997 assert(DstRegOp.isReg() && "expected register operand kind");
998 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000999 if (-32768 <= ImmValue && ImmValue <= 65535) {
1000 // For -32768 <= j <= 65535.
1001 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001002 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001003 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1004 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1005 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1006 Instructions.push_back(tmpInst);
1007 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001008 // For any other value of j that is representable as a 32-bit integer.
1009 // la d,j(s) => lui d,hi16(j)
1010 // ori d,d,lo16(j)
1011 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001012 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001013 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1014 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1015 Instructions.push_back(tmpInst);
1016 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001017 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001018 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1019 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1020 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1021 Instructions.push_back(tmpInst);
1022 tmpInst.clear();
1023 tmpInst.setOpcode(Mips::ADDu);
1024 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1025 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1026 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1027 Instructions.push_back(tmpInst);
1028 }
1029}
1030
Vladimir Medic4c299852013-11-06 11:27:05 +00001031void
1032MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1033 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001034 MCInst tmpInst;
1035 const MCOperand &ImmOp = Inst.getOperand(1);
1036 assert(ImmOp.isImm() && "expected immediate operand kind");
1037 const MCOperand &RegOp = Inst.getOperand(0);
1038 assert(RegOp.isReg() && "expected register operand kind");
1039 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001040 if (-32768 <= ImmValue && ImmValue <= 65535) {
1041 // For -32768 <= j <= 65535.
1042 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001043 tmpInst.setOpcode(Mips::ADDiu);
1044 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001045 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001046 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1047 Instructions.push_back(tmpInst);
1048 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001049 // For any other value of j that is representable as a 32-bit integer.
1050 // la d,j => lui d,hi16(j)
1051 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001052 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001053 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1054 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1055 Instructions.push_back(tmpInst);
1056 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001057 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001058 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1059 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1060 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1061 Instructions.push_back(tmpInst);
1062 }
1063}
1064
Jack Carter9e65aa32013-03-22 00:05:30 +00001065void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001066 SmallVectorImpl<MCInst> &Instructions,
1067 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001068 const MCSymbolRefExpr *SR;
1069 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001070 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001071 const MCExpr *ExprOffset;
1072 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +00001073 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001074 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +00001075 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001076 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1077 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001078 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001079 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1080 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001081 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001082 if (isImmOpnd) {
1083 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1084 ImmOffset = Inst.getOperand(2).getImm();
1085 LoOffset = ImmOffset & 0x0000ffff;
1086 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001087 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001088 if (LoOffset & 0x8000)
1089 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001090 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001091 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001092 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001093 TempInst.setLoc(IDLoc);
1094 // 1st instruction in expansion is LUi. For load instruction we can use
1095 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +00001096 // but for stores we must use $at.
1097 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +00001098 TempInst.setOpcode(Mips::LUi);
1099 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1100 if (isImmOpnd)
1101 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1102 else {
1103 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001104 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001105 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1106 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1107 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001108 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001109 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001110 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001111 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001112 }
1113 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001114 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001115 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001117 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001118 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001119 TempInst.setOpcode(Mips::ADDu);
1120 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1121 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1122 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1123 Instructions.push_back(TempInst);
1124 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001125 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001126 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001127 TempInst.setOpcode(Inst.getOpcode());
1128 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1129 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1130 if (isImmOpnd)
1131 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1132 else {
1133 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001134 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1135 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1136 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001137 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001138 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001139 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001140 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001141 }
1142 }
1143 Instructions.push_back(TempInst);
1144 TempInst.clear();
1145}
1146
Vladimir Medic4c299852013-11-06 11:27:05 +00001147bool MipsAsmParser::MatchAndEmitInstruction(
1148 SMLoc IDLoc, unsigned &Opcode,
1149 SmallVectorImpl<MCParsedAsmOperand *> &Operands, MCStreamer &Out,
1150 unsigned &ErrorInfo, bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001151 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001152 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001153 unsigned MatchResult =
1154 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001155
1156 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001157 default:
1158 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001159 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001160 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001161 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001162 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001163 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001164 return false;
1165 }
1166 case Match_MissingFeature:
1167 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1168 return true;
1169 case Match_InvalidOperand: {
1170 SMLoc ErrorLoc = IDLoc;
1171 if (ErrorInfo != ~0U) {
1172 if (ErrorInfo >= Operands.size())
1173 return Error(IDLoc, "too few operands for instruction");
1174
Vladimir Medic4c299852013-11-06 11:27:05 +00001175 ErrorLoc = ((MipsOperand *)Operands[ErrorInfo])->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001176 if (ErrorLoc == SMLoc())
1177 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001178 }
1179
1180 return Error(ErrorLoc, "invalid operand for instruction");
1181 }
1182 case Match_MnemonicFail:
1183 return Error(IDLoc, "invalid instruction");
1184 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001185 return true;
1186}
1187
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001188void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1189 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1190 if (RegIndex == 1)
1191 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001192 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001193 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1194 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001195 }
1196}
1197
Jack Carter1ac53222013-02-20 23:11:17 +00001198int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001199 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001200
Vladimir Medic4c299852013-11-06 11:27:05 +00001201 CC = StringSwitch<unsigned>(Name)
1202 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001203 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001204 .Case("a0", 4)
1205 .Case("a1", 5)
1206 .Case("a2", 6)
1207 .Case("a3", 7)
1208 .Case("v0", 2)
1209 .Case("v1", 3)
1210 .Case("s0", 16)
1211 .Case("s1", 17)
1212 .Case("s2", 18)
1213 .Case("s3", 19)
1214 .Case("s4", 20)
1215 .Case("s5", 21)
1216 .Case("s6", 22)
1217 .Case("s7", 23)
1218 .Case("k0", 26)
1219 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001220 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001221 .Case("sp", 29)
1222 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001223 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001224 .Case("ra", 31)
1225 .Case("t0", 8)
1226 .Case("t1", 9)
1227 .Case("t2", 10)
1228 .Case("t3", 11)
1229 .Case("t4", 12)
1230 .Case("t5", 13)
1231 .Case("t6", 14)
1232 .Case("t7", 15)
1233 .Case("t8", 24)
1234 .Case("t9", 25)
1235 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001236
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001237 if (isN32() || isN64()) {
1238 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1239 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1240 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1241 if (8 <= CC && CC <= 11)
1242 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001243
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001244 if (CC == -1)
1245 CC = StringSwitch<unsigned>(Name)
1246 .Case("a4", 8)
1247 .Case("a5", 9)
1248 .Case("a6", 10)
1249 .Case("a7", 11)
1250 .Case("kt0", 26)
1251 .Case("kt1", 27)
1252 .Default(-1);
1253 }
Jack Carter1ac53222013-02-20 23:11:17 +00001254
1255 return CC;
1256}
Jack Carterd0bd6422013-04-18 00:41:53 +00001257
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001258int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001259
Jack Cartera63b16a2012-09-07 00:23:42 +00001260 if (Name[0] == 'f') {
1261 StringRef NumString = Name.substr(1);
1262 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001263 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001264 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001265 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001266 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001267 return IntVal;
1268 }
1269 return -1;
1270}
Jack Cartera63b16a2012-09-07 00:23:42 +00001271
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001272int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1273
1274 if (Name.startswith("fcc")) {
1275 StringRef NumString = Name.substr(3);
1276 unsigned IntVal;
1277 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001278 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001279 if (IntVal > 7) // There are only 8 fcc registers.
1280 return -1;
1281 return IntVal;
1282 }
1283 return -1;
1284}
1285
1286int MipsAsmParser::matchACRegisterName(StringRef Name) {
1287
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001288 if (Name.startswith("ac")) {
1289 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001290 unsigned IntVal;
1291 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001292 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001293 if (IntVal > 3) // There are only 3 acc registers.
1294 return -1;
1295 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001296 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001297 return -1;
1298}
Jack Carterd0bd6422013-04-18 00:41:53 +00001299
Jack Carter5dc8ac92013-09-25 23:50:44 +00001300int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1301 unsigned IntVal;
1302
1303 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1304 return -1;
1305
1306 if (IntVal > 31)
1307 return -1;
1308
1309 return IntVal;
1310}
1311
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001312int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1313 int CC;
1314
1315 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001316 .Case("msair", 0)
1317 .Case("msacsr", 1)
1318 .Case("msaaccess", 2)
1319 .Case("msasave", 3)
1320 .Case("msamodify", 4)
1321 .Case("msarequest", 5)
1322 .Case("msamap", 6)
1323 .Case("msaunmap", 7)
1324 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001325
1326 return CC;
1327}
1328
Jack Carter0b744b32012-10-04 02:29:46 +00001329bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1330 if (Reg > 31)
1331 return false;
1332
1333 aTReg = Reg;
1334 return true;
1335}
1336
Daniel Sandersd89b1362014-03-24 16:48:01 +00001337int MipsAsmParser::getATReg() {
1338 int AT = Options.getATRegNum();
1339 if (AT == 0)
1340 TokError("Pseudo instruction requires $at, which is not available");
1341 return AT;
1342}
Jack Carter0b744b32012-10-04 02:29:46 +00001343
Jack Carterd0bd6422013-04-18 00:41:53 +00001344unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001345 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001346}
1347
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001348unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001349 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1350 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001351}
1352
Jack Carter873c7242013-01-12 01:03:14 +00001353int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001354 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001355 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001356 return -1;
1357
Jack Carter873c7242013-01-12 01:03:14 +00001358 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001359}
1360
Vladimir Medic4c299852013-11-06 11:27:05 +00001361bool
1362MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1363 StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001364 DEBUG(dbgs() << "ParseOperand\n");
1365
Jack Carter30a59822012-10-04 04:03:53 +00001366 // Check if the current operand has a custom associated parser, if so, try to
1367 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001368 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1369 if (ResTy == MatchOperand_Success)
1370 return false;
1371 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1372 // there was a match, but an error occurred, in which case, just return that
1373 // the operand parsing failed.
1374 if (ResTy == MatchOperand_ParseFail)
1375 return true;
1376
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001377 DEBUG(dbgs() << ".. Generic Parser\n");
1378
Jack Carterb4dbc172012-09-05 23:34:03 +00001379 switch (getLexer().getKind()) {
1380 default:
1381 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1382 return true;
1383 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001384 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001385 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001386
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001387 // Almost all registers have been parsed by custom parsers. There is only
1388 // one exception to this. $zero (and it's alias $0) will reach this point
1389 // for div, divu, and similar instructions because it is not an operand
1390 // to the instruction definition but an explicit register. Special case
1391 // this situation for now.
1392 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001393 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001394
Jack Carterd0bd6422013-04-18 00:41:53 +00001395 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001396 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001397 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001398 return true;
1399
Jack Carter873c7242013-01-12 01:03:14 +00001400 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001401 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001402 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001403 const MCExpr *Res =
1404 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001405
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001406 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001407 return false;
1408 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001409 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001410 case AsmToken::LParen:
1411 case AsmToken::Minus:
1412 case AsmToken::Plus:
1413 case AsmToken::Integer:
1414 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001415 DEBUG(dbgs() << ".. generic integer\n");
1416 OperandMatchResultTy ResTy = ParseImm(Operands);
1417 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001418 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001419 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001420 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001421 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001422 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001423 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001424 return true;
1425
Jack Carter873c7242013-01-12 01:03:14 +00001426 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1427
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001428 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001429 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001430 } // case AsmToken::Percent
1431 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001432 return true;
1433}
1434
Vladimir Medic4c299852013-11-06 11:27:05 +00001435const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001436 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001437 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001438 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001439 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001440 // It's a constant, evaluate reloc value.
1441 int16_t Val;
1442 switch (getVariantKind(RelocStr)) {
1443 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1444 // Get the 1st 16-bits.
1445 Val = MCE->getValue() & 0xffff;
1446 break;
1447 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1448 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1449 // 16 bits being negative.
1450 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1451 break;
1452 case MCSymbolRefExpr::VK_Mips_HIGHER:
1453 // Get the 3rd 16-bits.
1454 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1455 break;
1456 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1457 // Get the 4th 16-bits.
1458 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1459 break;
1460 default:
1461 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001462 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001463 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001464 }
1465
Jack Carterb5cf5902013-04-17 00:18:04 +00001466 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001467 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001468 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001469 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001470 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001471 return Res;
1472 }
1473
1474 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001475 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1476
Sasa Stankovic06c47802014-04-03 10:37:45 +00001477 // Try to create target expression.
1478 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1479 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001480
Jack Carterd0bd6422013-04-18 00:41:53 +00001481 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1482 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001483 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1484 return Res;
1485 }
1486
1487 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001488 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1489 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1490 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001491 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001492 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001493 return Expr;
1494}
1495
1496bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1497
1498 switch (Expr->getKind()) {
1499 case MCExpr::Constant:
1500 return true;
1501 case MCExpr::SymbolRef:
1502 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1503 case MCExpr::Binary:
1504 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1505 if (!isEvaluated(BE->getLHS()))
1506 return false;
1507 return isEvaluated(BE->getRHS());
1508 }
1509 case MCExpr::Unary:
1510 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001511 case MCExpr::Target:
1512 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001513 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001514 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001515}
Jack Carterd0bd6422013-04-18 00:41:53 +00001516
Jack Carterb5cf5902013-04-17 00:18:04 +00001517bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001518 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001519 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001520 if (Tok.isNot(AsmToken::Identifier))
1521 return true;
1522
1523 std::string Str = Tok.getIdentifier().str();
1524
Jack Carterd0bd6422013-04-18 00:41:53 +00001525 Parser.Lex(); // Eat the identifier.
1526 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001527 const MCExpr *IdVal;
1528 SMLoc EndLoc;
1529
1530 if (getLexer().getKind() == AsmToken::LParen) {
1531 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001532 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001533 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001534 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001535 const AsmToken &nextTok = Parser.getTok();
1536 if (nextTok.isNot(AsmToken::Identifier))
1537 return true;
1538 Str += "(%";
1539 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001540 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001541 if (getLexer().getKind() != AsmToken::LParen)
1542 return true;
1543 } else
1544 break;
1545 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001546 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001547 return true;
1548
1549 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001550 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001551
1552 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001553 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001554
Jack Carterd0bd6422013-04-18 00:41:53 +00001555 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001556 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001557}
1558
Jack Carterb4dbc172012-09-05 23:34:03 +00001559bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1560 SMLoc &EndLoc) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001561 SmallVector<MCParsedAsmOperand *, 1> Operands;
1562 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1563 if (ResTy == MatchOperand_Success) {
1564 assert(Operands.size() == 1);
1565 MipsOperand &Operand = *static_cast<MipsOperand *>(Operands.front());
1566 StartLoc = Operand.getStartLoc();
1567 EndLoc = Operand.getEndLoc();
1568
1569 // AFAIK, we only support numeric registers and named GPR's in CFI
1570 // directives.
1571 // Don't worry about eating tokens before failing. Using an unrecognised
1572 // register is a parse error.
1573 if (Operand.isGPRAsmReg()) {
1574 // Resolve to GPR32 or GPR64 appropriately.
1575 RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
1576 }
1577
NAKAMURA Takumibd524ef2014-04-15 14:06:27 +00001578 delete &Operand;
1579
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001580 return (RegNo == (unsigned)-1);
1581 }
1582
1583 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001584 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001585}
1586
Jack Carterb5cf5902013-04-17 00:18:04 +00001587bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001588 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001589 bool Result = true;
1590
1591 while (getLexer().getKind() == AsmToken::LParen)
1592 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001593
Jack Carterd0bd6422013-04-18 00:41:53 +00001594 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001595 default:
1596 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001597 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001598 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001599 case AsmToken::Integer:
1600 case AsmToken::Minus:
1601 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001602 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001604 else
1605 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001606 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001607 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001608 break;
Jack Carter873c7242013-01-12 01:03:14 +00001609 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001610 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001611 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001612 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001613}
1614
Jack Carterb4dbc172012-09-05 23:34:03 +00001615MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Vladimir Medic4c299852013-11-06 11:27:05 +00001616 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001617 DEBUG(dbgs() << "parseMemOperand\n");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001618 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001619 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001620 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001621 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001623 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001624
Jack Carterb5cf5902013-04-17 00:18:04 +00001625 if (getLexer().getKind() == AsmToken::LParen) {
1626 Parser.Lex();
1627 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001628 }
1629
Jack Carterb5cf5902013-04-17 00:18:04 +00001630 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001631 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001632 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001633
Jack Carterd0bd6422013-04-18 00:41:53 +00001634 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001635 if (Tok.isNot(AsmToken::LParen)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001636 MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
Jack Carterb5cf5902013-04-17 00:18:04 +00001637 if (Mnemonic->getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001638 SMLoc E =
1639 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001640 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001641 return MatchOperand_Success;
1642 }
1643 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001644 SMLoc E =
1645 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001646
Jack Carterd0bd6422013-04-18 00:41:53 +00001647 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001648 // "Base" will be managed by k_Memory.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001649 MipsOperand *Base = MipsOperand::CreateGPRReg(
1650 0, getContext().getRegisterInfo(), S, E, *this);
1651 Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001652 return MatchOperand_Success;
1653 }
1654 Error(Parser.getTok().getLoc(), "'(' expected");
1655 return MatchOperand_ParseFail;
1656 }
1657
Jack Carterd0bd6422013-04-18 00:41:53 +00001658 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001659 }
1660
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001661 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001662 if (Res != MatchOperand_Success)
1663 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001664
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001665 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001666 Error(Parser.getTok().getLoc(), "')' expected");
1667 return MatchOperand_ParseFail;
1668 }
1669
Jack Carter873c7242013-01-12 01:03:14 +00001670 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1671
Jack Carterd0bd6422013-04-18 00:41:53 +00001672 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001673
1674 if (IdVal == 0)
1675 IdVal = MCConstantExpr::Create(0, getContext());
1676
Jack Carterd0bd6422013-04-18 00:41:53 +00001677 // Replace the register operand with the memory operand.
Vladimir Medic4c299852013-11-06 11:27:05 +00001678 MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
Jack Carterd0bd6422013-04-18 00:41:53 +00001679 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001680 // "op" will be managed by k_Memory.
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 Sandersb50ccf82014-04-01 10:35:28 +00001692 Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001693 return MatchOperand_Success;
1694}
1695
Daniel Sanderse34a1202014-03-31 18:51:43 +00001696bool MipsAsmParser::searchSymbolAlias(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001697 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001698
Jack Carterd76b2372013-03-21 21:44:16 +00001699 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 Sandersb50ccf82014-04-01 10:35:28 +00001711 OperandMatchResultTy ResTy =
1712 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001713 if (ResTy == MatchOperand_Success) {
1714 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001715 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001716 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001717 llvm_unreachable("Should never ParseFail");
1718 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001719 }
1720 } else if (Expr->getKind() == MCExpr::Constant) {
1721 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001722 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
1723 MipsOperand *op =
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001724 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this);
Jack Carterd76b2372013-03-21 21:44:16 +00001725 Operands.push_back(op);
1726 return true;
1727 }
1728 }
1729 return false;
1730}
Jack Carterd0bd6422013-04-18 00:41:53 +00001731
Jack Carter873c7242013-01-12 01:03:14 +00001732MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001733MipsAsmParser::MatchAnyRegisterNameWithoutDollar(
1734 SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
1735 SMLoc S) {
1736 int Index = matchCPURegisterName(Identifier);
1737 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001738 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) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001745 Operands.push_back(MipsOperand::CreateFGRReg(
1746 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1747 return MatchOperand_Success;
1748 }
1749
1750 Index = matchFCCRegisterName(Identifier);
1751 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001752 Operands.push_back(MipsOperand::CreateFCCReg(
1753 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1754 return MatchOperand_Success;
1755 }
1756
1757 Index = matchACRegisterName(Identifier);
1758 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001759 Operands.push_back(MipsOperand::CreateACCReg(
1760 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1761 return MatchOperand_Success;
1762 }
1763
1764 Index = matchMSA128RegisterName(Identifier);
1765 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001766 Operands.push_back(MipsOperand::CreateMSA128Reg(
1767 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1768 return MatchOperand_Success;
1769 }
1770
1771 Index = matchMSA128CtrlRegisterName(Identifier);
1772 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001773 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1774 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1775 return MatchOperand_Success;
1776 }
1777
1778 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001779}
1780
1781MipsAsmParser::OperandMatchResultTy
Daniel Sanders21bce302014-04-01 12:35:23 +00001782MipsAsmParser::MatchAnyRegisterWithoutDollar(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001783 SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00001784 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001785
1786 if (Token.is(AsmToken::Identifier)) {
1787 DEBUG(dbgs() << ".. identifier\n");
1788 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00001789 OperandMatchResultTy ResTy =
1790 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00001791 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001792 } else if (Token.is(AsmToken::Integer)) {
1793 DEBUG(dbgs() << ".. integer\n");
1794 Operands.push_back(MipsOperand::CreateNumericReg(
1795 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
1796 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001797 return MatchOperand_Success;
1798 }
1799
1800 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
1801
1802 return MatchOperand_NoMatch;
1803}
1804
1805MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
1806 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1807 DEBUG(dbgs() << "ParseAnyRegister\n");
1808
1809 auto Token = Parser.getTok();
1810
1811 SMLoc S = Token.getLoc();
1812
1813 if (Token.isNot(AsmToken::Dollar)) {
1814 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
1815 if (Token.is(AsmToken::Identifier)) {
1816 if (searchSymbolAlias(Operands))
1817 return MatchOperand_Success;
1818 }
1819 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
1820 return MatchOperand_NoMatch;
1821 }
1822 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001823
Daniel Sanders21bce302014-04-01 12:35:23 +00001824 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00001825 if (ResTy == MatchOperand_Success) {
1826 Parser.Lex(); // $
1827 Parser.Lex(); // identifier
1828 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001829 return ResTy;
1830}
1831
1832MipsAsmParser::OperandMatchResultTy
1833MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1834 switch (getLexer().getKind()) {
1835 default:
1836 return MatchOperand_NoMatch;
1837 case AsmToken::LParen:
1838 case AsmToken::Minus:
1839 case AsmToken::Plus:
1840 case AsmToken::Integer:
1841 case AsmToken::String:
1842 break;
1843 }
1844
1845 const MCExpr *IdVal;
1846 SMLoc S = Parser.getTok().getLoc();
1847 if (getParser().parseExpression(IdVal))
1848 return MatchOperand_ParseFail;
1849
1850 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1851 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
1852 return MatchOperand_Success;
1853}
1854
1855MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
1856 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1857 DEBUG(dbgs() << "ParseJumpTarget\n");
1858
1859 SMLoc S = getLexer().getLoc();
1860
1861 // Integers and expressions are acceptable
1862 OperandMatchResultTy ResTy = ParseImm(Operands);
1863 if (ResTy != MatchOperand_NoMatch)
1864 return ResTy;
1865
Daniel Sanders315386c2014-04-01 10:40:14 +00001866 // Registers are a valid target and have priority over symbols.
1867 ResTy = ParseAnyRegister(Operands);
1868 if (ResTy != MatchOperand_NoMatch)
1869 return ResTy;
1870
Daniel Sandersffd84362014-04-01 10:41:48 +00001871 const MCExpr *Expr = nullptr;
1872 if (Parser.parseExpression(Expr)) {
1873 // We have no way of knowing if a symbol was consumed so we must ParseFail
1874 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001875 }
Daniel Sandersffd84362014-04-01 10:41:48 +00001876 Operands.push_back(
1877 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001878 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00001879}
1880
Vladimir Medic2b953d02013-10-01 09:48:56 +00001881MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001882MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00001883 const MCExpr *IdVal;
1884 // If the first token is '$' we may have register operand.
1885 if (Parser.getTok().is(AsmToken::Dollar))
1886 return MatchOperand_NoMatch;
1887 SMLoc S = Parser.getTok().getLoc();
1888 if (getParser().parseExpression(IdVal))
1889 return MatchOperand_ParseFail;
1890 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00001891 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00001892 int64_t Val = MCE->getValue();
1893 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1894 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001895 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00001896 return MatchOperand_Success;
1897}
1898
Matheus Almeida779c5932013-11-18 12:32:49 +00001899MipsAsmParser::OperandMatchResultTy
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001900MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00001901 switch (getLexer().getKind()) {
1902 default:
1903 return MatchOperand_NoMatch;
1904 case AsmToken::LParen:
1905 case AsmToken::Plus:
1906 case AsmToken::Minus:
1907 case AsmToken::Integer:
1908 break;
1909 }
1910
1911 const MCExpr *Expr;
1912 SMLoc S = Parser.getTok().getLoc();
1913
1914 if (getParser().parseExpression(Expr))
1915 return MatchOperand_ParseFail;
1916
1917 int64_t Val;
1918 if (!Expr->EvaluateAsAbsolute(Val)) {
1919 Error(S, "expected immediate value");
1920 return MatchOperand_ParseFail;
1921 }
1922
1923 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
1924 // and because the CPU always adds one to the immediate field, the allowed
1925 // range becomes 1..4. We'll only check the range here and will deal
1926 // with the addition/subtraction when actually decoding/encoding
1927 // the instruction.
1928 if (Val < 1 || Val > 4) {
1929 Error(S, "immediate not in range (1..4)");
1930 return MatchOperand_ParseFail;
1931 }
1932
Jack Carter3b2c96e2014-01-22 23:31:38 +00001933 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001934 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00001935 return MatchOperand_Success;
1936}
1937
Jack Carterdc1e35d2012-09-06 20:00:02 +00001938MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1939
Vladimir Medic4c299852013-11-06 11:27:05 +00001940 MCSymbolRefExpr::VariantKind VK =
1941 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1942 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1943 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1944 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1945 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1946 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1947 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1948 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1949 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1950 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1951 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1952 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1953 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1954 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1955 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1956 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1957 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1958 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00001959 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
1960 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
1961 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
1962 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
1963 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
1964 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Vladimir Medic4c299852013-11-06 11:27:05 +00001965 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001966
Daniel Sandersa567da52014-03-31 15:15:02 +00001967 assert (VK != MCSymbolRefExpr::VK_None);
1968
Jack Carterdc1e35d2012-09-06 20:00:02 +00001969 return VK;
1970}
Jack Cartera63b16a2012-09-07 00:23:42 +00001971
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001972/// Sometimes (i.e. load/stores) the operand may be followed immediately by
1973/// either this.
1974/// ::= '(', register, ')'
1975/// handle it before we iterate so we don't get tripped up by the lack of
1976/// a comma.
1977bool MipsAsmParser::ParseParenSuffix(
1978 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1979 if (getLexer().is(AsmToken::LParen)) {
1980 Operands.push_back(
1981 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
1982 Parser.Lex();
1983 if (ParseOperand(Operands, Name)) {
1984 SMLoc Loc = getLexer().getLoc();
1985 Parser.eatToEndOfStatement();
1986 return Error(Loc, "unexpected token in argument list");
1987 }
1988 if (Parser.getTok().isNot(AsmToken::RParen)) {
1989 SMLoc Loc = getLexer().getLoc();
1990 Parser.eatToEndOfStatement();
1991 return Error(Loc, "unexpected token, expected ')'");
1992 }
1993 Operands.push_back(
1994 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
1995 Parser.Lex();
1996 }
1997 return false;
1998}
1999
2000/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2001/// either one of these.
2002/// ::= '[', register, ']'
2003/// ::= '[', integer, ']'
2004/// handle it before we iterate so we don't get tripped up by the lack of
2005/// a comma.
2006bool MipsAsmParser::ParseBracketSuffix(
2007 StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2008 if (getLexer().is(AsmToken::LBrac)) {
2009 Operands.push_back(
2010 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2011 Parser.Lex();
2012 if (ParseOperand(Operands, Name)) {
2013 SMLoc Loc = getLexer().getLoc();
2014 Parser.eatToEndOfStatement();
2015 return Error(Loc, "unexpected token in argument list");
2016 }
2017 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2018 SMLoc Loc = getLexer().getLoc();
2019 Parser.eatToEndOfStatement();
2020 return Error(Loc, "unexpected token, expected ']'");
2021 }
2022 Operands.push_back(
2023 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2024 Parser.Lex();
2025 }
2026 return false;
2027}
2028
Vladimir Medic4c299852013-11-06 11:27:05 +00002029bool MipsAsmParser::ParseInstruction(
2030 ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
2031 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002032 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medic74593e62013-07-17 15:00:42 +00002033 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002034 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002035 Parser.eatToEndOfStatement();
2036 return Error(NameLoc, "Unknown instruction");
2037 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002038 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002039 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002040
2041 // Read the remaining operands.
2042 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2043 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002044 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002045 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002046 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002047 return Error(Loc, "unexpected token in argument list");
2048 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002049 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2050 return true;
2051 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002052
Jack Carterd0bd6422013-04-18 00:41:53 +00002053 while (getLexer().is(AsmToken::Comma)) {
2054 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002055 // Parse and remember the operand.
2056 if (ParseOperand(Operands, Name)) {
2057 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002058 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002059 return Error(Loc, "unexpected token in argument list");
2060 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002061 // Parse bracket and parenthesis suffixes before we iterate
2062 if (getLexer().is(AsmToken::LBrac)) {
2063 if (ParseBracketSuffix(Name, Operands))
2064 return true;
2065 } else if (getLexer().is(AsmToken::LParen) &&
2066 ParseParenSuffix(Name, Operands))
2067 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002068 }
2069 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002070 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2071 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002072 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002073 return Error(Loc, "unexpected token in argument list");
2074 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002075 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002076 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002077}
2078
Jack Carter0b744b32012-10-04 02:29:46 +00002079bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002080 SMLoc Loc = getLexer().getLoc();
2081 Parser.eatToEndOfStatement();
2082 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002083}
2084
2085bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002086 // Line should look like: ".set noat".
2087 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002088 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002089 // eat noat
2090 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002091 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002092 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2093 reportParseError("unexpected token in statement");
2094 return false;
2095 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002096 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002097 return false;
2098}
Jack Carterd0bd6422013-04-18 00:41:53 +00002099
Jack Carter0b744b32012-10-04 02:29:46 +00002100bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002101 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002102 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002103 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002104 getParser().Lex();
2105 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002106 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002107 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002108 return false;
2109 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002110 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002111 if (getLexer().isNot(AsmToken::Dollar)) {
2112 reportParseError("unexpected token in statement");
2113 return false;
2114 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002115 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002116 const AsmToken &Reg = Parser.getTok();
2117 if (Reg.is(AsmToken::Identifier)) {
2118 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2119 } else if (Reg.is(AsmToken::Integer)) {
2120 AtRegNo = Reg.getIntVal();
2121 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002122 reportParseError("unexpected token in statement");
2123 return false;
2124 }
Jack Carter1ac53222013-02-20 23:11:17 +00002125
Daniel Sanders71a89d922014-03-25 13:01:06 +00002126 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002127 reportParseError("unexpected token in statement");
2128 return false;
2129 }
2130
2131 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002132 reportParseError("unexpected token in statement");
2133 return false;
2134 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002135 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002136
2137 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2138 reportParseError("unexpected token in statement");
2139 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002140 }
2141 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002142 return false;
2143 } else {
2144 reportParseError("unexpected token in statement");
2145 return false;
2146 }
2147}
2148
2149bool MipsAsmParser::parseSetReorderDirective() {
2150 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002151 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002152 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2153 reportParseError("unexpected token in statement");
2154 return false;
2155 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002156 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002157 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002158 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002159 return false;
2160}
2161
2162bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002163 Parser.Lex();
2164 // If this is not the end of the statement, report an error.
2165 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2166 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002167 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002168 }
2169 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002170 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002171 Parser.Lex(); // Consume the EndOfStatement.
2172 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002173}
2174
2175bool MipsAsmParser::parseSetMacroDirective() {
2176 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002177 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002178 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2179 reportParseError("unexpected token in statement");
2180 return false;
2181 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002182 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002183 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002184 return false;
2185}
2186
2187bool MipsAsmParser::parseSetNoMacroDirective() {
2188 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002189 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002190 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2191 reportParseError("`noreorder' must be set before `nomacro'");
2192 return false;
2193 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002194 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002195 reportParseError("`noreorder' must be set before `nomacro'");
2196 return false;
2197 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002198 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002199 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002200 return false;
2201}
Jack Carterd76b2372013-03-21 21:44:16 +00002202
Jack Carter39536722014-01-22 23:08:42 +00002203bool MipsAsmParser::parseSetNoMips16Directive() {
2204 Parser.Lex();
2205 // If this is not the end of the statement, report an error.
2206 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2207 reportParseError("unexpected token in statement");
2208 return false;
2209 }
2210 // For now do nothing.
2211 Parser.Lex(); // Consume the EndOfStatement.
2212 return false;
2213}
2214
Jack Carterd76b2372013-03-21 21:44:16 +00002215bool MipsAsmParser::parseSetAssignment() {
2216 StringRef Name;
2217 const MCExpr *Value;
2218
2219 if (Parser.parseIdentifier(Name))
2220 reportParseError("expected identifier after .set");
2221
2222 if (getLexer().isNot(AsmToken::Comma))
2223 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002224 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002225
Jack Carter3b2c96e2014-01-22 23:31:38 +00002226 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002227 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002228
Jack Carterd0bd6422013-04-18 00:41:53 +00002229 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002230 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002231 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002232 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002233 Sym = getContext().GetOrCreateSymbol(Name);
2234 Sym->setVariableValue(Value);
2235
2236 return false;
2237}
Jack Carterd0bd6422013-04-18 00:41:53 +00002238
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002239bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2240 Parser.Lex();
2241 if (getLexer().isNot(AsmToken::EndOfStatement))
2242 return reportParseError("unexpected token in .set directive");
2243
2244 switch(Feature) {
2245 default: llvm_unreachable("Unimplemented feature");
2246 case Mips::FeatureDSP:
2247 setFeatureBits(Mips::FeatureDSP, "dsp");
2248 getTargetStreamer().emitDirectiveSetDsp();
2249 break;
2250 case Mips::FeatureMicroMips:
2251 getTargetStreamer().emitDirectiveSetMicroMips();
2252 break;
2253 case Mips::FeatureMips16:
2254 getTargetStreamer().emitDirectiveSetMips16();
2255 break;
2256 case Mips::FeatureMips32r2:
2257 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2258 getTargetStreamer().emitDirectiveSetMips32R2();
2259 break;
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002260 case Mips::FeatureMips64:
2261 setFeatureBits(Mips::FeatureMips64, "mips64");
2262 getTargetStreamer().emitDirectiveSetMips64();
2263 break;
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002264 case Mips::FeatureMips64r2:
2265 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2266 getTargetStreamer().emitDirectiveSetMips64R2();
2267 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002268 }
2269 return false;
2270}
2271
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002272bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2273 if (!getLexer().is(AsmToken::Dollar))
2274 return false;
2275
2276 Parser.Lex();
2277
2278 const AsmToken &Reg = Parser.getTok();
2279 if (Reg.is(AsmToken::Identifier)) {
2280 RegNum = matchCPURegisterName(Reg.getIdentifier());
2281 } else if (Reg.is(AsmToken::Integer)) {
2282 RegNum = Reg.getIntVal();
2283 } else {
2284 return false;
2285 }
2286
2287 Parser.Lex();
2288 return true;
2289}
2290
2291bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2292 if (getLexer().isNot(AsmToken::Comma)) {
2293 SMLoc Loc = getLexer().getLoc();
2294 Parser.eatToEndOfStatement();
2295 return Error(Loc, ErrorStr);
2296 }
2297
2298 Parser.Lex(); // Eat the comma.
2299 return true;
2300}
2301
2302bool MipsAsmParser::parseDirectiveCPSetup() {
2303 unsigned FuncReg;
2304 unsigned Save;
2305 bool SaveIsReg = true;
2306
2307 if (!parseRegister(FuncReg))
2308 return reportParseError("expected register containing function address");
2309 FuncReg = getGPR(FuncReg);
2310
2311 if (!eatComma("expected comma parsing directive"))
2312 return true;
2313
2314 if (!parseRegister(Save)) {
2315 const AsmToken &Tok = Parser.getTok();
2316 if (Tok.is(AsmToken::Integer)) {
2317 Save = Tok.getIntVal();
2318 SaveIsReg = false;
2319 Parser.Lex();
2320 } else
2321 return reportParseError("expected save register or stack offset");
2322 } else
2323 Save = getGPR(Save);
2324
2325 if (!eatComma("expected comma parsing directive"))
2326 return true;
2327
2328 StringRef Name;
2329 if (Parser.parseIdentifier(Name))
2330 reportParseError("expected identifier");
2331 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
2332 unsigned GPReg = getGPR(matchCPURegisterName("gp"));
2333
2334 // FIXME: The code below this point should be in the TargetStreamers.
2335 // Only N32 and N64 emit anything for .cpsetup
2336 // FIXME: We should only emit something for PIC mode too.
2337 if (!isN32() && !isN64())
2338 return false;
2339
2340 MCStreamer &TS = getStreamer();
2341 MCInst Inst;
2342 // Either store the old $gp in a register or on the stack
2343 if (SaveIsReg) {
2344 // move $save, $gpreg
2345 Inst.setOpcode(Mips::DADDu);
2346 Inst.addOperand(MCOperand::CreateReg(Save));
2347 Inst.addOperand(MCOperand::CreateReg(GPReg));
2348 Inst.addOperand(MCOperand::CreateReg(getGPR(0)));
2349 } else {
2350 // sd $gpreg, offset($sp)
2351 Inst.setOpcode(Mips::SD);
2352 Inst.addOperand(MCOperand::CreateReg(GPReg));
2353 Inst.addOperand(MCOperand::CreateReg(getGPR(matchCPURegisterName("sp"))));
2354 Inst.addOperand(MCOperand::CreateImm(Save));
2355 }
2356 TS.EmitInstruction(Inst, STI);
2357 Inst.clear();
2358
2359 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2360 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI,
2361 getContext());
2362 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2363 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO,
2364 getContext());
2365 // lui $gp, %hi(%neg(%gp_rel(funcSym)))
2366 Inst.setOpcode(Mips::LUi);
2367 Inst.addOperand(MCOperand::CreateReg(GPReg));
2368 Inst.addOperand(MCOperand::CreateExpr(HiExpr));
2369 TS.EmitInstruction(Inst, STI);
2370 Inst.clear();
2371
2372 // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
2373 Inst.setOpcode(Mips::ADDiu);
2374 Inst.addOperand(MCOperand::CreateReg(GPReg));
2375 Inst.addOperand(MCOperand::CreateReg(GPReg));
2376 Inst.addOperand(MCOperand::CreateExpr(LoExpr));
2377 TS.EmitInstruction(Inst, STI);
2378 Inst.clear();
2379
2380 // daddu $gp, $gp, $funcreg
2381 Inst.setOpcode(Mips::DADDu);
2382 Inst.addOperand(MCOperand::CreateReg(GPReg));
2383 Inst.addOperand(MCOperand::CreateReg(GPReg));
2384 Inst.addOperand(MCOperand::CreateReg(FuncReg));
2385 TS.EmitInstruction(Inst, STI);
2386 return false;
2387}
2388
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002389bool MipsAsmParser::parseDirectiveNaN() {
2390 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2391 const AsmToken &Tok = Parser.getTok();
2392
2393 if (Tok.getString() == "2008") {
2394 Parser.Lex();
2395 getTargetStreamer().emitDirectiveNaN2008();
2396 return false;
2397 } else if (Tok.getString() == "legacy") {
2398 Parser.Lex();
2399 getTargetStreamer().emitDirectiveNaNLegacy();
2400 return false;
2401 }
2402 }
2403 // If we don't recognize the option passed to the .nan
2404 // directive (e.g. no option or unknown option), emit an error.
2405 reportParseError("invalid option in .nan directive");
2406 return false;
2407}
2408
Jack Carter0b744b32012-10-04 02:29:46 +00002409bool MipsAsmParser::parseDirectiveSet() {
2410
Jack Carterd0bd6422013-04-18 00:41:53 +00002411 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002412 const AsmToken &Tok = Parser.getTok();
2413
2414 if (Tok.getString() == "noat") {
2415 return parseSetNoAtDirective();
2416 } else if (Tok.getString() == "at") {
2417 return parseSetAtDirective();
2418 } else if (Tok.getString() == "reorder") {
2419 return parseSetReorderDirective();
2420 } else if (Tok.getString() == "noreorder") {
2421 return parseSetNoReorderDirective();
2422 } else if (Tok.getString() == "macro") {
2423 return parseSetMacroDirective();
2424 } else if (Tok.getString() == "nomacro") {
2425 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002426 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002427 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002428 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002429 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002430 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002431 getTargetStreamer().emitDirectiveSetNoMicroMips();
2432 Parser.eatToEndOfStatement();
2433 return false;
2434 } else if (Tok.getString() == "micromips") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002435 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002436 } else if (Tok.getString() == "mips32r2") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002437 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002438 } else if (Tok.getString() == "mips64") {
2439 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002440 } else if (Tok.getString() == "mips64r2") {
2441 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002442 } else if (Tok.getString() == "dsp") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002443 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002444 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002445 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002446 parseSetAssignment();
2447 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002448 }
Jack Carter07c818d2013-01-25 01:31:34 +00002449
Jack Carter0b744b32012-10-04 02:29:46 +00002450 return true;
2451}
2452
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002453/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002454/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002455bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002456 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2457 for (;;) {
2458 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002459 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002460 return true;
2461
2462 getParser().getStreamer().EmitValue(Value, Size);
2463
2464 if (getLexer().is(AsmToken::EndOfStatement))
2465 break;
2466
2467 // FIXME: Improve diagnostic.
2468 if (getLexer().isNot(AsmToken::Comma))
2469 return Error(L, "unexpected token in directive");
2470 Parser.Lex();
2471 }
2472 }
2473
2474 Parser.Lex();
2475 return false;
2476}
2477
Vladimir Medic4c299852013-11-06 11:27:05 +00002478/// parseDirectiveGpWord
2479/// ::= .gpword local_sym
2480bool MipsAsmParser::parseDirectiveGpWord() {
2481 const MCExpr *Value;
2482 // EmitGPRel32Value requires an expression, so we are using base class
2483 // method to evaluate the expression.
2484 if (getParser().parseExpression(Value))
2485 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002486 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002487
Vladimir Medice10c1122013-11-13 13:18:04 +00002488 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002489 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002490 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002491 return false;
2492}
2493
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002494/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002495/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002496bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002497 const MCExpr *Value;
2498 // EmitGPRel64Value requires an expression, so we are using base class
2499 // method to evaluate the expression.
2500 if (getParser().parseExpression(Value))
2501 return true;
2502 getParser().getStreamer().EmitGPRel64Value(Value);
2503
2504 if (getLexer().isNot(AsmToken::EndOfStatement))
2505 return Error(getLexer().getLoc(), "unexpected token in directive");
2506 Parser.Lex(); // Eat EndOfStatement token.
2507 return false;
2508}
2509
Jack Carter0cd3c192014-01-06 23:27:31 +00002510bool MipsAsmParser::parseDirectiveOption() {
2511 // Get the option token.
2512 AsmToken Tok = Parser.getTok();
2513 // At the moment only identifiers are supported.
2514 if (Tok.isNot(AsmToken::Identifier)) {
2515 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2516 Parser.eatToEndOfStatement();
2517 return false;
2518 }
2519
2520 StringRef Option = Tok.getIdentifier();
2521
2522 if (Option == "pic0") {
2523 getTargetStreamer().emitDirectiveOptionPic0();
2524 Parser.Lex();
2525 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2526 Error(Parser.getTok().getLoc(),
2527 "unexpected token in .option pic0 directive");
2528 Parser.eatToEndOfStatement();
2529 }
2530 return false;
2531 }
2532
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002533 if (Option == "pic2") {
2534 getTargetStreamer().emitDirectiveOptionPic2();
2535 Parser.Lex();
2536 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2537 Error(Parser.getTok().getLoc(),
2538 "unexpected token in .option pic2 directive");
2539 Parser.eatToEndOfStatement();
2540 }
2541 return false;
2542 }
2543
Jack Carter0cd3c192014-01-06 23:27:31 +00002544 // Unknown option.
2545 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2546 Parser.eatToEndOfStatement();
2547 return false;
2548}
2549
Jack Carter0b744b32012-10-04 02:29:46 +00002550bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002551 StringRef IDVal = DirectiveID.getString();
2552
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002553 if (IDVal == ".dword") {
2554 parseDataDirective(8, DirectiveID.getLoc());
2555 return false;
2556 }
2557
Jack Carterd0bd6422013-04-18 00:41:53 +00002558 if (IDVal == ".ent") {
2559 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002560 Parser.Lex();
2561 return false;
2562 }
2563
Jack Carter07c818d2013-01-25 01:31:34 +00002564 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002565 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002566 Parser.Lex();
2567 return false;
2568 }
2569
Jack Carter07c818d2013-01-25 01:31:34 +00002570 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002572 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002573 return false;
2574 }
2575
Jack Carter07c818d2013-01-25 01:31:34 +00002576 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002577 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002578 }
2579
Jack Carter07c818d2013-01-25 01:31:34 +00002580 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002581 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002582 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002583 return false;
2584 }
2585
Jack Carter07c818d2013-01-25 01:31:34 +00002586 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002587 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002588 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002589 return false;
2590 }
2591
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002592 if (IDVal == ".nan")
2593 return parseDirectiveNaN();
2594
Jack Carter07c818d2013-01-25 01:31:34 +00002595 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002596 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002597 return false;
2598 }
2599
Rafael Espindolab59fb732014-03-28 18:50:26 +00002600 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002601 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002602 return false;
2603 }
2604
Jack Carter07c818d2013-01-25 01:31:34 +00002605 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002606 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002607 return false;
2608 }
2609
Jack Carter0cd3c192014-01-06 23:27:31 +00002610 if (IDVal == ".option")
2611 return parseDirectiveOption();
2612
2613 if (IDVal == ".abicalls") {
2614 getTargetStreamer().emitDirectiveAbiCalls();
2615 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2616 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2617 // Clear line
2618 Parser.eatToEndOfStatement();
2619 }
2620 return false;
2621 }
2622
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002623 if (IDVal == ".cpsetup")
2624 return parseDirectiveCPSetup();
2625
Rafael Espindola870c4e92012-01-11 03:56:41 +00002626 return true;
2627}
2628
Rafael Espindola870c4e92012-01-11 03:56:41 +00002629extern "C" void LLVMInitializeMipsAsmParser() {
2630 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2631 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2632 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2633 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2634}
Jack Carterb4dbc172012-09-05 23:34:03 +00002635
2636#define GET_REGISTER_MATCHER
2637#define GET_MATCHER_IMPLEMENTATION
2638#include "MipsGenAsmMatcher.inc"