blob: 2492bf8c143f795e29a5b727b0d800a128dbc28b [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"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
17#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCSubtargetInfo.h"
20#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000021#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Jack Carter02593002013-05-28 22:21:05 +000023#include "llvm/ADT/APInt.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000024
25using namespace llvm;
26
27namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000028class MipsAssemblerOptions {
29public:
30 MipsAssemblerOptions():
31 aTReg(1), reorder(true), macro(true) {
32 }
Jack Carterb4dbc172012-09-05 23:34:03 +000033
Jack Carter0b744b32012-10-04 02:29:46 +000034 unsigned getATRegNum() {return aTReg;}
35 bool setATReg(unsigned Reg);
36
37 bool isReorder() {return reorder;}
38 void setReorder() {reorder = true;}
39 void setNoreorder() {reorder = false;}
40
41 bool isMacro() {return macro;}
42 void setMacro() {macro = true;}
43 void setNomacro() {macro = false;}
44
45private:
46 unsigned aTReg;
47 bool reorder;
48 bool macro;
49};
50}
51
52namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000053class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000054
Jack Cartera63b16a2012-09-07 00:23:42 +000055 enum FpFormatTy {
56 FP_FORMAT_NONE = -1,
57 FP_FORMAT_S,
58 FP_FORMAT_D,
59 FP_FORMAT_L,
60 FP_FORMAT_W
61 } FpFormat;
62
Jack Carterb4dbc172012-09-05 23:34:03 +000063 MCSubtargetInfo &STI;
64 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000065 MipsAssemblerOptions Options;
Vladimir Medic27c87ea2013-08-13 13:07:09 +000066 bool hasConsumedDollar;
Jack Carter0b744b32012-10-04 02:29:46 +000067
Akira Hatanaka7605630c2012-08-17 20:16:42 +000068#define GET_ASSEMBLER_HEADER
69#include "MipsGenAsmMatcher.inc"
70
Chad Rosier49963552012-10-13 00:26:04 +000071 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +000072 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000073 MCStreamer &Out, unsigned &ErrorInfo,
74 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000075
76 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
77
Chad Rosierf0e87202012-10-25 20:41:34 +000078 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
79 SMLoc NameLoc,
Akira Hatanaka7605630c2012-08-17 20:16:42 +000080 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000081
82 bool ParseDirective(AsmToken DirectiveID);
83
Jack Carterb4dbc172012-09-05 23:34:03 +000084 MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +000085 parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
86 int RegKind);
Vladimir Medic64828a12013-07-16 10:07:14 +000087
88 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +000089 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
90
91 MipsAsmParser::OperandMatchResultTy
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +000092 parseGPR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +000093
94 MipsAsmParser::OperandMatchResultTy
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +000095 parseGPR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +000096
97 MipsAsmParser::OperandMatchResultTy
98 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
99
100 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +0000101 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000102
Vladimir Medic233dd512013-06-24 10:05:34 +0000103 MipsAsmParser::OperandMatchResultTy
104 parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
105
106 MipsAsmParser::OperandMatchResultTy
107 parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
108
109 MipsAsmParser::OperandMatchResultTy
110 parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
111
Vladimir Medic643b3982013-07-30 10:12:14 +0000112 MipsAsmParser::OperandMatchResultTy
113 parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
114
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000115 MipsAsmParser::OperandMatchResultTy
Akira Hatanaka00fcf2e2013-08-08 21:54:26 +0000116 parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000117
Jack Carterd76b2372013-03-21 21:44:16 +0000118 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +0000119 unsigned RegKind);
Jack Carterd76b2372013-03-21 21:44:16 +0000120
Jack Carterb4dbc172012-09-05 23:34:03 +0000121 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
122 StringRef Mnemonic);
123
Jack Carter873c7242013-01-12 01:03:14 +0000124 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000125
126 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000127 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000128
Jack Carter30a59822012-10-04 04:03:53 +0000129 bool needsExpansion(MCInst &Inst);
130
131 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000132 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000133 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000134 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000135 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
136 SmallVectorImpl<MCInst> &Instructions);
137 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
138 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000139 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
140 SmallVectorImpl<MCInst> &Instructions,
141 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000142 bool reportParseError(StringRef ErrorMsg);
143
Jack Carterb5cf5902013-04-17 00:18:04 +0000144 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000145 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000146
Jack Carterb5cf5902013-04-17 00:18:04 +0000147 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
148
149 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000150 bool parseDirectiveSet();
151
152 bool parseSetAtDirective();
153 bool parseSetNoAtDirective();
154 bool parseSetMacroDirective();
155 bool parseSetNoMacroDirective();
156 bool parseSetReorderDirective();
157 bool parseSetNoReorderDirective();
158
Jack Carterd76b2372013-03-21 21:44:16 +0000159 bool parseSetAssignment();
160
Jack Carter07c818d2013-01-25 01:31:34 +0000161 bool parseDirectiveWord(unsigned Size, SMLoc L);
162
Jack Carterdc1e35d2012-09-06 20:00:02 +0000163 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000164
Jack Carterb4dbc172012-09-05 23:34:03 +0000165 bool isMips64() const {
166 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
167 }
168
Jack Cartera63b16a2012-09-07 00:23:42 +0000169 bool isFP64() const {
170 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
171 }
172
Jack Carter873c7242013-01-12 01:03:14 +0000173 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000174
Jack Carter1ac53222013-02-20 23:11:17 +0000175 int matchCPURegisterName(StringRef Symbol);
176
Jack Carter873c7242013-01-12 01:03:14 +0000177 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000178
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000179 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000180
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000181 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000182
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000183 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000184
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000185 int regKindToRegClass(int RegKind);
Jack Cartera63b16a2012-09-07 00:23:42 +0000186
187 FpFormatTy getFpFormat() {return FpFormat;}
188
Jack Carterd0bd6422013-04-18 00:41:53 +0000189 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000190
Jack Carter1ac53222013-02-20 23:11:17 +0000191 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000192
193 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
194 SmallVectorImpl<MCInst> &Instructions);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000195public:
196 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000197 : MCTargetAsmParser(), STI(sti), Parser(parser), hasConsumedDollar(false) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000198 // Initialize the set of available features.
199 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000200 }
201
Jack Carterb4dbc172012-09-05 23:34:03 +0000202 MCAsmParser &getParser() const { return Parser; }
203 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
204
Rafael Espindola870c4e92012-01-11 03:56:41 +0000205};
206}
207
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000208namespace {
209
210/// MipsOperand - Instances of this class represent a parsed Mips machine
211/// instruction.
212class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000213
Jack Carter873c7242013-01-12 01:03:14 +0000214public:
215 enum RegisterKind {
216 Kind_None,
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000217 Kind_GPR32,
218 Kind_GPR64,
Jack Carter873c7242013-01-12 01:03:14 +0000219 Kind_HWRegs,
Jack Carter873c7242013-01-12 01:03:14 +0000220 Kind_FGR32Regs,
221 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000222 Kind_AFGR64Regs,
Vladimir Medic643b3982013-07-30 10:12:14 +0000223 Kind_CCRRegs,
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000224 Kind_FCCRegs,
Akira Hatanaka00fcf2e2013-08-08 21:54:26 +0000225 Kind_ACC64DSP
Jack Carter873c7242013-01-12 01:03:14 +0000226 };
227
228private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000229 enum KindTy {
230 k_CondCode,
231 k_CoprocNum,
232 k_Immediate,
233 k_Memory,
234 k_PostIndexRegister,
235 k_Register,
236 k_Token
237 } Kind;
238
239 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000240
Eric Christopher8996c5d2013-03-15 00:42:55 +0000241 struct Token {
242 const char *Data;
243 unsigned Length;
244 };
245
246 struct RegOp {
247 unsigned RegNum;
248 RegisterKind Kind;
249 };
250
251 struct ImmOp {
252 const MCExpr *Val;
253 };
254
255 struct MemOp {
256 unsigned Base;
257 const MCExpr *Off;
258 };
259
Jack Carterb4dbc172012-09-05 23:34:03 +0000260 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000261 struct Token Tok;
262 struct RegOp Reg;
263 struct ImmOp Imm;
264 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000265 };
266
267 SMLoc StartLoc, EndLoc;
268
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000269public:
270 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000271 assert(N == 1 && "Invalid number of operands!");
272 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000273 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000274
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000275 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000276 // Add as immediate when possible. Null MCExpr = 0.
277 if (Expr == 0)
278 Inst.addOperand(MCOperand::CreateImm(0));
279 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
280 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
281 else
282 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000283 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000284
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000285 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000286 assert(N == 1 && "Invalid number of operands!");
287 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000288 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000289 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000290
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000291 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000292 assert(N == 2 && "Invalid number of operands!");
293
294 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
295
296 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000297 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000298 }
299
300 bool isReg() const { return Kind == k_Register; }
301 bool isImm() const { return Kind == k_Immediate; }
302 bool isToken() const { return Kind == k_Token; }
303 bool isMem() const { return Kind == k_Memory; }
304
305 StringRef getToken() const {
306 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000307 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000308 }
309
310 unsigned getReg() const {
311 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000312 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000313 }
314
Jack Carter873c7242013-01-12 01:03:14 +0000315 void setRegKind(RegisterKind RegKind) {
316 assert((Kind == k_Register) && "Invalid access!");
317 Reg.Kind = RegKind;
318 }
319
Jack Carterb4dbc172012-09-05 23:34:03 +0000320 const MCExpr *getImm() const {
321 assert((Kind == k_Immediate) && "Invalid access!");
322 return Imm.Val;
323 }
324
Jack Carterdc1e35d2012-09-06 20:00:02 +0000325 unsigned getMemBase() const {
326 assert((Kind == k_Memory) && "Invalid access!");
327 return Mem.Base;
328 }
329
330 const MCExpr *getMemOff() const {
331 assert((Kind == k_Memory) && "Invalid access!");
332 return Mem.Off;
333 }
334
Jack Carterb4dbc172012-09-05 23:34:03 +0000335 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
336 MipsOperand *Op = new MipsOperand(k_Token);
337 Op->Tok.Data = Str.data();
338 Op->Tok.Length = Str.size();
339 Op->StartLoc = S;
340 Op->EndLoc = S;
341 return Op;
342 }
343
344 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
345 MipsOperand *Op = new MipsOperand(k_Register);
346 Op->Reg.RegNum = RegNum;
347 Op->StartLoc = S;
348 Op->EndLoc = E;
349 return Op;
350 }
351
352 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
353 MipsOperand *Op = new MipsOperand(k_Immediate);
354 Op->Imm.Val = Val;
355 Op->StartLoc = S;
356 Op->EndLoc = E;
357 return Op;
358 }
359
Jack Carterdc1e35d2012-09-06 20:00:02 +0000360 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
361 SMLoc S, SMLoc E) {
362 MipsOperand *Op = new MipsOperand(k_Memory);
363 Op->Mem.Base = Base;
364 Op->Mem.Off = Off;
365 Op->StartLoc = S;
366 Op->EndLoc = E;
367 return Op;
368 }
369
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000370 bool isGPR32Asm() const {
371 return Kind == k_Register && Reg.Kind == Kind_GPR32;
Jack Carter873c7242013-01-12 01:03:14 +0000372 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000373 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000374 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
375 }
376
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000377 bool isGPR64Asm() const {
378 return Kind == k_Register && Reg.Kind == Kind_GPR64;
Jack Carter873c7242013-01-12 01:03:14 +0000379 }
Jack Carter873c7242013-01-12 01:03:14 +0000380
381 bool isHWRegsAsm() const {
382 assert((Kind == k_Register) && "Invalid access!");
383 return Reg.Kind == Kind_HWRegs;
384 }
Jack Carter873c7242013-01-12 01:03:14 +0000385
Jack Carter873c7242013-01-12 01:03:14 +0000386 bool isCCRAsm() const {
387 assert((Kind == k_Register) && "Invalid access!");
388 return Reg.Kind == Kind_CCRRegs;
389 }
390
Vladimir Medic233dd512013-06-24 10:05:34 +0000391 bool isAFGR64Asm() const {
392 return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
393 }
394
395 bool isFGR64Asm() const {
396 return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
397 }
398
399 bool isFGR32Asm() const {
400 return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
401 }
402
Vladimir Medic643b3982013-07-30 10:12:14 +0000403 bool isFCCRegsAsm() const {
404 return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs;
405 }
406
Akira Hatanaka00fcf2e2013-08-08 21:54:26 +0000407 bool isACC64DSPAsm() const {
408 return Kind == k_Register && Reg.Kind == Kind_ACC64DSP;
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000409 }
410
Jack Carterb4dbc172012-09-05 23:34:03 +0000411 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000412 SMLoc getStartLoc() const {
413 return StartLoc;
414 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000415 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000416 SMLoc getEndLoc() const {
417 return EndLoc;
418 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000419
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000420 virtual void print(raw_ostream &OS) const {
421 llvm_unreachable("unimplemented!");
422 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000423}; // class MipsOperand
424} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000425
Jack Carter9e65aa32013-03-22 00:05:30 +0000426namespace llvm {
427extern const MCInstrDesc MipsInsts[];
428}
429static const MCInstrDesc &getInstDesc(unsigned Opcode) {
430 return MipsInsts[Opcode];
431}
432
433bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000434 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000435 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
436 Inst.setLoc(IDLoc);
Jack Carterc15c1d22013-04-25 23:31:35 +0000437 if (MCID.hasDelaySlot() && Options.isReorder()) {
438 // If this instruction has a delay slot and .set reorder is active,
439 // emit a NOP after it.
440 Instructions.push_back(Inst);
441 MCInst NopInst;
442 NopInst.setOpcode(Mips::SLL);
443 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
444 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
445 NopInst.addOperand(MCOperand::CreateImm(0));
446 Instructions.push_back(NopInst);
447 return false;
448 }
449
Jack Carter9e65aa32013-03-22 00:05:30 +0000450 if (MCID.mayLoad() || MCID.mayStore()) {
451 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000452 // reference or immediate we may have to expand instructions.
453 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000454 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000455 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
456 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000457 MCOperand &Op = Inst.getOperand(i);
458 if (Op.isImm()) {
459 int MemOffset = Op.getImm();
460 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000461 // Offset can't exceed 16bit value.
462 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000463 return false;
464 }
465 } else if (Op.isExpr()) {
466 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000467 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000468 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000469 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000470 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000471 // Expand symbol.
472 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000473 return false;
474 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000475 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000476 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000477 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000478 }
479 }
480 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000481 } // for
482 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000483
484 if (needsExpansion(Inst))
485 expandInstruction(Inst, IDLoc, Instructions);
486 else
487 Instructions.push_back(Inst);
488
489 return false;
490}
491
Jack Carter30a59822012-10-04 04:03:53 +0000492bool MipsAsmParser::needsExpansion(MCInst &Inst) {
493
Jack Carterd0bd6422013-04-18 00:41:53 +0000494 switch (Inst.getOpcode()) {
495 case Mips::LoadImm32Reg:
496 case Mips::LoadAddr32Imm:
497 case Mips::LoadAddr32Reg:
498 return true;
499 default:
500 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000501 }
502}
Jack Carter92995f12012-10-06 00:53:28 +0000503
Jack Carter30a59822012-10-04 04:03:53 +0000504void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000505 SmallVectorImpl<MCInst> &Instructions) {
506 switch (Inst.getOpcode()) {
507 case Mips::LoadImm32Reg:
508 return expandLoadImm(Inst, IDLoc, Instructions);
509 case Mips::LoadAddr32Imm:
510 return expandLoadAddressImm(Inst, IDLoc, Instructions);
511 case Mips::LoadAddr32Reg:
512 return expandLoadAddressReg(Inst, IDLoc, Instructions);
513 }
Jack Carter30a59822012-10-04 04:03:53 +0000514}
Jack Carter92995f12012-10-06 00:53:28 +0000515
Jack Carter30a59822012-10-04 04:03:53 +0000516void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000517 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000518 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000519 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000520 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000521 const MCOperand &RegOp = Inst.getOperand(0);
522 assert(RegOp.isReg() && "expected register operand kind");
523
524 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000525 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000526 if (0 <= ImmValue && ImmValue <= 65535) {
527 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000528 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000529 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000530 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000531 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000532 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000533 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000534 } else if (ImmValue < 0 && ImmValue >= -32768) {
535 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000536 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000537 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000538 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000539 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000540 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000541 Instructions.push_back(tmpInst);
542 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000543 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000544 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000545 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000546 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000547 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
548 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000549 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000550 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000551 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000552 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
553 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
554 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
555 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000556 Instructions.push_back(tmpInst);
557 }
558}
Jack Carter92995f12012-10-06 00:53:28 +0000559
Jack Carter543fdf82012-10-09 23:29:45 +0000560void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000561 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000562 MCInst tmpInst;
563 const MCOperand &ImmOp = Inst.getOperand(2);
564 assert(ImmOp.isImm() && "expected immediate operand kind");
565 const MCOperand &SrcRegOp = Inst.getOperand(1);
566 assert(SrcRegOp.isReg() && "expected register operand kind");
567 const MCOperand &DstRegOp = Inst.getOperand(0);
568 assert(DstRegOp.isReg() && "expected register operand kind");
569 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000570 if (-32768 <= ImmValue && ImmValue <= 65535) {
571 // For -32768 <= j <= 65535.
572 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000573 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000574 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
575 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
576 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
577 Instructions.push_back(tmpInst);
578 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000579 // For any other value of j that is representable as a 32-bit integer.
580 // la d,j(s) => lui d,hi16(j)
581 // ori d,d,lo16(j)
582 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000583 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000584 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
585 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
586 Instructions.push_back(tmpInst);
587 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000588 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000589 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
590 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
591 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
592 Instructions.push_back(tmpInst);
593 tmpInst.clear();
594 tmpInst.setOpcode(Mips::ADDu);
595 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
596 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
597 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
598 Instructions.push_back(tmpInst);
599 }
600}
601
602void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000603 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000604 MCInst tmpInst;
605 const MCOperand &ImmOp = Inst.getOperand(1);
606 assert(ImmOp.isImm() && "expected immediate operand kind");
607 const MCOperand &RegOp = Inst.getOperand(0);
608 assert(RegOp.isReg() && "expected register operand kind");
609 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000610 if (-32768 <= ImmValue && ImmValue <= 65535) {
611 // For -32768 <= j <= 65535.
612 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000613 tmpInst.setOpcode(Mips::ADDiu);
614 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000615 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000616 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
617 Instructions.push_back(tmpInst);
618 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000619 // For any other value of j that is representable as a 32-bit integer.
620 // la d,j => lui d,hi16(j)
621 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000622 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000623 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
624 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
625 Instructions.push_back(tmpInst);
626 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000627 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000628 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
629 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
630 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
631 Instructions.push_back(tmpInst);
632 }
633}
634
Jack Carter9e65aa32013-03-22 00:05:30 +0000635void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000636 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000637 const MCSymbolRefExpr *SR;
638 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000639 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000640 const MCExpr *ExprOffset;
641 unsigned TmpRegNum;
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000642 unsigned AtRegNum = getReg((isMips64()) ? Mips::GPR64RegClassID
643 : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +0000644 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000645 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
646 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000647 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000648 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
649 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000650 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000651 if (isImmOpnd) {
652 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
653 ImmOffset = Inst.getOperand(2).getImm();
654 LoOffset = ImmOffset & 0x0000ffff;
655 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000656 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000657 if (LoOffset & 0x8000)
658 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000659 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000660 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000661 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000662 TempInst.setLoc(IDLoc);
663 // 1st instruction in expansion is LUi. For load instruction we can use
664 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000665 // but for stores we must use $at.
666 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000667 TempInst.setOpcode(Mips::LUi);
668 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
669 if (isImmOpnd)
670 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
671 else {
672 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
673 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000674 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
675 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
676 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000677 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000678 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000679 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000680 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000681 }
682 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000683 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000684 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000685 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000686 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000687 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000688 TempInst.setOpcode(Mips::ADDu);
689 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
690 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
691 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
692 Instructions.push_back(TempInst);
693 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000694 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000695 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000696 TempInst.setOpcode(Inst.getOpcode());
697 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
698 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
699 if (isImmOpnd)
700 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
701 else {
702 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000703 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
704 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
705 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000706 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000707 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000708 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000709 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000710 }
711 }
712 Instructions.push_back(TempInst);
713 TempInst.clear();
714}
715
Rafael Espindola870c4e92012-01-11 03:56:41 +0000716bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000717MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000718 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000719 MCStreamer &Out, unsigned &ErrorInfo,
720 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000721 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000722 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000723 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000724 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000725
726 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000727 default:
728 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000729 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000730 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000731 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000732 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000733 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000734 return false;
735 }
736 case Match_MissingFeature:
737 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
738 return true;
739 case Match_InvalidOperand: {
740 SMLoc ErrorLoc = IDLoc;
741 if (ErrorInfo != ~0U) {
742 if (ErrorInfo >= Operands.size())
743 return Error(IDLoc, "too few operands for instruction");
744
Jack Carterd0bd6422013-04-18 00:41:53 +0000745 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
746 if (ErrorLoc == SMLoc())
747 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000748 }
749
750 return Error(ErrorLoc, "invalid operand for instruction");
751 }
752 case Match_MnemonicFail:
753 return Error(IDLoc, "invalid instruction");
754 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000755 return true;
756}
757
Jack Carter1ac53222013-02-20 23:11:17 +0000758int MipsAsmParser::matchCPURegisterName(StringRef Name) {
759 int CC;
760
761 if (Name == "at")
762 return getATReg();
763
764 CC = StringSwitch<unsigned>(Name)
765 .Case("zero", 0)
766 .Case("a0", 4)
767 .Case("a1", 5)
768 .Case("a2", 6)
769 .Case("a3", 7)
770 .Case("v0", 2)
771 .Case("v1", 3)
772 .Case("s0", 16)
773 .Case("s1", 17)
774 .Case("s2", 18)
775 .Case("s3", 19)
776 .Case("s4", 20)
777 .Case("s5", 21)
778 .Case("s6", 22)
779 .Case("s7", 23)
780 .Case("k0", 26)
781 .Case("k1", 27)
782 .Case("sp", 29)
783 .Case("fp", 30)
784 .Case("gp", 28)
785 .Case("ra", 31)
786 .Case("t0", 8)
787 .Case("t1", 9)
788 .Case("t2", 10)
789 .Case("t3", 11)
790 .Case("t4", 12)
791 .Case("t5", 13)
792 .Case("t6", 14)
793 .Case("t7", 15)
794 .Case("t8", 24)
795 .Case("t9", 25)
796 .Default(-1);
797
Jack Carterd0bd6422013-04-18 00:41:53 +0000798 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000799 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
800 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000801 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000802 CC += 4;
803
804 if (CC == -1 && isMips64())
805 CC = StringSwitch<unsigned>(Name)
806 .Case("a4", 8)
807 .Case("a5", 9)
808 .Case("a6", 10)
809 .Case("a7", 11)
810 .Case("kt0", 26)
811 .Case("kt1", 27)
812 .Case("s8", 30)
813 .Default(-1);
814
815 return CC;
816}
Jack Carterd0bd6422013-04-18 00:41:53 +0000817
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000818int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000819
Jack Cartera63b16a2012-09-07 00:23:42 +0000820 if (Name[0] == 'f') {
821 StringRef NumString = Name.substr(1);
822 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000823 if (NumString.getAsInteger(10, IntVal))
824 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000825 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +0000826 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000827 return IntVal;
828 }
829 return -1;
830}
Jack Cartera63b16a2012-09-07 00:23:42 +0000831
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000832int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
833
834 if (Name.startswith("fcc")) {
835 StringRef NumString = Name.substr(3);
836 unsigned IntVal;
837 if (NumString.getAsInteger(10, IntVal))
838 return -1; // This is not an integer.
839 if (IntVal > 7) // There are only 8 fcc registers.
840 return -1;
841 return IntVal;
842 }
843 return -1;
844}
845
846int MipsAsmParser::matchACRegisterName(StringRef Name) {
847
848 if (Name.startswith("acc")) {
849 StringRef NumString = Name.substr(3);
850 unsigned IntVal;
851 if (NumString.getAsInteger(10, IntVal))
852 return -1; // This is not an integer.
853 if (IntVal > 3) // There are only 3 acc registers.
854 return -1;
855 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +0000856 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000857 return -1;
858}
Jack Carterd0bd6422013-04-18 00:41:53 +0000859
Vladimir Medic8cd17102013-06-20 11:21:49 +0000860int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
861
Vladimir Medic8cd17102013-06-20 11:21:49 +0000862 int CC;
863 CC = matchCPURegisterName(Name);
864 if (CC != -1)
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000865 return matchRegisterByNumber(CC, is64BitReg ? Mips::GPR64RegClassID
866 : Mips::GPR32RegClassID);
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000867 CC= matchFPURegisterName(Name);
868 //TODO: decide about fpu register class
869 return matchRegisterByNumber(CC, isFP64() ? Mips::FGR64RegClassID
870 : Mips::FGR32RegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000871}
872
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000873int MipsAsmParser::regKindToRegClass(int RegKind) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000874
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000875 switch (RegKind) {
876 case MipsOperand::Kind_GPR32: return Mips::GPR32RegClassID;
877 case MipsOperand::Kind_GPR64: return Mips::GPR64RegClassID;
878 case MipsOperand::Kind_HWRegs: return Mips::HWRegsRegClassID;
879 case MipsOperand::Kind_FGR32Regs: return Mips::FGR32RegClassID;
880 case MipsOperand::Kind_FGR64Regs: return Mips::FGR64RegClassID;
881 case MipsOperand::Kind_AFGR64Regs: return Mips::AFGR64RegClassID;
882 case MipsOperand::Kind_CCRRegs: return Mips::CCRRegClassID;
883 case MipsOperand::Kind_ACC64DSP: return Mips::ACC64DSPRegClassID;
884 case MipsOperand::Kind_FCCRegs: return Mips::FCCRegClassID;
885 default :return -1;
886 }
Jack Cartera63b16a2012-09-07 00:23:42 +0000887
Jack Cartera63b16a2012-09-07 00:23:42 +0000888}
Jack Carterb4dbc172012-09-05 23:34:03 +0000889
Jack Carter0b744b32012-10-04 02:29:46 +0000890bool MipsAssemblerOptions::setATReg(unsigned Reg) {
891 if (Reg > 31)
892 return false;
893
894 aTReg = Reg;
895 return true;
896}
897
Jack Carter1ac53222013-02-20 23:11:17 +0000898int MipsAsmParser::getATReg() {
899 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000900}
901
Jack Carterd0bd6422013-04-18 00:41:53 +0000902unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000903 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +0000904}
905
Jack Carter873c7242013-01-12 01:03:14 +0000906int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000907 if (RegNum >
908 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs())
Jack Carterb4dbc172012-09-05 23:34:03 +0000909 return -1;
910
Jack Carter873c7242013-01-12 01:03:14 +0000911 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000912}
913
Jack Carter873c7242013-01-12 01:03:14 +0000914int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000915 const AsmToken &Tok = Parser.getTok();
916 int RegNum = -1;
917
918 if (Tok.is(AsmToken::Identifier)) {
919 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000920 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000921 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000922 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000923 is64BitReg ? Mips::GPR64RegClassID : Mips::GPR32RegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000924 return RegNum;
925}
926
Jack Carterd0bd6422013-04-18 00:41:53 +0000927bool MipsAsmParser::tryParseRegisterOperand(
928 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000929
930 SMLoc S = Parser.getTok().getLoc();
931 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000932
Jack Carter873c7242013-01-12 01:03:14 +0000933 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000934 if (RegNo == -1)
935 return true;
936
Jack Carter873c7242013-01-12 01:03:14 +0000937 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000938 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000939 Parser.Lex(); // Eat register token.
940 return false;
941}
942
943bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
944 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000945 // Check if the current operand has a custom associated parser, if so, try to
946 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000947 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
948 if (ResTy == MatchOperand_Success)
949 return false;
950 // If there wasn't a custom match, try the generic matcher below. Otherwise,
951 // there was a match, but an error occurred, in which case, just return that
952 // the operand parsing failed.
953 if (ResTy == MatchOperand_ParseFail)
954 return true;
955
956 switch (getLexer().getKind()) {
957 default:
958 Error(Parser.getTok().getLoc(), "unexpected token in operand");
959 return true;
960 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000961 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000962 SMLoc S = Parser.getTok().getLoc();
963 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000964 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000965 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000966 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000967 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000968 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000969 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000970 if (getLexer().isNot(AsmToken::Dollar))
971 return true;
972
Jack Carterd0bd6422013-04-18 00:41:53 +0000973 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000974 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000975 return true;
976
977 if (!getLexer().is(AsmToken::RParen))
978 return true;
979
980 S = Parser.getTok().getLoc();
981 Operands.push_back(MipsOperand::CreateToken(")", S));
982 Parser.Lex();
983 }
984 return false;
985 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000986 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000987 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000988 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000989 return true;
990
Jack Carter873c7242013-01-12 01:03:14 +0000991 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000992
Benjamin Kramerfa530572012-09-07 09:47:42 +0000993 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000994
Jack Carterd0bd6422013-04-18 00:41:53 +0000995 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000996 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000997 getContext());
998
999 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
1000 return false;
1001 }
1002 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +00001003 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +00001004 // we need to assigne the propper RegisterKind.
1005 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
1006 return false;
1007 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001008 case AsmToken::LParen:
1009 case AsmToken::Minus:
1010 case AsmToken::Plus:
1011 case AsmToken::Integer:
1012 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001013 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +00001014 const MCExpr *IdVal;
1015 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001016 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +00001017 return true;
Jack Carter873c7242013-01-12 01:03:14 +00001018 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001019 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1020 return false;
1021 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001022 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001023 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001024 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001025 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001026 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001027 return true;
1028
Jack Carter873c7242013-01-12 01:03:14 +00001029 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1030
Jack Carterdc1e35d2012-09-06 20:00:02 +00001031 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1032 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001033 } // case AsmToken::Percent
1034 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001035 return true;
1036}
1037
Jack Carterb5cf5902013-04-17 00:18:04 +00001038const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1039 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001040 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001041 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001042 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001043 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001044 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001045 short Val = MCE->getValue();
1046 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001047 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001048 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001049 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001050 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001051 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001052 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001053 if (LoSign)
1054 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001055 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001056 } else {
1057 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001058 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001059 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001060 }
1061
Jack Carterb5cf5902013-04-17 00:18:04 +00001062 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001063 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001064 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001065 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001066 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001067 return Res;
1068 }
1069
1070 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001071 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1072 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001073 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1074 return Res;
1075 }
1076
1077 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001078 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1079 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1080 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001081 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001082 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001083 return Expr;
1084}
1085
1086bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1087
1088 switch (Expr->getKind()) {
1089 case MCExpr::Constant:
1090 return true;
1091 case MCExpr::SymbolRef:
1092 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1093 case MCExpr::Binary:
1094 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1095 if (!isEvaluated(BE->getLHS()))
1096 return false;
1097 return isEvaluated(BE->getRHS());
1098 }
1099 case MCExpr::Unary:
1100 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1101 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001102 return false;
1103 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001104 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001105}
Jack Carterd0bd6422013-04-18 00:41:53 +00001106
Jack Carterb5cf5902013-04-17 00:18:04 +00001107bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001108 Parser.Lex(); // Eat the % token.
1109 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001110 if (Tok.isNot(AsmToken::Identifier))
1111 return true;
1112
1113 std::string Str = Tok.getIdentifier().str();
1114
Jack Carterd0bd6422013-04-18 00:41:53 +00001115 Parser.Lex(); // Eat the identifier.
1116 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001117 const MCExpr *IdVal;
1118 SMLoc EndLoc;
1119
1120 if (getLexer().getKind() == AsmToken::LParen) {
1121 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001122 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001123 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001124 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001125 const AsmToken &nextTok = Parser.getTok();
1126 if (nextTok.isNot(AsmToken::Identifier))
1127 return true;
1128 Str += "(%";
1129 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001130 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001131 if (getLexer().getKind() != AsmToken::LParen)
1132 return true;
1133 } else
1134 break;
1135 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001136 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001137 return true;
1138
1139 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001140 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001141
1142 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001143 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001144
Jack Carterd0bd6422013-04-18 00:41:53 +00001145 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001146 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001147}
1148
Jack Carterb4dbc172012-09-05 23:34:03 +00001149bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1150 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001151 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001152 RegNo = tryParseRegister(isMips64());
1153 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001154 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001155}
1156
Jack Carterb5cf5902013-04-17 00:18:04 +00001157bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001158 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001159 bool Result = true;
1160
1161 while (getLexer().getKind() == AsmToken::LParen)
1162 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001163
Jack Carterd0bd6422013-04-18 00:41:53 +00001164 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001165 default:
1166 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001167 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001168 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001169 case AsmToken::Integer:
1170 case AsmToken::Minus:
1171 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001172 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001173 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001174 else
1175 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001176 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001177 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001178 break;
Jack Carter873c7242013-01-12 01:03:14 +00001179 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001180 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001181 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001182 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001183}
1184
Jack Carterb4dbc172012-09-05 23:34:03 +00001185MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001186 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001187
1188 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001189 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001190 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001191 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001192 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001193 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001194
Jack Carterb5cf5902013-04-17 00:18:04 +00001195 if (getLexer().getKind() == AsmToken::LParen) {
1196 Parser.Lex();
1197 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001198 }
1199
Jack Carterb5cf5902013-04-17 00:18:04 +00001200 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001201 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001202 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001203
Jack Carterd0bd6422013-04-18 00:41:53 +00001204 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001205 if (Tok.isNot(AsmToken::LParen)) {
1206 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1207 if (Mnemonic->getToken() == "la") {
1208 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001209 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001210 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1211 return MatchOperand_Success;
1212 }
1213 if (Tok.is(AsmToken::EndOfStatement)) {
1214 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001215 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001216
Jack Carterd0bd6422013-04-18 00:41:53 +00001217 // Zero register assumed, add a memory operand with ZERO as its base.
1218 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1219 : Mips::ZERO,
1220 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001221 return MatchOperand_Success;
1222 }
1223 Error(Parser.getTok().getLoc(), "'(' expected");
1224 return MatchOperand_ParseFail;
1225 }
1226
Jack Carterd0bd6422013-04-18 00:41:53 +00001227 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001228 }
1229
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001230 Res = parseRegs(Operands, isMips64()? (int) MipsOperand::Kind_GPR64:
1231 (int) MipsOperand::Kind_GPR32);
1232 if (Res != MatchOperand_Success)
1233 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001234
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001235 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001236 Error(Parser.getTok().getLoc(), "')' expected");
1237 return MatchOperand_ParseFail;
1238 }
1239
Jack Carter873c7242013-01-12 01:03:14 +00001240 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1241
Jack Carterd0bd6422013-04-18 00:41:53 +00001242 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001243
1244 if (IdVal == 0)
1245 IdVal = MCConstantExpr::Create(0, getContext());
1246
Jack Carterd0bd6422013-04-18 00:41:53 +00001247 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001248 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1249 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001250 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001251 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001252 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001253 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1254 int64_t Imm;
1255 if (IdVal->EvaluateAsAbsolute(Imm))
1256 IdVal = MCConstantExpr::Create(Imm, getContext());
1257 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1258 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1259 getContext());
1260 }
1261
Jack Carterdc1e35d2012-09-06 20:00:02 +00001262 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1263 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001264 return MatchOperand_Success;
1265}
1266
Jack Carter873c7242013-01-12 01:03:14 +00001267MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +00001268MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1269 int RegKind) {
1270 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001271 if (getLexer().getKind() == AsmToken::Identifier
1272 && !hasConsumedDollar) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001273 if (searchSymbolAlias(Operands, Kind))
Jack Carterd76b2372013-03-21 21:44:16 +00001274 return MatchOperand_Success;
1275 return MatchOperand_NoMatch;
1276 }
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001277 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001278 // If the first token is not '$', we have an error.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001279 if (Parser.getTok().isNot(AsmToken::Dollar) && !hasConsumedDollar)
Jack Carter873c7242013-01-12 01:03:14 +00001280 return MatchOperand_NoMatch;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001281 if (!hasConsumedDollar) {
1282 Parser.Lex(); // Eat the '$'
1283 hasConsumedDollar = true;
1284 }
1285 if (getLexer().getKind() == AsmToken::Identifier) {
1286 int RegNum = -1;
1287 std::string RegName = Parser.getTok().getString().lower();
1288 // Match register by name
1289 switch (RegKind) {
1290 case MipsOperand::Kind_GPR32:
1291 case MipsOperand::Kind_GPR64:
1292 RegNum = matchCPURegisterName(RegName);
1293 break;
1294 case MipsOperand::Kind_AFGR64Regs:
1295 case MipsOperand::Kind_FGR64Regs:
1296 case MipsOperand::Kind_FGR32Regs:
1297 RegNum = matchFPURegisterName(RegName);
1298 if (RegKind == MipsOperand::Kind_AFGR64Regs)
1299 RegNum /= 2;
1300 break;
1301 case MipsOperand::Kind_FCCRegs:
1302 RegNum = matchFCCRegisterName(RegName);
1303 break;
1304 case MipsOperand::Kind_ACC64DSP:
1305 RegNum = matchACRegisterName(RegName);
1306 break;
1307 default: break; // No match, value is set to -1.
1308 }
1309 // No match found, return _NoMatch to give a chance to other round.
1310 if (RegNum < 0)
1311 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001312
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001313 int RegVal = getReg(regKindToRegClass(Kind), RegNum);
1314 if (RegVal == -1)
1315 return MatchOperand_NoMatch;
1316
1317 MipsOperand *Op = MipsOperand::CreateReg(RegVal, S,
1318 Parser.getTok().getLoc());
1319 Op->setRegKind(Kind);
1320 Operands.push_back(Op);
1321 hasConsumedDollar = false;
1322 Parser.Lex(); // Eat the register name.
1323 if ((RegKind == MipsOperand::Kind_GPR32)
1324 && (getLexer().is(AsmToken::LParen))) {
1325 // Check if it is indexed addressing operand.
1326 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1327 Parser.Lex(); // Eat the parenthesis.
1328 if (parseRegs(Operands,RegKind) != MatchOperand_Success)
1329 return MatchOperand_NoMatch;
1330 if (getLexer().isNot(AsmToken::RParen))
1331 return MatchOperand_NoMatch;
1332 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1333 Parser.Lex();
1334 }
1335 return MatchOperand_Success;
1336 } else if (getLexer().getKind() == AsmToken::Integer) {
1337 unsigned RegNum = Parser.getTok().getIntVal();
1338 if (Kind == MipsOperand::Kind_HWRegs) {
1339 if (RegNum != 29)
1340 return MatchOperand_NoMatch;
1341 // Only hwreg 29 is supported, found at index 0.
1342 RegNum = 0;
1343 }
1344 int Reg = matchRegisterByNumber(RegNum, regKindToRegClass(Kind));
1345 if (Reg == -1)
1346 return MatchOperand_NoMatch;
1347 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1348 Op->setRegKind(Kind);
1349 Operands.push_back(Op);
1350 hasConsumedDollar = false;
1351 Parser.Lex(); // Eat the register number.
1352 if ((RegKind == MipsOperand::Kind_GPR32)
Vladimir Medic3467b902013-07-18 09:28:35 +00001353 && (getLexer().is(AsmToken::LParen))) {
1354 // Check if it is indexed addressing operand.
1355 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1356 Parser.Lex(); // Eat the parenthesis.
1357 if (parseRegs(Operands,RegKind) != MatchOperand_Success)
1358 return MatchOperand_NoMatch;
1359 if (getLexer().isNot(AsmToken::RParen))
1360 return MatchOperand_NoMatch;
1361 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1362 Parser.Lex();
1363 }
Jack Carter873c7242013-01-12 01:03:14 +00001364 return MatchOperand_Success;
1365 }
1366 return MatchOperand_NoMatch;
1367}
Vladimir Medic64828a12013-07-16 10:07:14 +00001368
Vladimir Medic8cd17102013-06-20 11:21:49 +00001369MipsAsmParser::OperandMatchResultTy
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001370MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001371
1372 if (!isMips64())
1373 return MatchOperand_NoMatch;
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001374 return parseRegs(Operands, (int) MipsOperand::Kind_GPR64);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001375}
1376
1377MipsAsmParser::OperandMatchResultTy
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001378MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1379 return parseRegs(Operands, (int) MipsOperand::Kind_GPR32);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001380}
Jack Carter873c7242013-01-12 01:03:14 +00001381
Vladimir Medic233dd512013-06-24 10:05:34 +00001382MipsAsmParser::OperandMatchResultTy
1383MipsAsmParser::parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1384
1385 if (isFP64())
1386 return MatchOperand_NoMatch;
Vladimir Medic233dd512013-06-24 10:05:34 +00001387 return parseRegs(Operands, (int) MipsOperand::Kind_AFGR64Regs);
1388}
1389
1390MipsAsmParser::OperandMatchResultTy
1391MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1392 if (!isFP64())
1393 return MatchOperand_NoMatch;
Vladimir Medic233dd512013-06-24 10:05:34 +00001394 return parseRegs(Operands, (int) MipsOperand::Kind_FGR64Regs);
1395}
1396
1397MipsAsmParser::OperandMatchResultTy
1398MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic233dd512013-06-24 10:05:34 +00001399 return parseRegs(Operands, (int) MipsOperand::Kind_FGR32Regs);
1400}
1401
Vladimir Medic643b3982013-07-30 10:12:14 +00001402MipsAsmParser::OperandMatchResultTy
1403MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001404 return parseRegs(Operands, (int) MipsOperand::Kind_FCCRegs);
Vladimir Medic643b3982013-07-30 10:12:14 +00001405}
1406
Akira Hatanaka34a32c02013-08-06 22:20:40 +00001407MipsAsmParser::OperandMatchResultTy
Akira Hatanaka00fcf2e2013-08-08 21:54:26 +00001408MipsAsmParser::parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001409 return parseRegs(Operands, (int) MipsOperand::Kind_ACC64DSP);
Akira Hatanaka34a32c02013-08-06 22:20:40 +00001410}
1411
Jack Carterd0bd6422013-04-18 00:41:53 +00001412bool MipsAsmParser::searchSymbolAlias(
Vladimir Medic8cd17102013-06-20 11:21:49 +00001413 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001414
1415 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1416 if (Sym) {
1417 SMLoc S = Parser.getTok().getLoc();
1418 const MCExpr *Expr;
1419 if (Sym->isVariable())
1420 Expr = Sym->getVariableValue();
1421 else
1422 return false;
1423 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001424 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind) RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001425 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1426 const StringRef DefSymbol = Ref->getSymbol().getName();
1427 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00001428 int RegNum = -1;
1429 APInt IntVal(32, -1);
1430 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
1431 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
Vladimir Medic64828a12013-07-16 10:07:14 +00001432 isMips64()
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001433 ? Mips::GPR64RegClassID
1434 : Mips::GPR32RegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001435 else {
1436 // Lookup for the register with the corresponding name.
1437 switch (Kind) {
1438 case MipsOperand::Kind_AFGR64Regs:
1439 case MipsOperand::Kind_FGR64Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001440 RegNum = matchFPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00001441 break;
1442 case MipsOperand::Kind_FGR32Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001443 RegNum = matchFPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00001444 break;
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001445 case MipsOperand::Kind_GPR64:
1446 case MipsOperand::Kind_GPR32:
Vladimir Medic8cd17102013-06-20 11:21:49 +00001447 default:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001448 RegNum = matchCPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00001449 break;
1450 }
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001451 if (RegNum > -1)
1452 RegNum = getReg(regKindToRegClass(Kind), RegNum);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001453 }
Jack Carterd76b2372013-03-21 21:44:16 +00001454 if (RegNum > -1) {
1455 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001456 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1457 Parser.getTok().getLoc());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001458 op->setRegKind(Kind);
Jack Carterd76b2372013-03-21 21:44:16 +00001459 Operands.push_back(op);
1460 return true;
1461 }
1462 }
1463 } else if (Expr->getKind() == MCExpr::Constant) {
1464 Parser.Lex();
1465 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001466 MipsOperand *op = MipsOperand::CreateImm(Const, S,
Vladimir Medic64828a12013-07-16 10:07:14 +00001467 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001468 Operands.push_back(op);
1469 return true;
1470 }
1471 }
1472 return false;
1473}
Jack Carterd0bd6422013-04-18 00:41:53 +00001474
Jack Carter873c7242013-01-12 01:03:14 +00001475MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +00001476MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001477 return parseRegs(Operands, (int) MipsOperand::Kind_HWRegs);
Jack Carter873c7242013-01-12 01:03:14 +00001478}
1479
1480MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +00001481MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001482 return parseRegs(Operands, (int) MipsOperand::Kind_CCRRegs);
Jack Carter873c7242013-01-12 01:03:14 +00001483}
1484
Jack Carterdc1e35d2012-09-06 20:00:02 +00001485MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1486
1487 MCSymbolRefExpr::VariantKind VK
1488 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1489 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1490 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1491 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1492 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1493 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1494 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1495 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1496 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1497 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1498 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1499 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1500 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1501 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1502 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1503 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1504 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1505 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1506 .Default(MCSymbolRefExpr::VK_None);
1507
1508 return VK;
1509}
Jack Cartera63b16a2012-09-07 00:23:42 +00001510
Rafael Espindola870c4e92012-01-11 03:56:41 +00001511bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001512ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001513 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic74593e62013-07-17 15:00:42 +00001514 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00001515 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00001516 Parser.eatToEndOfStatement();
1517 return Error(NameLoc, "Unknown instruction");
1518 }
Vladimir Medic64828a12013-07-16 10:07:14 +00001519 // First operand in MCInst is instruction mnemonic.
1520 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterb4dbc172012-09-05 23:34:03 +00001521
1522 // Read the remaining operands.
1523 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1524 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00001525 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001526 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001527 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001528 return Error(Loc, "unexpected token in argument list");
1529 }
1530
Jack Carterd0bd6422013-04-18 00:41:53 +00001531 while (getLexer().is(AsmToken::Comma)) {
1532 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001533 // Parse and remember the operand.
1534 if (ParseOperand(Operands, Name)) {
1535 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001536 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001537 return Error(Loc, "unexpected token in argument list");
1538 }
1539 }
1540 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001541 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1542 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001543 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001544 return Error(Loc, "unexpected token in argument list");
1545 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001546 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001547 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001548}
1549
Jack Carter0b744b32012-10-04 02:29:46 +00001550bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001551 SMLoc Loc = getLexer().getLoc();
1552 Parser.eatToEndOfStatement();
1553 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001554}
1555
1556bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001557 // Line should look like: ".set noat".
1558 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001559 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001560 // eat noat
1561 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001562 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001563 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1564 reportParseError("unexpected token in statement");
1565 return false;
1566 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001567 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001568 return false;
1569}
Jack Carterd0bd6422013-04-18 00:41:53 +00001570
Jack Carter0b744b32012-10-04 02:29:46 +00001571bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001572 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001573 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001574 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001575 getParser().Lex();
1576 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001577 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001578 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001579 return false;
1580 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001581 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001582 if (getLexer().isNot(AsmToken::Dollar)) {
1583 reportParseError("unexpected token in statement");
1584 return false;
1585 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001586 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001587 const AsmToken &Reg = Parser.getTok();
1588 if (Reg.is(AsmToken::Identifier)) {
1589 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1590 } else if (Reg.is(AsmToken::Integer)) {
1591 AtRegNo = Reg.getIntVal();
1592 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001593 reportParseError("unexpected token in statement");
1594 return false;
1595 }
Jack Carter1ac53222013-02-20 23:11:17 +00001596
Jack Carterd0bd6422013-04-18 00:41:53 +00001597 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001598 reportParseError("unexpected token in statement");
1599 return false;
1600 }
1601
1602 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001603 reportParseError("unexpected token in statement");
1604 return false;
1605 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001606 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001607
1608 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1609 reportParseError("unexpected token in statement");
1610 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001611 }
1612 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001613 return false;
1614 } else {
1615 reportParseError("unexpected token in statement");
1616 return false;
1617 }
1618}
1619
1620bool MipsAsmParser::parseSetReorderDirective() {
1621 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001622 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001623 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1624 reportParseError("unexpected token in statement");
1625 return false;
1626 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001627 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001628 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001629 return false;
1630}
1631
1632bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001633 Parser.Lex();
1634 // If this is not the end of the statement, report an error.
1635 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1636 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001637 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001638 }
1639 Options.setNoreorder();
1640 Parser.Lex(); // Consume the EndOfStatement.
1641 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001642}
1643
1644bool MipsAsmParser::parseSetMacroDirective() {
1645 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001646 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001647 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1648 reportParseError("unexpected token in statement");
1649 return false;
1650 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001651 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001652 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001653 return false;
1654}
1655
1656bool MipsAsmParser::parseSetNoMacroDirective() {
1657 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001658 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001659 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1660 reportParseError("`noreorder' must be set before `nomacro'");
1661 return false;
1662 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001663 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001664 reportParseError("`noreorder' must be set before `nomacro'");
1665 return false;
1666 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001667 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001668 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001669 return false;
1670}
Jack Carterd76b2372013-03-21 21:44:16 +00001671
1672bool MipsAsmParser::parseSetAssignment() {
1673 StringRef Name;
1674 const MCExpr *Value;
1675
1676 if (Parser.parseIdentifier(Name))
1677 reportParseError("expected identifier after .set");
1678
1679 if (getLexer().isNot(AsmToken::Comma))
1680 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001681 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001682
Jack Carter02593002013-05-28 22:21:05 +00001683 if (getLexer().is(AsmToken::Dollar)) {
1684 MCSymbol *Symbol;
1685 SMLoc DollarLoc = getLexer().getLoc();
1686 // Consume the dollar sign, and check for a following identifier.
1687 Parser.Lex();
1688 // We have a '$' followed by something, make sure they are adjacent.
1689 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
1690 return true;
1691 StringRef Res = StringRef(DollarLoc.getPointer(),
1692 getTok().getEndLoc().getPointer() - DollarLoc.getPointer());
1693 Symbol = getContext().GetOrCreateSymbol(Res);
1694 Parser.Lex();
1695 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
1696 getContext());
1697 } else if (Parser.parseExpression(Value))
1698 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00001699
Jack Carterd0bd6422013-04-18 00:41:53 +00001700 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001701 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001702 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001703 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001704 Sym = getContext().GetOrCreateSymbol(Name);
1705 Sym->setVariableValue(Value);
1706
1707 return false;
1708}
Jack Carterd0bd6422013-04-18 00:41:53 +00001709
Jack Carter0b744b32012-10-04 02:29:46 +00001710bool MipsAsmParser::parseDirectiveSet() {
1711
Jack Carterd0bd6422013-04-18 00:41:53 +00001712 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001713 const AsmToken &Tok = Parser.getTok();
1714
1715 if (Tok.getString() == "noat") {
1716 return parseSetNoAtDirective();
1717 } else if (Tok.getString() == "at") {
1718 return parseSetAtDirective();
1719 } else if (Tok.getString() == "reorder") {
1720 return parseSetReorderDirective();
1721 } else if (Tok.getString() == "noreorder") {
1722 return parseSetNoReorderDirective();
1723 } else if (Tok.getString() == "macro") {
1724 return parseSetMacroDirective();
1725 } else if (Tok.getString() == "nomacro") {
1726 return parseSetNoMacroDirective();
1727 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001729 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001730 return false;
1731 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001732 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001733 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001734 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001735 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001736 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001737 parseSetAssignment();
1738 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001739 }
Jack Carter07c818d2013-01-25 01:31:34 +00001740
Jack Carter0b744b32012-10-04 02:29:46 +00001741 return true;
1742}
1743
Jack Carter07c818d2013-01-25 01:31:34 +00001744/// parseDirectiveWord
1745/// ::= .word [ expression (, expression)* ]
1746bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1747 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1748 for (;;) {
1749 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001750 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001751 return true;
1752
1753 getParser().getStreamer().EmitValue(Value, Size);
1754
1755 if (getLexer().is(AsmToken::EndOfStatement))
1756 break;
1757
1758 // FIXME: Improve diagnostic.
1759 if (getLexer().isNot(AsmToken::Comma))
1760 return Error(L, "unexpected token in directive");
1761 Parser.Lex();
1762 }
1763 }
1764
1765 Parser.Lex();
1766 return false;
1767}
1768
Jack Carter0b744b32012-10-04 02:29:46 +00001769bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001770
Jack Carter07c818d2013-01-25 01:31:34 +00001771 StringRef IDVal = DirectiveID.getString();
1772
Jack Carterd0bd6422013-04-18 00:41:53 +00001773 if (IDVal == ".ent") {
1774 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001775 Parser.Lex();
1776 return false;
1777 }
1778
Jack Carter07c818d2013-01-25 01:31:34 +00001779 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001781 Parser.Lex();
1782 return false;
1783 }
1784
Jack Carter07c818d2013-01-25 01:31:34 +00001785 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001786 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001787 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001788 return false;
1789 }
1790
Jack Carter07c818d2013-01-25 01:31:34 +00001791 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001792 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001793 }
1794
Jack Carter07c818d2013-01-25 01:31:34 +00001795 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001796 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001797 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001798 return false;
1799 }
1800
Jack Carter07c818d2013-01-25 01:31:34 +00001801 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001802 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001803 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001804 return false;
1805 }
1806
Jack Carter07c818d2013-01-25 01:31:34 +00001807 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001808 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001809 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001810 return false;
1811 }
1812
Jack Carter07c818d2013-01-25 01:31:34 +00001813 if (IDVal == ".word") {
1814 parseDirectiveWord(4, DirectiveID.getLoc());
1815 return false;
1816 }
1817
Rafael Espindola870c4e92012-01-11 03:56:41 +00001818 return true;
1819}
1820
Rafael Espindola870c4e92012-01-11 03:56:41 +00001821extern "C" void LLVMInitializeMipsAsmParser() {
1822 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1823 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1824 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1825 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1826}
Jack Carterb4dbc172012-09-05 23:34:03 +00001827
1828#define GET_REGISTER_MATCHER
1829#define GET_MATCHER_IMPLEMENTATION
1830#include "MipsGenAsmMatcher.inc"