blob: ff55905dfe73945d570f97d7d9b31336722fa26d [file] [log] [blame]
Jia Liuc5707112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindolafddf8042012-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 Carterec65be82012-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"
16#include "llvm/MC/MCStreamer.h"
17#include "llvm/MC/MCSubtargetInfo.h"
18#include "llvm/MC/MCSymbol.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000020#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterec65be82012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carter30116cd2012-10-04 02:29:46 +000027class MipsAssemblerOptions {
28public:
29 MipsAssemblerOptions():
30 aTReg(1), reorder(true), macro(true) {
31 }
Jack Carterec65be82012-09-05 23:34:03 +000032
Jack Carter30116cd2012-10-04 02:29:46 +000033 unsigned getATRegNum() {return aTReg;}
34 bool setATReg(unsigned Reg);
35
36 bool isReorder() {return reorder;}
37 void setReorder() {reorder = true;}
38 void setNoreorder() {reorder = false;}
39
40 bool isMacro() {return macro;}
41 void setMacro() {macro = true;}
42 void setNomacro() {macro = false;}
43
44private:
45 unsigned aTReg;
46 bool reorder;
47 bool macro;
48};
49}
50
51namespace {
Rafael Espindolafddf8042012-01-11 03:56:41 +000052class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000053
Jack Carterf740d6e2012-09-07 00:23:42 +000054 enum FpFormatTy {
55 FP_FORMAT_NONE = -1,
56 FP_FORMAT_S,
57 FP_FORMAT_D,
58 FP_FORMAT_L,
59 FP_FORMAT_W
60 } FpFormat;
61
Jack Carterec65be82012-09-05 23:34:03 +000062 MCSubtargetInfo &STI;
63 MCAsmParser &Parser;
Jack Carter30116cd2012-10-04 02:29:46 +000064 MipsAssemblerOptions *Options;
65
Jack Carterec65be82012-09-05 23:34:03 +000066
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Rafael Espindolafddf8042012-01-11 03:56:41 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc,
71 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
72 MCStreamer &Out);
73
74 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
75
76 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000077 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000078
Jack Carterf740d6e2012-09-07 00:23:42 +000079 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
80 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
81
Rafael Espindolafddf8042012-01-11 03:56:41 +000082 bool ParseDirective(AsmToken DirectiveID);
83
Jack Carterec65be82012-09-05 23:34:03 +000084 MipsAsmParser::OperandMatchResultTy
85 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier038f3e32012-09-03 18:47:45 +000086
Jack Carterec65be82012-09-05 23:34:03 +000087 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
88 StringRef Mnemonic);
89
90 int tryParseRegister(StringRef Mnemonic);
91
92 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
93 StringRef Mnemonic);
94
Jack Carter30116cd2012-10-04 02:29:46 +000095 bool reportParseError(StringRef ErrorMsg);
96
Jack Carter6b96c3f2012-09-06 20:00:02 +000097 bool parseMemOffset(const MCExpr *&Res);
98 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter30116cd2012-10-04 02:29:46 +000099
100 bool parseDirectiveSet();
101
102 bool parseSetAtDirective();
103 bool parseSetNoAtDirective();
104 bool parseSetMacroDirective();
105 bool parseSetNoMacroDirective();
106 bool parseSetReorderDirective();
107 bool parseSetNoReorderDirective();
108
Jack Carter6b96c3f2012-09-06 20:00:02 +0000109 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +0000110
Jack Carterec65be82012-09-05 23:34:03 +0000111 bool isMips64() const {
112 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
113 }
114
Jack Carterf740d6e2012-09-07 00:23:42 +0000115 bool isFP64() const {
116 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
117 }
118
Jack Carterec65be82012-09-05 23:34:03 +0000119 int matchRegisterName(StringRef Symbol);
120
121 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
122
Jack Carterf740d6e2012-09-07 00:23:42 +0000123 void setFpFormat(FpFormatTy Format) {
124 FpFormat = Format;
125 }
126
127 void setDefaultFpFormat();
128
129 void setFpFormat(StringRef Format);
130
131 FpFormatTy getFpFormat() {return FpFormat;}
132
133 bool requestsDoubleOperand(StringRef Mnemonic);
134
Jack Carterec65be82012-09-05 23:34:03 +0000135 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000136
Jack Carter30116cd2012-10-04 02:29:46 +0000137 unsigned getATReg();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000138public:
139 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000140 : MCTargetAsmParser(), STI(sti), Parser(parser) {
141 // Initialize the set of available features.
142 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jack Carter30116cd2012-10-04 02:29:46 +0000143 Options = new MipsAssemblerOptions();
Rafael Espindolafddf8042012-01-11 03:56:41 +0000144 }
145
Jack Carterec65be82012-09-05 23:34:03 +0000146 MCAsmParser &getParser() const { return Parser; }
147 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
148
Rafael Espindolafddf8042012-01-11 03:56:41 +0000149};
150}
151
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000152namespace {
153
154/// MipsOperand - Instances of this class represent a parsed Mips machine
155/// instruction.
156class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000157
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000158 enum KindTy {
159 k_CondCode,
160 k_CoprocNum,
161 k_Immediate,
162 k_Memory,
163 k_PostIndexRegister,
164 k_Register,
165 k_Token
166 } Kind;
167
168 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000169
170 union {
171 struct {
172 const char *Data;
173 unsigned Length;
174 } Tok;
175
176 struct {
177 unsigned RegNum;
178 } Reg;
179
180 struct {
181 const MCExpr *Val;
182 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000183
184 struct {
185 unsigned Base;
186 const MCExpr *Off;
187 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000188 };
189
190 SMLoc StartLoc, EndLoc;
191
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000192public:
193 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000194 assert(N == 1 && "Invalid number of operands!");
195 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000196 }
Jack Carterec65be82012-09-05 23:34:03 +0000197
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000198 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000199 // Add as immediate when possible. Null MCExpr = 0.
200 if (Expr == 0)
201 Inst.addOperand(MCOperand::CreateImm(0));
202 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
203 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
204 else
205 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000206 }
Jack Carterec65be82012-09-05 23:34:03 +0000207
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000208 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000209 assert(N == 1 && "Invalid number of operands!");
210 const MCExpr *Expr = getImm();
211 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000212 }
Jack Carterec65be82012-09-05 23:34:03 +0000213
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000214 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000215 assert(N == 2 && "Invalid number of operands!");
216
217 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
218
219 const MCExpr *Expr = getMemOff();
220 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000221 }
222
223 bool isReg() const { return Kind == k_Register; }
224 bool isImm() const { return Kind == k_Immediate; }
225 bool isToken() const { return Kind == k_Token; }
226 bool isMem() const { return Kind == k_Memory; }
227
228 StringRef getToken() const {
229 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000230 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000231 }
232
233 unsigned getReg() const {
234 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000235 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000236 }
237
Jack Carterec65be82012-09-05 23:34:03 +0000238 const MCExpr *getImm() const {
239 assert((Kind == k_Immediate) && "Invalid access!");
240 return Imm.Val;
241 }
242
Jack Carter6b96c3f2012-09-06 20:00:02 +0000243 unsigned getMemBase() const {
244 assert((Kind == k_Memory) && "Invalid access!");
245 return Mem.Base;
246 }
247
248 const MCExpr *getMemOff() const {
249 assert((Kind == k_Memory) && "Invalid access!");
250 return Mem.Off;
251 }
252
Jack Carterec65be82012-09-05 23:34:03 +0000253 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
254 MipsOperand *Op = new MipsOperand(k_Token);
255 Op->Tok.Data = Str.data();
256 Op->Tok.Length = Str.size();
257 Op->StartLoc = S;
258 Op->EndLoc = S;
259 return Op;
260 }
261
262 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
263 MipsOperand *Op = new MipsOperand(k_Register);
264 Op->Reg.RegNum = RegNum;
265 Op->StartLoc = S;
266 Op->EndLoc = E;
267 return Op;
268 }
269
270 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
271 MipsOperand *Op = new MipsOperand(k_Immediate);
272 Op->Imm.Val = Val;
273 Op->StartLoc = S;
274 Op->EndLoc = E;
275 return Op;
276 }
277
Jack Carter6b96c3f2012-09-06 20:00:02 +0000278 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
279 SMLoc S, SMLoc E) {
280 MipsOperand *Op = new MipsOperand(k_Memory);
281 Op->Mem.Base = Base;
282 Op->Mem.Off = Off;
283 Op->StartLoc = S;
284 Op->EndLoc = E;
285 return Op;
286 }
287
Jack Carterec65be82012-09-05 23:34:03 +0000288 /// getStartLoc - Get the location of the first token of this operand.
289 SMLoc getStartLoc() const { return StartLoc; }
290 /// getEndLoc - Get the location of the last token of this operand.
291 SMLoc getEndLoc() const { return EndLoc; }
292
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000293 virtual void print(raw_ostream &OS) const {
294 llvm_unreachable("unimplemented!");
295 }
296};
297}
298
Rafael Espindolafddf8042012-01-11 03:56:41 +0000299bool MipsAsmParser::
300MatchAndEmitInstruction(SMLoc IDLoc,
301 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
302 MCStreamer &Out) {
Jack Carterec65be82012-09-05 23:34:03 +0000303 MCInst Inst;
Jack Carterec65be82012-09-05 23:34:03 +0000304 unsigned Kind;
Chad Rosier22685872012-10-01 23:45:51 +0000305 unsigned ErrorInfo;
306 SmallVector<std::pair< unsigned, std::string >, 4> MapAndConstraints;
307 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
308 MapAndConstraints, ErrorInfo,
309 /*matchingInlineAsm*/ false);
Jack Carterec65be82012-09-05 23:34:03 +0000310
311 switch (MatchResult) {
312 default: break;
313 case Match_Success: {
314 Inst.setLoc(IDLoc);
315 Out.EmitInstruction(Inst);
316 return false;
317 }
318 case Match_MissingFeature:
319 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
320 return true;
321 case Match_InvalidOperand: {
322 SMLoc ErrorLoc = IDLoc;
323 if (ErrorInfo != ~0U) {
324 if (ErrorInfo >= Operands.size())
325 return Error(IDLoc, "too few operands for instruction");
326
327 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
328 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
329 }
330
331 return Error(ErrorLoc, "invalid operand for instruction");
332 }
333 case Match_MnemonicFail:
334 return Error(IDLoc, "invalid instruction");
335 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000336 return true;
337}
338
Jack Carterec65be82012-09-05 23:34:03 +0000339int MipsAsmParser::matchRegisterName(StringRef Name) {
340
341 int CC = StringSwitch<unsigned>(Name)
342 .Case("zero", Mips::ZERO)
343 .Case("a0", Mips::A0)
344 .Case("a1", Mips::A1)
345 .Case("a2", Mips::A2)
346 .Case("a3", Mips::A3)
347 .Case("v0", Mips::V0)
348 .Case("v1", Mips::V1)
349 .Case("s0", Mips::S0)
350 .Case("s1", Mips::S1)
351 .Case("s2", Mips::S2)
352 .Case("s3", Mips::S3)
353 .Case("s4", Mips::S4)
354 .Case("s5", Mips::S5)
355 .Case("s6", Mips::S6)
356 .Case("s7", Mips::S7)
357 .Case("k0", Mips::K0)
358 .Case("k1", Mips::K1)
359 .Case("sp", Mips::SP)
360 .Case("fp", Mips::FP)
361 .Case("gp", Mips::GP)
362 .Case("ra", Mips::RA)
363 .Case("t0", Mips::T0)
364 .Case("t1", Mips::T1)
365 .Case("t2", Mips::T2)
366 .Case("t3", Mips::T3)
367 .Case("t4", Mips::T4)
368 .Case("t5", Mips::T5)
369 .Case("t6", Mips::T6)
370 .Case("t7", Mips::T7)
371 .Case("t8", Mips::T8)
372 .Case("t9", Mips::T9)
373 .Case("at", Mips::AT)
374 .Case("fcc0", Mips::FCC0)
375 .Default(-1);
376
377 if (CC != -1) {
378 //64 bit register in Mips are following 32 bit definitions.
379 if (isMips64())
380 CC++;
381 return CC;
382 }
383
Jack Carterf740d6e2012-09-07 00:23:42 +0000384 if (Name[0] == 'f') {
385 StringRef NumString = Name.substr(1);
386 unsigned IntVal;
387 if( NumString.getAsInteger(10, IntVal))
388 return -1; //not integer
389 if (IntVal > 31)
390 return -1;
391
392 FpFormatTy Format = getFpFormat();
393
394 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
395 return getReg(Mips::FGR32RegClassID, IntVal);
396 if (Format == FP_FORMAT_D) {
397 if(isFP64()) {
398 return getReg(Mips::FGR64RegClassID, IntVal);
399 }
400 //only even numbers available as register pairs
401 if (( IntVal > 31) || (IntVal%2 != 0))
402 return -1;
403 return getReg(Mips::AFGR64RegClassID, IntVal/2);
404 }
405 }
406
Jack Carterec65be82012-09-05 23:34:03 +0000407 return -1;
408}
Jack Carterf740d6e2012-09-07 00:23:42 +0000409void MipsAsmParser::setDefaultFpFormat() {
410
411 if (isMips64() || isFP64())
412 FpFormat = FP_FORMAT_D;
413 else
414 FpFormat = FP_FORMAT_S;
415}
416
417bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
418
419 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
420 .Case("ldxc1", true)
421 .Case("ldc1", true)
422 .Case("sdxc1", true)
423 .Case("sdc1", true)
424 .Default(false);
425
426 return IsDouble;
427}
428void MipsAsmParser::setFpFormat(StringRef Format) {
429
430 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
431 .Case(".s", FP_FORMAT_S)
432 .Case(".d", FP_FORMAT_D)
433 .Case(".l", FP_FORMAT_L)
434 .Case(".w", FP_FORMAT_W)
435 .Default(FP_FORMAT_NONE);
436}
Jack Carterec65be82012-09-05 23:34:03 +0000437
Jack Carter30116cd2012-10-04 02:29:46 +0000438bool MipsAssemblerOptions::setATReg(unsigned Reg) {
439 if (Reg > 31)
440 return false;
441
442 aTReg = Reg;
443 return true;
444}
445
446unsigned MipsAsmParser::getATReg() {
447 unsigned Reg = Options->getATRegNum();
448 if (isMips64())
449 return getReg(Mips::CPU64RegsRegClassID,Reg);
450 else
451 return getReg(Mips::CPURegsRegClassID,Reg);
452}
453
454unsigned MipsAsmParser::getReg(int RC,int RegNo) {
Jack Carterec65be82012-09-05 23:34:03 +0000455 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
456}
457
Jack Carter30116cd2012-10-04 02:29:46 +0000458int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
Jack Carterec65be82012-09-05 23:34:03 +0000459
460 if (Mnemonic.lower() == "rdhwr") {
461 //at the moment only hwreg29 is supported
462 if (RegNum != 29)
463 return -1;
464 return Mips::HWR29;
465 }
466
467 if (RegNum > 31)
468 return -1;
469
Jack Carter30116cd2012-10-04 02:29:46 +0000470 return getReg(Mips::CPURegsRegClassID, RegNum);
Jack Carterec65be82012-09-05 23:34:03 +0000471}
472
473int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
474 const AsmToken &Tok = Parser.getTok();
475 int RegNum = -1;
476
477 if (Tok.is(AsmToken::Identifier)) {
478 std::string lowerCase = Tok.getString().lower();
479 RegNum = matchRegisterName(lowerCase);
480 } else if (Tok.is(AsmToken::Integer))
Jack Carter6b96c3f2012-09-06 20:00:02 +0000481 RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()),
482 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000483 else
484 return RegNum; //error
485 //64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
486 if (isMips64() && RegNum == Mips::ZERO_64) {
487 if (Mnemonic.find("ddiv") != StringRef::npos)
488 RegNum = Mips::ZERO;
489 }
Jack Carterec65be82012-09-05 23:34:03 +0000490 return RegNum;
491}
492
Rafael Espindolafddf8042012-01-11 03:56:41 +0000493bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000494 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
495 StringRef Mnemonic){
496
497 SMLoc S = Parser.getTok().getLoc();
498 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000499
500 //FIXME: we should make a more generic method for CCR
501 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
502 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
503 RegNo = Parser.getTok().getIntVal(); //get the int value
504 //at the moment only fcc0 is supported
505 if (RegNo == 0)
506 RegNo = Mips::FCC0;
507 } else
508 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000509 if (RegNo == -1)
510 return true;
511
512 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000513 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000514 Parser.Lex(); // Eat register token.
515 return false;
516}
517
518bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
519 StringRef Mnemonic) {
520 //Check if the current operand has a custom associated parser, if so, try to
521 //custom parse the operand, or fallback to the general approach.
522 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
523 if (ResTy == MatchOperand_Success)
524 return false;
525 // If there wasn't a custom match, try the generic matcher below. Otherwise,
526 // there was a match, but an error occurred, in which case, just return that
527 // the operand parsing failed.
528 if (ResTy == MatchOperand_ParseFail)
529 return true;
530
531 switch (getLexer().getKind()) {
532 default:
533 Error(Parser.getTok().getLoc(), "unexpected token in operand");
534 return true;
535 case AsmToken::Dollar: {
536 //parse register
537 SMLoc S = Parser.getTok().getLoc();
538 Parser.Lex(); // Eat dollar token.
539 //parse register operand
540 if (!tryParseRegisterOperand(Operands,Mnemonic)) {
541 if (getLexer().is(AsmToken::LParen)) {
542 //check if it is indexed addressing operand
543 Operands.push_back(MipsOperand::CreateToken("(", S));
544 Parser.Lex(); //eat parenthesis
545 if (getLexer().isNot(AsmToken::Dollar))
546 return true;
547
548 Parser.Lex(); //eat dollar
549 if (tryParseRegisterOperand(Operands,Mnemonic))
550 return true;
551
552 if (!getLexer().is(AsmToken::RParen))
553 return true;
554
555 S = Parser.getTok().getLoc();
556 Operands.push_back(MipsOperand::CreateToken(")", S));
557 Parser.Lex();
558 }
559 return false;
560 }
561 //maybe it is a symbol reference
562 StringRef Identifier;
563 if (Parser.ParseIdentifier(Identifier))
564 return true;
565
Jack Carter6b96c3f2012-09-06 20:00:02 +0000566 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000567
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000568 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000569
570 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000571 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000572 getContext());
573
574 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
575 return false;
576 }
577 case AsmToken::Identifier:
578 case AsmToken::LParen:
579 case AsmToken::Minus:
580 case AsmToken::Plus:
581 case AsmToken::Integer:
582 case AsmToken::String: {
583 // quoted label names
584 const MCExpr *IdVal;
585 SMLoc S = Parser.getTok().getLoc();
586 if (getParser().ParseExpression(IdVal))
587 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000588 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000589 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
590 return false;
591 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000592 case AsmToken::Percent: {
593 //it is a symbol reference or constant expression
594 const MCExpr *IdVal;
595 SMLoc S = Parser.getTok().getLoc(); //start location of the operand
596 if (parseRelocOperand(IdVal))
597 return true;
598
599 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
600
601 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
602 return false;
Jack Carter30116cd2012-10-04 02:29:46 +0000603 } // case AsmToken::Percent
604 } // switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000605 return true;
606}
607
Jack Carter6b96c3f2012-09-06 20:00:02 +0000608bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
609
Jack Carter30116cd2012-10-04 02:29:46 +0000610 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000611 const AsmToken &Tok = Parser.getTok(); //get next token, operation
612 if (Tok.isNot(AsmToken::Identifier))
613 return true;
614
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000615 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000616
617 Parser.Lex(); //eat identifier
Jack Carter30116cd2012-10-04 02:29:46 +0000618 // now make expression from the rest of the operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000619 const MCExpr *IdVal;
620 SMLoc EndLoc;
621
622 if (getLexer().getKind() == AsmToken::LParen) {
623 while (1) {
Jack Carter30116cd2012-10-04 02:29:46 +0000624 Parser.Lex(); // eat '(' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000625 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carter30116cd2012-10-04 02:29:46 +0000626 Parser.Lex(); // eat % token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000627 const AsmToken &nextTok = Parser.getTok();
628 if (nextTok.isNot(AsmToken::Identifier))
629 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000630 Str += "(%";
631 Str += nextTok.getIdentifier();
Jack Carter30116cd2012-10-04 02:29:46 +0000632 Parser.Lex(); // eat identifier
Jack Carter6b96c3f2012-09-06 20:00:02 +0000633 if (getLexer().getKind() != AsmToken::LParen)
634 return true;
635 } else
636 break;
637 }
638 if (getParser().ParseParenExpression(IdVal,EndLoc))
639 return true;
640
641 while (getLexer().getKind() == AsmToken::RParen)
Jack Carter30116cd2012-10-04 02:29:46 +0000642 Parser.Lex(); // eat ')' token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000643
644 } else
Jack Carter30116cd2012-10-04 02:29:46 +0000645 return true; // parenthesis must follow reloc operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000646
Jack Carter30116cd2012-10-04 02:29:46 +0000647 // Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000648 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000649 //it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000650 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000651 if (Str == "lo") {
652 Val = Val & 0xffff;
653 } else if (Str == "hi") {
654 Val = (Val & 0xffff0000) >> 16;
655 }
656 Res = MCConstantExpr::Create(Val, getContext());
657 return false;
658 }
659
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000660 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter30116cd2012-10-04 02:29:46 +0000661 // it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000662 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000663 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
664 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
665 return false;
666 }
667 return true;
668}
669
Jack Carterec65be82012-09-05 23:34:03 +0000670bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
671 SMLoc &EndLoc) {
672
673 StartLoc = Parser.getTok().getLoc();
674 RegNo = tryParseRegister("");
675 EndLoc = Parser.getTok().getLoc();
676 return (RegNo == (unsigned)-1);
677}
678
Jack Carter6b96c3f2012-09-06 20:00:02 +0000679bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
680
681 SMLoc S;
682
683 switch(getLexer().getKind()) {
684 default:
685 return true;
686 case AsmToken::Integer:
687 case AsmToken::Minus:
688 case AsmToken::Plus:
689 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000690 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000691 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000692 case AsmToken::LParen:
Jack Carter30116cd2012-10-04 02:29:46 +0000693 return false; // it's probably assuming 0
Jack Carter6b96c3f2012-09-06 20:00:02 +0000694 }
695 return true;
696}
697
Jack Carterec65be82012-09-05 23:34:03 +0000698MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
699 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000700
701 const MCExpr *IdVal = 0;
702 SMLoc S;
Jack Carter30116cd2012-10-04 02:29:46 +0000703 // first operand is the offset
Jack Carter6b96c3f2012-09-06 20:00:02 +0000704 S = Parser.getTok().getLoc();
705
706 if (parseMemOffset(IdVal))
707 return MatchOperand_ParseFail;
708
Jack Carter30116cd2012-10-04 02:29:46 +0000709 const AsmToken &Tok = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000710 if (Tok.isNot(AsmToken::LParen)) {
711 Error(Parser.getTok().getLoc(), "'(' expected");
712 return MatchOperand_ParseFail;
713 }
714
715 Parser.Lex(); // Eat '(' token.
716
717 const AsmToken &Tok1 = Parser.getTok(); //get next token
718 if (Tok1.is(AsmToken::Dollar)) {
719 Parser.Lex(); // Eat '$' token.
720 if (tryParseRegisterOperand(Operands,"")) {
721 Error(Parser.getTok().getLoc(), "unexpected token in operand");
722 return MatchOperand_ParseFail;
723 }
724
725 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000726 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carter6b96c3f2012-09-06 20:00:02 +0000727 return MatchOperand_ParseFail;
728 }
729
Jack Carter30116cd2012-10-04 02:29:46 +0000730 const AsmToken &Tok2 = Parser.getTok(); // get next token
Jack Carter6b96c3f2012-09-06 20:00:02 +0000731 if (Tok2.isNot(AsmToken::RParen)) {
732 Error(Parser.getTok().getLoc(), "')' expected");
733 return MatchOperand_ParseFail;
734 }
735
736 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
737
738 Parser.Lex(); // Eat ')' token.
739
740 if (IdVal == 0)
741 IdVal = MCConstantExpr::Create(0, getContext());
742
Jack Carter30116cd2012-10-04 02:29:46 +0000743 // now replace register operand with the mem operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000744 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
745 int RegNo = op->getReg();
Jack Carter30116cd2012-10-04 02:29:46 +0000746 // remove register from operands
Jack Carter6b96c3f2012-09-06 20:00:02 +0000747 Operands.pop_back();
Jack Carter30116cd2012-10-04 02:29:46 +0000748 // and add memory operand
Jack Carter6b96c3f2012-09-06 20:00:02 +0000749 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
750 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000751 return MatchOperand_Success;
752}
753
Jack Carter6b96c3f2012-09-06 20:00:02 +0000754MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
755
756 MCSymbolRefExpr::VariantKind VK
757 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
758 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
759 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
760 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
761 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
762 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
763 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
764 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
765 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
766 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
767 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
768 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
769 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
770 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
771 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
772 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
773 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
774 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
775 .Default(MCSymbolRefExpr::VK_None);
776
777 return VK;
778}
779
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000780static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000781 int CC = StringSwitch<unsigned>(CondString)
782 .Case(".f", 0)
783 .Case(".un", 1)
784 .Case(".eq", 2)
785 .Case(".ueq", 3)
786 .Case(".olt", 4)
787 .Case(".ult", 5)
788 .Case(".ole", 6)
789 .Case(".ule", 7)
790 .Case(".sf", 8)
791 .Case(".ngle", 9)
792 .Case(".seq", 10)
793 .Case(".ngl", 11)
794 .Case(".lt", 12)
795 .Case(".nge", 13)
796 .Case(".le", 14)
797 .Case(".ngt", 15)
798 .Default(-1);
799
800 return CC;
801}
802
803bool MipsAsmParser::
804parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter30116cd2012-10-04 02:29:46 +0000805 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
806 // split the format
Jack Carterf740d6e2012-09-07 00:23:42 +0000807 size_t Start = Name.find('.'), Next = Name.rfind('.');
808 StringRef Format1 = Name.slice(Start, Next);
Jack Carter30116cd2012-10-04 02:29:46 +0000809 // and add the first format to the operands
Jack Carterf740d6e2012-09-07 00:23:42 +0000810 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carter30116cd2012-10-04 02:29:46 +0000811 // now for the second format
Jack Carterf740d6e2012-09-07 00:23:42 +0000812 StringRef Format2 = Name.slice(Next, StringRef::npos);
813 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
814
Jack Carter30116cd2012-10-04 02:29:46 +0000815 // set the format for the first register
Jack Carterf740d6e2012-09-07 00:23:42 +0000816 setFpFormat(Format1);
817
818 // Read the remaining operands.
819 if (getLexer().isNot(AsmToken::EndOfStatement)) {
820 // Read the first operand.
821 if (ParseOperand(Operands, Name)) {
822 SMLoc Loc = getLexer().getLoc();
823 Parser.EatToEndOfStatement();
824 return Error(Loc, "unexpected token in argument list");
825 }
826
827 if (getLexer().isNot(AsmToken::Comma)) {
828 SMLoc Loc = getLexer().getLoc();
829 Parser.EatToEndOfStatement();
830 return Error(Loc, "unexpected token in argument list");
831
832 }
833 Parser.Lex(); // Eat the comma.
834
835 //set the format for the first register
836 setFpFormat(Format2);
837
838 // Parse and remember the operand.
839 if (ParseOperand(Operands, Name)) {
840 SMLoc Loc = getLexer().getLoc();
841 Parser.EatToEndOfStatement();
842 return Error(Loc, "unexpected token in argument list");
843 }
844 }
845
846 if (getLexer().isNot(AsmToken::EndOfStatement)) {
847 SMLoc Loc = getLexer().getLoc();
848 Parser.EatToEndOfStatement();
849 return Error(Loc, "unexpected token in argument list");
850 }
851
852 Parser.Lex(); // Consume the EndOfStatement
853 return false;
854}
855
Rafael Espindolafddf8042012-01-11 03:56:41 +0000856bool MipsAsmParser::
857ParseInstruction(StringRef Name, SMLoc NameLoc,
858 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter30116cd2012-10-04 02:29:46 +0000859 // floating point instructions: should register be treated as double?
Jack Carterf740d6e2012-09-07 00:23:42 +0000860 if (requestsDoubleOperand(Name)) {
861 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +0000862 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +0000863 }
864 else {
865 setDefaultFpFormat();
866 // Create the leading tokens for the mnemonic, split by '.' characters.
867 size_t Start = 0, Next = Name.find('.');
868 StringRef Mnemonic = Name.slice(Start, Next);
869
870 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
871
872 if (Next != StringRef::npos) {
Jack Carter30116cd2012-10-04 02:29:46 +0000873 // there is a format token in mnemonic
874 // StringRef Rest = Name.slice(Next, StringRef::npos);
Jack Carterf740d6e2012-09-07 00:23:42 +0000875 size_t Dot = Name.find('.', Next+1);
876 StringRef Format = Name.slice(Next, Dot);
877 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
878 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
879 else {
880 if (Name.startswith("c.")){
881 // floating point compare, add '.' and immediate represent for cc
882 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
883 int Cc = ConvertCcString(Format);
884 if (Cc == -1) {
885 return Error(NameLoc, "Invalid conditional code");
886 }
887 SMLoc E = SMLoc::getFromPointer(
888 Parser.getTok().getLoc().getPointer() -1 );
889 Operands.push_back(MipsOperand::CreateImm(
890 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
891 } else {
Jack Carter30116cd2012-10-04 02:29:46 +0000892 // trunc, ceil, floor ...
Jack Carterf740d6e2012-09-07 00:23:42 +0000893 return parseMathOperation(Name, NameLoc, Operands);
894 }
895
Jack Carter30116cd2012-10-04 02:29:46 +0000896 // the rest is a format
Jack Carterf740d6e2012-09-07 00:23:42 +0000897 Format = Name.slice(Dot, StringRef::npos);
898 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
899 }
900
901 setFpFormat(Format);
902 }
903 }
Jack Carterec65be82012-09-05 23:34:03 +0000904
905 // Read the remaining operands.
906 if (getLexer().isNot(AsmToken::EndOfStatement)) {
907 // Read the first operand.
908 if (ParseOperand(Operands, Name)) {
909 SMLoc Loc = getLexer().getLoc();
910 Parser.EatToEndOfStatement();
911 return Error(Loc, "unexpected token in argument list");
912 }
913
914 while (getLexer().is(AsmToken::Comma) ) {
915 Parser.Lex(); // Eat the comma.
916
917 // Parse and remember the operand.
918 if (ParseOperand(Operands, Name)) {
919 SMLoc Loc = getLexer().getLoc();
920 Parser.EatToEndOfStatement();
921 return Error(Loc, "unexpected token in argument list");
922 }
923 }
924 }
925
926 if (getLexer().isNot(AsmToken::EndOfStatement)) {
927 SMLoc Loc = getLexer().getLoc();
928 Parser.EatToEndOfStatement();
929 return Error(Loc, "unexpected token in argument list");
930 }
931
932 Parser.Lex(); // Consume the EndOfStatement
933 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +0000934}
935
Jack Carter30116cd2012-10-04 02:29:46 +0000936bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
937 SMLoc Loc = getLexer().getLoc();
938 Parser.EatToEndOfStatement();
939 return Error(Loc, ErrorMsg);
940}
941
942bool MipsAsmParser::parseSetNoAtDirective() {
943 // line should look like:
944 // .set noat
945 // set at reg to 0
946 Options->setATReg(0);
947 // eat noat
948 Parser.Lex();
949 // if this is not the end of the statement, report error
950 if (getLexer().isNot(AsmToken::EndOfStatement)) {
951 reportParseError("unexpected token in statement");
952 return false;
953 }
954 Parser.Lex(); // Consume the EndOfStatement
955 return false;
956}
957bool MipsAsmParser::parseSetAtDirective() {
958 // line can be
959 // .set at - defaults to $1
960 // or .set at=$reg
961 getParser().Lex();
962 if (getLexer().is(AsmToken::EndOfStatement)) {
963 Options->setATReg(1);
964 Parser.Lex(); // Consume the EndOfStatement
965 return false;
966 } else if (getLexer().is(AsmToken::Equal)) {
967 getParser().Lex(); //eat '='
968 if (getLexer().isNot(AsmToken::Dollar)) {
969 reportParseError("unexpected token in statement");
970 return false;
971 }
972 Parser.Lex(); // eat '$'
973 if (getLexer().isNot(AsmToken::Integer)) {
974 reportParseError("unexpected token in statement");
975 return false;
976 }
977 const AsmToken &Reg = Parser.getTok();
978 if (!Options->setATReg(Reg.getIntVal())) {
979 reportParseError("unexpected token in statement");
980 return false;
981 }
982 getParser().Lex(); //eat reg
983
984 if (getLexer().isNot(AsmToken::EndOfStatement)) {
985 reportParseError("unexpected token in statement");
986 return false;
987 }
988 Parser.Lex(); // Consume the EndOfStatement
989 return false;
990 } else {
991 reportParseError("unexpected token in statement");
992 return false;
993 }
994}
995
996bool MipsAsmParser::parseSetReorderDirective() {
997 Parser.Lex();
998 // if this is not the end of the statement, report error
999 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1000 reportParseError("unexpected token in statement");
1001 return false;
1002 }
1003 Options->setReorder();
1004 Parser.Lex(); // Consume the EndOfStatement
1005 return false;
1006}
1007
1008bool MipsAsmParser::parseSetNoReorderDirective() {
1009 Parser.Lex();
1010 // if this is not the end of the statement, report error
1011 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1012 reportParseError("unexpected token in statement");
1013 return false;
1014 }
1015 Options->setNoreorder();
1016 Parser.Lex(); // Consume the EndOfStatement
1017 return false;
1018}
1019
1020bool MipsAsmParser::parseSetMacroDirective() {
1021 Parser.Lex();
1022 // if this is not the end of the statement, report error
1023 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1024 reportParseError("unexpected token in statement");
1025 return false;
1026 }
1027 Options->setMacro();
1028 Parser.Lex(); // Consume the EndOfStatement
1029 return false;
1030}
1031
1032bool MipsAsmParser::parseSetNoMacroDirective() {
1033 Parser.Lex();
1034 // if this is not the end of the statement, report error
1035 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1036 reportParseError("`noreorder' must be set before `nomacro'");
1037 return false;
1038 }
1039 if (Options->isReorder()) {
1040 reportParseError("`noreorder' must be set before `nomacro'");
1041 return false;
1042 }
1043 Options->setNomacro();
1044 Parser.Lex(); // Consume the EndOfStatement
1045 return false;
1046}
1047bool MipsAsmParser::parseDirectiveSet() {
1048
1049 // get next token
1050 const AsmToken &Tok = Parser.getTok();
1051
1052 if (Tok.getString() == "noat") {
1053 return parseSetNoAtDirective();
1054 } else if (Tok.getString() == "at") {
1055 return parseSetAtDirective();
1056 } else if (Tok.getString() == "reorder") {
1057 return parseSetReorderDirective();
1058 } else if (Tok.getString() == "noreorder") {
1059 return parseSetNoReorderDirective();
1060 } else if (Tok.getString() == "macro") {
1061 return parseSetMacroDirective();
1062 } else if (Tok.getString() == "nomacro") {
1063 return parseSetNoMacroDirective();
1064 } else if (Tok.getString() == "nomips16") {
1065 // ignore this directive for now
1066 Parser.EatToEndOfStatement();
1067 return false;
1068 } else if (Tok.getString() == "nomicromips") {
1069 // ignore this directive for now
1070 Parser.EatToEndOfStatement();
1071 return false;
1072 }
1073 return true;
1074}
1075
1076bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +00001077
1078 if (DirectiveID.getString() == ".ent") {
Jack Carter30116cd2012-10-04 02:29:46 +00001079 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001080 Parser.Lex();
1081 return false;
1082 }
1083
1084 if (DirectiveID.getString() == ".end") {
Jack Carter30116cd2012-10-04 02:29:46 +00001085 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001086 Parser.Lex();
1087 return false;
1088 }
1089
1090 if (DirectiveID.getString() == ".frame") {
Jack Carter30116cd2012-10-04 02:29:46 +00001091 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001092 Parser.EatToEndOfStatement();
1093 return false;
1094 }
1095
1096 if (DirectiveID.getString() == ".set") {
Jack Carter30116cd2012-10-04 02:29:46 +00001097 // ignore this directive for now
1098 //Parser.EatToEndOfStatement();
1099 return parseDirectiveSet();
Jack Carteracbea452012-09-07 00:48:02 +00001100 }
1101
1102 if (DirectiveID.getString() == ".fmask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001103 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001104 Parser.EatToEndOfStatement();
1105 return false;
1106 }
1107
1108 if (DirectiveID.getString() == ".mask") {
Jack Carter30116cd2012-10-04 02:29:46 +00001109 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001110 Parser.EatToEndOfStatement();
1111 return false;
1112 }
1113
1114 if (DirectiveID.getString() == ".gpword") {
Jack Carter30116cd2012-10-04 02:29:46 +00001115 // ignore this directive for now
Jack Carteracbea452012-09-07 00:48:02 +00001116 Parser.EatToEndOfStatement();
1117 return false;
1118 }
1119
Rafael Espindolafddf8042012-01-11 03:56:41 +00001120 return true;
1121}
1122
Rafael Espindolafddf8042012-01-11 03:56:41 +00001123extern "C" void LLVMInitializeMipsAsmParser() {
1124 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1125 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1126 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1127 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1128}
Jack Carterec65be82012-09-05 23:34:03 +00001129
1130#define GET_REGISTER_MATCHER
1131#define GET_MATCHER_IMPLEMENTATION
1132#include "MipsGenAsmMatcher.inc"