blob: 7e7b39bb5aa5ad20e0b537d9743e08cf3705830f [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;
Jack Carter0b744b32012-10-04 02:29:46 +000066
Akira Hatanaka7605630c2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Chad Rosier49963552012-10-13 00:26:04 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +000071 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000072 MCStreamer &Out, unsigned &ErrorInfo,
73 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000074
75 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
76
Chad Rosierf0e87202012-10-25 20:41:34 +000077 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
78 SMLoc NameLoc,
Akira Hatanaka7605630c2012-08-17 20:16:42 +000079 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000080
81 bool ParseDirective(AsmToken DirectiveID);
82
Jack Carterb4dbc172012-09-05 23:34:03 +000083 MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +000084 parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
85 int RegKind);
Vladimir Medic64828a12013-07-16 10:07:14 +000086
87 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +000088 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
89
90 MipsAsmParser::OperandMatchResultTy
91 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
92
93 MipsAsmParser::OperandMatchResultTy
94 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
95
96 MipsAsmParser::OperandMatchResultTy
97 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
98
99 MipsAsmParser::OperandMatchResultTy
100 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
101
102 MipsAsmParser::OperandMatchResultTy
103 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000104
Vladimir Medic233dd512013-06-24 10:05:34 +0000105 MipsAsmParser::OperandMatchResultTy
106 parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
107
108 MipsAsmParser::OperandMatchResultTy
109 parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
110
111 MipsAsmParser::OperandMatchResultTy
112 parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
113
Vladimir Medic643b3982013-07-30 10:12:14 +0000114 MipsAsmParser::OperandMatchResultTy
115 parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
116
Jack Carterd76b2372013-03-21 21:44:16 +0000117 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +0000118 unsigned RegKind);
Jack Carterd76b2372013-03-21 21:44:16 +0000119
Jack Carterb4dbc172012-09-05 23:34:03 +0000120 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
121 StringRef Mnemonic);
122
Jack Carter873c7242013-01-12 01:03:14 +0000123 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000124
125 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000126 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000127
Jack Carter30a59822012-10-04 04:03:53 +0000128 bool needsExpansion(MCInst &Inst);
129
130 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000131 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000132 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000133 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000134 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
135 SmallVectorImpl<MCInst> &Instructions);
136 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
137 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000138 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
139 SmallVectorImpl<MCInst> &Instructions,
140 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000141 bool reportParseError(StringRef ErrorMsg);
142
Jack Carterb5cf5902013-04-17 00:18:04 +0000143 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000144 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000145
Jack Carterb5cf5902013-04-17 00:18:04 +0000146 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
147
148 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000149 bool parseDirectiveSet();
150
151 bool parseSetAtDirective();
152 bool parseSetNoAtDirective();
153 bool parseSetMacroDirective();
154 bool parseSetNoMacroDirective();
155 bool parseSetReorderDirective();
156 bool parseSetNoReorderDirective();
157
Jack Carterd76b2372013-03-21 21:44:16 +0000158 bool parseSetAssignment();
159
Jack Carter07c818d2013-01-25 01:31:34 +0000160 bool parseDirectiveWord(unsigned Size, SMLoc L);
161
Jack Carterdc1e35d2012-09-06 20:00:02 +0000162 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000163
Jack Carterb4dbc172012-09-05 23:34:03 +0000164 bool isMips64() const {
165 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
166 }
167
Jack Cartera63b16a2012-09-07 00:23:42 +0000168 bool isFP64() const {
169 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
170 }
171
Jack Carter873c7242013-01-12 01:03:14 +0000172 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000173
Jack Carter1ac53222013-02-20 23:11:17 +0000174 int matchCPURegisterName(StringRef Symbol);
175
Jack Carter873c7242013-01-12 01:03:14 +0000176 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000177
Vladimir Medic8cd17102013-06-20 11:21:49 +0000178 int matchFPURegisterName(StringRef Name, FpFormatTy Format);
179
Jack Cartera63b16a2012-09-07 00:23:42 +0000180 void setFpFormat(FpFormatTy Format) {
181 FpFormat = Format;
182 }
183
184 void setDefaultFpFormat();
185
186 void setFpFormat(StringRef Format);
187
188 FpFormatTy getFpFormat() {return FpFormat;}
189
Jack Carterd0bd6422013-04-18 00:41:53 +0000190 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000191
Jack Carter1ac53222013-02-20 23:11:17 +0000192 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000193
194 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
195 SmallVectorImpl<MCInst> &Instructions);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000196public:
197 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000198 : MCTargetAsmParser(), STI(sti), Parser(parser) {
199 // Initialize the set of available features.
200 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000201 }
202
Jack Carterb4dbc172012-09-05 23:34:03 +0000203 MCAsmParser &getParser() const { return Parser; }
204 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
205
Rafael Espindola870c4e92012-01-11 03:56:41 +0000206};
207}
208
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000209namespace {
210
211/// MipsOperand - Instances of this class represent a parsed Mips machine
212/// instruction.
213class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000214
Jack Carter873c7242013-01-12 01:03:14 +0000215public:
216 enum RegisterKind {
217 Kind_None,
218 Kind_CPURegs,
219 Kind_CPU64Regs,
220 Kind_HWRegs,
221 Kind_HW64Regs,
222 Kind_FGR32Regs,
223 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000224 Kind_AFGR64Regs,
Vladimir Medic643b3982013-07-30 10:12:14 +0000225 Kind_CCRRegs,
226 Kind_FCCRegs
Jack Carter873c7242013-01-12 01:03:14 +0000227 };
228
229private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000230 enum KindTy {
231 k_CondCode,
232 k_CoprocNum,
233 k_Immediate,
234 k_Memory,
235 k_PostIndexRegister,
236 k_Register,
237 k_Token
238 } Kind;
239
240 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000241
Eric Christopher8996c5d2013-03-15 00:42:55 +0000242 struct Token {
243 const char *Data;
244 unsigned Length;
245 };
246
247 struct RegOp {
248 unsigned RegNum;
249 RegisterKind Kind;
250 };
251
252 struct ImmOp {
253 const MCExpr *Val;
254 };
255
256 struct MemOp {
257 unsigned Base;
258 const MCExpr *Off;
259 };
260
Jack Carterb4dbc172012-09-05 23:34:03 +0000261 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000262 struct Token Tok;
263 struct RegOp Reg;
264 struct ImmOp Imm;
265 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000266 };
267
268 SMLoc StartLoc, EndLoc;
269
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000270public:
271 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000272 assert(N == 1 && "Invalid number of operands!");
273 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000274 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000275
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000276 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000277 // Add as immediate when possible. Null MCExpr = 0.
278 if (Expr == 0)
279 Inst.addOperand(MCOperand::CreateImm(0));
280 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
281 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
282 else
283 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000284 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000285
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000286 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000287 assert(N == 1 && "Invalid number of operands!");
288 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000289 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000290 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000291
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000292 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000293 assert(N == 2 && "Invalid number of operands!");
294
295 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
296
297 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000298 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000299 }
300
301 bool isReg() const { return Kind == k_Register; }
302 bool isImm() const { return Kind == k_Immediate; }
303 bool isToken() const { return Kind == k_Token; }
304 bool isMem() const { return Kind == k_Memory; }
305
306 StringRef getToken() const {
307 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000308 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000309 }
310
311 unsigned getReg() const {
312 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000313 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000314 }
315
Jack Carter873c7242013-01-12 01:03:14 +0000316 void setRegKind(RegisterKind RegKind) {
317 assert((Kind == k_Register) && "Invalid access!");
318 Reg.Kind = RegKind;
319 }
320
Jack Carterb4dbc172012-09-05 23:34:03 +0000321 const MCExpr *getImm() const {
322 assert((Kind == k_Immediate) && "Invalid access!");
323 return Imm.Val;
324 }
325
Jack Carterdc1e35d2012-09-06 20:00:02 +0000326 unsigned getMemBase() const {
327 assert((Kind == k_Memory) && "Invalid access!");
328 return Mem.Base;
329 }
330
331 const MCExpr *getMemOff() const {
332 assert((Kind == k_Memory) && "Invalid access!");
333 return Mem.Off;
334 }
335
Jack Carterb4dbc172012-09-05 23:34:03 +0000336 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
337 MipsOperand *Op = new MipsOperand(k_Token);
338 Op->Tok.Data = Str.data();
339 Op->Tok.Length = Str.size();
340 Op->StartLoc = S;
341 Op->EndLoc = S;
342 return Op;
343 }
344
345 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
346 MipsOperand *Op = new MipsOperand(k_Register);
347 Op->Reg.RegNum = RegNum;
348 Op->StartLoc = S;
349 Op->EndLoc = E;
350 return Op;
351 }
352
353 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
354 MipsOperand *Op = new MipsOperand(k_Immediate);
355 Op->Imm.Val = Val;
356 Op->StartLoc = S;
357 Op->EndLoc = E;
358 return Op;
359 }
360
Jack Carterdc1e35d2012-09-06 20:00:02 +0000361 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
362 SMLoc S, SMLoc E) {
363 MipsOperand *Op = new MipsOperand(k_Memory);
364 Op->Mem.Base = Base;
365 Op->Mem.Off = Off;
366 Op->StartLoc = S;
367 Op->EndLoc = E;
368 return Op;
369 }
370
Jack Carter873c7242013-01-12 01:03:14 +0000371 bool isCPURegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000372 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carter873c7242013-01-12 01:03:14 +0000373 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000374 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000375 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
376 }
377
378 bool isCPU64RegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000379 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carter873c7242013-01-12 01:03:14 +0000380 }
Jack Carter873c7242013-01-12 01:03:14 +0000381
382 bool isHWRegsAsm() const {
383 assert((Kind == k_Register) && "Invalid access!");
384 return Reg.Kind == Kind_HWRegs;
385 }
Jack Carter873c7242013-01-12 01:03:14 +0000386
387 bool isHW64RegsAsm() const {
388 assert((Kind == k_Register) && "Invalid access!");
389 return Reg.Kind == Kind_HW64Regs;
390 }
Jack Carter873c7242013-01-12 01:03:14 +0000391
392 bool isCCRAsm() const {
393 assert((Kind == k_Register) && "Invalid access!");
394 return Reg.Kind == Kind_CCRRegs;
395 }
396
Vladimir Medic233dd512013-06-24 10:05:34 +0000397 bool isAFGR64Asm() const {
398 return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
399 }
400
401 bool isFGR64Asm() const {
402 return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
403 }
404
405 bool isFGR32Asm() const {
406 return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
407 }
408
Vladimir Medic643b3982013-07-30 10:12:14 +0000409 bool isFCCRegsAsm() const {
410 return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs;
411 }
412
Jack Carterb4dbc172012-09-05 23:34:03 +0000413 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000414 SMLoc getStartLoc() const {
415 return StartLoc;
416 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000417 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000418 SMLoc getEndLoc() const {
419 return EndLoc;
420 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000421
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000422 virtual void print(raw_ostream &OS) const {
423 llvm_unreachable("unimplemented!");
424 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000425}; // class MipsOperand
426} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000427
Jack Carter9e65aa32013-03-22 00:05:30 +0000428namespace llvm {
429extern const MCInstrDesc MipsInsts[];
430}
431static const MCInstrDesc &getInstDesc(unsigned Opcode) {
432 return MipsInsts[Opcode];
433}
434
435bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000436 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000437 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
438 Inst.setLoc(IDLoc);
Jack Carterc15c1d22013-04-25 23:31:35 +0000439 if (MCID.hasDelaySlot() && Options.isReorder()) {
440 // If this instruction has a delay slot and .set reorder is active,
441 // emit a NOP after it.
442 Instructions.push_back(Inst);
443 MCInst NopInst;
444 NopInst.setOpcode(Mips::SLL);
445 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
446 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
447 NopInst.addOperand(MCOperand::CreateImm(0));
448 Instructions.push_back(NopInst);
449 return false;
450 }
451
Jack Carter9e65aa32013-03-22 00:05:30 +0000452 if (MCID.mayLoad() || MCID.mayStore()) {
453 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000454 // reference or immediate we may have to expand instructions.
455 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000456 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000457 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
458 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000459 MCOperand &Op = Inst.getOperand(i);
460 if (Op.isImm()) {
461 int MemOffset = Op.getImm();
462 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000463 // Offset can't exceed 16bit value.
464 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000465 return false;
466 }
467 } else if (Op.isExpr()) {
468 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000469 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000470 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000471 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000472 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000473 // Expand symbol.
474 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000475 return false;
476 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000477 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000478 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000479 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000480 }
481 }
482 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000483 } // for
484 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000485
486 if (needsExpansion(Inst))
487 expandInstruction(Inst, IDLoc, Instructions);
488 else
489 Instructions.push_back(Inst);
490
491 return false;
492}
493
Jack Carter30a59822012-10-04 04:03:53 +0000494bool MipsAsmParser::needsExpansion(MCInst &Inst) {
495
Jack Carterd0bd6422013-04-18 00:41:53 +0000496 switch (Inst.getOpcode()) {
497 case Mips::LoadImm32Reg:
498 case Mips::LoadAddr32Imm:
499 case Mips::LoadAddr32Reg:
500 return true;
501 default:
502 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000503 }
504}
Jack Carter92995f12012-10-06 00:53:28 +0000505
Jack Carter30a59822012-10-04 04:03:53 +0000506void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000507 SmallVectorImpl<MCInst> &Instructions) {
508 switch (Inst.getOpcode()) {
509 case Mips::LoadImm32Reg:
510 return expandLoadImm(Inst, IDLoc, Instructions);
511 case Mips::LoadAddr32Imm:
512 return expandLoadAddressImm(Inst, IDLoc, Instructions);
513 case Mips::LoadAddr32Reg:
514 return expandLoadAddressReg(Inst, IDLoc, Instructions);
515 }
Jack Carter30a59822012-10-04 04:03:53 +0000516}
Jack Carter92995f12012-10-06 00:53:28 +0000517
Jack Carter30a59822012-10-04 04:03:53 +0000518void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000519 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000520 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000521 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000522 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000523 const MCOperand &RegOp = Inst.getOperand(0);
524 assert(RegOp.isReg() && "expected register operand kind");
525
526 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000527 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000528 if (0 <= ImmValue && ImmValue <= 65535) {
529 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000530 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000531 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000532 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000533 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000534 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000535 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000536 } else if (ImmValue < 0 && ImmValue >= -32768) {
537 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000538 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000539 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000540 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000541 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000542 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000543 Instructions.push_back(tmpInst);
544 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000545 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000546 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000547 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000548 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000549 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
550 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000551 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000552 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000553 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000554 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
555 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
556 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
557 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000558 Instructions.push_back(tmpInst);
559 }
560}
Jack Carter92995f12012-10-06 00:53:28 +0000561
Jack Carter543fdf82012-10-09 23:29:45 +0000562void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000563 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000564 MCInst tmpInst;
565 const MCOperand &ImmOp = Inst.getOperand(2);
566 assert(ImmOp.isImm() && "expected immediate operand kind");
567 const MCOperand &SrcRegOp = Inst.getOperand(1);
568 assert(SrcRegOp.isReg() && "expected register operand kind");
569 const MCOperand &DstRegOp = Inst.getOperand(0);
570 assert(DstRegOp.isReg() && "expected register operand kind");
571 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000572 if (-32768 <= ImmValue && ImmValue <= 65535) {
573 // For -32768 <= j <= 65535.
574 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000575 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000576 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
577 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
578 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
579 Instructions.push_back(tmpInst);
580 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000581 // For any other value of j that is representable as a 32-bit integer.
582 // la d,j(s) => lui d,hi16(j)
583 // ori d,d,lo16(j)
584 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000585 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000586 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
587 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
588 Instructions.push_back(tmpInst);
589 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000590 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000591 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
592 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
593 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
594 Instructions.push_back(tmpInst);
595 tmpInst.clear();
596 tmpInst.setOpcode(Mips::ADDu);
597 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
598 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
599 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
600 Instructions.push_back(tmpInst);
601 }
602}
603
604void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000605 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000606 MCInst tmpInst;
607 const MCOperand &ImmOp = Inst.getOperand(1);
608 assert(ImmOp.isImm() && "expected immediate operand kind");
609 const MCOperand &RegOp = Inst.getOperand(0);
610 assert(RegOp.isReg() && "expected register operand kind");
611 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000612 if (-32768 <= ImmValue && ImmValue <= 65535) {
613 // For -32768 <= j <= 65535.
614 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000615 tmpInst.setOpcode(Mips::ADDiu);
616 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000617 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000618 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
619 Instructions.push_back(tmpInst);
620 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000621 // For any other value of j that is representable as a 32-bit integer.
622 // la d,j => lui d,hi16(j)
623 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000624 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000625 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
626 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
627 Instructions.push_back(tmpInst);
628 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000629 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000630 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
631 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
632 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
633 Instructions.push_back(tmpInst);
634 }
635}
636
Jack Carter9e65aa32013-03-22 00:05:30 +0000637void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000638 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000639 const MCSymbolRefExpr *SR;
640 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000641 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000642 const MCExpr *ExprOffset;
643 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +0000644 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
645 : Mips::CPURegsRegClassID, getATReg());
646 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000647 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
648 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000649 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000650 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
651 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000652 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000653 if (isImmOpnd) {
654 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
655 ImmOffset = Inst.getOperand(2).getImm();
656 LoOffset = ImmOffset & 0x0000ffff;
657 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000658 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000659 if (LoOffset & 0x8000)
660 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000661 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000662 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000663 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000664 TempInst.setLoc(IDLoc);
665 // 1st instruction in expansion is LUi. For load instruction we can use
666 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000667 // but for stores we must use $at.
668 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000669 TempInst.setOpcode(Mips::LUi);
670 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
671 if (isImmOpnd)
672 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
673 else {
674 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
675 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000676 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
677 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
678 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000679 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000680 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000681 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000682 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000683 }
684 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000685 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000686 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000687 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000688 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000689 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000690 TempInst.setOpcode(Mips::ADDu);
691 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
692 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
693 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
694 Instructions.push_back(TempInst);
695 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000696 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000697 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000698 TempInst.setOpcode(Inst.getOpcode());
699 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
700 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
701 if (isImmOpnd)
702 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
703 else {
704 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000705 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
706 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
707 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000708 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000709 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000710 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000711 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000712 }
713 }
714 Instructions.push_back(TempInst);
715 TempInst.clear();
716}
717
Rafael Espindola870c4e92012-01-11 03:56:41 +0000718bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000719MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000720 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000721 MCStreamer &Out, unsigned &ErrorInfo,
722 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000723 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000724 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000725 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000726 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000727
728 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000729 default:
730 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000731 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000732 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000733 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000734 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000735 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000736 return false;
737 }
738 case Match_MissingFeature:
739 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
740 return true;
741 case Match_InvalidOperand: {
742 SMLoc ErrorLoc = IDLoc;
743 if (ErrorInfo != ~0U) {
744 if (ErrorInfo >= Operands.size())
745 return Error(IDLoc, "too few operands for instruction");
746
Jack Carterd0bd6422013-04-18 00:41:53 +0000747 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
748 if (ErrorLoc == SMLoc())
749 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000750 }
751
752 return Error(ErrorLoc, "invalid operand for instruction");
753 }
754 case Match_MnemonicFail:
755 return Error(IDLoc, "invalid instruction");
756 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000757 return true;
758}
759
Jack Carter1ac53222013-02-20 23:11:17 +0000760int MipsAsmParser::matchCPURegisterName(StringRef Name) {
761 int CC;
762
763 if (Name == "at")
764 return getATReg();
765
766 CC = StringSwitch<unsigned>(Name)
767 .Case("zero", 0)
768 .Case("a0", 4)
769 .Case("a1", 5)
770 .Case("a2", 6)
771 .Case("a3", 7)
772 .Case("v0", 2)
773 .Case("v1", 3)
774 .Case("s0", 16)
775 .Case("s1", 17)
776 .Case("s2", 18)
777 .Case("s3", 19)
778 .Case("s4", 20)
779 .Case("s5", 21)
780 .Case("s6", 22)
781 .Case("s7", 23)
782 .Case("k0", 26)
783 .Case("k1", 27)
784 .Case("sp", 29)
785 .Case("fp", 30)
786 .Case("gp", 28)
787 .Case("ra", 31)
788 .Case("t0", 8)
789 .Case("t1", 9)
790 .Case("t2", 10)
791 .Case("t3", 11)
792 .Case("t4", 12)
793 .Case("t5", 13)
794 .Case("t6", 14)
795 .Case("t7", 15)
796 .Case("t8", 24)
797 .Case("t9", 25)
798 .Default(-1);
799
Jack Carterd0bd6422013-04-18 00:41:53 +0000800 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000801 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
802 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000803 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000804 CC += 4;
805
806 if (CC == -1 && isMips64())
807 CC = StringSwitch<unsigned>(Name)
808 .Case("a4", 8)
809 .Case("a5", 9)
810 .Case("a6", 10)
811 .Case("a7", 11)
812 .Case("kt0", 26)
813 .Case("kt1", 27)
814 .Case("s8", 30)
815 .Default(-1);
816
817 return CC;
818}
Jack Carterd0bd6422013-04-18 00:41:53 +0000819
Vladimir Medic8cd17102013-06-20 11:21:49 +0000820int MipsAsmParser::matchFPURegisterName(StringRef Name, FpFormatTy Format) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000821
Jack Cartera63b16a2012-09-07 00:23:42 +0000822 if (Name[0] == 'f') {
823 StringRef NumString = Name.substr(1);
824 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000825 if (NumString.getAsInteger(10, IntVal))
826 return -1; // This is not an integer.
Jack Cartera63b16a2012-09-07 00:23:42 +0000827 if (IntVal > 31)
828 return -1;
829
Jack Cartera63b16a2012-09-07 00:23:42 +0000830 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
831 return getReg(Mips::FGR32RegClassID, IntVal);
832 if (Format == FP_FORMAT_D) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000833 if (isFP64()) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000834 return getReg(Mips::FGR64RegClassID, IntVal);
835 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000836 // Only even numbers available as register pairs.
837 if ((IntVal > 31) || (IntVal % 2 != 0))
Jack Cartera63b16a2012-09-07 00:23:42 +0000838 return -1;
Jack Carterd0bd6422013-04-18 00:41:53 +0000839 return getReg(Mips::AFGR64RegClassID, IntVal / 2);
Jack Cartera63b16a2012-09-07 00:23:42 +0000840 }
841 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000842 return -1;
843}
Jack Carterd0bd6422013-04-18 00:41:53 +0000844
Vladimir Medic8cd17102013-06-20 11:21:49 +0000845int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
846
847 if (Name.equals("fcc0"))
848 return Mips::FCC0;
849
850 int CC;
851 CC = matchCPURegisterName(Name);
852 if (CC != -1)
853 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
854 : Mips::CPURegsRegClassID);
855 return matchFPURegisterName(Name, getFpFormat());
856}
857
Jack Cartera63b16a2012-09-07 00:23:42 +0000858void MipsAsmParser::setDefaultFpFormat() {
859
860 if (isMips64() || isFP64())
861 FpFormat = FP_FORMAT_D;
862 else
863 FpFormat = FP_FORMAT_S;
864}
865
Jack Cartera63b16a2012-09-07 00:23:42 +0000866void MipsAsmParser::setFpFormat(StringRef Format) {
867
868 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
869 .Case(".s", FP_FORMAT_S)
870 .Case(".d", FP_FORMAT_D)
871 .Case(".l", FP_FORMAT_L)
872 .Case(".w", FP_FORMAT_W)
873 .Default(FP_FORMAT_NONE);
874}
Jack Carterb4dbc172012-09-05 23:34:03 +0000875
Jack Carter0b744b32012-10-04 02:29:46 +0000876bool MipsAssemblerOptions::setATReg(unsigned Reg) {
877 if (Reg > 31)
878 return false;
879
880 aTReg = Reg;
881 return true;
882}
883
Jack Carter1ac53222013-02-20 23:11:17 +0000884int MipsAsmParser::getATReg() {
885 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000886}
887
Jack Carterd0bd6422013-04-18 00:41:53 +0000888unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000889 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +0000890}
891
Jack Carter873c7242013-01-12 01:03:14 +0000892int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000893
894 if (RegNum > 31)
895 return -1;
896
Jack Carter873c7242013-01-12 01:03:14 +0000897 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000898}
899
Jack Carter873c7242013-01-12 01:03:14 +0000900int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000901 const AsmToken &Tok = Parser.getTok();
902 int RegNum = -1;
903
904 if (Tok.is(AsmToken::Identifier)) {
905 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000906 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000907 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000908 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterd0bd6422013-04-18 00:41:53 +0000909 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000910 return RegNum;
911}
912
Jack Carterd0bd6422013-04-18 00:41:53 +0000913bool MipsAsmParser::tryParseRegisterOperand(
914 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000915
916 SMLoc S = Parser.getTok().getLoc();
917 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000918
Jack Carter873c7242013-01-12 01:03:14 +0000919 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000920 if (RegNo == -1)
921 return true;
922
Jack Carter873c7242013-01-12 01:03:14 +0000923 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000924 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000925 Parser.Lex(); // Eat register token.
926 return false;
927}
928
929bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
930 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000931 // Check if the current operand has a custom associated parser, if so, try to
932 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000933 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
934 if (ResTy == MatchOperand_Success)
935 return false;
936 // If there wasn't a custom match, try the generic matcher below. Otherwise,
937 // there was a match, but an error occurred, in which case, just return that
938 // the operand parsing failed.
939 if (ResTy == MatchOperand_ParseFail)
940 return true;
941
942 switch (getLexer().getKind()) {
943 default:
944 Error(Parser.getTok().getLoc(), "unexpected token in operand");
945 return true;
946 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000947 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000948 SMLoc S = Parser.getTok().getLoc();
949 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000950 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000951 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000952 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000953 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000954 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000955 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000956 if (getLexer().isNot(AsmToken::Dollar))
957 return true;
958
Jack Carterd0bd6422013-04-18 00:41:53 +0000959 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000960 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000961 return true;
962
963 if (!getLexer().is(AsmToken::RParen))
964 return true;
965
966 S = Parser.getTok().getLoc();
967 Operands.push_back(MipsOperand::CreateToken(")", S));
968 Parser.Lex();
969 }
970 return false;
971 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000972 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000973 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000974 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000975 return true;
976
Jack Carter873c7242013-01-12 01:03:14 +0000977 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000978
Benjamin Kramerfa530572012-09-07 09:47:42 +0000979 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000980
Jack Carterd0bd6422013-04-18 00:41:53 +0000981 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000982 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000983 getContext());
984
985 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
986 return false;
987 }
988 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000989 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +0000990 // we need to assigne the propper RegisterKind.
991 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
992 return false;
993 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +0000994 case AsmToken::LParen:
995 case AsmToken::Minus:
996 case AsmToken::Plus:
997 case AsmToken::Integer:
998 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000999 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +00001000 const MCExpr *IdVal;
1001 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001002 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +00001003 return true;
Jack Carter873c7242013-01-12 01:03:14 +00001004 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001005 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1006 return false;
1007 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001008 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001009 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001010 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001011 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001012 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001013 return true;
1014
Jack Carter873c7242013-01-12 01:03:14 +00001015 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1016
Jack Carterdc1e35d2012-09-06 20:00:02 +00001017 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1018 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001019 } // case AsmToken::Percent
1020 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001021 return true;
1022}
1023
Jack Carterb5cf5902013-04-17 00:18:04 +00001024const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1025 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001026 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001027 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001028 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001029 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001030 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001031 short Val = MCE->getValue();
1032 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001033 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001034 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001035 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001036 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001037 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001038 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001039 if (LoSign)
1040 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001041 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001042 } else {
1043 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001044 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001045 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001046 }
1047
Jack Carterb5cf5902013-04-17 00:18:04 +00001048 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001049 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001050 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001051 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001052 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001053 return Res;
1054 }
1055
1056 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001057 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1058 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001059 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1060 return Res;
1061 }
1062
1063 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001064 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1065 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1066 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001067 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001068 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001069 return Expr;
1070}
1071
1072bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1073
1074 switch (Expr->getKind()) {
1075 case MCExpr::Constant:
1076 return true;
1077 case MCExpr::SymbolRef:
1078 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1079 case MCExpr::Binary:
1080 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1081 if (!isEvaluated(BE->getLHS()))
1082 return false;
1083 return isEvaluated(BE->getRHS());
1084 }
1085 case MCExpr::Unary:
1086 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1087 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001088 return false;
1089 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001090 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001091}
Jack Carterd0bd6422013-04-18 00:41:53 +00001092
Jack Carterb5cf5902013-04-17 00:18:04 +00001093bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001094 Parser.Lex(); // Eat the % token.
1095 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001096 if (Tok.isNot(AsmToken::Identifier))
1097 return true;
1098
1099 std::string Str = Tok.getIdentifier().str();
1100
Jack Carterd0bd6422013-04-18 00:41:53 +00001101 Parser.Lex(); // Eat the identifier.
1102 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001103 const MCExpr *IdVal;
1104 SMLoc EndLoc;
1105
1106 if (getLexer().getKind() == AsmToken::LParen) {
1107 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001108 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001109 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001110 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001111 const AsmToken &nextTok = Parser.getTok();
1112 if (nextTok.isNot(AsmToken::Identifier))
1113 return true;
1114 Str += "(%";
1115 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001117 if (getLexer().getKind() != AsmToken::LParen)
1118 return true;
1119 } else
1120 break;
1121 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001122 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001123 return true;
1124
1125 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001126 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001127
1128 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001129 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001130
Jack Carterd0bd6422013-04-18 00:41:53 +00001131 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001132 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001133}
1134
Jack Carterb4dbc172012-09-05 23:34:03 +00001135bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1136 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001137 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001138 RegNo = tryParseRegister(isMips64());
1139 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001140 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001141}
1142
Jack Carterb5cf5902013-04-17 00:18:04 +00001143bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001144 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001145 bool Result = true;
1146
1147 while (getLexer().getKind() == AsmToken::LParen)
1148 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001149
Jack Carterd0bd6422013-04-18 00:41:53 +00001150 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001151 default:
1152 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001153 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001154 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001155 case AsmToken::Integer:
1156 case AsmToken::Minus:
1157 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001158 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001159 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001160 else
1161 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001162 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001163 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001164 break;
Jack Carter873c7242013-01-12 01:03:14 +00001165 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001166 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001167 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001168 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001169}
1170
Jack Carterb4dbc172012-09-05 23:34:03 +00001171MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001172 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001173
1174 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001175 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001176 bool isParenExpr = false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001177 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001178 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001179
Jack Carterb5cf5902013-04-17 00:18:04 +00001180 if (getLexer().getKind() == AsmToken::LParen) {
1181 Parser.Lex();
1182 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001183 }
1184
Jack Carterb5cf5902013-04-17 00:18:04 +00001185 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001186 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001187 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001188
Jack Carterd0bd6422013-04-18 00:41:53 +00001189 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001190 if (Tok.isNot(AsmToken::LParen)) {
1191 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1192 if (Mnemonic->getToken() == "la") {
1193 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001194 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001195 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1196 return MatchOperand_Success;
1197 }
1198 if (Tok.is(AsmToken::EndOfStatement)) {
1199 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001200 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001201
Jack Carterd0bd6422013-04-18 00:41:53 +00001202 // Zero register assumed, add a memory operand with ZERO as its base.
1203 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1204 : Mips::ZERO,
1205 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001206 return MatchOperand_Success;
1207 }
1208 Error(Parser.getTok().getLoc(), "'(' expected");
1209 return MatchOperand_ParseFail;
1210 }
1211
Jack Carterd0bd6422013-04-18 00:41:53 +00001212 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001213 }
1214
1215 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001216 if (Tok1.is(AsmToken::Dollar)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001217 Parser.Lex(); // Eat the '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001218 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001219 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1220 return MatchOperand_ParseFail;
1221 }
1222
1223 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001224 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001225 return MatchOperand_ParseFail;
1226 }
1227
Jack Carterd0bd6422013-04-18 00:41:53 +00001228 const AsmToken &Tok2 = Parser.getTok(); // Get next token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001229 if (Tok2.isNot(AsmToken::RParen)) {
1230 Error(Parser.getTok().getLoc(), "')' expected");
1231 return MatchOperand_ParseFail;
1232 }
1233
Jack Carter873c7242013-01-12 01:03:14 +00001234 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1235
Jack Carterd0bd6422013-04-18 00:41:53 +00001236 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001237
1238 if (IdVal == 0)
1239 IdVal = MCConstantExpr::Create(0, getContext());
1240
Jack Carterd0bd6422013-04-18 00:41:53 +00001241 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001242 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1243 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001244 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001245 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001246 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001247 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1248 int64_t Imm;
1249 if (IdVal->EvaluateAsAbsolute(Imm))
1250 IdVal = MCConstantExpr::Create(Imm, getContext());
1251 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1252 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1253 getContext());
1254 }
1255
Jack Carterdc1e35d2012-09-06 20:00:02 +00001256 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1257 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001258 return MatchOperand_Success;
1259}
1260
Jack Carter873c7242013-01-12 01:03:14 +00001261MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +00001262MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1263 int RegKind) {
1264 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001265 if (getLexer().getKind() == AsmToken::Identifier) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001266 if (searchSymbolAlias(Operands, Kind))
Jack Carterd76b2372013-03-21 21:44:16 +00001267 return MatchOperand_Success;
1268 return MatchOperand_NoMatch;
1269 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001270 // If the first token is not '$', we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001271 if (Parser.getTok().isNot(AsmToken::Dollar))
1272 return MatchOperand_NoMatch;
1273
1274 Parser.Lex(); // Eat $
Vladimir Medic8cd17102013-06-20 11:21:49 +00001275 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001276 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001277 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001278 op->setRegKind(Kind);
Vladimir Medic3467b902013-07-18 09:28:35 +00001279 if ((Kind == MipsOperand::Kind_CPURegs)
1280 && (getLexer().is(AsmToken::LParen))) {
1281 // Check if it is indexed addressing operand.
1282 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1283 Parser.Lex(); // Eat the parenthesis.
1284 if (parseRegs(Operands,RegKind) != MatchOperand_Success)
1285 return MatchOperand_NoMatch;
1286 if (getLexer().isNot(AsmToken::RParen))
1287 return MatchOperand_NoMatch;
1288 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1289 Parser.Lex();
1290 }
Jack Carter873c7242013-01-12 01:03:14 +00001291 return MatchOperand_Success;
1292 }
1293 return MatchOperand_NoMatch;
1294}
Vladimir Medic64828a12013-07-16 10:07:14 +00001295
Vladimir Medic8cd17102013-06-20 11:21:49 +00001296MipsAsmParser::OperandMatchResultTy
1297MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1298
1299 if (!isMips64())
1300 return MatchOperand_NoMatch;
1301 return parseRegs(Operands, (int) MipsOperand::Kind_CPU64Regs);
1302}
1303
1304MipsAsmParser::OperandMatchResultTy
1305MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1306 return parseRegs(Operands, (int) MipsOperand::Kind_CPURegs);
1307}
Jack Carter873c7242013-01-12 01:03:14 +00001308
Vladimir Medic233dd512013-06-24 10:05:34 +00001309MipsAsmParser::OperandMatchResultTy
1310MipsAsmParser::parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1311
1312 if (isFP64())
1313 return MatchOperand_NoMatch;
1314 // Double operand is expected, set appropriate format
1315 setFpFormat(FP_FORMAT_D);
1316
1317 return parseRegs(Operands, (int) MipsOperand::Kind_AFGR64Regs);
1318}
1319
1320MipsAsmParser::OperandMatchResultTy
1321MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1322 if (!isFP64())
1323 return MatchOperand_NoMatch;
1324 // Double operand is expected, set appropriate format
1325 setFpFormat(FP_FORMAT_D);
1326
1327 return parseRegs(Operands, (int) MipsOperand::Kind_FGR64Regs);
1328}
1329
1330MipsAsmParser::OperandMatchResultTy
1331MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1332 // Single operand is expected, set appropriate format
1333 setFpFormat(FP_FORMAT_S);
1334 return parseRegs(Operands, (int) MipsOperand::Kind_FGR32Regs);
1335}
1336
Vladimir Medic643b3982013-07-30 10:12:14 +00001337MipsAsmParser::OperandMatchResultTy
1338MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1339 // If the first token is not '$' we have an error.
1340 if (Parser.getTok().isNot(AsmToken::Dollar))
1341 return MatchOperand_NoMatch;
1342
1343 SMLoc S = Parser.getTok().getLoc();
1344 Parser.Lex(); // Eat the '$'
1345
1346 const AsmToken &Tok = Parser.getTok(); // Get next token.
1347
1348 if (Tok.isNot(AsmToken::Identifier))
1349 return MatchOperand_NoMatch;
1350
1351 if (!Tok.getIdentifier().startswith("fcc"))
1352 return MatchOperand_NoMatch;
1353
1354 StringRef NumString = Tok.getIdentifier().substr(3);
1355
1356 unsigned IntVal;
1357 if (NumString.getAsInteger(10, IntVal))
1358 return MatchOperand_NoMatch;
1359
1360 unsigned Reg = matchRegisterByNumber(IntVal, Mips::FCCRegClassID);
1361
1362 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1363 Op->setRegKind(MipsOperand::Kind_FCCRegs);
1364 Operands.push_back(Op);
1365
1366 Parser.Lex(); // Eat the register number.
1367 return MatchOperand_Success;
1368}
1369
Jack Carterd0bd6422013-04-18 00:41:53 +00001370bool MipsAsmParser::searchSymbolAlias(
Vladimir Medic8cd17102013-06-20 11:21:49 +00001371 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001372
1373 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1374 if (Sym) {
1375 SMLoc S = Parser.getTok().getLoc();
1376 const MCExpr *Expr;
1377 if (Sym->isVariable())
1378 Expr = Sym->getVariableValue();
1379 else
1380 return false;
1381 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001382 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind) RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001383 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1384 const StringRef DefSymbol = Ref->getSymbol().getName();
1385 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00001386 int RegNum = -1;
1387 APInt IntVal(32, -1);
1388 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
1389 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
Vladimir Medic64828a12013-07-16 10:07:14 +00001390 isMips64()
1391 ? Mips::CPU64RegsRegClassID
1392 : Mips::CPURegsRegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001393 else {
1394 // Lookup for the register with the corresponding name.
1395 switch (Kind) {
1396 case MipsOperand::Kind_AFGR64Regs:
1397 case MipsOperand::Kind_FGR64Regs:
1398 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_D);
1399 break;
1400 case MipsOperand::Kind_FGR32Regs:
1401 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_S);
1402 break;
1403 case MipsOperand::Kind_CPU64Regs:
1404 case MipsOperand::Kind_CPURegs:
1405 default:
1406 RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
1407 break;
1408 }
1409 }
Jack Carterd76b2372013-03-21 21:44:16 +00001410 if (RegNum > -1) {
1411 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1413 Parser.getTok().getLoc());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001414 op->setRegKind(Kind);
Jack Carterd76b2372013-03-21 21:44:16 +00001415 Operands.push_back(op);
1416 return true;
1417 }
1418 }
1419 } else if (Expr->getKind() == MCExpr::Constant) {
1420 Parser.Lex();
1421 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001422 MipsOperand *op = MipsOperand::CreateImm(Const, S,
Vladimir Medic64828a12013-07-16 10:07:14 +00001423 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001424 Operands.push_back(op);
1425 return true;
1426 }
1427 }
1428 return false;
1429}
Jack Carterd0bd6422013-04-18 00:41:53 +00001430
Jack Carter873c7242013-01-12 01:03:14 +00001431MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +00001432MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1433
Jack Carter2a74a87b2013-01-17 00:28:20 +00001434 if (isMips64())
1435 return MatchOperand_NoMatch;
1436
Jack Carterd0bd6422013-04-18 00:41:53 +00001437 // If the first token is not '$' we have error.
Jack Carter873c7242013-01-12 01:03:14 +00001438 if (Parser.getTok().isNot(AsmToken::Dollar))
1439 return MatchOperand_NoMatch;
1440 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001441 Parser.Lex(); // Eat the '$'.
Jack Carter873c7242013-01-12 01:03:14 +00001442
Jack Carterd0bd6422013-04-18 00:41:53 +00001443 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001444 if (Tok.isNot(AsmToken::Integer))
1445 return MatchOperand_NoMatch;
1446
1447 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001448 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001449 if (RegNum != 29)
1450 return MatchOperand_ParseFail;
1451
1452 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001453 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001454 op->setRegKind(MipsOperand::Kind_HWRegs);
1455 Operands.push_back(op);
1456
Jack Carterd0bd6422013-04-18 00:41:53 +00001457 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001458 return MatchOperand_Success;
1459}
1460
1461MipsAsmParser::OperandMatchResultTy
Jack Carterd0bd6422013-04-18 00:41:53 +00001462MipsAsmParser::parseHW64Regs(
1463 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001464
1465 if (!isMips64())
1466 return MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001467 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001468 if (Parser.getTok().isNot(AsmToken::Dollar))
1469 return MatchOperand_NoMatch;
1470 SMLoc S = Parser.getTok().getLoc();
1471 Parser.Lex(); // Eat $
1472
Jack Carterd0bd6422013-04-18 00:41:53 +00001473 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001474 if (Tok.isNot(AsmToken::Integer))
1475 return MatchOperand_NoMatch;
1476
1477 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001478 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001479 if (RegNum != 29)
1480 return MatchOperand_ParseFail;
1481
1482 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001483 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001484 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001485 Operands.push_back(op);
1486
Jack Carterd0bd6422013-04-18 00:41:53 +00001487 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001488 return MatchOperand_Success;
1489}
1490
1491MipsAsmParser::OperandMatchResultTy
1492MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001493 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001494 if (Parser.getTok().isNot(AsmToken::Dollar))
Akira Hatanakadade526a2013-07-24 18:43:52 +00001495 return MatchOperand_NoMatch;
Akira Hatanaka4d2ea3c2013-07-22 19:30:38 +00001496
Jack Carter873c7242013-01-12 01:03:14 +00001497 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001498 Parser.Lex(); // Eat the '$'
Jack Carter873c7242013-01-12 01:03:14 +00001499
Jack Carterd0bd6422013-04-18 00:41:53 +00001500 const AsmToken &Tok = Parser.getTok(); // Get next token.
Jack Carter873c7242013-01-12 01:03:14 +00001501
Akira Hatanaka4d2ea3c2013-07-22 19:30:38 +00001502 if (Tok.isNot(AsmToken::Integer))
Akira Hatanakadade526a2013-07-24 18:43:52 +00001503 return MatchOperand_NoMatch;
Akira Hatanaka4d2ea3c2013-07-22 19:30:38 +00001504
1505 unsigned Reg = matchRegisterByNumber(Tok.getIntVal(), Mips::CCRRegClassID);
1506
1507 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1508 Op->setRegKind(MipsOperand::Kind_CCRRegs);
1509 Operands.push_back(Op);
Jack Carter873c7242013-01-12 01:03:14 +00001510
Jack Carterd0bd6422013-04-18 00:41:53 +00001511 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001512 return MatchOperand_Success;
1513}
1514
Jack Carterdc1e35d2012-09-06 20:00:02 +00001515MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1516
1517 MCSymbolRefExpr::VariantKind VK
1518 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1519 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1520 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1521 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1522 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1523 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1524 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1525 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1526 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1527 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1528 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1529 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1530 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1531 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1532 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1533 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1534 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1535 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1536 .Default(MCSymbolRefExpr::VK_None);
1537
1538 return VK;
1539}
Jack Cartera63b16a2012-09-07 00:23:42 +00001540
Rafael Espindola870c4e92012-01-11 03:56:41 +00001541bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001542ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001543 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Vladimir Medic74593e62013-07-17 15:00:42 +00001544 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00001545 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00001546 Parser.eatToEndOfStatement();
1547 return Error(NameLoc, "Unknown instruction");
1548 }
Vladimir Medic64828a12013-07-16 10:07:14 +00001549 // First operand in MCInst is instruction mnemonic.
1550 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterb4dbc172012-09-05 23:34:03 +00001551
1552 // Read the remaining operands.
1553 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1554 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00001555 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001556 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001557 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001558 return Error(Loc, "unexpected token in argument list");
1559 }
1560
Jack Carterd0bd6422013-04-18 00:41:53 +00001561 while (getLexer().is(AsmToken::Comma)) {
1562 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001563 // Parse and remember the operand.
1564 if (ParseOperand(Operands, Name)) {
1565 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001566 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001567 return Error(Loc, "unexpected token in argument list");
1568 }
1569 }
1570 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001571 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1572 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001573 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001574 return Error(Loc, "unexpected token in argument list");
1575 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001576 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001577 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001578}
1579
Jack Carter0b744b32012-10-04 02:29:46 +00001580bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001581 SMLoc Loc = getLexer().getLoc();
1582 Parser.eatToEndOfStatement();
1583 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001584}
1585
1586bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001587 // Line should look like: ".set noat".
1588 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001589 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001590 // eat noat
1591 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001592 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001593 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1594 reportParseError("unexpected token in statement");
1595 return false;
1596 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001597 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001598 return false;
1599}
Jack Carterd0bd6422013-04-18 00:41:53 +00001600
Jack Carter0b744b32012-10-04 02:29:46 +00001601bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001602 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001603 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001604 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001605 getParser().Lex();
1606 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001607 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001608 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001609 return false;
1610 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001611 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001612 if (getLexer().isNot(AsmToken::Dollar)) {
1613 reportParseError("unexpected token in statement");
1614 return false;
1615 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001616 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001617 const AsmToken &Reg = Parser.getTok();
1618 if (Reg.is(AsmToken::Identifier)) {
1619 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1620 } else if (Reg.is(AsmToken::Integer)) {
1621 AtRegNo = Reg.getIntVal();
1622 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001623 reportParseError("unexpected token in statement");
1624 return false;
1625 }
Jack Carter1ac53222013-02-20 23:11:17 +00001626
Jack Carterd0bd6422013-04-18 00:41:53 +00001627 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001628 reportParseError("unexpected token in statement");
1629 return false;
1630 }
1631
1632 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001633 reportParseError("unexpected token in statement");
1634 return false;
1635 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001636 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001637
1638 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1639 reportParseError("unexpected token in statement");
1640 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001641 }
1642 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001643 return false;
1644 } else {
1645 reportParseError("unexpected token in statement");
1646 return false;
1647 }
1648}
1649
1650bool MipsAsmParser::parseSetReorderDirective() {
1651 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001652 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001653 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1654 reportParseError("unexpected token in statement");
1655 return false;
1656 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001657 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001658 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001659 return false;
1660}
1661
1662bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001663 Parser.Lex();
1664 // If this is not the end of the statement, report an error.
1665 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1666 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001667 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001668 }
1669 Options.setNoreorder();
1670 Parser.Lex(); // Consume the EndOfStatement.
1671 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001672}
1673
1674bool MipsAsmParser::parseSetMacroDirective() {
1675 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001677 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1678 reportParseError("unexpected token in statement");
1679 return false;
1680 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001681 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001682 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001683 return false;
1684}
1685
1686bool MipsAsmParser::parseSetNoMacroDirective() {
1687 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001688 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001689 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1690 reportParseError("`noreorder' must be set before `nomacro'");
1691 return false;
1692 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001693 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001694 reportParseError("`noreorder' must be set before `nomacro'");
1695 return false;
1696 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001697 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001698 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001699 return false;
1700}
Jack Carterd76b2372013-03-21 21:44:16 +00001701
1702bool MipsAsmParser::parseSetAssignment() {
1703 StringRef Name;
1704 const MCExpr *Value;
1705
1706 if (Parser.parseIdentifier(Name))
1707 reportParseError("expected identifier after .set");
1708
1709 if (getLexer().isNot(AsmToken::Comma))
1710 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001711 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001712
Jack Carter02593002013-05-28 22:21:05 +00001713 if (getLexer().is(AsmToken::Dollar)) {
1714 MCSymbol *Symbol;
1715 SMLoc DollarLoc = getLexer().getLoc();
1716 // Consume the dollar sign, and check for a following identifier.
1717 Parser.Lex();
1718 // We have a '$' followed by something, make sure they are adjacent.
1719 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
1720 return true;
1721 StringRef Res = StringRef(DollarLoc.getPointer(),
1722 getTok().getEndLoc().getPointer() - DollarLoc.getPointer());
1723 Symbol = getContext().GetOrCreateSymbol(Res);
1724 Parser.Lex();
1725 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
1726 getContext());
1727 } else if (Parser.parseExpression(Value))
1728 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00001729
Jack Carterd0bd6422013-04-18 00:41:53 +00001730 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001731 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001732 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001733 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001734 Sym = getContext().GetOrCreateSymbol(Name);
1735 Sym->setVariableValue(Value);
1736
1737 return false;
1738}
Jack Carterd0bd6422013-04-18 00:41:53 +00001739
Jack Carter0b744b32012-10-04 02:29:46 +00001740bool MipsAsmParser::parseDirectiveSet() {
1741
Jack Carterd0bd6422013-04-18 00:41:53 +00001742 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001743 const AsmToken &Tok = Parser.getTok();
1744
1745 if (Tok.getString() == "noat") {
1746 return parseSetNoAtDirective();
1747 } else if (Tok.getString() == "at") {
1748 return parseSetAtDirective();
1749 } else if (Tok.getString() == "reorder") {
1750 return parseSetReorderDirective();
1751 } else if (Tok.getString() == "noreorder") {
1752 return parseSetNoReorderDirective();
1753 } else if (Tok.getString() == "macro") {
1754 return parseSetMacroDirective();
1755 } else if (Tok.getString() == "nomacro") {
1756 return parseSetNoMacroDirective();
1757 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001758 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001759 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001760 return false;
1761 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001762 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001763 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001764 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001765 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001766 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001767 parseSetAssignment();
1768 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001769 }
Jack Carter07c818d2013-01-25 01:31:34 +00001770
Jack Carter0b744b32012-10-04 02:29:46 +00001771 return true;
1772}
1773
Jack Carter07c818d2013-01-25 01:31:34 +00001774/// parseDirectiveWord
1775/// ::= .word [ expression (, expression)* ]
1776bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1777 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1778 for (;;) {
1779 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001780 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001781 return true;
1782
1783 getParser().getStreamer().EmitValue(Value, Size);
1784
1785 if (getLexer().is(AsmToken::EndOfStatement))
1786 break;
1787
1788 // FIXME: Improve diagnostic.
1789 if (getLexer().isNot(AsmToken::Comma))
1790 return Error(L, "unexpected token in directive");
1791 Parser.Lex();
1792 }
1793 }
1794
1795 Parser.Lex();
1796 return false;
1797}
1798
Jack Carter0b744b32012-10-04 02:29:46 +00001799bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001800
Jack Carter07c818d2013-01-25 01:31:34 +00001801 StringRef IDVal = DirectiveID.getString();
1802
Jack Carterd0bd6422013-04-18 00:41:53 +00001803 if (IDVal == ".ent") {
1804 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001805 Parser.Lex();
1806 return false;
1807 }
1808
Jack Carter07c818d2013-01-25 01:31:34 +00001809 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001810 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001811 Parser.Lex();
1812 return false;
1813 }
1814
Jack Carter07c818d2013-01-25 01:31:34 +00001815 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001816 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001817 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001818 return false;
1819 }
1820
Jack Carter07c818d2013-01-25 01:31:34 +00001821 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001822 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001823 }
1824
Jack Carter07c818d2013-01-25 01:31:34 +00001825 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001826 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001827 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001828 return false;
1829 }
1830
Jack Carter07c818d2013-01-25 01:31:34 +00001831 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001832 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001833 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001834 return false;
1835 }
1836
Jack Carter07c818d2013-01-25 01:31:34 +00001837 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001838 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001839 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001840 return false;
1841 }
1842
Jack Carter07c818d2013-01-25 01:31:34 +00001843 if (IDVal == ".word") {
1844 parseDirectiveWord(4, DirectiveID.getLoc());
1845 return false;
1846 }
1847
Rafael Espindola870c4e92012-01-11 03:56:41 +00001848 return true;
1849}
1850
Rafael Espindola870c4e92012-01-11 03:56:41 +00001851extern "C" void LLVMInitializeMipsAsmParser() {
1852 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1853 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1854 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1855 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1856}
Jack Carterb4dbc172012-09-05 23:34:03 +00001857
1858#define GET_REGISTER_MATCHER
1859#define GET_MATCHER_IMPLEMENTATION
1860#include "MipsGenAsmMatcher.inc"