blob: 4d805a7f1143084106c9bf7c022f99a25d01d5e8 [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
Jack Cartera63b16a2012-09-07 00:23:42 +000081 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
82 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
83
Rafael Espindola870c4e92012-01-11 03:56:41 +000084 bool ParseDirective(AsmToken DirectiveID);
85
Jack Carterb4dbc172012-09-05 23:34:03 +000086 MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +000087 parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
88 int RegKind);
89 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +000090 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
91
92 MipsAsmParser::OperandMatchResultTy
93 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
94
95 MipsAsmParser::OperandMatchResultTy
96 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
97
98 MipsAsmParser::OperandMatchResultTy
99 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
100
101 MipsAsmParser::OperandMatchResultTy
102 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
103
104 MipsAsmParser::OperandMatchResultTy
105 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000106
Vladimir Medic233dd512013-06-24 10:05:34 +0000107 MipsAsmParser::OperandMatchResultTy
108 parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
109
110 MipsAsmParser::OperandMatchResultTy
111 parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
112
113 MipsAsmParser::OperandMatchResultTy
114 parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
115
Jack Carterd76b2372013-03-21 21:44:16 +0000116 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +0000117 unsigned RegKind);
Jack Carterd76b2372013-03-21 21:44:16 +0000118
Jack Carterb4dbc172012-09-05 23:34:03 +0000119 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
120 StringRef Mnemonic);
121
Jack Carter873c7242013-01-12 01:03:14 +0000122 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000123
124 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000125 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000126
Jack Carter30a59822012-10-04 04:03:53 +0000127 bool needsExpansion(MCInst &Inst);
128
129 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000130 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000131 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000132 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000133 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
134 SmallVectorImpl<MCInst> &Instructions);
135 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
136 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000137 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
138 SmallVectorImpl<MCInst> &Instructions,
139 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000140 bool reportParseError(StringRef ErrorMsg);
141
Jack Carterb5cf5902013-04-17 00:18:04 +0000142 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000143 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000144
Jack Carterb5cf5902013-04-17 00:18:04 +0000145 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
146
147 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000148 bool parseDirectiveSet();
149
150 bool parseSetAtDirective();
151 bool parseSetNoAtDirective();
152 bool parseSetMacroDirective();
153 bool parseSetNoMacroDirective();
154 bool parseSetReorderDirective();
155 bool parseSetNoReorderDirective();
156
Jack Carterd76b2372013-03-21 21:44:16 +0000157 bool parseSetAssignment();
158
Jack Carter07c818d2013-01-25 01:31:34 +0000159 bool parseDirectiveWord(unsigned Size, SMLoc L);
160
Jack Carterdc1e35d2012-09-06 20:00:02 +0000161 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000162
Jack Carterb4dbc172012-09-05 23:34:03 +0000163 bool isMips64() const {
164 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
165 }
166
Jack Cartera63b16a2012-09-07 00:23:42 +0000167 bool isFP64() const {
168 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
169 }
170
Jack Carter873c7242013-01-12 01:03:14 +0000171 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000172
Jack Carter1ac53222013-02-20 23:11:17 +0000173 int matchCPURegisterName(StringRef Symbol);
174
Jack Carter873c7242013-01-12 01:03:14 +0000175 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000176
Vladimir Medic8cd17102013-06-20 11:21:49 +0000177 int matchFPURegisterName(StringRef Name, FpFormatTy Format);
178
Jack Cartera63b16a2012-09-07 00:23:42 +0000179 void setFpFormat(FpFormatTy Format) {
180 FpFormat = Format;
181 }
182
183 void setDefaultFpFormat();
184
185 void setFpFormat(StringRef Format);
186
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)
Jack Carterb4dbc172012-09-05 23:34:03 +0000197 : MCTargetAsmParser(), STI(sti), Parser(parser) {
198 // 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,
217 Kind_CPURegs,
218 Kind_CPU64Regs,
219 Kind_HWRegs,
220 Kind_HW64Regs,
221 Kind_FGR32Regs,
222 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000223 Kind_AFGR64Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000224 Kind_CCRRegs
225 };
226
227private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000228 enum KindTy {
229 k_CondCode,
230 k_CoprocNum,
231 k_Immediate,
232 k_Memory,
233 k_PostIndexRegister,
234 k_Register,
235 k_Token
236 } Kind;
237
238 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000239
Eric Christopher8996c5d2013-03-15 00:42:55 +0000240 struct Token {
241 const char *Data;
242 unsigned Length;
243 };
244
245 struct RegOp {
246 unsigned RegNum;
247 RegisterKind Kind;
248 };
249
250 struct ImmOp {
251 const MCExpr *Val;
252 };
253
254 struct MemOp {
255 unsigned Base;
256 const MCExpr *Off;
257 };
258
Jack Carterb4dbc172012-09-05 23:34:03 +0000259 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000260 struct Token Tok;
261 struct RegOp Reg;
262 struct ImmOp Imm;
263 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000264 };
265
266 SMLoc StartLoc, EndLoc;
267
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000268public:
269 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000270 assert(N == 1 && "Invalid number of operands!");
271 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000272 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000273
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000274 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000275 // Add as immediate when possible. Null MCExpr = 0.
276 if (Expr == 0)
277 Inst.addOperand(MCOperand::CreateImm(0));
278 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
279 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
280 else
281 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000282 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000283
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000284 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000285 assert(N == 1 && "Invalid number of operands!");
286 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000287 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000288 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000289
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000290 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000291 assert(N == 2 && "Invalid number of operands!");
292
293 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
294
295 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000296 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000297 }
298
299 bool isReg() const { return Kind == k_Register; }
300 bool isImm() const { return Kind == k_Immediate; }
301 bool isToken() const { return Kind == k_Token; }
302 bool isMem() const { return Kind == k_Memory; }
303
304 StringRef getToken() const {
305 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000306 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000307 }
308
309 unsigned getReg() const {
310 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000311 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000312 }
313
Jack Carter873c7242013-01-12 01:03:14 +0000314 void setRegKind(RegisterKind RegKind) {
315 assert((Kind == k_Register) && "Invalid access!");
316 Reg.Kind = RegKind;
317 }
318
Jack Carterb4dbc172012-09-05 23:34:03 +0000319 const MCExpr *getImm() const {
320 assert((Kind == k_Immediate) && "Invalid access!");
321 return Imm.Val;
322 }
323
Jack Carterdc1e35d2012-09-06 20:00:02 +0000324 unsigned getMemBase() const {
325 assert((Kind == k_Memory) && "Invalid access!");
326 return Mem.Base;
327 }
328
329 const MCExpr *getMemOff() const {
330 assert((Kind == k_Memory) && "Invalid access!");
331 return Mem.Off;
332 }
333
Jack Carterb4dbc172012-09-05 23:34:03 +0000334 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
335 MipsOperand *Op = new MipsOperand(k_Token);
336 Op->Tok.Data = Str.data();
337 Op->Tok.Length = Str.size();
338 Op->StartLoc = S;
339 Op->EndLoc = S;
340 return Op;
341 }
342
343 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
344 MipsOperand *Op = new MipsOperand(k_Register);
345 Op->Reg.RegNum = RegNum;
346 Op->StartLoc = S;
347 Op->EndLoc = E;
348 return Op;
349 }
350
351 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
352 MipsOperand *Op = new MipsOperand(k_Immediate);
353 Op->Imm.Val = Val;
354 Op->StartLoc = S;
355 Op->EndLoc = E;
356 return Op;
357 }
358
Jack Carterdc1e35d2012-09-06 20:00:02 +0000359 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
360 SMLoc S, SMLoc E) {
361 MipsOperand *Op = new MipsOperand(k_Memory);
362 Op->Mem.Base = Base;
363 Op->Mem.Off = Off;
364 Op->StartLoc = S;
365 Op->EndLoc = E;
366 return Op;
367 }
368
Jack Carter873c7242013-01-12 01:03:14 +0000369 bool isCPURegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000370 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carter873c7242013-01-12 01:03:14 +0000371 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000372 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000373 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
374 }
375
376 bool isCPU64RegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000377 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carter873c7242013-01-12 01:03:14 +0000378 }
Jack Carter873c7242013-01-12 01:03:14 +0000379
380 bool isHWRegsAsm() const {
381 assert((Kind == k_Register) && "Invalid access!");
382 return Reg.Kind == Kind_HWRegs;
383 }
Jack Carter873c7242013-01-12 01:03:14 +0000384
385 bool isHW64RegsAsm() const {
386 assert((Kind == k_Register) && "Invalid access!");
387 return Reg.Kind == Kind_HW64Regs;
388 }
Jack Carter873c7242013-01-12 01:03:14 +0000389
390 bool isCCRAsm() const {
391 assert((Kind == k_Register) && "Invalid access!");
392 return Reg.Kind == Kind_CCRRegs;
393 }
394
Vladimir Medic233dd512013-06-24 10:05:34 +0000395 bool isAFGR64Asm() const {
396 return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
397 }
398
399 bool isFGR64Asm() const {
400 return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
401 }
402
403 bool isFGR32Asm() const {
404 return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
405 }
406
Jack Carterb4dbc172012-09-05 23:34:03 +0000407 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000408 SMLoc getStartLoc() const {
409 return StartLoc;
410 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000411 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000412 SMLoc getEndLoc() const {
413 return EndLoc;
414 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000415
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000416 virtual void print(raw_ostream &OS) const {
417 llvm_unreachable("unimplemented!");
418 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000419}; // class MipsOperand
420} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000421
Jack Carter9e65aa32013-03-22 00:05:30 +0000422namespace llvm {
423extern const MCInstrDesc MipsInsts[];
424}
425static const MCInstrDesc &getInstDesc(unsigned Opcode) {
426 return MipsInsts[Opcode];
427}
428
429bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000430 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000431 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
432 Inst.setLoc(IDLoc);
Jack Carterc15c1d22013-04-25 23:31:35 +0000433 if (MCID.hasDelaySlot() && Options.isReorder()) {
434 // If this instruction has a delay slot and .set reorder is active,
435 // emit a NOP after it.
436 Instructions.push_back(Inst);
437 MCInst NopInst;
438 NopInst.setOpcode(Mips::SLL);
439 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
440 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
441 NopInst.addOperand(MCOperand::CreateImm(0));
442 Instructions.push_back(NopInst);
443 return false;
444 }
445
Jack Carter9e65aa32013-03-22 00:05:30 +0000446 if (MCID.mayLoad() || MCID.mayStore()) {
447 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000448 // reference or immediate we may have to expand instructions.
449 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000450 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000451 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
452 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000453 MCOperand &Op = Inst.getOperand(i);
454 if (Op.isImm()) {
455 int MemOffset = Op.getImm();
456 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000457 // Offset can't exceed 16bit value.
458 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000459 return false;
460 }
461 } else if (Op.isExpr()) {
462 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000463 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000464 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000465 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000466 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000467 // Expand symbol.
468 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000469 return false;
470 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000471 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000472 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000473 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000474 }
475 }
476 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000477 } // for
478 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000479
480 if (needsExpansion(Inst))
481 expandInstruction(Inst, IDLoc, Instructions);
482 else
483 Instructions.push_back(Inst);
484
485 return false;
486}
487
Jack Carter30a59822012-10-04 04:03:53 +0000488bool MipsAsmParser::needsExpansion(MCInst &Inst) {
489
Jack Carterd0bd6422013-04-18 00:41:53 +0000490 switch (Inst.getOpcode()) {
491 case Mips::LoadImm32Reg:
492 case Mips::LoadAddr32Imm:
493 case Mips::LoadAddr32Reg:
494 return true;
495 default:
496 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000497 }
498}
Jack Carter92995f12012-10-06 00:53:28 +0000499
Jack Carter30a59822012-10-04 04:03:53 +0000500void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000501 SmallVectorImpl<MCInst> &Instructions) {
502 switch (Inst.getOpcode()) {
503 case Mips::LoadImm32Reg:
504 return expandLoadImm(Inst, IDLoc, Instructions);
505 case Mips::LoadAddr32Imm:
506 return expandLoadAddressImm(Inst, IDLoc, Instructions);
507 case Mips::LoadAddr32Reg:
508 return expandLoadAddressReg(Inst, IDLoc, Instructions);
509 }
Jack Carter30a59822012-10-04 04:03:53 +0000510}
Jack Carter92995f12012-10-06 00:53:28 +0000511
Jack Carter30a59822012-10-04 04:03:53 +0000512void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000513 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000514 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000515 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000516 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000517 const MCOperand &RegOp = Inst.getOperand(0);
518 assert(RegOp.isReg() && "expected register operand kind");
519
520 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000521 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000522 if (0 <= ImmValue && ImmValue <= 65535) {
523 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000524 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000525 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000526 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000527 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000528 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000529 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000530 } else if (ImmValue < 0 && ImmValue >= -32768) {
531 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000532 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000533 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000534 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000535 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000536 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000537 Instructions.push_back(tmpInst);
538 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000539 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000540 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000541 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000542 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000543 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
544 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000545 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000546 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000547 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000548 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
549 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
550 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
551 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000552 Instructions.push_back(tmpInst);
553 }
554}
Jack Carter92995f12012-10-06 00:53:28 +0000555
Jack Carter543fdf82012-10-09 23:29:45 +0000556void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000557 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000558 MCInst tmpInst;
559 const MCOperand &ImmOp = Inst.getOperand(2);
560 assert(ImmOp.isImm() && "expected immediate operand kind");
561 const MCOperand &SrcRegOp = Inst.getOperand(1);
562 assert(SrcRegOp.isReg() && "expected register operand kind");
563 const MCOperand &DstRegOp = Inst.getOperand(0);
564 assert(DstRegOp.isReg() && "expected register operand kind");
565 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000566 if (-32768 <= ImmValue && ImmValue <= 65535) {
567 // For -32768 <= j <= 65535.
568 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000569 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000570 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
571 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
572 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
573 Instructions.push_back(tmpInst);
574 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000575 // For any other value of j that is representable as a 32-bit integer.
576 // la d,j(s) => lui d,hi16(j)
577 // ori d,d,lo16(j)
578 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000579 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000580 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
581 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
582 Instructions.push_back(tmpInst);
583 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000584 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000585 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
586 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
587 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
588 Instructions.push_back(tmpInst);
589 tmpInst.clear();
590 tmpInst.setOpcode(Mips::ADDu);
591 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
592 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
593 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
594 Instructions.push_back(tmpInst);
595 }
596}
597
598void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000599 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000600 MCInst tmpInst;
601 const MCOperand &ImmOp = Inst.getOperand(1);
602 assert(ImmOp.isImm() && "expected immediate operand kind");
603 const MCOperand &RegOp = Inst.getOperand(0);
604 assert(RegOp.isReg() && "expected register operand kind");
605 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000606 if (-32768 <= ImmValue && ImmValue <= 65535) {
607 // For -32768 <= j <= 65535.
608 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000609 tmpInst.setOpcode(Mips::ADDiu);
610 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000611 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000612 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
613 Instructions.push_back(tmpInst);
614 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000615 // For any other value of j that is representable as a 32-bit integer.
616 // la d,j => lui d,hi16(j)
617 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000618 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000619 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
620 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
621 Instructions.push_back(tmpInst);
622 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000623 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000624 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
625 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
626 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
627 Instructions.push_back(tmpInst);
628 }
629}
630
Jack Carter9e65aa32013-03-22 00:05:30 +0000631void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000632 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000633 const MCSymbolRefExpr *SR;
634 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000635 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000636 const MCExpr *ExprOffset;
637 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +0000638 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
639 : Mips::CPURegsRegClassID, getATReg());
640 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000641 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
642 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000643 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000644 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
645 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000646 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000647 if (isImmOpnd) {
648 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
649 ImmOffset = Inst.getOperand(2).getImm();
650 LoOffset = ImmOffset & 0x0000ffff;
651 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000652 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000653 if (LoOffset & 0x8000)
654 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000655 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000656 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000657 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000658 TempInst.setLoc(IDLoc);
659 // 1st instruction in expansion is LUi. For load instruction we can use
660 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000661 // but for stores we must use $at.
662 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000663 TempInst.setOpcode(Mips::LUi);
664 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
665 if (isImmOpnd)
666 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
667 else {
668 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
669 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000670 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
671 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
672 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000673 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000674 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000675 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000676 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000677 }
678 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000679 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000680 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000681 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000682 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000683 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000684 TempInst.setOpcode(Mips::ADDu);
685 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
686 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
687 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
688 Instructions.push_back(TempInst);
689 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000690 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000691 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000692 TempInst.setOpcode(Inst.getOpcode());
693 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
694 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
695 if (isImmOpnd)
696 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
697 else {
698 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000699 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
700 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
701 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000702 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000703 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000704 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000705 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000706 }
707 }
708 Instructions.push_back(TempInst);
709 TempInst.clear();
710}
711
Rafael Espindola870c4e92012-01-11 03:56:41 +0000712bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000713MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000714 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000715 MCStreamer &Out, unsigned &ErrorInfo,
716 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000717 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000718 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000719 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000720 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000721
722 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000723 default:
724 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000725 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000726 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000727 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000728 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000729 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000730 return false;
731 }
732 case Match_MissingFeature:
733 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
734 return true;
735 case Match_InvalidOperand: {
736 SMLoc ErrorLoc = IDLoc;
737 if (ErrorInfo != ~0U) {
738 if (ErrorInfo >= Operands.size())
739 return Error(IDLoc, "too few operands for instruction");
740
Jack Carterd0bd6422013-04-18 00:41:53 +0000741 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
742 if (ErrorLoc == SMLoc())
743 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000744 }
745
746 return Error(ErrorLoc, "invalid operand for instruction");
747 }
748 case Match_MnemonicFail:
749 return Error(IDLoc, "invalid instruction");
750 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000751 return true;
752}
753
Jack Carter1ac53222013-02-20 23:11:17 +0000754int MipsAsmParser::matchCPURegisterName(StringRef Name) {
755 int CC;
756
757 if (Name == "at")
758 return getATReg();
759
760 CC = StringSwitch<unsigned>(Name)
761 .Case("zero", 0)
762 .Case("a0", 4)
763 .Case("a1", 5)
764 .Case("a2", 6)
765 .Case("a3", 7)
766 .Case("v0", 2)
767 .Case("v1", 3)
768 .Case("s0", 16)
769 .Case("s1", 17)
770 .Case("s2", 18)
771 .Case("s3", 19)
772 .Case("s4", 20)
773 .Case("s5", 21)
774 .Case("s6", 22)
775 .Case("s7", 23)
776 .Case("k0", 26)
777 .Case("k1", 27)
778 .Case("sp", 29)
779 .Case("fp", 30)
780 .Case("gp", 28)
781 .Case("ra", 31)
782 .Case("t0", 8)
783 .Case("t1", 9)
784 .Case("t2", 10)
785 .Case("t3", 11)
786 .Case("t4", 12)
787 .Case("t5", 13)
788 .Case("t6", 14)
789 .Case("t7", 15)
790 .Case("t8", 24)
791 .Case("t9", 25)
792 .Default(-1);
793
Jack Carterd0bd6422013-04-18 00:41:53 +0000794 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000795 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
796 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000797 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000798 CC += 4;
799
800 if (CC == -1 && isMips64())
801 CC = StringSwitch<unsigned>(Name)
802 .Case("a4", 8)
803 .Case("a5", 9)
804 .Case("a6", 10)
805 .Case("a7", 11)
806 .Case("kt0", 26)
807 .Case("kt1", 27)
808 .Case("s8", 30)
809 .Default(-1);
810
811 return CC;
812}
Jack Carterd0bd6422013-04-18 00:41:53 +0000813
Vladimir Medic8cd17102013-06-20 11:21:49 +0000814int MipsAsmParser::matchFPURegisterName(StringRef Name, FpFormatTy Format) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000815
Jack Cartera63b16a2012-09-07 00:23:42 +0000816 if (Name[0] == 'f') {
817 StringRef NumString = Name.substr(1);
818 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000819 if (NumString.getAsInteger(10, IntVal))
820 return -1; // This is not an integer.
Jack Cartera63b16a2012-09-07 00:23:42 +0000821 if (IntVal > 31)
822 return -1;
823
Jack Cartera63b16a2012-09-07 00:23:42 +0000824 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
825 return getReg(Mips::FGR32RegClassID, IntVal);
826 if (Format == FP_FORMAT_D) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000827 if (isFP64()) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000828 return getReg(Mips::FGR64RegClassID, IntVal);
829 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000830 // Only even numbers available as register pairs.
831 if ((IntVal > 31) || (IntVal % 2 != 0))
Jack Cartera63b16a2012-09-07 00:23:42 +0000832 return -1;
Jack Carterd0bd6422013-04-18 00:41:53 +0000833 return getReg(Mips::AFGR64RegClassID, IntVal / 2);
Jack Cartera63b16a2012-09-07 00:23:42 +0000834 }
835 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000836 return -1;
837}
Jack Carterd0bd6422013-04-18 00:41:53 +0000838
Vladimir Medic8cd17102013-06-20 11:21:49 +0000839int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
840
841 if (Name.equals("fcc0"))
842 return Mips::FCC0;
843
844 int CC;
845 CC = matchCPURegisterName(Name);
846 if (CC != -1)
847 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
848 : Mips::CPURegsRegClassID);
849 return matchFPURegisterName(Name, getFpFormat());
850}
851
Jack Cartera63b16a2012-09-07 00:23:42 +0000852void MipsAsmParser::setDefaultFpFormat() {
853
854 if (isMips64() || isFP64())
855 FpFormat = FP_FORMAT_D;
856 else
857 FpFormat = FP_FORMAT_S;
858}
859
Jack Cartera63b16a2012-09-07 00:23:42 +0000860void MipsAsmParser::setFpFormat(StringRef Format) {
861
862 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
863 .Case(".s", FP_FORMAT_S)
864 .Case(".d", FP_FORMAT_D)
865 .Case(".l", FP_FORMAT_L)
866 .Case(".w", FP_FORMAT_W)
867 .Default(FP_FORMAT_NONE);
868}
Jack Carterb4dbc172012-09-05 23:34:03 +0000869
Jack Carter0b744b32012-10-04 02:29:46 +0000870bool MipsAssemblerOptions::setATReg(unsigned Reg) {
871 if (Reg > 31)
872 return false;
873
874 aTReg = Reg;
875 return true;
876}
877
Jack Carter1ac53222013-02-20 23:11:17 +0000878int MipsAsmParser::getATReg() {
879 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000880}
881
Jack Carterd0bd6422013-04-18 00:41:53 +0000882unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000883 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +0000884}
885
Jack Carter873c7242013-01-12 01:03:14 +0000886int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000887
888 if (RegNum > 31)
889 return -1;
890
Jack Carter873c7242013-01-12 01:03:14 +0000891 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000892}
893
Jack Carter873c7242013-01-12 01:03:14 +0000894int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000895 const AsmToken &Tok = Parser.getTok();
896 int RegNum = -1;
897
898 if (Tok.is(AsmToken::Identifier)) {
899 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000900 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000901 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000902 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterd0bd6422013-04-18 00:41:53 +0000903 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000904 return RegNum;
905}
906
Jack Carterd0bd6422013-04-18 00:41:53 +0000907bool MipsAsmParser::tryParseRegisterOperand(
908 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000909
910 SMLoc S = Parser.getTok().getLoc();
911 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000912
Jack Carter873c7242013-01-12 01:03:14 +0000913 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000914 if (RegNo == -1)
915 return true;
916
Jack Carter873c7242013-01-12 01:03:14 +0000917 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000918 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000919 Parser.Lex(); // Eat register token.
920 return false;
921}
922
923bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
924 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000925 // Check if the current operand has a custom associated parser, if so, try to
926 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000927 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
928 if (ResTy == MatchOperand_Success)
929 return false;
930 // If there wasn't a custom match, try the generic matcher below. Otherwise,
931 // there was a match, but an error occurred, in which case, just return that
932 // the operand parsing failed.
933 if (ResTy == MatchOperand_ParseFail)
934 return true;
935
936 switch (getLexer().getKind()) {
937 default:
938 Error(Parser.getTok().getLoc(), "unexpected token in operand");
939 return true;
940 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000941 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000942 SMLoc S = Parser.getTok().getLoc();
943 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000944 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000945 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000946 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000947 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000948 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000949 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000950 if (getLexer().isNot(AsmToken::Dollar))
951 return true;
952
Jack Carterd0bd6422013-04-18 00:41:53 +0000953 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000954 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000955 return true;
956
957 if (!getLexer().is(AsmToken::RParen))
958 return true;
959
960 S = Parser.getTok().getLoc();
961 Operands.push_back(MipsOperand::CreateToken(")", S));
962 Parser.Lex();
963 }
964 return false;
965 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000966 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000967 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000968 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000969 return true;
970
Jack Carter873c7242013-01-12 01:03:14 +0000971 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000972
Benjamin Kramerfa530572012-09-07 09:47:42 +0000973 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000974
Jack Carterd0bd6422013-04-18 00:41:53 +0000975 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000976 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000977 getContext());
978
979 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
980 return false;
981 }
982 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000983 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +0000984 // we need to assigne the propper RegisterKind.
985 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
986 return false;
987 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +0000988 case AsmToken::LParen:
989 case AsmToken::Minus:
990 case AsmToken::Plus:
991 case AsmToken::Integer:
992 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000993 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +0000994 const MCExpr *IdVal;
995 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000996 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +0000997 return true;
Jack Carter873c7242013-01-12 01:03:14 +0000998 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000999 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1000 return false;
1001 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001002 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001003 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001004 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001005 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001006 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001007 return true;
1008
Jack Carter873c7242013-01-12 01:03:14 +00001009 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1010
Jack Carterdc1e35d2012-09-06 20:00:02 +00001011 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1012 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001013 } // case AsmToken::Percent
1014 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001015 return true;
1016}
1017
Jack Carterb5cf5902013-04-17 00:18:04 +00001018const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1019 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001020 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001021 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001022 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001023 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001024 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001025 short Val = MCE->getValue();
1026 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001027 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001028 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001029 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001030 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001031 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001032 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001033 if (LoSign)
1034 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001035 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001036 } else {
1037 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001038 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001039 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001040 }
1041
Jack Carterb5cf5902013-04-17 00:18:04 +00001042 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001043 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001044 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001045 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001046 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001047 return Res;
1048 }
1049
1050 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001051 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1052 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001053 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1054 return Res;
1055 }
1056
1057 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001058 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1059 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1060 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001061 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001062 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001063 return Expr;
1064}
1065
1066bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1067
1068 switch (Expr->getKind()) {
1069 case MCExpr::Constant:
1070 return true;
1071 case MCExpr::SymbolRef:
1072 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1073 case MCExpr::Binary:
1074 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1075 if (!isEvaluated(BE->getLHS()))
1076 return false;
1077 return isEvaluated(BE->getRHS());
1078 }
1079 case MCExpr::Unary:
1080 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1081 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001082 return false;
1083 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001084 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001085}
Jack Carterd0bd6422013-04-18 00:41:53 +00001086
Jack Carterb5cf5902013-04-17 00:18:04 +00001087bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 Parser.Lex(); // Eat the % token.
1089 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001090 if (Tok.isNot(AsmToken::Identifier))
1091 return true;
1092
1093 std::string Str = Tok.getIdentifier().str();
1094
Jack Carterd0bd6422013-04-18 00:41:53 +00001095 Parser.Lex(); // Eat the identifier.
1096 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001097 const MCExpr *IdVal;
1098 SMLoc EndLoc;
1099
1100 if (getLexer().getKind() == AsmToken::LParen) {
1101 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001102 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001103 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001104 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001105 const AsmToken &nextTok = Parser.getTok();
1106 if (nextTok.isNot(AsmToken::Identifier))
1107 return true;
1108 Str += "(%";
1109 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001110 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001111 if (getLexer().getKind() != AsmToken::LParen)
1112 return true;
1113 } else
1114 break;
1115 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001117 return true;
1118
1119 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001120 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001121
1122 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001123 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001124
Jack Carterd0bd6422013-04-18 00:41:53 +00001125 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001126 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001127}
1128
Jack Carterb4dbc172012-09-05 23:34:03 +00001129bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1130 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001131 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001132 RegNo = tryParseRegister(isMips64());
1133 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001134 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001135}
1136
Jack Carterb5cf5902013-04-17 00:18:04 +00001137bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001138 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001139 bool Result = true;
1140
1141 while (getLexer().getKind() == AsmToken::LParen)
1142 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001143
Jack Carterd0bd6422013-04-18 00:41:53 +00001144 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001145 default:
1146 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001147 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001148 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001149 case AsmToken::Integer:
1150 case AsmToken::Minus:
1151 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001152 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001153 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001154 else
1155 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001156 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001157 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001158 break;
Jack Carter873c7242013-01-12 01:03:14 +00001159 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001160 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001161 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001162 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001163}
1164
Jack Carterb4dbc172012-09-05 23:34:03 +00001165MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001166 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001167
1168 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001169 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001170 bool isParenExpr = false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001171 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001172 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001173
Jack Carterb5cf5902013-04-17 00:18:04 +00001174 if (getLexer().getKind() == AsmToken::LParen) {
1175 Parser.Lex();
1176 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001177 }
1178
Jack Carterb5cf5902013-04-17 00:18:04 +00001179 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001180 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001181 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001182
Jack Carterd0bd6422013-04-18 00:41:53 +00001183 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001184 if (Tok.isNot(AsmToken::LParen)) {
1185 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1186 if (Mnemonic->getToken() == "la") {
1187 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001188 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001189 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1190 return MatchOperand_Success;
1191 }
1192 if (Tok.is(AsmToken::EndOfStatement)) {
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
Jack Carterd0bd6422013-04-18 00:41:53 +00001196 // Zero register assumed, add a memory operand with ZERO as its base.
1197 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1198 : Mips::ZERO,
1199 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001200 return MatchOperand_Success;
1201 }
1202 Error(Parser.getTok().getLoc(), "'(' expected");
1203 return MatchOperand_ParseFail;
1204 }
1205
Jack Carterd0bd6422013-04-18 00:41:53 +00001206 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001207 }
1208
1209 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001210 if (Tok1.is(AsmToken::Dollar)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001211 Parser.Lex(); // Eat the '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001212 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001213 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1214 return MatchOperand_ParseFail;
1215 }
1216
1217 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001218 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001219 return MatchOperand_ParseFail;
1220 }
1221
Jack Carterd0bd6422013-04-18 00:41:53 +00001222 const AsmToken &Tok2 = Parser.getTok(); // Get next token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001223 if (Tok2.isNot(AsmToken::RParen)) {
1224 Error(Parser.getTok().getLoc(), "')' expected");
1225 return MatchOperand_ParseFail;
1226 }
1227
Jack Carter873c7242013-01-12 01:03:14 +00001228 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1229
Jack Carterd0bd6422013-04-18 00:41:53 +00001230 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001231
1232 if (IdVal == 0)
1233 IdVal = MCConstantExpr::Create(0, getContext());
1234
Jack Carterd0bd6422013-04-18 00:41:53 +00001235 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001236 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1237 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001238 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001239 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001240 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001241 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1242 int64_t Imm;
1243 if (IdVal->EvaluateAsAbsolute(Imm))
1244 IdVal = MCConstantExpr::Create(Imm, getContext());
1245 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1246 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1247 getContext());
1248 }
1249
Jack Carterdc1e35d2012-09-06 20:00:02 +00001250 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1251 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001252 return MatchOperand_Success;
1253}
1254
Jack Carter873c7242013-01-12 01:03:14 +00001255MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +00001256MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1257 int RegKind) {
1258 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001259 if (getLexer().getKind() == AsmToken::Identifier) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001260 if (searchSymbolAlias(Operands, Kind))
Jack Carterd76b2372013-03-21 21:44:16 +00001261 return MatchOperand_Success;
1262 return MatchOperand_NoMatch;
1263 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001264 // If the first token is not '$', we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001265 if (Parser.getTok().isNot(AsmToken::Dollar))
1266 return MatchOperand_NoMatch;
1267
1268 Parser.Lex(); // Eat $
Vladimir Medic8cd17102013-06-20 11:21:49 +00001269 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001270 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001271 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001272 op->setRegKind(Kind);
Jack Carter873c7242013-01-12 01:03:14 +00001273 return MatchOperand_Success;
1274 }
1275 return MatchOperand_NoMatch;
1276}
Vladimir Medic8cd17102013-06-20 11:21:49 +00001277MipsAsmParser::OperandMatchResultTy
1278MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1279
1280 if (!isMips64())
1281 return MatchOperand_NoMatch;
1282 return parseRegs(Operands, (int) MipsOperand::Kind_CPU64Regs);
1283}
1284
1285MipsAsmParser::OperandMatchResultTy
1286MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1287 return parseRegs(Operands, (int) MipsOperand::Kind_CPURegs);
1288}
Jack Carter873c7242013-01-12 01:03:14 +00001289
Vladimir Medic233dd512013-06-24 10:05:34 +00001290MipsAsmParser::OperandMatchResultTy
1291MipsAsmParser::parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1292
1293 if (isFP64())
1294 return MatchOperand_NoMatch;
1295 // Double operand is expected, set appropriate format
1296 setFpFormat(FP_FORMAT_D);
1297
1298 return parseRegs(Operands, (int) MipsOperand::Kind_AFGR64Regs);
1299}
1300
1301MipsAsmParser::OperandMatchResultTy
1302MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1303 if (!isFP64())
1304 return MatchOperand_NoMatch;
1305 // Double operand is expected, set appropriate format
1306 setFpFormat(FP_FORMAT_D);
1307
1308 return parseRegs(Operands, (int) MipsOperand::Kind_FGR64Regs);
1309}
1310
1311MipsAsmParser::OperandMatchResultTy
1312MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1313 // Single operand is expected, set appropriate format
1314 setFpFormat(FP_FORMAT_S);
1315 return parseRegs(Operands, (int) MipsOperand::Kind_FGR32Regs);
1316}
1317
Jack Carterd0bd6422013-04-18 00:41:53 +00001318bool MipsAsmParser::searchSymbolAlias(
Vladimir Medic8cd17102013-06-20 11:21:49 +00001319 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001320
1321 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1322 if (Sym) {
1323 SMLoc S = Parser.getTok().getLoc();
1324 const MCExpr *Expr;
1325 if (Sym->isVariable())
1326 Expr = Sym->getVariableValue();
1327 else
1328 return false;
1329 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001330 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind) RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001331 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1332 const StringRef DefSymbol = Ref->getSymbol().getName();
1333 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00001334 int RegNum = -1;
1335 APInt IntVal(32, -1);
1336 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
1337 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
1338 isMips64()
1339 ? Mips::CPU64RegsRegClassID
1340 : Mips::CPURegsRegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001341 else {
1342 // Lookup for the register with the corresponding name.
1343 switch (Kind) {
1344 case MipsOperand::Kind_AFGR64Regs:
1345 case MipsOperand::Kind_FGR64Regs:
1346 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_D);
1347 break;
1348 case MipsOperand::Kind_FGR32Regs:
1349 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_S);
1350 break;
1351 case MipsOperand::Kind_CPU64Regs:
1352 case MipsOperand::Kind_CPURegs:
1353 default:
1354 RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
1355 break;
1356 }
1357 }
Jack Carterd76b2372013-03-21 21:44:16 +00001358 if (RegNum > -1) {
1359 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001360 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1361 Parser.getTok().getLoc());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001362 op->setRegKind(Kind);
Jack Carterd76b2372013-03-21 21:44:16 +00001363 Operands.push_back(op);
1364 return true;
1365 }
1366 }
1367 } else if (Expr->getKind() == MCExpr::Constant) {
1368 Parser.Lex();
1369 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001370 MipsOperand *op = MipsOperand::CreateImm(Const, S,
Jack Carter02593002013-05-28 22:21:05 +00001371 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001372 Operands.push_back(op);
1373 return true;
1374 }
1375 }
1376 return false;
1377}
Jack Carterd0bd6422013-04-18 00:41:53 +00001378
Jack Carter873c7242013-01-12 01:03:14 +00001379MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +00001380MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1381
Jack Carter2a74a87b2013-01-17 00:28:20 +00001382 if (isMips64())
1383 return MatchOperand_NoMatch;
1384
Jack Carterd0bd6422013-04-18 00:41:53 +00001385 // If the first token is not '$' we have error.
Jack Carter873c7242013-01-12 01:03:14 +00001386 if (Parser.getTok().isNot(AsmToken::Dollar))
1387 return MatchOperand_NoMatch;
1388 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001389 Parser.Lex(); // Eat the '$'.
Jack Carter873c7242013-01-12 01:03:14 +00001390
Jack Carterd0bd6422013-04-18 00:41:53 +00001391 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001392 if (Tok.isNot(AsmToken::Integer))
1393 return MatchOperand_NoMatch;
1394
1395 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001396 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001397 if (RegNum != 29)
1398 return MatchOperand_ParseFail;
1399
1400 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001401 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001402 op->setRegKind(MipsOperand::Kind_HWRegs);
1403 Operands.push_back(op);
1404
Jack Carterd0bd6422013-04-18 00:41:53 +00001405 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001406 return MatchOperand_Success;
1407}
1408
1409MipsAsmParser::OperandMatchResultTy
Jack Carterd0bd6422013-04-18 00:41:53 +00001410MipsAsmParser::parseHW64Regs(
1411 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001412
1413 if (!isMips64())
1414 return MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001415 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001416 if (Parser.getTok().isNot(AsmToken::Dollar))
1417 return MatchOperand_NoMatch;
1418 SMLoc S = Parser.getTok().getLoc();
1419 Parser.Lex(); // Eat $
1420
Jack Carterd0bd6422013-04-18 00:41:53 +00001421 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001422 if (Tok.isNot(AsmToken::Integer))
1423 return MatchOperand_NoMatch;
1424
1425 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001426 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001427 if (RegNum != 29)
1428 return MatchOperand_ParseFail;
1429
1430 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001431 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001432 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001433 Operands.push_back(op);
1434
Jack Carterd0bd6422013-04-18 00:41:53 +00001435 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001436 return MatchOperand_Success;
1437}
1438
1439MipsAsmParser::OperandMatchResultTy
1440MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1441 unsigned RegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001442 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001443 if (Parser.getTok().isNot(AsmToken::Dollar))
1444 return MatchOperand_NoMatch;
1445 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001446 Parser.Lex(); // Eat the '$'
Jack Carter873c7242013-01-12 01:03:14 +00001447
Jack Carterd0bd6422013-04-18 00:41:53 +00001448 const AsmToken &Tok = Parser.getTok(); // Get next token.
Jack Carter873c7242013-01-12 01:03:14 +00001449 if (Tok.is(AsmToken::Integer)) {
1450 RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001451 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001452 if (RegNum != 0)
1453 return MatchOperand_ParseFail;
1454 } else if (Tok.is(AsmToken::Identifier)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001455 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001456 if (Tok.getIdentifier() != "fcc0")
1457 return MatchOperand_ParseFail;
1458 } else
1459 return MatchOperand_NoMatch;
1460
1461 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001462 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001463 op->setRegKind(MipsOperand::Kind_CCRRegs);
1464 Operands.push_back(op);
1465
Jack Carterd0bd6422013-04-18 00:41:53 +00001466 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001467 return MatchOperand_Success;
1468}
1469
Jack Carterdc1e35d2012-09-06 20:00:02 +00001470MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1471
1472 MCSymbolRefExpr::VariantKind VK
1473 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1474 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1475 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1476 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1477 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1478 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1479 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1480 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1481 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1482 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1483 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1484 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1485 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1486 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1487 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1488 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1489 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1490 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1491 .Default(MCSymbolRefExpr::VK_None);
1492
1493 return VK;
1494}
Vladimir Medicea381912013-06-04 08:28:53 +00001495// Converts condition string to immediate operand value.
Benjamin Kramer47b5c572012-09-10 11:52:14 +00001496static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001497 int CC = StringSwitch<unsigned>(CondString)
Jack Carterd0bd6422013-04-18 00:41:53 +00001498 .Case(".f", 0)
1499 .Case(".un", 1)
1500 .Case(".eq", 2)
1501 .Case(".ueq", 3)
1502 .Case(".olt", 4)
1503 .Case(".ult", 5)
1504 .Case(".ole", 6)
1505 .Case(".ule", 7)
1506 .Case(".sf", 8)
1507 .Case(".ngle", 9)
1508 .Case(".seq", 10)
1509 .Case(".ngl", 11)
1510 .Case(".lt", 12)
1511 .Case(".nge", 13)
1512 .Case(".le", 14)
1513 .Case(".ngt", 15)
1514 .Default(-1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001515
1516 return CC;
1517}
1518
1519bool MipsAsmParser::
1520parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001521 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001522 // Split the format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001523 size_t Start = Name.find('.'), Next = Name.rfind('.');
1524 StringRef Format1 = Name.slice(Start, Next);
Jack Carterd0bd6422013-04-18 00:41:53 +00001525 // Add the first format to the operands.
Jack Cartera63b16a2012-09-07 00:23:42 +00001526 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carterd0bd6422013-04-18 00:41:53 +00001527 // Now for the second format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001528 StringRef Format2 = Name.slice(Next, StringRef::npos);
1529 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1530
Jack Carterd0bd6422013-04-18 00:41:53 +00001531 // Set the format for the first register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001532 setFpFormat(Format1);
1533
1534 // Read the remaining operands.
1535 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1536 // Read the first operand.
1537 if (ParseOperand(Operands, Name)) {
1538 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001539 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001540 return Error(Loc, "unexpected token in argument list");
1541 }
1542
1543 if (getLexer().isNot(AsmToken::Comma)) {
1544 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001545 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001546 return Error(Loc, "unexpected token in argument list");
Jack Cartera63b16a2012-09-07 00:23:42 +00001547 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001548 Parser.Lex(); // Eat the comma.
Jack Cartera63b16a2012-09-07 00:23:42 +00001549
Jack Carterb5cf5902013-04-17 00:18:04 +00001550 // Set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001551 setFpFormat(Format2);
1552
1553 // Parse and remember the operand.
1554 if (ParseOperand(Operands, Name)) {
1555 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001556 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001557 return Error(Loc, "unexpected token in argument list");
1558 }
1559 }
1560
1561 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1562 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001563 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001564 return Error(Loc, "unexpected token in argument list");
1565 }
1566
Jack Carterd0bd6422013-04-18 00:41:53 +00001567 Parser.Lex(); // Consume the EndOfStatement.
Jack Cartera63b16a2012-09-07 00:23:42 +00001568 return false;
1569}
1570
Rafael Espindola870c4e92012-01-11 03:56:41 +00001571bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001572ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001573 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter1ac53222013-02-20 23:11:17 +00001574 StringRef Mnemonic;
Jack Cartera63b16a2012-09-07 00:23:42 +00001575
Vladimir Medic233dd512013-06-24 10:05:34 +00001576 setDefaultFpFormat();
1577 // Create the leading tokens for the mnemonic, split by '.' characters.
1578 size_t Start = 0, Next = Name.find('.');
1579 Mnemonic = Name.slice(Start, Next);
Jack Cartera63b16a2012-09-07 00:23:42 +00001580
Vladimir Medic233dd512013-06-24 10:05:34 +00001581 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1582
1583 if (Next != StringRef::npos) {
1584 // There is a format token in mnemonic.
1585 size_t Dot = Name.find('.', Next + 1);
1586 StringRef Format = Name.slice(Next, Dot);
1587 if (Dot == StringRef::npos) // Only one '.' in a string, it's a format.
1588 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1589 else {
1590 if (Name.startswith("c.")) {
1591 // Floating point compare, add '.' and immediate represent for cc.
1592 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1593 int Cc = ConvertCcString(Format);
1594 if (Cc == -1) {
1595 return Error(NameLoc, "Invalid conditional code");
Jack Cartera63b16a2012-09-07 00:23:42 +00001596 }
Vladimir Medic233dd512013-06-24 10:05:34 +00001597 SMLoc E = SMLoc::getFromPointer(
1598 Parser.getTok().getLoc().getPointer() - 1);
1599 Operands.push_back(
1600 MipsOperand::CreateImm(MCConstantExpr::Create(Cc, getContext()),
1601 NameLoc, E));
1602 } else {
1603 // trunc, ceil, floor ...
1604 return parseMathOperation(Name, NameLoc, Operands);
Jack Cartera63b16a2012-09-07 00:23:42 +00001605 }
1606
Vladimir Medic233dd512013-06-24 10:05:34 +00001607 // The rest is a format.
1608 Format = Name.slice(Dot, StringRef::npos);
1609 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
Jack Cartera63b16a2012-09-07 00:23:42 +00001610 }
Vladimir Medic233dd512013-06-24 10:05:34 +00001611
1612 setFpFormat(Format);
Jack Cartera63b16a2012-09-07 00:23:42 +00001613 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001614
1615 // Read the remaining operands.
1616 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1617 // Read the first operand.
Jack Carter1ac53222013-02-20 23:11:17 +00001618 if (ParseOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001619 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001620 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001621 return Error(Loc, "unexpected token in argument list");
1622 }
1623
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 while (getLexer().is(AsmToken::Comma)) {
1625 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001626
1627 // Parse and remember the operand.
1628 if (ParseOperand(Operands, Name)) {
1629 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001630 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001631 return Error(Loc, "unexpected token in argument list");
1632 }
1633 }
1634 }
1635
1636 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1637 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001638 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001639 return Error(Loc, "unexpected token in argument list");
1640 }
1641
Jack Carterd0bd6422013-04-18 00:41:53 +00001642 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001643 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001644}
1645
Jack Carter0b744b32012-10-04 02:29:46 +00001646bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001647 SMLoc Loc = getLexer().getLoc();
1648 Parser.eatToEndOfStatement();
1649 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001650}
1651
1652bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001653 // Line should look like: ".set noat".
1654 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001655 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001656 // eat noat
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("unexpected token in statement");
1661 return false;
1662 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001663 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001664 return false;
1665}
Jack Carterd0bd6422013-04-18 00:41:53 +00001666
Jack Carter0b744b32012-10-04 02:29:46 +00001667bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001668 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001669 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001670 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001671 getParser().Lex();
1672 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001673 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001674 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001675 return false;
1676 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001677 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001678 if (getLexer().isNot(AsmToken::Dollar)) {
1679 reportParseError("unexpected token in statement");
1680 return false;
1681 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001682 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001683 const AsmToken &Reg = Parser.getTok();
1684 if (Reg.is(AsmToken::Identifier)) {
1685 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1686 } else if (Reg.is(AsmToken::Integer)) {
1687 AtRegNo = Reg.getIntVal();
1688 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001689 reportParseError("unexpected token in statement");
1690 return false;
1691 }
Jack Carter1ac53222013-02-20 23:11:17 +00001692
Jack Carterd0bd6422013-04-18 00:41:53 +00001693 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001694 reportParseError("unexpected token in statement");
1695 return false;
1696 }
1697
1698 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001699 reportParseError("unexpected token in statement");
1700 return false;
1701 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001702 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001703
1704 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1705 reportParseError("unexpected token in statement");
1706 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001707 }
1708 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001709 return false;
1710 } else {
1711 reportParseError("unexpected token in statement");
1712 return false;
1713 }
1714}
1715
1716bool MipsAsmParser::parseSetReorderDirective() {
1717 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001718 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001719 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1720 reportParseError("unexpected token in statement");
1721 return false;
1722 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001723 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001724 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001725 return false;
1726}
1727
1728bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001729 Parser.Lex();
1730 // If this is not the end of the statement, report an error.
1731 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1732 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001733 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001734 }
1735 Options.setNoreorder();
1736 Parser.Lex(); // Consume the EndOfStatement.
1737 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001738}
1739
1740bool MipsAsmParser::parseSetMacroDirective() {
1741 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001742 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001743 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1744 reportParseError("unexpected token in statement");
1745 return false;
1746 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001747 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001748 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001749 return false;
1750}
1751
1752bool MipsAsmParser::parseSetNoMacroDirective() {
1753 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001754 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001755 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1756 reportParseError("`noreorder' must be set before `nomacro'");
1757 return false;
1758 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001759 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001760 reportParseError("`noreorder' must be set before `nomacro'");
1761 return false;
1762 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001763 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001764 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001765 return false;
1766}
Jack Carterd76b2372013-03-21 21:44:16 +00001767
1768bool MipsAsmParser::parseSetAssignment() {
1769 StringRef Name;
1770 const MCExpr *Value;
1771
1772 if (Parser.parseIdentifier(Name))
1773 reportParseError("expected identifier after .set");
1774
1775 if (getLexer().isNot(AsmToken::Comma))
1776 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001777 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001778
Jack Carter02593002013-05-28 22:21:05 +00001779 if (getLexer().is(AsmToken::Dollar)) {
1780 MCSymbol *Symbol;
1781 SMLoc DollarLoc = getLexer().getLoc();
1782 // Consume the dollar sign, and check for a following identifier.
1783 Parser.Lex();
1784 // We have a '$' followed by something, make sure they are adjacent.
1785 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
1786 return true;
1787 StringRef Res = StringRef(DollarLoc.getPointer(),
1788 getTok().getEndLoc().getPointer() - DollarLoc.getPointer());
1789 Symbol = getContext().GetOrCreateSymbol(Res);
1790 Parser.Lex();
1791 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
1792 getContext());
1793 } else if (Parser.parseExpression(Value))
1794 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00001795
Jack Carterd0bd6422013-04-18 00:41:53 +00001796 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001797 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001798 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001799 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001800 Sym = getContext().GetOrCreateSymbol(Name);
1801 Sym->setVariableValue(Value);
1802
1803 return false;
1804}
Jack Carterd0bd6422013-04-18 00:41:53 +00001805
Jack Carter0b744b32012-10-04 02:29:46 +00001806bool MipsAsmParser::parseDirectiveSet() {
1807
Jack Carterd0bd6422013-04-18 00:41:53 +00001808 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001809 const AsmToken &Tok = Parser.getTok();
1810
1811 if (Tok.getString() == "noat") {
1812 return parseSetNoAtDirective();
1813 } else if (Tok.getString() == "at") {
1814 return parseSetAtDirective();
1815 } else if (Tok.getString() == "reorder") {
1816 return parseSetReorderDirective();
1817 } else if (Tok.getString() == "noreorder") {
1818 return parseSetNoReorderDirective();
1819 } else if (Tok.getString() == "macro") {
1820 return parseSetMacroDirective();
1821 } else if (Tok.getString() == "nomacro") {
1822 return parseSetNoMacroDirective();
1823 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001824 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001825 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001826 return false;
1827 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001828 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001829 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001830 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001831 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001832 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001833 parseSetAssignment();
1834 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001835 }
Jack Carter07c818d2013-01-25 01:31:34 +00001836
Jack Carter0b744b32012-10-04 02:29:46 +00001837 return true;
1838}
1839
Jack Carter07c818d2013-01-25 01:31:34 +00001840/// parseDirectiveWord
1841/// ::= .word [ expression (, expression)* ]
1842bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1843 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1844 for (;;) {
1845 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001846 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001847 return true;
1848
1849 getParser().getStreamer().EmitValue(Value, Size);
1850
1851 if (getLexer().is(AsmToken::EndOfStatement))
1852 break;
1853
1854 // FIXME: Improve diagnostic.
1855 if (getLexer().isNot(AsmToken::Comma))
1856 return Error(L, "unexpected token in directive");
1857 Parser.Lex();
1858 }
1859 }
1860
1861 Parser.Lex();
1862 return false;
1863}
1864
Jack Carter0b744b32012-10-04 02:29:46 +00001865bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001866
Jack Carter07c818d2013-01-25 01:31:34 +00001867 StringRef IDVal = DirectiveID.getString();
1868
Jack Carterd0bd6422013-04-18 00:41:53 +00001869 if (IDVal == ".ent") {
1870 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001871 Parser.Lex();
1872 return false;
1873 }
1874
Jack Carter07c818d2013-01-25 01:31:34 +00001875 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001876 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001877 Parser.Lex();
1878 return false;
1879 }
1880
Jack Carter07c818d2013-01-25 01:31:34 +00001881 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001882 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001883 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001884 return false;
1885 }
1886
Jack Carter07c818d2013-01-25 01:31:34 +00001887 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001888 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001889 }
1890
Jack Carter07c818d2013-01-25 01:31:34 +00001891 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001892 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001893 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001894 return false;
1895 }
1896
Jack Carter07c818d2013-01-25 01:31:34 +00001897 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001898 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001899 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001900 return false;
1901 }
1902
Jack Carter07c818d2013-01-25 01:31:34 +00001903 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001904 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001905 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001906 return false;
1907 }
1908
Jack Carter07c818d2013-01-25 01:31:34 +00001909 if (IDVal == ".word") {
1910 parseDirectiveWord(4, DirectiveID.getLoc());
1911 return false;
1912 }
1913
Rafael Espindola870c4e92012-01-11 03:56:41 +00001914 return true;
1915}
1916
Rafael Espindola870c4e92012-01-11 03:56:41 +00001917extern "C" void LLVMInitializeMipsAsmParser() {
1918 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1919 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1920 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1921 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1922}
Jack Carterb4dbc172012-09-05 23:34:03 +00001923
1924#define GET_REGISTER_MATCHER
1925#define GET_MATCHER_IMPLEMENTATION
1926#include "MipsGenAsmMatcher.inc"