blob: ae9d2764fb2224269c38895317e37678eeff6121 [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
10#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000011#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000012#include "MipsTargetStreamer.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000013#include "llvm/ADT/StringSwitch.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCExpr.h"
16#include "llvm/MC/MCInst.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000017#include "llvm/MC/MCParser/MCAsmLexer.h"
18#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000019#include "llvm/MC/MCStreamer.h"
20#include "llvm/MC/MCSubtargetInfo.h"
21#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000022#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000023#include "llvm/Support/TargetRegistry.h"
Jack Carter02593002013-05-28 22:21:05 +000024#include "llvm/ADT/APInt.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000025
26using namespace llvm;
27
Joey Gouly0e76fa72013-09-12 10:28:05 +000028namespace llvm {
29class MCInstrInfo;
30}
31
Rafael Espindola870c4e92012-01-11 03:56:41 +000032namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000033class MipsAssemblerOptions {
34public:
35 MipsAssemblerOptions():
36 aTReg(1), reorder(true), macro(true) {
37 }
Jack Carterb4dbc172012-09-05 23:34:03 +000038
Jack Carter0b744b32012-10-04 02:29:46 +000039 unsigned getATRegNum() {return aTReg;}
40 bool setATReg(unsigned Reg);
41
42 bool isReorder() {return reorder;}
43 void setReorder() {reorder = true;}
44 void setNoreorder() {reorder = false;}
45
46 bool isMacro() {return macro;}
47 void setMacro() {macro = true;}
48 void setNomacro() {macro = false;}
49
50private:
51 unsigned aTReg;
52 bool reorder;
53 bool macro;
54};
55}
56
57namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000058class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000059
Rafael Espindolaa17151a2013-10-08 13:08:17 +000060 MipsTargetStreamer &getTargetStreamer() {
61 MCTargetStreamer &TS = Parser.getStreamer().getTargetStreamer();
62 return static_cast<MipsTargetStreamer &>(TS);
63 }
64
Jack Carterb4dbc172012-09-05 23:34:03 +000065 MCSubtargetInfo &STI;
66 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000067 MipsAssemblerOptions Options;
Vladimir Medic27c87ea2013-08-13 13:07:09 +000068 bool hasConsumedDollar;
Jack Carter0b744b32012-10-04 02:29:46 +000069
Akira Hatanaka7605630c2012-08-17 20:16:42 +000070#define GET_ASSEMBLER_HEADER
71#include "MipsGenAsmMatcher.inc"
72
Chad Rosier49963552012-10-13 00:26:04 +000073 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +000074 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000075 MCStreamer &Out, unsigned &ErrorInfo,
76 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000077
78 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
79
Chad Rosierf0e87202012-10-25 20:41:34 +000080 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
81 SMLoc NameLoc,
Akira Hatanaka7605630c2012-08-17 20:16:42 +000082 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000083
84 bool ParseDirective(AsmToken DirectiveID);
85
Jack Carterb4dbc172012-09-05 23:34:03 +000086 MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +000087 parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
88 int RegKind);
Vladimir Medic64828a12013-07-16 10:07:14 +000089
90 MipsAsmParser::OperandMatchResultTy
Jack Carter5dc8ac92013-09-25 23:50:44 +000091 parseMSARegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
92 int RegKind);
93
94 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +000095 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
96
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000097 bool parsePtrReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands, int RegKind);
98
99 MipsAsmParser::OperandMatchResultTy
100 parsePtrReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
101
Jack Carter873c7242013-01-12 01:03:14 +0000102 MipsAsmParser::OperandMatchResultTy
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000103 parseGPR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000104
105 MipsAsmParser::OperandMatchResultTy
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000106 parseGPR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000107
108 MipsAsmParser::OperandMatchResultTy
109 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
110
111 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +0000112 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000113
Vladimir Medic233dd512013-06-24 10:05:34 +0000114 MipsAsmParser::OperandMatchResultTy
115 parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
116
117 MipsAsmParser::OperandMatchResultTy
118 parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
119
120 MipsAsmParser::OperandMatchResultTy
121 parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
122
Vladimir Medic643b3982013-07-30 10:12:14 +0000123 MipsAsmParser::OperandMatchResultTy
Akira Hatanaka14e31a22013-08-20 22:58:56 +0000124 parseFGRH32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
125
126 MipsAsmParser::OperandMatchResultTy
Vladimir Medic643b3982013-07-30 10:12:14 +0000127 parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
128
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000129 MipsAsmParser::OperandMatchResultTy
Akira Hatanaka00fcf2e2013-08-08 21:54:26 +0000130 parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000131
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000132 MipsAsmParser::OperandMatchResultTy
133 parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
134
135 MipsAsmParser::OperandMatchResultTy
136 parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
137
Vladimir Medic05bcde62013-09-16 10:29:42 +0000138 MipsAsmParser::OperandMatchResultTy
139 parseCOP2(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
140
Jack Carter5dc8ac92013-09-25 23:50:44 +0000141 MipsAsmParser::OperandMatchResultTy
142 parseMSA128BRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
143
144 MipsAsmParser::OperandMatchResultTy
145 parseMSA128HRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
146
147 MipsAsmParser::OperandMatchResultTy
148 parseMSA128WRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
149
150 MipsAsmParser::OperandMatchResultTy
151 parseMSA128DRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
152
Vladimir Medic2b953d02013-10-01 09:48:56 +0000153 MipsAsmParser::OperandMatchResultTy
154 parseInvNum(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
155
Jack Carterd76b2372013-03-21 21:44:16 +0000156 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +0000157 unsigned RegKind);
Jack Carterd76b2372013-03-21 21:44:16 +0000158
Jack Carterb4dbc172012-09-05 23:34:03 +0000159 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
160 StringRef Mnemonic);
161
Jack Carter873c7242013-01-12 01:03:14 +0000162 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000163
164 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000165 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000166
Jack Carter30a59822012-10-04 04:03:53 +0000167 bool needsExpansion(MCInst &Inst);
168
169 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000170 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000171 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000172 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000173 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
174 SmallVectorImpl<MCInst> &Instructions);
175 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
176 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000177 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions,
179 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000180 bool reportParseError(StringRef ErrorMsg);
181
Jack Carterb5cf5902013-04-17 00:18:04 +0000182 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000183 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000184
Jack Carterb5cf5902013-04-17 00:18:04 +0000185 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
186
187 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000188 bool parseDirectiveSet();
Rafael Espindolaac4ad252013-10-05 16:42:21 +0000189 bool parseDirectiveMipsHackStocg();
190 bool parseDirectiveMipsHackELFFlags();
Jack Carter0b744b32012-10-04 02:29:46 +0000191
192 bool parseSetAtDirective();
193 bool parseSetNoAtDirective();
194 bool parseSetMacroDirective();
195 bool parseSetNoMacroDirective();
196 bool parseSetReorderDirective();
197 bool parseSetNoReorderDirective();
198
Jack Carterd76b2372013-03-21 21:44:16 +0000199 bool parseSetAssignment();
200
Jack Carter07c818d2013-01-25 01:31:34 +0000201 bool parseDirectiveWord(unsigned Size, SMLoc L);
202
Jack Carterdc1e35d2012-09-06 20:00:02 +0000203 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000204
Jack Carterb4dbc172012-09-05 23:34:03 +0000205 bool isMips64() const {
206 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
207 }
208
Jack Cartera63b16a2012-09-07 00:23:42 +0000209 bool isFP64() const {
210 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
211 }
212
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000213 bool isN64() const {
214 return STI.getFeatureBits() & Mips::FeatureN64;
215 }
216
Jack Carter873c7242013-01-12 01:03:14 +0000217 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000218
Jack Carter1ac53222013-02-20 23:11:17 +0000219 int matchCPURegisterName(StringRef Symbol);
220
Jack Carter873c7242013-01-12 01:03:14 +0000221 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000222
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000223 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000224
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000225 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000226
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000227 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000228
Jack Carter5dc8ac92013-09-25 23:50:44 +0000229 int matchMSA128RegisterName(StringRef Name);
230
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000231 int regKindToRegClass(int RegKind);
Jack Cartera63b16a2012-09-07 00:23:42 +0000232
Jack Carterd0bd6422013-04-18 00:41:53 +0000233 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000234
Jack Carter1ac53222013-02-20 23:11:17 +0000235 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000236
237 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
238 SmallVectorImpl<MCInst> &Instructions);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000239public:
Joey Gouly0e76fa72013-09-12 10:28:05 +0000240 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
241 const MCInstrInfo &MII)
242 : MCTargetAsmParser(), STI(sti), Parser(parser),
243 hasConsumedDollar(false) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000244 // Initialize the set of available features.
245 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000246 }
247
Jack Carterb4dbc172012-09-05 23:34:03 +0000248 MCAsmParser &getParser() const { return Parser; }
249 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
250
Rafael Espindola870c4e92012-01-11 03:56:41 +0000251};
252}
253
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000254namespace {
255
256/// MipsOperand - Instances of this class represent a parsed Mips machine
257/// instruction.
258class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000259
Jack Carter873c7242013-01-12 01:03:14 +0000260public:
261 enum RegisterKind {
262 Kind_None,
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000263 Kind_GPR32,
264 Kind_GPR64,
Jack Carter873c7242013-01-12 01:03:14 +0000265 Kind_HWRegs,
Jack Carter873c7242013-01-12 01:03:14 +0000266 Kind_FGR32Regs,
Akira Hatanaka14e31a22013-08-20 22:58:56 +0000267 Kind_FGRH32Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000268 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000269 Kind_AFGR64Regs,
Vladimir Medic643b3982013-07-30 10:12:14 +0000270 Kind_CCRRegs,
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000271 Kind_FCCRegs,
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000272 Kind_ACC64DSP,
273 Kind_LO32DSP,
Vladimir Medic05bcde62013-09-16 10:29:42 +0000274 Kind_HI32DSP,
Jack Carter5dc8ac92013-09-25 23:50:44 +0000275 Kind_COP2,
276 Kind_MSA128BRegs,
277 Kind_MSA128HRegs,
278 Kind_MSA128WRegs,
279 Kind_MSA128DRegs
Jack Carter873c7242013-01-12 01:03:14 +0000280 };
281
282private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000283 enum KindTy {
284 k_CondCode,
285 k_CoprocNum,
286 k_Immediate,
287 k_Memory,
288 k_PostIndexRegister,
289 k_Register,
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000290 k_PtrReg,
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000291 k_Token
292 } Kind;
293
294 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000295
Eric Christopher8996c5d2013-03-15 00:42:55 +0000296 struct Token {
297 const char *Data;
298 unsigned Length;
299 };
300
301 struct RegOp {
302 unsigned RegNum;
303 RegisterKind Kind;
304 };
305
306 struct ImmOp {
307 const MCExpr *Val;
308 };
309
310 struct MemOp {
311 unsigned Base;
312 const MCExpr *Off;
313 };
314
Jack Carterb4dbc172012-09-05 23:34:03 +0000315 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000316 struct Token Tok;
317 struct RegOp Reg;
318 struct ImmOp Imm;
319 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000320 };
321
322 SMLoc StartLoc, EndLoc;
323
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000324public:
325 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000326 assert(N == 1 && "Invalid number of operands!");
327 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000328 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000329
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000330 void addPtrRegOperands(MCInst &Inst, unsigned N) const {
331 assert(N == 1 && "Invalid number of operands!");
332 Inst.addOperand(MCOperand::CreateReg(getPtrReg()));
333 }
334
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000335 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000336 // Add as immediate when possible. Null MCExpr = 0.
337 if (Expr == 0)
338 Inst.addOperand(MCOperand::CreateImm(0));
339 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
340 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
341 else
342 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000343 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000344
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000345 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000346 assert(N == 1 && "Invalid number of operands!");
347 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000348 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000349 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000350
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000351 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000352 assert(N == 2 && "Invalid number of operands!");
353
354 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
355
356 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000357 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000358 }
359
360 bool isReg() const { return Kind == k_Register; }
361 bool isImm() const { return Kind == k_Immediate; }
362 bool isToken() const { return Kind == k_Token; }
363 bool isMem() const { return Kind == k_Memory; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000364 bool isPtrReg() const { return Kind == k_PtrReg; }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000365 bool isInvNum() const { return Kind == k_Immediate; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000366
367 StringRef getToken() const {
368 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000369 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000370 }
371
372 unsigned getReg() const {
373 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000374 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000375 }
376
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000377 unsigned getPtrReg() const {
378 assert((Kind == k_PtrReg) && "Invalid access!");
379 return Reg.RegNum;
380 }
381
Jack Carter873c7242013-01-12 01:03:14 +0000382 void setRegKind(RegisterKind RegKind) {
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000383 assert((Kind == k_Register || Kind == k_PtrReg) && "Invalid access!");
Jack Carter873c7242013-01-12 01:03:14 +0000384 Reg.Kind = RegKind;
385 }
386
Jack Carterb4dbc172012-09-05 23:34:03 +0000387 const MCExpr *getImm() const {
388 assert((Kind == k_Immediate) && "Invalid access!");
389 return Imm.Val;
390 }
391
Jack Carterdc1e35d2012-09-06 20:00:02 +0000392 unsigned getMemBase() const {
393 assert((Kind == k_Memory) && "Invalid access!");
394 return Mem.Base;
395 }
396
397 const MCExpr *getMemOff() const {
398 assert((Kind == k_Memory) && "Invalid access!");
399 return Mem.Off;
400 }
401
Jack Carterb4dbc172012-09-05 23:34:03 +0000402 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
403 MipsOperand *Op = new MipsOperand(k_Token);
404 Op->Tok.Data = Str.data();
405 Op->Tok.Length = Str.size();
406 Op->StartLoc = S;
407 Op->EndLoc = S;
408 return Op;
409 }
410
411 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
412 MipsOperand *Op = new MipsOperand(k_Register);
413 Op->Reg.RegNum = RegNum;
414 Op->StartLoc = S;
415 Op->EndLoc = E;
416 return Op;
417 }
418
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000419 static MipsOperand *CreatePtrReg(unsigned RegNum, SMLoc S, SMLoc E) {
420 MipsOperand *Op = new MipsOperand(k_PtrReg);
421 Op->Reg.RegNum = RegNum;
422 Op->StartLoc = S;
423 Op->EndLoc = E;
424 return Op;
425 }
426
Jack Carterb4dbc172012-09-05 23:34:03 +0000427 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
428 MipsOperand *Op = new MipsOperand(k_Immediate);
429 Op->Imm.Val = Val;
430 Op->StartLoc = S;
431 Op->EndLoc = E;
432 return Op;
433 }
434
Jack Carterdc1e35d2012-09-06 20:00:02 +0000435 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
436 SMLoc S, SMLoc E) {
437 MipsOperand *Op = new MipsOperand(k_Memory);
438 Op->Mem.Base = Base;
439 Op->Mem.Off = Off;
440 Op->StartLoc = S;
441 Op->EndLoc = E;
442 return Op;
443 }
444
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000445 bool isGPR32Asm() const {
446 return Kind == k_Register && Reg.Kind == Kind_GPR32;
Jack Carter873c7242013-01-12 01:03:14 +0000447 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000448 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000449 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
450 }
451
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000452 bool isGPR64Asm() const {
453 return Kind == k_Register && Reg.Kind == Kind_GPR64;
Jack Carter873c7242013-01-12 01:03:14 +0000454 }
Jack Carter873c7242013-01-12 01:03:14 +0000455
456 bool isHWRegsAsm() const {
457 assert((Kind == k_Register) && "Invalid access!");
458 return Reg.Kind == Kind_HWRegs;
459 }
Jack Carter873c7242013-01-12 01:03:14 +0000460
Jack Carter873c7242013-01-12 01:03:14 +0000461 bool isCCRAsm() const {
462 assert((Kind == k_Register) && "Invalid access!");
463 return Reg.Kind == Kind_CCRRegs;
464 }
465
Vladimir Medic233dd512013-06-24 10:05:34 +0000466 bool isAFGR64Asm() const {
467 return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
468 }
469
470 bool isFGR64Asm() const {
471 return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
472 }
473
474 bool isFGR32Asm() const {
475 return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
476 }
477
Akira Hatanaka14e31a22013-08-20 22:58:56 +0000478 bool isFGRH32Asm() const {
479 return (Kind == k_Register) && Reg.Kind == Kind_FGRH32Regs;
480 }
481
Vladimir Medic643b3982013-07-30 10:12:14 +0000482 bool isFCCRegsAsm() const {
483 return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs;
484 }
485
Akira Hatanaka00fcf2e2013-08-08 21:54:26 +0000486 bool isACC64DSPAsm() const {
487 return Kind == k_Register && Reg.Kind == Kind_ACC64DSP;
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000488 }
489
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000490 bool isLO32DSPAsm() const {
491 return Kind == k_Register && Reg.Kind == Kind_LO32DSP;
492 }
493
494 bool isHI32DSPAsm() const {
495 return Kind == k_Register && Reg.Kind == Kind_HI32DSP;
496 }
497
Vladimir Medic05bcde62013-09-16 10:29:42 +0000498 bool isCOP2Asm() const {
499 return Kind == k_Register && Reg.Kind == Kind_COP2;
500 }
501
Jack Carter5dc8ac92013-09-25 23:50:44 +0000502 bool isMSA128BAsm() const {
503 return Kind == k_Register && Reg.Kind == Kind_MSA128BRegs;
504 }
505
506 bool isMSA128HAsm() const {
507 return Kind == k_Register && Reg.Kind == Kind_MSA128HRegs;
508 }
509
510 bool isMSA128WAsm() const {
511 return Kind == k_Register && Reg.Kind == Kind_MSA128WRegs;
512 }
513
514 bool isMSA128DAsm() const {
515 return Kind == k_Register && Reg.Kind == Kind_MSA128DRegs;
516 }
517
Jack Carterb4dbc172012-09-05 23:34:03 +0000518 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000519 SMLoc getStartLoc() const {
520 return StartLoc;
521 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000522 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000523 SMLoc getEndLoc() const {
524 return EndLoc;
525 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000526
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000527 virtual void print(raw_ostream &OS) const {
528 llvm_unreachable("unimplemented!");
529 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000530}; // class MipsOperand
531} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000532
Jack Carter9e65aa32013-03-22 00:05:30 +0000533namespace llvm {
534extern const MCInstrDesc MipsInsts[];
535}
536static const MCInstrDesc &getInstDesc(unsigned Opcode) {
537 return MipsInsts[Opcode];
538}
539
540bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000541 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000542 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
543 Inst.setLoc(IDLoc);
Jack Carterc15c1d22013-04-25 23:31:35 +0000544 if (MCID.hasDelaySlot() && Options.isReorder()) {
545 // If this instruction has a delay slot and .set reorder is active,
546 // emit a NOP after it.
547 Instructions.push_back(Inst);
548 MCInst NopInst;
549 NopInst.setOpcode(Mips::SLL);
550 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
551 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
552 NopInst.addOperand(MCOperand::CreateImm(0));
553 Instructions.push_back(NopInst);
554 return false;
555 }
556
Jack Carter9e65aa32013-03-22 00:05:30 +0000557 if (MCID.mayLoad() || MCID.mayStore()) {
558 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000559 // reference or immediate we may have to expand instructions.
560 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000561 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000562 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
563 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000564 MCOperand &Op = Inst.getOperand(i);
565 if (Op.isImm()) {
566 int MemOffset = Op.getImm();
567 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000568 // Offset can't exceed 16bit value.
569 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000570 return false;
571 }
572 } else if (Op.isExpr()) {
573 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000574 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000575 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000576 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000577 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000578 // Expand symbol.
579 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000580 return false;
581 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000582 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000583 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000584 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000585 }
586 }
587 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000588 } // for
589 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000590
591 if (needsExpansion(Inst))
592 expandInstruction(Inst, IDLoc, Instructions);
593 else
594 Instructions.push_back(Inst);
595
596 return false;
597}
598
Jack Carter30a59822012-10-04 04:03:53 +0000599bool MipsAsmParser::needsExpansion(MCInst &Inst) {
600
Jack Carterd0bd6422013-04-18 00:41:53 +0000601 switch (Inst.getOpcode()) {
602 case Mips::LoadImm32Reg:
603 case Mips::LoadAddr32Imm:
604 case Mips::LoadAddr32Reg:
605 return true;
606 default:
607 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000608 }
609}
Jack Carter92995f12012-10-06 00:53:28 +0000610
Jack Carter30a59822012-10-04 04:03:53 +0000611void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000612 SmallVectorImpl<MCInst> &Instructions) {
613 switch (Inst.getOpcode()) {
614 case Mips::LoadImm32Reg:
615 return expandLoadImm(Inst, IDLoc, Instructions);
616 case Mips::LoadAddr32Imm:
617 return expandLoadAddressImm(Inst, IDLoc, Instructions);
618 case Mips::LoadAddr32Reg:
619 return expandLoadAddressReg(Inst, IDLoc, Instructions);
620 }
Jack Carter30a59822012-10-04 04:03:53 +0000621}
Jack Carter92995f12012-10-06 00:53:28 +0000622
Jack Carter30a59822012-10-04 04:03:53 +0000623void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000624 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000625 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000626 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000627 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000628 const MCOperand &RegOp = Inst.getOperand(0);
629 assert(RegOp.isReg() && "expected register operand kind");
630
631 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000632 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000633 if (0 <= ImmValue && ImmValue <= 65535) {
634 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000635 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000636 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000637 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000638 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000639 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000640 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000641 } else if (ImmValue < 0 && ImmValue >= -32768) {
642 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000643 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000644 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000645 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000646 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000647 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000648 Instructions.push_back(tmpInst);
649 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000650 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000651 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000652 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000653 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000654 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
655 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000656 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000657 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000658 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000659 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
660 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
661 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
662 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000663 Instructions.push_back(tmpInst);
664 }
665}
Jack Carter92995f12012-10-06 00:53:28 +0000666
Jack Carter543fdf82012-10-09 23:29:45 +0000667void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000668 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000669 MCInst tmpInst;
670 const MCOperand &ImmOp = Inst.getOperand(2);
671 assert(ImmOp.isImm() && "expected immediate operand kind");
672 const MCOperand &SrcRegOp = Inst.getOperand(1);
673 assert(SrcRegOp.isReg() && "expected register operand kind");
674 const MCOperand &DstRegOp = Inst.getOperand(0);
675 assert(DstRegOp.isReg() && "expected register operand kind");
676 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000677 if (-32768 <= ImmValue && ImmValue <= 65535) {
678 // For -32768 <= j <= 65535.
679 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000680 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000681 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
682 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
683 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
684 Instructions.push_back(tmpInst);
685 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000686 // For any other value of j that is representable as a 32-bit integer.
687 // la d,j(s) => lui d,hi16(j)
688 // ori d,d,lo16(j)
689 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000690 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000691 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
692 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
693 Instructions.push_back(tmpInst);
694 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000695 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000696 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
697 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
698 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
699 Instructions.push_back(tmpInst);
700 tmpInst.clear();
701 tmpInst.setOpcode(Mips::ADDu);
702 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
703 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
704 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
705 Instructions.push_back(tmpInst);
706 }
707}
708
709void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000710 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000711 MCInst tmpInst;
712 const MCOperand &ImmOp = Inst.getOperand(1);
713 assert(ImmOp.isImm() && "expected immediate operand kind");
714 const MCOperand &RegOp = Inst.getOperand(0);
715 assert(RegOp.isReg() && "expected register operand kind");
716 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000717 if (-32768 <= ImmValue && ImmValue <= 65535) {
718 // For -32768 <= j <= 65535.
719 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000720 tmpInst.setOpcode(Mips::ADDiu);
721 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000722 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000723 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
724 Instructions.push_back(tmpInst);
725 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000726 // For any other value of j that is representable as a 32-bit integer.
727 // la d,j => lui d,hi16(j)
728 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000729 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000730 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
731 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
732 Instructions.push_back(tmpInst);
733 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000734 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000735 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
736 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
737 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
738 Instructions.push_back(tmpInst);
739 }
740}
741
Jack Carter9e65aa32013-03-22 00:05:30 +0000742void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000743 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000744 const MCSymbolRefExpr *SR;
745 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000746 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000747 const MCExpr *ExprOffset;
748 unsigned TmpRegNum;
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000749 unsigned AtRegNum = getReg((isMips64()) ? Mips::GPR64RegClassID
750 : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +0000751 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000752 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
753 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000754 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000755 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
756 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000757 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000758 if (isImmOpnd) {
759 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
760 ImmOffset = Inst.getOperand(2).getImm();
761 LoOffset = ImmOffset & 0x0000ffff;
762 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000763 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000764 if (LoOffset & 0x8000)
765 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000766 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000767 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000768 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000769 TempInst.setLoc(IDLoc);
770 // 1st instruction in expansion is LUi. For load instruction we can use
771 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000772 // but for stores we must use $at.
773 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000774 TempInst.setOpcode(Mips::LUi);
775 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
776 if (isImmOpnd)
777 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
778 else {
779 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
780 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000781 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
782 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
783 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000784 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000785 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000786 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000787 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000788 }
789 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000790 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000791 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000792 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000793 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000794 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000795 TempInst.setOpcode(Mips::ADDu);
796 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
797 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
798 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
799 Instructions.push_back(TempInst);
800 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000801 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000802 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000803 TempInst.setOpcode(Inst.getOpcode());
804 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
805 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
806 if (isImmOpnd)
807 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
808 else {
809 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000810 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
811 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
812 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000813 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000814 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000815 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000816 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000817 }
818 }
819 Instructions.push_back(TempInst);
820 TempInst.clear();
821}
822
Rafael Espindola870c4e92012-01-11 03:56:41 +0000823bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000824MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000825 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000826 MCStreamer &Out, unsigned &ErrorInfo,
827 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000828 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000829 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000830 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000831 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000832
833 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000834 default:
835 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000836 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000837 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000838 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000839 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000840 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000841 return false;
842 }
843 case Match_MissingFeature:
844 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
845 return true;
846 case Match_InvalidOperand: {
847 SMLoc ErrorLoc = IDLoc;
848 if (ErrorInfo != ~0U) {
849 if (ErrorInfo >= Operands.size())
850 return Error(IDLoc, "too few operands for instruction");
851
Jack Carterd0bd6422013-04-18 00:41:53 +0000852 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
853 if (ErrorLoc == SMLoc())
854 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000855 }
856
857 return Error(ErrorLoc, "invalid operand for instruction");
858 }
859 case Match_MnemonicFail:
860 return Error(IDLoc, "invalid instruction");
861 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000862 return true;
863}
864
Jack Carter1ac53222013-02-20 23:11:17 +0000865int MipsAsmParser::matchCPURegisterName(StringRef Name) {
866 int CC;
867
868 if (Name == "at")
869 return getATReg();
870
871 CC = StringSwitch<unsigned>(Name)
872 .Case("zero", 0)
873 .Case("a0", 4)
874 .Case("a1", 5)
875 .Case("a2", 6)
876 .Case("a3", 7)
877 .Case("v0", 2)
878 .Case("v1", 3)
879 .Case("s0", 16)
880 .Case("s1", 17)
881 .Case("s2", 18)
882 .Case("s3", 19)
883 .Case("s4", 20)
884 .Case("s5", 21)
885 .Case("s6", 22)
886 .Case("s7", 23)
887 .Case("k0", 26)
888 .Case("k1", 27)
889 .Case("sp", 29)
890 .Case("fp", 30)
891 .Case("gp", 28)
892 .Case("ra", 31)
893 .Case("t0", 8)
894 .Case("t1", 9)
895 .Case("t2", 10)
896 .Case("t3", 11)
897 .Case("t4", 12)
898 .Case("t5", 13)
899 .Case("t6", 14)
900 .Case("t7", 15)
901 .Case("t8", 24)
902 .Case("t9", 25)
903 .Default(-1);
904
Jack Carterd0bd6422013-04-18 00:41:53 +0000905 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000906 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
907 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000908 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000909 CC += 4;
910
911 if (CC == -1 && isMips64())
912 CC = StringSwitch<unsigned>(Name)
913 .Case("a4", 8)
914 .Case("a5", 9)
915 .Case("a6", 10)
916 .Case("a7", 11)
917 .Case("kt0", 26)
918 .Case("kt1", 27)
919 .Case("s8", 30)
920 .Default(-1);
921
922 return CC;
923}
Jack Carterd0bd6422013-04-18 00:41:53 +0000924
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000925int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000926
Jack Cartera63b16a2012-09-07 00:23:42 +0000927 if (Name[0] == 'f') {
928 StringRef NumString = Name.substr(1);
929 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000930 if (NumString.getAsInteger(10, IntVal))
931 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000932 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +0000933 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000934 return IntVal;
935 }
936 return -1;
937}
Jack Cartera63b16a2012-09-07 00:23:42 +0000938
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000939int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
940
941 if (Name.startswith("fcc")) {
942 StringRef NumString = Name.substr(3);
943 unsigned IntVal;
944 if (NumString.getAsInteger(10, IntVal))
945 return -1; // This is not an integer.
946 if (IntVal > 7) // There are only 8 fcc registers.
947 return -1;
948 return IntVal;
949 }
950 return -1;
951}
952
953int MipsAsmParser::matchACRegisterName(StringRef Name) {
954
Akira Hatanaka274d24c2013-08-14 01:15:52 +0000955 if (Name.startswith("ac")) {
956 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000957 unsigned IntVal;
958 if (NumString.getAsInteger(10, IntVal))
959 return -1; // This is not an integer.
960 if (IntVal > 3) // There are only 3 acc registers.
961 return -1;
962 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +0000963 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000964 return -1;
965}
Jack Carterd0bd6422013-04-18 00:41:53 +0000966
Jack Carter5dc8ac92013-09-25 23:50:44 +0000967int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
968 unsigned IntVal;
969
970 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
971 return -1;
972
973 if (IntVal > 31)
974 return -1;
975
976 return IntVal;
977}
978
Vladimir Medic8cd17102013-06-20 11:21:49 +0000979int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
980
Vladimir Medic8cd17102013-06-20 11:21:49 +0000981 int CC;
982 CC = matchCPURegisterName(Name);
983 if (CC != -1)
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000984 return matchRegisterByNumber(CC, is64BitReg ? Mips::GPR64RegClassID
985 : Mips::GPR32RegClassID);
Jack Carter5dc8ac92013-09-25 23:50:44 +0000986 CC = matchFPURegisterName(Name);
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000987 //TODO: decide about fpu register class
Jack Carter5dc8ac92013-09-25 23:50:44 +0000988 if (CC != -1)
989 return matchRegisterByNumber(CC, isFP64() ? Mips::FGR64RegClassID
990 : Mips::FGR32RegClassID);
991 return matchMSA128RegisterName(Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000992}
993
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000994int MipsAsmParser::regKindToRegClass(int RegKind) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000995
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000996 switch (RegKind) {
997 case MipsOperand::Kind_GPR32: return Mips::GPR32RegClassID;
998 case MipsOperand::Kind_GPR64: return Mips::GPR64RegClassID;
999 case MipsOperand::Kind_HWRegs: return Mips::HWRegsRegClassID;
1000 case MipsOperand::Kind_FGR32Regs: return Mips::FGR32RegClassID;
Akira Hatanaka14e31a22013-08-20 22:58:56 +00001001 case MipsOperand::Kind_FGRH32Regs: return Mips::FGRH32RegClassID;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001002 case MipsOperand::Kind_FGR64Regs: return Mips::FGR64RegClassID;
1003 case MipsOperand::Kind_AFGR64Regs: return Mips::AFGR64RegClassID;
1004 case MipsOperand::Kind_CCRRegs: return Mips::CCRRegClassID;
1005 case MipsOperand::Kind_ACC64DSP: return Mips::ACC64DSPRegClassID;
1006 case MipsOperand::Kind_FCCRegs: return Mips::FCCRegClassID;
Jack Carter5dc8ac92013-09-25 23:50:44 +00001007 case MipsOperand::Kind_MSA128BRegs: return Mips::MSA128BRegClassID;
1008 case MipsOperand::Kind_MSA128HRegs: return Mips::MSA128HRegClassID;
1009 case MipsOperand::Kind_MSA128WRegs: return Mips::MSA128WRegClassID;
1010 case MipsOperand::Kind_MSA128DRegs: return Mips::MSA128DRegClassID;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001011 default :return -1;
1012 }
Jack Cartera63b16a2012-09-07 00:23:42 +00001013
Jack Cartera63b16a2012-09-07 00:23:42 +00001014}
Jack Carterb4dbc172012-09-05 23:34:03 +00001015
Jack Carter0b744b32012-10-04 02:29:46 +00001016bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1017 if (Reg > 31)
1018 return false;
1019
1020 aTReg = Reg;
1021 return true;
1022}
1023
Jack Carter1ac53222013-02-20 23:11:17 +00001024int MipsAsmParser::getATReg() {
1025 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +00001026}
1027
Jack Carterd0bd6422013-04-18 00:41:53 +00001028unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001029 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001030}
1031
Jack Carter873c7242013-01-12 01:03:14 +00001032int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001033 if (RegNum >
1034 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs())
Jack Carterb4dbc172012-09-05 23:34:03 +00001035 return -1;
1036
Jack Carter873c7242013-01-12 01:03:14 +00001037 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001038}
1039
Jack Carter873c7242013-01-12 01:03:14 +00001040int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001041 const AsmToken &Tok = Parser.getTok();
1042 int RegNum = -1;
1043
1044 if (Tok.is(AsmToken::Identifier)) {
1045 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +00001046 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +00001047 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +00001048 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001049 is64BitReg ? Mips::GPR64RegClassID : Mips::GPR32RegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +00001050 return RegNum;
1051}
1052
Jack Carterd0bd6422013-04-18 00:41:53 +00001053bool MipsAsmParser::tryParseRegisterOperand(
1054 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001055
1056 SMLoc S = Parser.getTok().getLoc();
1057 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +00001058
Jack Carter873c7242013-01-12 01:03:14 +00001059 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +00001060 if (RegNo == -1)
1061 return true;
1062
Jack Carter873c7242013-01-12 01:03:14 +00001063 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001064 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +00001065 Parser.Lex(); // Eat register token.
1066 return false;
1067}
1068
1069bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
1070 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +00001071 // Check if the current operand has a custom associated parser, if so, try to
1072 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001073 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1074 if (ResTy == MatchOperand_Success)
1075 return false;
1076 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1077 // there was a match, but an error occurred, in which case, just return that
1078 // the operand parsing failed.
1079 if (ResTy == MatchOperand_ParseFail)
1080 return true;
1081
1082 switch (getLexer().getKind()) {
1083 default:
1084 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1085 return true;
1086 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001087 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001088 SMLoc S = Parser.getTok().getLoc();
1089 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001090 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +00001091 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001092 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001093 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +00001094 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +00001095 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +00001096 if (getLexer().isNot(AsmToken::Dollar))
1097 return true;
1098
Jack Carterd0bd6422013-04-18 00:41:53 +00001099 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +00001100 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +00001101 return true;
1102
1103 if (!getLexer().is(AsmToken::RParen))
1104 return true;
1105
1106 S = Parser.getTok().getLoc();
1107 Operands.push_back(MipsOperand::CreateToken(")", S));
1108 Parser.Lex();
1109 }
1110 return false;
1111 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001112 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001113 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001114 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001115 return true;
1116
Jack Carter873c7242013-01-12 01:03:14 +00001117 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001118
Benjamin Kramerfa530572012-09-07 09:47:42 +00001119 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +00001120
Jack Carterd0bd6422013-04-18 00:41:53 +00001121 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001122 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +00001123 getContext());
1124
1125 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
1126 return false;
1127 }
1128 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +00001129 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +00001130 // we need to assigne the propper RegisterKind.
1131 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
1132 return false;
1133 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001134 case AsmToken::LParen:
1135 case AsmToken::Minus:
1136 case AsmToken::Plus:
1137 case AsmToken::Integer:
1138 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001139 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +00001140 const MCExpr *IdVal;
1141 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001142 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +00001143 return true;
Jack Carter873c7242013-01-12 01:03:14 +00001144 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001145 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1146 return false;
1147 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001148 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001149 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001150 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001151 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001152 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001153 return true;
1154
Jack Carter873c7242013-01-12 01:03:14 +00001155 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1156
Jack Carterdc1e35d2012-09-06 20:00:02 +00001157 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1158 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001159 } // case AsmToken::Percent
1160 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001161 return true;
1162}
1163
Jack Carterb5cf5902013-04-17 00:18:04 +00001164const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1165 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001166 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001167 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001168 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001169 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001170 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001171 short Val = MCE->getValue();
1172 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001173 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001174 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001175 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001176 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001177 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001178 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001179 if (LoSign)
1180 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001181 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001182 } else {
1183 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001184 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001185 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001186 }
1187
Jack Carterb5cf5902013-04-17 00:18:04 +00001188 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001189 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001190 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001191 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001192 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001193 return Res;
1194 }
1195
1196 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001197 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1198 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001199 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1200 return Res;
1201 }
1202
1203 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001204 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1205 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1206 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001207 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001208 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001209 return Expr;
1210}
1211
1212bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1213
1214 switch (Expr->getKind()) {
1215 case MCExpr::Constant:
1216 return true;
1217 case MCExpr::SymbolRef:
1218 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1219 case MCExpr::Binary:
1220 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1221 if (!isEvaluated(BE->getLHS()))
1222 return false;
1223 return isEvaluated(BE->getRHS());
1224 }
1225 case MCExpr::Unary:
1226 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1227 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001228 return false;
1229 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001230 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001231}
Jack Carterd0bd6422013-04-18 00:41:53 +00001232
Jack Carterb5cf5902013-04-17 00:18:04 +00001233bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001234 Parser.Lex(); // Eat the % token.
1235 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001236 if (Tok.isNot(AsmToken::Identifier))
1237 return true;
1238
1239 std::string Str = Tok.getIdentifier().str();
1240
Jack Carterd0bd6422013-04-18 00:41:53 +00001241 Parser.Lex(); // Eat the identifier.
1242 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001243 const MCExpr *IdVal;
1244 SMLoc EndLoc;
1245
1246 if (getLexer().getKind() == AsmToken::LParen) {
1247 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001248 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001249 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001250 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001251 const AsmToken &nextTok = Parser.getTok();
1252 if (nextTok.isNot(AsmToken::Identifier))
1253 return true;
1254 Str += "(%";
1255 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001256 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001257 if (getLexer().getKind() != AsmToken::LParen)
1258 return true;
1259 } else
1260 break;
1261 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001262 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001263 return true;
1264
1265 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001266 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001267
1268 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001269 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001270
Jack Carterd0bd6422013-04-18 00:41:53 +00001271 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001272 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001273}
1274
Jack Carterb4dbc172012-09-05 23:34:03 +00001275bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1276 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001277 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001278 RegNo = tryParseRegister(isMips64());
1279 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001280 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001281}
1282
Jack Carterb5cf5902013-04-17 00:18:04 +00001283bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001284 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001285 bool Result = true;
1286
1287 while (getLexer().getKind() == AsmToken::LParen)
1288 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001289
Jack Carterd0bd6422013-04-18 00:41:53 +00001290 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001291 default:
1292 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001293 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001294 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001295 case AsmToken::Integer:
1296 case AsmToken::Minus:
1297 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001298 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001299 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001300 else
1301 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001302 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001303 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001304 break;
Jack Carter873c7242013-01-12 01:03:14 +00001305 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001306 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001307 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001308 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001309}
1310
Jack Carterb4dbc172012-09-05 23:34:03 +00001311MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001312 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001313
1314 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001315 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001316 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001317 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001318 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001319 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001320
Jack Carterb5cf5902013-04-17 00:18:04 +00001321 if (getLexer().getKind() == AsmToken::LParen) {
1322 Parser.Lex();
1323 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001324 }
1325
Jack Carterb5cf5902013-04-17 00:18:04 +00001326 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001327 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001328 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001329
Jack Carterd0bd6422013-04-18 00:41:53 +00001330 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001331 if (Tok.isNot(AsmToken::LParen)) {
1332 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1333 if (Mnemonic->getToken() == "la") {
1334 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001335 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001336 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1337 return MatchOperand_Success;
1338 }
1339 if (Tok.is(AsmToken::EndOfStatement)) {
1340 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001341 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001342
Jack Carterd0bd6422013-04-18 00:41:53 +00001343 // Zero register assumed, add a memory operand with ZERO as its base.
1344 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1345 : Mips::ZERO,
1346 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001347 return MatchOperand_Success;
1348 }
1349 Error(Parser.getTok().getLoc(), "'(' expected");
1350 return MatchOperand_ParseFail;
1351 }
1352
Jack Carterd0bd6422013-04-18 00:41:53 +00001353 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001354 }
1355
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001356 Res = parseRegs(Operands, isMips64()? (int) MipsOperand::Kind_GPR64:
1357 (int) MipsOperand::Kind_GPR32);
1358 if (Res != MatchOperand_Success)
1359 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001360
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001361 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001362 Error(Parser.getTok().getLoc(), "')' expected");
1363 return MatchOperand_ParseFail;
1364 }
1365
Jack Carter873c7242013-01-12 01:03:14 +00001366 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1367
Jack Carterd0bd6422013-04-18 00:41:53 +00001368 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001369
1370 if (IdVal == 0)
1371 IdVal = MCConstantExpr::Create(0, getContext());
1372
Jack Carterd0bd6422013-04-18 00:41:53 +00001373 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001374 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1375 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001376 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001377 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001378 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001379 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1380 int64_t Imm;
1381 if (IdVal->EvaluateAsAbsolute(Imm))
1382 IdVal = MCConstantExpr::Create(Imm, getContext());
1383 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1384 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1385 getContext());
1386 }
1387
Jack Carterdc1e35d2012-09-06 20:00:02 +00001388 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1389 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001390 return MatchOperand_Success;
1391}
1392
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001393bool
1394MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1395 int RegKind) {
1396 // If the first token is not '$' we have an error.
1397 if (Parser.getTok().isNot(AsmToken::Dollar))
1398 return false;
1399
1400 SMLoc S = Parser.getTok().getLoc();
1401 Parser.Lex();
1402 AsmToken::TokenKind TkKind = getLexer().getKind();
1403 int Reg;
1404
1405 if (TkKind == AsmToken::Integer) {
1406 Reg = matchRegisterByNumber(Parser.getTok().getIntVal(),
1407 regKindToRegClass(RegKind));
1408 if (Reg == -1)
1409 return false;
1410 } else if (TkKind == AsmToken::Identifier) {
1411 if ((Reg = matchCPURegisterName(Parser.getTok().getString().lower())) == -1)
1412 return false;
1413 Reg = getReg(regKindToRegClass(RegKind), Reg);
1414 } else {
1415 return false;
1416 }
1417
1418 MipsOperand *Op = MipsOperand::CreatePtrReg(Reg, S, Parser.getTok().getLoc());
1419 Op->setRegKind((MipsOperand::RegisterKind)RegKind);
1420 Operands.push_back(Op);
1421 Parser.Lex();
1422 return true;
1423}
1424
1425MipsAsmParser::OperandMatchResultTy
1426MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1427 MipsOperand::RegisterKind RegKind = isN64() ? MipsOperand::Kind_GPR64 :
1428 MipsOperand::Kind_GPR32;
1429
1430 // Parse index register.
1431 if (!parsePtrReg(Operands, RegKind))
1432 return MatchOperand_NoMatch;
1433
1434 // Parse '('.
1435 if (Parser.getTok().isNot(AsmToken::LParen))
1436 return MatchOperand_NoMatch;
1437
1438 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1439 Parser.Lex();
1440
1441 // Parse base register.
1442 if (!parsePtrReg(Operands, RegKind))
1443 return MatchOperand_NoMatch;
1444
1445 // Parse ')'.
1446 if (Parser.getTok().isNot(AsmToken::RParen))
1447 return MatchOperand_NoMatch;
1448
1449 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1450 Parser.Lex();
1451
1452 return MatchOperand_Success;
1453}
1454
Jack Carter873c7242013-01-12 01:03:14 +00001455MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +00001456MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1457 int RegKind) {
1458 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001459 if (getLexer().getKind() == AsmToken::Identifier
1460 && !hasConsumedDollar) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001461 if (searchSymbolAlias(Operands, Kind))
Jack Carterd76b2372013-03-21 21:44:16 +00001462 return MatchOperand_Success;
1463 return MatchOperand_NoMatch;
1464 }
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001465 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001466 // If the first token is not '$', we have an error.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001467 if (Parser.getTok().isNot(AsmToken::Dollar) && !hasConsumedDollar)
Jack Carter873c7242013-01-12 01:03:14 +00001468 return MatchOperand_NoMatch;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001469 if (!hasConsumedDollar) {
1470 Parser.Lex(); // Eat the '$'
1471 hasConsumedDollar = true;
1472 }
1473 if (getLexer().getKind() == AsmToken::Identifier) {
1474 int RegNum = -1;
1475 std::string RegName = Parser.getTok().getString().lower();
1476 // Match register by name
1477 switch (RegKind) {
1478 case MipsOperand::Kind_GPR32:
1479 case MipsOperand::Kind_GPR64:
1480 RegNum = matchCPURegisterName(RegName);
1481 break;
1482 case MipsOperand::Kind_AFGR64Regs:
1483 case MipsOperand::Kind_FGR64Regs:
1484 case MipsOperand::Kind_FGR32Regs:
Akira Hatanaka14e31a22013-08-20 22:58:56 +00001485 case MipsOperand::Kind_FGRH32Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001486 RegNum = matchFPURegisterName(RegName);
1487 if (RegKind == MipsOperand::Kind_AFGR64Regs)
1488 RegNum /= 2;
Vladimir Medic65cd5742013-09-10 09:50:01 +00001489 else if (RegKind == MipsOperand::Kind_FGRH32Regs
1490 && !isFP64())
1491 if (RegNum != -1 && RegNum %2 != 0)
1492 Warning(S, "Float register should be even.");
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001493 break;
1494 case MipsOperand::Kind_FCCRegs:
1495 RegNum = matchFCCRegisterName(RegName);
1496 break;
1497 case MipsOperand::Kind_ACC64DSP:
1498 RegNum = matchACRegisterName(RegName);
1499 break;
1500 default: break; // No match, value is set to -1.
1501 }
1502 // No match found, return _NoMatch to give a chance to other round.
1503 if (RegNum < 0)
1504 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001505
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001506 int RegVal = getReg(regKindToRegClass(Kind), RegNum);
1507 if (RegVal == -1)
1508 return MatchOperand_NoMatch;
1509
1510 MipsOperand *Op = MipsOperand::CreateReg(RegVal, S,
1511 Parser.getTok().getLoc());
1512 Op->setRegKind(Kind);
1513 Operands.push_back(Op);
1514 hasConsumedDollar = false;
1515 Parser.Lex(); // Eat the register name.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001516 return MatchOperand_Success;
1517 } else if (getLexer().getKind() == AsmToken::Integer) {
1518 unsigned RegNum = Parser.getTok().getIntVal();
1519 if (Kind == MipsOperand::Kind_HWRegs) {
1520 if (RegNum != 29)
1521 return MatchOperand_NoMatch;
1522 // Only hwreg 29 is supported, found at index 0.
1523 RegNum = 0;
1524 }
1525 int Reg = matchRegisterByNumber(RegNum, regKindToRegClass(Kind));
1526 if (Reg == -1)
1527 return MatchOperand_NoMatch;
1528 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1529 Op->setRegKind(Kind);
1530 Operands.push_back(Op);
1531 hasConsumedDollar = false;
1532 Parser.Lex(); // Eat the register number.
1533 if ((RegKind == MipsOperand::Kind_GPR32)
Vladimir Medic3467b902013-07-18 09:28:35 +00001534 && (getLexer().is(AsmToken::LParen))) {
1535 // Check if it is indexed addressing operand.
1536 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1537 Parser.Lex(); // Eat the parenthesis.
1538 if (parseRegs(Operands,RegKind) != MatchOperand_Success)
1539 return MatchOperand_NoMatch;
1540 if (getLexer().isNot(AsmToken::RParen))
1541 return MatchOperand_NoMatch;
1542 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1543 Parser.Lex();
1544 }
Jack Carter873c7242013-01-12 01:03:14 +00001545 return MatchOperand_Success;
1546 }
1547 return MatchOperand_NoMatch;
1548}
Vladimir Medic64828a12013-07-16 10:07:14 +00001549
Vladimir Medic8cd17102013-06-20 11:21:49 +00001550MipsAsmParser::OperandMatchResultTy
Jack Carter5dc8ac92013-09-25 23:50:44 +00001551MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1552 int RegKind) {
1553 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
1554 SMLoc S = Parser.getTok().getLoc();
1555 std::string RegName;
1556
1557 if (Parser.getTok().isNot(AsmToken::Dollar))
1558 return MatchOperand_NoMatch;
1559
1560 switch (RegKind) {
1561 default:
1562 return MatchOperand_ParseFail;
1563 case MipsOperand::Kind_MSA128BRegs:
1564 case MipsOperand::Kind_MSA128HRegs:
1565 case MipsOperand::Kind_MSA128WRegs:
1566 case MipsOperand::Kind_MSA128DRegs:
1567 break;
1568 }
1569
1570 Parser.Lex(); // Eat the '$'.
1571 if (getLexer().getKind() == AsmToken::Identifier)
1572 RegName = Parser.getTok().getString().lower();
1573 else
1574 return MatchOperand_ParseFail;
1575
1576 int RegNum = matchMSA128RegisterName(RegName);
1577
1578 if (RegNum < 0 || RegNum > 31)
1579 return MatchOperand_ParseFail;
1580
1581 int RegVal = getReg(regKindToRegClass(Kind), RegNum);
1582 if (RegVal == -1)
1583 return MatchOperand_ParseFail;
1584
1585 MipsOperand *Op = MipsOperand::CreateReg(RegVal, S,
1586 Parser.getTok().getLoc());
1587 Op->setRegKind(Kind);
1588 Operands.push_back(Op);
1589
1590 Parser.Lex(); // Eat the register identifier.
1591
1592 return MatchOperand_Success;
1593}
1594
1595MipsAsmParser::OperandMatchResultTy
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001596MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001597
1598 if (!isMips64())
1599 return MatchOperand_NoMatch;
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001600 return parseRegs(Operands, (int) MipsOperand::Kind_GPR64);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001601}
1602
1603MipsAsmParser::OperandMatchResultTy
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001604MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1605 return parseRegs(Operands, (int) MipsOperand::Kind_GPR32);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001606}
Jack Carter873c7242013-01-12 01:03:14 +00001607
Vladimir Medic233dd512013-06-24 10:05:34 +00001608MipsAsmParser::OperandMatchResultTy
1609MipsAsmParser::parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1610
1611 if (isFP64())
1612 return MatchOperand_NoMatch;
Vladimir Medic233dd512013-06-24 10:05:34 +00001613 return parseRegs(Operands, (int) MipsOperand::Kind_AFGR64Regs);
1614}
1615
1616MipsAsmParser::OperandMatchResultTy
1617MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1618 if (!isFP64())
1619 return MatchOperand_NoMatch;
Vladimir Medic233dd512013-06-24 10:05:34 +00001620 return parseRegs(Operands, (int) MipsOperand::Kind_FGR64Regs);
1621}
1622
1623MipsAsmParser::OperandMatchResultTy
1624MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic233dd512013-06-24 10:05:34 +00001625 return parseRegs(Operands, (int) MipsOperand::Kind_FGR32Regs);
1626}
1627
Vladimir Medic643b3982013-07-30 10:12:14 +00001628MipsAsmParser::OperandMatchResultTy
Akira Hatanaka14e31a22013-08-20 22:58:56 +00001629MipsAsmParser::parseFGRH32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1630 return parseRegs(Operands, (int) MipsOperand::Kind_FGRH32Regs);
1631}
1632
1633MipsAsmParser::OperandMatchResultTy
Vladimir Medic643b3982013-07-30 10:12:14 +00001634MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001635 return parseRegs(Operands, (int) MipsOperand::Kind_FCCRegs);
Vladimir Medic643b3982013-07-30 10:12:14 +00001636}
1637
Akira Hatanaka34a32c02013-08-06 22:20:40 +00001638MipsAsmParser::OperandMatchResultTy
Akira Hatanaka00fcf2e2013-08-08 21:54:26 +00001639MipsAsmParser::parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001640 return parseRegs(Operands, (int) MipsOperand::Kind_ACC64DSP);
Akira Hatanaka34a32c02013-08-06 22:20:40 +00001641}
1642
Akira Hatanakafeb7ee82013-08-14 01:02:20 +00001643MipsAsmParser::OperandMatchResultTy
1644MipsAsmParser::parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1645 // If the first token is not '$' we have an error.
1646 if (Parser.getTok().isNot(AsmToken::Dollar))
1647 return MatchOperand_NoMatch;
1648
1649 SMLoc S = Parser.getTok().getLoc();
1650 Parser.Lex(); // Eat the '$'
1651
1652 const AsmToken &Tok = Parser.getTok(); // Get next token.
1653
1654 if (Tok.isNot(AsmToken::Identifier))
1655 return MatchOperand_NoMatch;
1656
1657 if (!Tok.getIdentifier().startswith("ac"))
1658 return MatchOperand_NoMatch;
1659
1660 StringRef NumString = Tok.getIdentifier().substr(2);
1661
1662 unsigned IntVal;
1663 if (NumString.getAsInteger(10, IntVal))
1664 return MatchOperand_NoMatch;
1665
1666 unsigned Reg = matchRegisterByNumber(IntVal, Mips::LO32DSPRegClassID);
1667
1668 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1669 Op->setRegKind(MipsOperand::Kind_LO32DSP);
1670 Operands.push_back(Op);
1671
1672 Parser.Lex(); // Eat the register number.
1673 return MatchOperand_Success;
1674}
1675
1676MipsAsmParser::OperandMatchResultTy
1677MipsAsmParser::parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1678 // If the first token is not '$' we have an error.
1679 if (Parser.getTok().isNot(AsmToken::Dollar))
1680 return MatchOperand_NoMatch;
1681
1682 SMLoc S = Parser.getTok().getLoc();
1683 Parser.Lex(); // Eat the '$'
1684
1685 const AsmToken &Tok = Parser.getTok(); // Get next token.
1686
1687 if (Tok.isNot(AsmToken::Identifier))
1688 return MatchOperand_NoMatch;
1689
1690 if (!Tok.getIdentifier().startswith("ac"))
1691 return MatchOperand_NoMatch;
1692
1693 StringRef NumString = Tok.getIdentifier().substr(2);
1694
1695 unsigned IntVal;
1696 if (NumString.getAsInteger(10, IntVal))
1697 return MatchOperand_NoMatch;
1698
1699 unsigned Reg = matchRegisterByNumber(IntVal, Mips::HI32DSPRegClassID);
1700
1701 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1702 Op->setRegKind(MipsOperand::Kind_HI32DSP);
1703 Operands.push_back(Op);
1704
1705 Parser.Lex(); // Eat the register number.
1706 return MatchOperand_Success;
1707}
1708
Vladimir Medic05bcde62013-09-16 10:29:42 +00001709MipsAsmParser::OperandMatchResultTy
1710MipsAsmParser::parseCOP2(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1711 // If the first token is not '$' we have an error.
1712 if (Parser.getTok().isNot(AsmToken::Dollar))
1713 return MatchOperand_NoMatch;
1714
1715 SMLoc S = Parser.getTok().getLoc();
1716 Parser.Lex(); // Eat the '$'
1717
1718 const AsmToken &Tok = Parser.getTok(); // Get next token.
1719
1720 if (Tok.isNot(AsmToken::Integer))
1721 return MatchOperand_NoMatch;
1722
1723 unsigned IntVal = Tok.getIntVal();
1724
1725 unsigned Reg = matchRegisterByNumber(IntVal, Mips::COP2RegClassID);
1726
1727 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1728 Op->setRegKind(MipsOperand::Kind_COP2);
1729 Operands.push_back(Op);
1730
1731 Parser.Lex(); // Eat the register number.
1732 return MatchOperand_Success;
1733}
1734
Jack Carter5dc8ac92013-09-25 23:50:44 +00001735MipsAsmParser::OperandMatchResultTy
1736MipsAsmParser::parseMSA128BRegs(
1737 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1738 return parseMSARegs(Operands, (int) MipsOperand::Kind_MSA128BRegs);
1739}
1740
1741MipsAsmParser::OperandMatchResultTy
1742MipsAsmParser::parseMSA128HRegs(
1743 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1744 return parseMSARegs(Operands, (int) MipsOperand::Kind_MSA128HRegs);
1745}
1746
1747MipsAsmParser::OperandMatchResultTy
1748MipsAsmParser::parseMSA128WRegs(
1749 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1750 return parseMSARegs(Operands, (int) MipsOperand::Kind_MSA128WRegs);
1751}
1752
1753MipsAsmParser::OperandMatchResultTy
1754MipsAsmParser::parseMSA128DRegs(
1755 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1756 return parseMSARegs(Operands, (int) MipsOperand::Kind_MSA128DRegs);
1757}
1758
Jack Carterd0bd6422013-04-18 00:41:53 +00001759bool MipsAsmParser::searchSymbolAlias(
Vladimir Medic8cd17102013-06-20 11:21:49 +00001760 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001761
1762 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1763 if (Sym) {
1764 SMLoc S = Parser.getTok().getLoc();
1765 const MCExpr *Expr;
1766 if (Sym->isVariable())
1767 Expr = Sym->getVariableValue();
1768 else
1769 return false;
1770 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001771 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind) RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001772 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1773 const StringRef DefSymbol = Ref->getSymbol().getName();
1774 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00001775 int RegNum = -1;
1776 APInt IntVal(32, -1);
1777 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
1778 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
Vladimir Medic64828a12013-07-16 10:07:14 +00001779 isMips64()
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001780 ? Mips::GPR64RegClassID
1781 : Mips::GPR32RegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001782 else {
1783 // Lookup for the register with the corresponding name.
1784 switch (Kind) {
1785 case MipsOperand::Kind_AFGR64Regs:
1786 case MipsOperand::Kind_FGR64Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001787 RegNum = matchFPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00001788 break;
1789 case MipsOperand::Kind_FGR32Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001790 RegNum = matchFPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00001791 break;
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001792 case MipsOperand::Kind_GPR64:
1793 case MipsOperand::Kind_GPR32:
Vladimir Medic8cd17102013-06-20 11:21:49 +00001794 default:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001795 RegNum = matchCPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00001796 break;
1797 }
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001798 if (RegNum > -1)
1799 RegNum = getReg(regKindToRegClass(Kind), RegNum);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001800 }
Jack Carterd76b2372013-03-21 21:44:16 +00001801 if (RegNum > -1) {
1802 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001803 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1804 Parser.getTok().getLoc());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001805 op->setRegKind(Kind);
Jack Carterd76b2372013-03-21 21:44:16 +00001806 Operands.push_back(op);
1807 return true;
1808 }
1809 }
1810 } else if (Expr->getKind() == MCExpr::Constant) {
1811 Parser.Lex();
1812 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001813 MipsOperand *op = MipsOperand::CreateImm(Const, S,
Vladimir Medic64828a12013-07-16 10:07:14 +00001814 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001815 Operands.push_back(op);
1816 return true;
1817 }
1818 }
1819 return false;
1820}
Jack Carterd0bd6422013-04-18 00:41:53 +00001821
Jack Carter873c7242013-01-12 01:03:14 +00001822MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +00001823MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001824 return parseRegs(Operands, (int) MipsOperand::Kind_HWRegs);
Jack Carter873c7242013-01-12 01:03:14 +00001825}
1826
1827MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +00001828MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001829 return parseRegs(Operands, (int) MipsOperand::Kind_CCRRegs);
Jack Carter873c7242013-01-12 01:03:14 +00001830}
1831
Vladimir Medic2b953d02013-10-01 09:48:56 +00001832MipsAsmParser::OperandMatchResultTy
1833MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1834 const MCExpr *IdVal;
1835 // If the first token is '$' we may have register operand.
1836 if (Parser.getTok().is(AsmToken::Dollar))
1837 return MatchOperand_NoMatch;
1838 SMLoc S = Parser.getTok().getLoc();
1839 if (getParser().parseExpression(IdVal))
1840 return MatchOperand_ParseFail;
1841 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
1842 assert( MCE && "Unexpected MCExpr type.");
1843 int64_t Val = MCE->getValue();
1844 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1845 Operands.push_back(MipsOperand::CreateImm(
1846 MCConstantExpr::Create(0 - Val, getContext()), S, E));
1847 return MatchOperand_Success;
1848}
1849
Jack Carterdc1e35d2012-09-06 20:00:02 +00001850MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1851
1852 MCSymbolRefExpr::VariantKind VK
1853 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1854 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1855 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1856 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1857 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1858 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1859 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1860 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1861 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1862 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1863 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1864 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1865 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1866 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1867 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1868 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1869 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1870 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1871 .Default(MCSymbolRefExpr::VK_None);
1872
1873 return VK;
1874}
Jack Cartera63b16a2012-09-07 00:23:42 +00001875
Rafael Espindola870c4e92012-01-11 03:56:41 +00001876bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001877ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001878 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic74593e62013-07-17 15:00:42 +00001879 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00001880 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00001881 Parser.eatToEndOfStatement();
1882 return Error(NameLoc, "Unknown instruction");
1883 }
Vladimir Medic64828a12013-07-16 10:07:14 +00001884 // First operand in MCInst is instruction mnemonic.
1885 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterb4dbc172012-09-05 23:34:03 +00001886
1887 // Read the remaining operands.
1888 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1889 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00001890 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001891 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001892 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001893 return Error(Loc, "unexpected token in argument list");
1894 }
1895
Jack Carterd0bd6422013-04-18 00:41:53 +00001896 while (getLexer().is(AsmToken::Comma)) {
1897 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001898 // Parse and remember the operand.
1899 if (ParseOperand(Operands, Name)) {
1900 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001901 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001902 return Error(Loc, "unexpected token in argument list");
1903 }
1904 }
1905 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001906 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1907 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001908 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001909 return Error(Loc, "unexpected token in argument list");
1910 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001911 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001912 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001913}
1914
Jack Carter0b744b32012-10-04 02:29:46 +00001915bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001916 SMLoc Loc = getLexer().getLoc();
1917 Parser.eatToEndOfStatement();
1918 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001919}
1920
1921bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001922 // Line should look like: ".set noat".
1923 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001924 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001925 // eat noat
1926 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001927 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001928 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1929 reportParseError("unexpected token in statement");
1930 return false;
1931 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001932 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001933 return false;
1934}
Jack Carterd0bd6422013-04-18 00:41:53 +00001935
Jack Carter0b744b32012-10-04 02:29:46 +00001936bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001937 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001938 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001939 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001940 getParser().Lex();
1941 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001942 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001943 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001944 return false;
1945 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001946 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001947 if (getLexer().isNot(AsmToken::Dollar)) {
1948 reportParseError("unexpected token in statement");
1949 return false;
1950 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001951 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001952 const AsmToken &Reg = Parser.getTok();
1953 if (Reg.is(AsmToken::Identifier)) {
1954 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1955 } else if (Reg.is(AsmToken::Integer)) {
1956 AtRegNo = Reg.getIntVal();
1957 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001958 reportParseError("unexpected token in statement");
1959 return false;
1960 }
Jack Carter1ac53222013-02-20 23:11:17 +00001961
Jack Carterd0bd6422013-04-18 00:41:53 +00001962 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001963 reportParseError("unexpected token in statement");
1964 return false;
1965 }
1966
1967 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001968 reportParseError("unexpected token in statement");
1969 return false;
1970 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001971 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001972
1973 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1974 reportParseError("unexpected token in statement");
1975 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001976 }
1977 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001978 return false;
1979 } else {
1980 reportParseError("unexpected token in statement");
1981 return false;
1982 }
1983}
1984
1985bool MipsAsmParser::parseSetReorderDirective() {
1986 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001987 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001988 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1989 reportParseError("unexpected token in statement");
1990 return false;
1991 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001992 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001993 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001994 return false;
1995}
1996
1997bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001998 Parser.Lex();
1999 // If this is not the end of the statement, report an error.
2000 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2001 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002002 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002003 }
2004 Options.setNoreorder();
2005 Parser.Lex(); // Consume the EndOfStatement.
2006 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002007}
2008
2009bool MipsAsmParser::parseSetMacroDirective() {
2010 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002011 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002012 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2013 reportParseError("unexpected token in statement");
2014 return false;
2015 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002016 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002017 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002018 return false;
2019}
2020
2021bool MipsAsmParser::parseSetNoMacroDirective() {
2022 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002023 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002024 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2025 reportParseError("`noreorder' must be set before `nomacro'");
2026 return false;
2027 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002028 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002029 reportParseError("`noreorder' must be set before `nomacro'");
2030 return false;
2031 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002032 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002033 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002034 return false;
2035}
Jack Carterd76b2372013-03-21 21:44:16 +00002036
2037bool MipsAsmParser::parseSetAssignment() {
2038 StringRef Name;
2039 const MCExpr *Value;
2040
2041 if (Parser.parseIdentifier(Name))
2042 reportParseError("expected identifier after .set");
2043
2044 if (getLexer().isNot(AsmToken::Comma))
2045 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002046 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002047
Jack Carter02593002013-05-28 22:21:05 +00002048 if (getLexer().is(AsmToken::Dollar)) {
2049 MCSymbol *Symbol;
2050 SMLoc DollarLoc = getLexer().getLoc();
2051 // Consume the dollar sign, and check for a following identifier.
2052 Parser.Lex();
2053 // We have a '$' followed by something, make sure they are adjacent.
2054 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
2055 return true;
2056 StringRef Res = StringRef(DollarLoc.getPointer(),
2057 getTok().getEndLoc().getPointer() - DollarLoc.getPointer());
2058 Symbol = getContext().GetOrCreateSymbol(Res);
2059 Parser.Lex();
2060 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
2061 getContext());
2062 } else if (Parser.parseExpression(Value))
2063 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002064
Jack Carterd0bd6422013-04-18 00:41:53 +00002065 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002066 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002067 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002068 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002069 Sym = getContext().GetOrCreateSymbol(Name);
2070 Sym->setVariableValue(Value);
2071
2072 return false;
2073}
Jack Carterd0bd6422013-04-18 00:41:53 +00002074
Jack Carter0b744b32012-10-04 02:29:46 +00002075bool MipsAsmParser::parseDirectiveSet() {
2076
Jack Carterd0bd6422013-04-18 00:41:53 +00002077 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002078 const AsmToken &Tok = Parser.getTok();
2079
2080 if (Tok.getString() == "noat") {
2081 return parseSetNoAtDirective();
2082 } else if (Tok.getString() == "at") {
2083 return parseSetAtDirective();
2084 } else if (Tok.getString() == "reorder") {
2085 return parseSetReorderDirective();
2086 } else if (Tok.getString() == "noreorder") {
2087 return parseSetNoReorderDirective();
2088 } else if (Tok.getString() == "macro") {
2089 return parseSetMacroDirective();
2090 } else if (Tok.getString() == "nomacro") {
2091 return parseSetNoMacroDirective();
2092 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002093 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002094 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00002095 return false;
2096 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002097 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002098 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00002099 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002100 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002101 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002102 parseSetAssignment();
2103 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002104 }
Jack Carter07c818d2013-01-25 01:31:34 +00002105
Jack Carter0b744b32012-10-04 02:29:46 +00002106 return true;
2107}
2108
Rafael Espindolaac4ad252013-10-05 16:42:21 +00002109bool MipsAsmParser::parseDirectiveMipsHackStocg() {
2110 MCAsmParser &Parser = getParser();
2111 StringRef Name;
2112 if (Parser.parseIdentifier(Name))
2113 reportParseError("expected identifier");
2114
2115 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
2116 if (getLexer().isNot(AsmToken::Comma))
2117 return TokError("unexpected token");
2118 Lex();
2119
2120 int64_t Flags = 0;
2121 if (Parser.parseAbsoluteExpression(Flags))
2122 return TokError("unexpected token");
2123
Rafael Espindolaa17151a2013-10-08 13:08:17 +00002124 getTargetStreamer().emitMipsHackSTOCG(Sym, Flags);
Rafael Espindolaac4ad252013-10-05 16:42:21 +00002125 return false;
2126}
2127
2128bool MipsAsmParser::parseDirectiveMipsHackELFFlags() {
2129 int64_t Flags = 0;
2130 if (Parser.parseAbsoluteExpression(Flags))
2131 return TokError("unexpected token");
2132
Rafael Espindolaa17151a2013-10-08 13:08:17 +00002133 getTargetStreamer().emitMipsHackELFFlags(Flags);
Rafael Espindolaac4ad252013-10-05 16:42:21 +00002134 return false;
2135}
2136
Jack Carter07c818d2013-01-25 01:31:34 +00002137/// parseDirectiveWord
2138/// ::= .word [ expression (, expression)* ]
2139bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
2140 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2141 for (;;) {
2142 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002143 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002144 return true;
2145
2146 getParser().getStreamer().EmitValue(Value, Size);
2147
2148 if (getLexer().is(AsmToken::EndOfStatement))
2149 break;
2150
2151 // FIXME: Improve diagnostic.
2152 if (getLexer().isNot(AsmToken::Comma))
2153 return Error(L, "unexpected token in directive");
2154 Parser.Lex();
2155 }
2156 }
2157
2158 Parser.Lex();
2159 return false;
2160}
2161
Jack Carter0b744b32012-10-04 02:29:46 +00002162bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00002163
Jack Carter07c818d2013-01-25 01:31:34 +00002164 StringRef IDVal = DirectiveID.getString();
2165
Jack Carterd0bd6422013-04-18 00:41:53 +00002166 if (IDVal == ".ent") {
2167 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002168 Parser.Lex();
2169 return false;
2170 }
2171
Jack Carter07c818d2013-01-25 01:31:34 +00002172 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002173 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002174 Parser.Lex();
2175 return false;
2176 }
2177
Jack Carter07c818d2013-01-25 01:31:34 +00002178 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002179 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002180 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002181 return false;
2182 }
2183
Jack Carter07c818d2013-01-25 01:31:34 +00002184 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002185 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002186 }
2187
Jack Carter07c818d2013-01-25 01:31:34 +00002188 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002189 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002190 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002191 return false;
2192 }
2193
Jack Carter07c818d2013-01-25 01:31:34 +00002194 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002195 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002196 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002197 return false;
2198 }
2199
Jack Carter07c818d2013-01-25 01:31:34 +00002200 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002201 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002202 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002203 return false;
2204 }
2205
Jack Carter07c818d2013-01-25 01:31:34 +00002206 if (IDVal == ".word") {
2207 parseDirectiveWord(4, DirectiveID.getLoc());
2208 return false;
2209 }
2210
Rafael Espindolaac4ad252013-10-05 16:42:21 +00002211 if (IDVal == ".mips_hack_stocg")
2212 return parseDirectiveMipsHackStocg();
2213
2214 if (IDVal == ".mips_hack_elf_flags")
2215 return parseDirectiveMipsHackELFFlags();
2216
Rafael Espindola870c4e92012-01-11 03:56:41 +00002217 return true;
2218}
2219
Rafael Espindola870c4e92012-01-11 03:56:41 +00002220extern "C" void LLVMInitializeMipsAsmParser() {
2221 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2222 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2223 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2224 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2225}
Jack Carterb4dbc172012-09-05 23:34:03 +00002226
2227#define GET_REGISTER_MATCHER
2228#define GET_MATCHER_IMPLEMENTATION
2229#include "MipsGenAsmMatcher.inc"