[ms-inline asm] Expose the mnemonicIsValid() function in the AsmParser.
[oota-llvm.git] / lib / Target / Mips / AsmParser / MipsAsmParser.cpp
1 //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
2 //
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"
11 #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"
19 #include "llvm/MC/MCParser/MCAsmLexer.h"
20 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21 #include "llvm/MC/MCTargetAsmParser.h"
22 #include "llvm/Support/TargetRegistry.h"
23
24 using namespace llvm;
25
26 namespace {
27
28 class MipsAsmParser : public MCTargetAsmParser {
29
30   enum FpFormatTy {
31     FP_FORMAT_NONE = -1,
32     FP_FORMAT_S,
33     FP_FORMAT_D,
34     FP_FORMAT_L,
35     FP_FORMAT_W
36   } FpFormat;
37
38   MCSubtargetInfo &STI;
39   MCAsmParser &Parser;
40
41 #define GET_ASSEMBLER_HEADER
42 #include "MipsGenAsmMatcher.inc"
43
44   bool mnemonicIsValid(StringRef Mnemonic) {
45     return mnemonicIsValidImpl(Mnemonic);
46   }
47
48   bool MatchAndEmitInstruction(SMLoc IDLoc,
49                                SmallVectorImpl<MCParsedAsmOperand*> &Operands,
50                                MCStreamer &Out);
51
52   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
53
54   bool ParseInstruction(StringRef Name, SMLoc NameLoc,
55                         SmallVectorImpl<MCParsedAsmOperand*> &Operands);
56
57   bool parseMathOperation(StringRef Name, SMLoc NameLoc,
58                         SmallVectorImpl<MCParsedAsmOperand*> &Operands);
59
60   bool ParseDirective(AsmToken DirectiveID);
61
62   MipsAsmParser::OperandMatchResultTy
63   parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
64
65   unsigned
66   getMCInstOperandNum(unsigned Kind, MCInst &Inst,
67                       const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
68                       unsigned OperandNum, unsigned &NumMCOperands);
69
70   bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
71                     StringRef Mnemonic);
72
73   int tryParseRegister(StringRef Mnemonic);
74
75   bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
76                                StringRef Mnemonic);
77
78   bool parseMemOffset(const MCExpr *&Res);
79   bool parseRelocOperand(const MCExpr *&Res);
80   MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
81
82   bool isMips64() const {
83     return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
84   }
85
86   bool isFP64() const {
87     return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
88   }
89
90   int matchRegisterName(StringRef Symbol);
91
92   int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
93
94   void setFpFormat(FpFormatTy Format) {
95     FpFormat = Format;
96   }
97
98   void setDefaultFpFormat();
99
100   void setFpFormat(StringRef Format);
101
102   FpFormatTy getFpFormat() {return FpFormat;}
103
104   bool requestsDoubleOperand(StringRef Mnemonic);
105
106   unsigned getReg(int RC,int RegNo);
107
108 public:
109   MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
110     : MCTargetAsmParser(), STI(sti), Parser(parser) {
111     // Initialize the set of available features.
112     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
113   }
114
115   MCAsmParser &getParser() const { return Parser; }
116   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
117
118 };
119 }
120
121 namespace {
122
123 /// MipsOperand - Instances of this class represent a parsed Mips machine
124 /// instruction.
125 class MipsOperand : public MCParsedAsmOperand {
126
127   enum KindTy {
128     k_CondCode,
129     k_CoprocNum,
130     k_Immediate,
131     k_Memory,
132     k_PostIndexRegister,
133     k_Register,
134     k_Token
135   } Kind;
136
137   MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
138
139   union {
140     struct {
141       const char *Data;
142       unsigned Length;
143     } Tok;
144
145     struct {
146       unsigned RegNum;
147     } Reg;
148
149     struct {
150       const MCExpr *Val;
151     } Imm;
152
153     struct {
154       unsigned Base;
155       const MCExpr *Off;
156     } Mem;
157   };
158
159   SMLoc StartLoc, EndLoc;
160
161 public:
162   void addRegOperands(MCInst &Inst, unsigned N) const {
163     assert(N == 1 && "Invalid number of operands!");
164     Inst.addOperand(MCOperand::CreateReg(getReg()));
165   }
166
167   void addExpr(MCInst &Inst, const MCExpr *Expr) const{
168     // Add as immediate when possible.  Null MCExpr = 0.
169     if (Expr == 0)
170       Inst.addOperand(MCOperand::CreateImm(0));
171     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
172       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
173     else
174       Inst.addOperand(MCOperand::CreateExpr(Expr));
175   }
176
177   void addImmOperands(MCInst &Inst, unsigned N) const {
178     assert(N == 1 && "Invalid number of operands!");
179     const MCExpr *Expr = getImm();
180     addExpr(Inst,Expr);
181   }
182
183   void addMemOperands(MCInst &Inst, unsigned N) const {
184     assert(N == 2 && "Invalid number of operands!");
185
186     Inst.addOperand(MCOperand::CreateReg(getMemBase()));
187
188     const MCExpr *Expr = getMemOff();
189     addExpr(Inst,Expr);
190   }
191
192   bool isReg() const { return Kind == k_Register; }
193   bool isImm() const { return Kind == k_Immediate; }
194   bool isToken() const { return Kind == k_Token; }
195   bool isMem() const { return Kind == k_Memory; }
196
197   StringRef getToken() const {
198     assert(Kind == k_Token && "Invalid access!");
199     return StringRef(Tok.Data, Tok.Length);
200   }
201
202   unsigned getReg() const {
203     assert((Kind == k_Register) && "Invalid access!");
204     return Reg.RegNum;
205   }
206
207   const MCExpr *getImm() const {
208     assert((Kind == k_Immediate) && "Invalid access!");
209     return Imm.Val;
210   }
211
212   unsigned getMemBase() const {
213     assert((Kind == k_Memory) && "Invalid access!");
214     return Mem.Base;
215   }
216
217   const MCExpr *getMemOff() const {
218     assert((Kind == k_Memory) && "Invalid access!");
219     return Mem.Off;
220   }
221
222   static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
223     MipsOperand *Op = new MipsOperand(k_Token);
224     Op->Tok.Data = Str.data();
225     Op->Tok.Length = Str.size();
226     Op->StartLoc = S;
227     Op->EndLoc = S;
228     return Op;
229   }
230
231   static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
232     MipsOperand *Op = new MipsOperand(k_Register);
233     Op->Reg.RegNum = RegNum;
234     Op->StartLoc = S;
235     Op->EndLoc = E;
236     return Op;
237   }
238
239   static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
240     MipsOperand *Op = new MipsOperand(k_Immediate);
241     Op->Imm.Val = Val;
242     Op->StartLoc = S;
243     Op->EndLoc = E;
244     return Op;
245   }
246
247   static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
248                                  SMLoc S, SMLoc E) {
249     MipsOperand *Op = new MipsOperand(k_Memory);
250     Op->Mem.Base = Base;
251     Op->Mem.Off = Off;
252     Op->StartLoc = S;
253     Op->EndLoc = E;
254     return Op;
255   }
256
257   /// getStartLoc - Get the location of the first token of this operand.
258   SMLoc getStartLoc() const { return StartLoc; }
259   /// getEndLoc - Get the location of the last token of this operand.
260   SMLoc getEndLoc() const { return EndLoc; }
261
262   virtual void print(raw_ostream &OS) const {
263     llvm_unreachable("unimplemented!");
264   }
265 };
266 }
267
268 unsigned MipsAsmParser::
269 getMCInstOperandNum(unsigned Kind, MCInst &Inst,
270                     const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
271                     unsigned OperandNum, unsigned &NumMCOperands) {
272   assert (0 && "getMCInstOperandNum() not supported by the Mips target.");
273   // The Mips backend doesn't currently include the matcher implementation, so
274   // the getMCInstOperandNumImpl() is undefined.  This is a temporary
275   // work around.
276   NumMCOperands = 0;
277   return 0;
278 }
279
280 bool MipsAsmParser::
281 MatchAndEmitInstruction(SMLoc IDLoc,
282                         SmallVectorImpl<MCParsedAsmOperand*> &Operands,
283                         MCStreamer &Out) {
284   MCInst Inst;
285   unsigned ErrorInfo;
286   unsigned Kind;
287   unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst, ErrorInfo);
288
289   switch (MatchResult) {
290   default: break;
291   case Match_Success: {
292     Inst.setLoc(IDLoc);
293     Out.EmitInstruction(Inst);
294     return false;
295   }
296   case Match_MissingFeature:
297     Error(IDLoc, "instruction requires a CPU feature not currently enabled");
298     return true;
299   case Match_InvalidOperand: {
300     SMLoc ErrorLoc = IDLoc;
301     if (ErrorInfo != ~0U) {
302       if (ErrorInfo >= Operands.size())
303         return Error(IDLoc, "too few operands for instruction");
304
305       ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
306       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
307     }
308
309     return Error(ErrorLoc, "invalid operand for instruction");
310   }
311   case Match_MnemonicFail:
312     return Error(IDLoc, "invalid instruction");
313   }
314   return true;
315 }
316
317 int MipsAsmParser::matchRegisterName(StringRef Name) {
318
319    int CC = StringSwitch<unsigned>(Name)
320     .Case("zero",  Mips::ZERO)
321     .Case("a0",  Mips::A0)
322     .Case("a1",  Mips::A1)
323     .Case("a2",  Mips::A2)
324     .Case("a3",  Mips::A3)
325     .Case("v0",  Mips::V0)
326     .Case("v1",  Mips::V1)
327     .Case("s0",  Mips::S0)
328     .Case("s1",  Mips::S1)
329     .Case("s2",  Mips::S2)
330     .Case("s3",  Mips::S3)
331     .Case("s4",  Mips::S4)
332     .Case("s5",  Mips::S5)
333     .Case("s6",  Mips::S6)
334     .Case("s7",  Mips::S7)
335     .Case("k0",  Mips::K0)
336     .Case("k1",  Mips::K1)
337     .Case("sp",  Mips::SP)
338     .Case("fp",  Mips::FP)
339     .Case("gp",  Mips::GP)
340     .Case("ra",  Mips::RA)
341     .Case("t0",  Mips::T0)
342     .Case("t1",  Mips::T1)
343     .Case("t2",  Mips::T2)
344     .Case("t3",  Mips::T3)
345     .Case("t4",  Mips::T4)
346     .Case("t5",  Mips::T5)
347     .Case("t6",  Mips::T6)
348     .Case("t7",  Mips::T7)
349     .Case("t8",  Mips::T8)
350     .Case("t9",  Mips::T9)
351     .Case("at",  Mips::AT)
352     .Case("fcc0",  Mips::FCC0)
353     .Default(-1);
354
355   if (CC != -1) {
356     //64 bit register in Mips are following 32 bit definitions.
357     if (isMips64())
358       CC++;
359     return CC;
360   }
361
362   if (Name[0] == 'f') {
363     StringRef NumString = Name.substr(1);
364     unsigned IntVal;
365     if( NumString.getAsInteger(10, IntVal))
366       return -1; //not integer
367     if (IntVal > 31)
368       return -1;
369
370     FpFormatTy Format = getFpFormat();
371
372     if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
373       return getReg(Mips::FGR32RegClassID, IntVal);
374     if (Format == FP_FORMAT_D) {
375       if(isFP64()) {
376         return getReg(Mips::FGR64RegClassID, IntVal);
377       }
378       //only even numbers available as register pairs
379       if (( IntVal > 31) || (IntVal%2 !=  0))
380         return -1;
381       return getReg(Mips::AFGR64RegClassID, IntVal/2);
382     }
383   }
384
385   return -1;
386 }
387 void MipsAsmParser::setDefaultFpFormat() {
388
389   if (isMips64() || isFP64())
390     FpFormat = FP_FORMAT_D;
391   else
392     FpFormat = FP_FORMAT_S;
393 }
394
395 bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
396
397   bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
398     .Case("ldxc1", true)
399     .Case("ldc1",  true)
400     .Case("sdxc1", true)
401     .Case("sdc1",  true)
402     .Default(false);
403
404   return IsDouble;
405 }
406 void MipsAsmParser::setFpFormat(StringRef Format) {
407
408   FpFormat = StringSwitch<FpFormatTy>(Format.lower())
409     .Case(".s",  FP_FORMAT_S)
410     .Case(".d",  FP_FORMAT_D)
411     .Case(".l",  FP_FORMAT_L)
412     .Case(".w",  FP_FORMAT_W)
413     .Default(FP_FORMAT_NONE);
414 }
415
416 unsigned MipsAsmParser::getReg(int RC,int RegNo){
417   return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
418 }
419
420 int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
421
422   if (Mnemonic.lower() == "rdhwr") {
423     //at the moment only hwreg29 is supported
424     if (RegNum != 29)
425       return -1;
426     return Mips::HWR29;
427   }
428
429   if (RegNum > 31)
430     return -1;
431
432   return getReg(Mips::CPURegsRegClassID,RegNum);
433 }
434
435 int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
436   const AsmToken &Tok = Parser.getTok();
437   int RegNum = -1;
438
439   if (Tok.is(AsmToken::Identifier)) {
440     std::string lowerCase = Tok.getString().lower();
441     RegNum = matchRegisterName(lowerCase);
442   } else if (Tok.is(AsmToken::Integer))
443     RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()),
444                                    Mnemonic.lower());
445     else
446       return RegNum;  //error
447   //64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
448   if (isMips64() && RegNum == Mips::ZERO_64) {
449     if (Mnemonic.find("ddiv") != StringRef::npos)
450       RegNum = Mips::ZERO;
451   }
452   return RegNum;
453 }
454
455 bool MipsAsmParser::
456   tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
457                           StringRef Mnemonic){
458
459   SMLoc S = Parser.getTok().getLoc();
460   int RegNo = -1;
461
462   //FIXME: we should make a more generic method for CCR
463   if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
464       && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
465     RegNo = Parser.getTok().getIntVal();  //get the int value
466     //at the moment only fcc0 is supported
467     if (RegNo ==  0)
468       RegNo = Mips::FCC0;
469   } else
470     RegNo = tryParseRegister(Mnemonic);
471   if (RegNo == -1)
472     return true;
473
474   Operands.push_back(MipsOperand::CreateReg(RegNo, S,
475       Parser.getTok().getLoc()));
476   Parser.Lex(); // Eat register token.
477   return false;
478 }
479
480 bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
481                                  StringRef Mnemonic) {
482   //Check if the current operand has a custom associated parser, if so, try to
483   //custom parse the operand, or fallback to the general approach.
484   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
485   if (ResTy == MatchOperand_Success)
486     return false;
487   // If there wasn't a custom match, try the generic matcher below. Otherwise,
488   // there was a match, but an error occurred, in which case, just return that
489   // the operand parsing failed.
490   if (ResTy == MatchOperand_ParseFail)
491     return true;
492
493   switch (getLexer().getKind()) {
494   default:
495     Error(Parser.getTok().getLoc(), "unexpected token in operand");
496     return true;
497   case AsmToken::Dollar: {
498     //parse register
499     SMLoc S = Parser.getTok().getLoc();
500     Parser.Lex(); // Eat dollar token.
501     //parse register operand
502     if (!tryParseRegisterOperand(Operands,Mnemonic)) {
503       if (getLexer().is(AsmToken::LParen)) {
504         //check if it is indexed addressing operand
505         Operands.push_back(MipsOperand::CreateToken("(", S));
506         Parser.Lex(); //eat parenthesis
507         if (getLexer().isNot(AsmToken::Dollar))
508           return true;
509
510         Parser.Lex(); //eat dollar
511         if (tryParseRegisterOperand(Operands,Mnemonic))
512           return true;
513
514         if (!getLexer().is(AsmToken::RParen))
515           return true;
516
517         S = Parser.getTok().getLoc();
518         Operands.push_back(MipsOperand::CreateToken(")", S));
519         Parser.Lex();
520       }
521       return false;
522     }
523     //maybe it is a symbol reference
524     StringRef Identifier;
525     if (Parser.ParseIdentifier(Identifier))
526       return true;
527
528     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
529
530     MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
531
532     // Otherwise create a symbol ref.
533     const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
534                                                 getContext());
535
536     Operands.push_back(MipsOperand::CreateImm(Res, S, E));
537     return false;
538   }
539   case AsmToken::Identifier:
540   case AsmToken::LParen:
541   case AsmToken::Minus:
542   case AsmToken::Plus:
543   case AsmToken::Integer:
544   case AsmToken::String: {
545      // quoted label names
546     const MCExpr *IdVal;
547     SMLoc S = Parser.getTok().getLoc();
548     if (getParser().ParseExpression(IdVal))
549       return true;
550     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
551     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
552     return false;
553   }
554   case AsmToken::Percent: {
555     //it is a symbol reference or constant expression
556     const MCExpr *IdVal;
557     SMLoc S = Parser.getTok().getLoc(); //start location of the operand
558     if (parseRelocOperand(IdVal))
559       return true;
560
561     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
562
563     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
564     return false;
565   }//case AsmToken::Percent
566   }//switch(getLexer().getKind())
567   return true;
568 }
569
570 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
571
572   Parser.Lex(); //eat % token
573   const AsmToken &Tok = Parser.getTok(); //get next token, operation
574   if (Tok.isNot(AsmToken::Identifier))
575     return true;
576
577   std::string Str = Tok.getIdentifier().str();
578
579   Parser.Lex(); //eat identifier
580   //now make expression from the rest of the operand
581   const MCExpr *IdVal;
582   SMLoc EndLoc;
583
584   if (getLexer().getKind() == AsmToken::LParen) {
585     while (1) {
586       Parser.Lex(); //eat '(' token
587       if (getLexer().getKind() == AsmToken::Percent) {
588         Parser.Lex(); //eat % token
589         const AsmToken &nextTok = Parser.getTok();
590         if (nextTok.isNot(AsmToken::Identifier))
591           return true;
592         Str += "(%";
593         Str += nextTok.getIdentifier();
594         Parser.Lex(); //eat identifier
595         if (getLexer().getKind() != AsmToken::LParen)
596           return true;
597       } else
598         break;
599     }
600     if (getParser().ParseParenExpression(IdVal,EndLoc))
601       return true;
602
603     while (getLexer().getKind() == AsmToken::RParen)
604       Parser.Lex(); //eat ')' token
605
606   } else
607     return true; //parenthesis must follow reloc operand
608
609   //Check the type of the expression
610   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
611     //it's a constant, evaluate lo or hi value
612     int Val = MCE->getValue();
613     if (Str == "lo") {
614       Val = Val & 0xffff;
615     } else if (Str == "hi") {
616       Val = (Val & 0xffff0000) >> 16;
617     }
618     Res = MCConstantExpr::Create(Val, getContext());
619     return false;
620   }
621
622   if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
623     //it's a symbol, create symbolic expression from symbol
624     StringRef Symbol = MSRE->getSymbol().getName();
625     MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
626     Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
627     return false;
628   }
629   return true;
630 }
631
632 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
633                                   SMLoc &EndLoc) {
634
635   StartLoc = Parser.getTok().getLoc();
636   RegNo = tryParseRegister("");
637   EndLoc = Parser.getTok().getLoc();
638   return (RegNo == (unsigned)-1);
639 }
640
641 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
642
643   SMLoc S;
644
645   switch(getLexer().getKind()) {
646   default:
647     return true;
648   case AsmToken::Integer:
649   case AsmToken::Minus:
650   case AsmToken::Plus:
651     return (getParser().ParseExpression(Res));
652   case AsmToken::Percent:
653     return parseRelocOperand(Res);
654   case AsmToken::LParen:
655     return false;  //it's probably assuming 0
656   }
657   return true;
658 }
659
660 MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
661                SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
662
663   const MCExpr *IdVal = 0;
664   SMLoc S;
665   //first operand is the offset
666   S = Parser.getTok().getLoc();
667
668   if (parseMemOffset(IdVal))
669     return MatchOperand_ParseFail;
670
671   const AsmToken &Tok = Parser.getTok(); //get next token
672   if (Tok.isNot(AsmToken::LParen)) {
673     Error(Parser.getTok().getLoc(), "'(' expected");
674     return MatchOperand_ParseFail;
675   }
676
677   Parser.Lex(); // Eat '(' token.
678
679   const AsmToken &Tok1 = Parser.getTok(); //get next token
680   if (Tok1.is(AsmToken::Dollar)) {
681     Parser.Lex(); // Eat '$' token.
682     if (tryParseRegisterOperand(Operands,"")) {
683       Error(Parser.getTok().getLoc(), "unexpected token in operand");
684       return MatchOperand_ParseFail;
685     }
686
687   } else {
688     Error(Parser.getTok().getLoc(),"unexpected token in operand");
689     return MatchOperand_ParseFail;
690   }
691
692   const AsmToken &Tok2 = Parser.getTok(); //get next token
693   if (Tok2.isNot(AsmToken::RParen)) {
694     Error(Parser.getTok().getLoc(), "')' expected");
695     return MatchOperand_ParseFail;
696   }
697
698   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
699
700   Parser.Lex(); // Eat ')' token.
701
702   if (IdVal == 0)
703     IdVal = MCConstantExpr::Create(0, getContext());
704
705   //now replace register operand with the mem operand
706   MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
707   int RegNo = op->getReg();
708   //remove register from operands
709   Operands.pop_back();
710   //and add memory operand
711   Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
712   delete op;
713   return MatchOperand_Success;
714 }
715
716 MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
717
718   MCSymbolRefExpr::VariantKind VK
719                    = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
720     .Case("hi",          MCSymbolRefExpr::VK_Mips_ABS_HI)
721     .Case("lo",          MCSymbolRefExpr::VK_Mips_ABS_LO)
722     .Case("gp_rel",      MCSymbolRefExpr::VK_Mips_GPREL)
723     .Case("call16",      MCSymbolRefExpr::VK_Mips_GOT_CALL)
724     .Case("got",         MCSymbolRefExpr::VK_Mips_GOT)
725     .Case("tlsgd",       MCSymbolRefExpr::VK_Mips_TLSGD)
726     .Case("tlsldm",      MCSymbolRefExpr::VK_Mips_TLSLDM)
727     .Case("dtprel_hi",   MCSymbolRefExpr::VK_Mips_DTPREL_HI)
728     .Case("dtprel_lo",   MCSymbolRefExpr::VK_Mips_DTPREL_LO)
729     .Case("gottprel",    MCSymbolRefExpr::VK_Mips_GOTTPREL)
730     .Case("tprel_hi",    MCSymbolRefExpr::VK_Mips_TPREL_HI)
731     .Case("tprel_lo",    MCSymbolRefExpr::VK_Mips_TPREL_LO)
732     .Case("got_disp",    MCSymbolRefExpr::VK_Mips_GOT_DISP)
733     .Case("got_page",    MCSymbolRefExpr::VK_Mips_GOT_PAGE)
734     .Case("got_ofst",    MCSymbolRefExpr::VK_Mips_GOT_OFST)
735     .Case("hi(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_HI)
736     .Case("lo(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_LO)
737     .Default(MCSymbolRefExpr::VK_None);
738
739   return VK;
740 }
741
742 static int ConvertCcString(StringRef CondString) {
743   int CC = StringSwitch<unsigned>(CondString)
744       .Case(".f",    0)
745       .Case(".un",   1)
746       .Case(".eq",   2)
747       .Case(".ueq",  3)
748       .Case(".olt",  4)
749       .Case(".ult",  5)
750       .Case(".ole",  6)
751       .Case(".ule",  7)
752       .Case(".sf",   8)
753       .Case(".ngle", 9)
754       .Case(".seq",  10)
755       .Case(".ngl",  11)
756       .Case(".lt",   12)
757       .Case(".nge",  13)
758       .Case(".le",   14)
759       .Case(".ngt",  15)
760       .Default(-1);
761
762   return CC;
763 }
764
765 bool MipsAsmParser::
766 parseMathOperation(StringRef Name, SMLoc NameLoc,
767                         SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
768   //split the format
769   size_t Start = Name.find('.'), Next = Name.rfind('.');
770   StringRef Format1 = Name.slice(Start, Next);
771   //and add the first format to the operands
772   Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
773   //now for the second format
774   StringRef Format2 = Name.slice(Next, StringRef::npos);
775   Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
776
777   //set the format for the first register
778   setFpFormat(Format1);
779
780   // Read the remaining operands.
781   if (getLexer().isNot(AsmToken::EndOfStatement)) {
782     // Read the first operand.
783     if (ParseOperand(Operands, Name)) {
784       SMLoc Loc = getLexer().getLoc();
785       Parser.EatToEndOfStatement();
786       return Error(Loc, "unexpected token in argument list");
787     }
788
789     if (getLexer().isNot(AsmToken::Comma)) {
790       SMLoc Loc = getLexer().getLoc();
791       Parser.EatToEndOfStatement();
792       return Error(Loc, "unexpected token in argument list");
793
794     }
795     Parser.Lex();  // Eat the comma.
796
797     //set the format for the first register
798     setFpFormat(Format2);
799
800     // Parse and remember the operand.
801     if (ParseOperand(Operands, Name)) {
802       SMLoc Loc = getLexer().getLoc();
803       Parser.EatToEndOfStatement();
804       return Error(Loc, "unexpected token in argument list");
805     }
806   }
807
808   if (getLexer().isNot(AsmToken::EndOfStatement)) {
809     SMLoc Loc = getLexer().getLoc();
810     Parser.EatToEndOfStatement();
811     return Error(Loc, "unexpected token in argument list");
812   }
813
814   Parser.Lex(); // Consume the EndOfStatement
815   return false;
816 }
817
818 bool MipsAsmParser::
819 ParseInstruction(StringRef Name, SMLoc NameLoc,
820                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
821   //floating point instructions: should register be treated as double?
822   if (requestsDoubleOperand(Name)) {
823     setFpFormat(FP_FORMAT_D);
824   Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
825   }
826   else {
827     setDefaultFpFormat();
828     // Create the leading tokens for the mnemonic, split by '.' characters.
829     size_t Start = 0, Next = Name.find('.');
830     StringRef Mnemonic = Name.slice(Start, Next);
831
832     Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
833
834     if (Next != StringRef::npos) {
835       //there is a format token in mnemonic
836       //StringRef Rest = Name.slice(Next, StringRef::npos);
837       size_t Dot = Name.find('.', Next+1);
838       StringRef Format = Name.slice(Next, Dot);
839       if (Dot == StringRef::npos) //only one '.' in a string, it's a format
840         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
841       else {
842         if (Name.startswith("c.")){
843           // floating point compare, add '.' and immediate represent for cc
844           Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
845           int Cc = ConvertCcString(Format);
846           if (Cc == -1) {
847             return Error(NameLoc, "Invalid conditional code");
848           }
849           SMLoc E = SMLoc::getFromPointer(
850               Parser.getTok().getLoc().getPointer() -1 );
851           Operands.push_back(MipsOperand::CreateImm(
852               MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
853         } else {
854           //trunc, ceil, floor ...
855           return parseMathOperation(Name, NameLoc, Operands);
856         }
857
858         //the rest is a format
859         Format = Name.slice(Dot, StringRef::npos);
860         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
861       }
862
863       setFpFormat(Format);
864     }
865   }
866
867   // Read the remaining operands.
868   if (getLexer().isNot(AsmToken::EndOfStatement)) {
869     // Read the first operand.
870     if (ParseOperand(Operands, Name)) {
871       SMLoc Loc = getLexer().getLoc();
872       Parser.EatToEndOfStatement();
873       return Error(Loc, "unexpected token in argument list");
874     }
875
876     while (getLexer().is(AsmToken::Comma) ) {
877       Parser.Lex();  // Eat the comma.
878
879       // Parse and remember the operand.
880       if (ParseOperand(Operands, Name)) {
881         SMLoc Loc = getLexer().getLoc();
882         Parser.EatToEndOfStatement();
883         return Error(Loc, "unexpected token in argument list");
884       }
885     }
886   }
887
888   if (getLexer().isNot(AsmToken::EndOfStatement)) {
889     SMLoc Loc = getLexer().getLoc();
890     Parser.EatToEndOfStatement();
891     return Error(Loc, "unexpected token in argument list");
892   }
893
894   Parser.Lex(); // Consume the EndOfStatement
895   return false;
896 }
897
898 bool MipsAsmParser::
899 ParseDirective(AsmToken DirectiveID) {
900
901   if (DirectiveID.getString() == ".ent") {
902     //ignore this directive for now
903     Parser.Lex();
904     return false;
905   }
906
907   if (DirectiveID.getString() == ".end") {
908     //ignore this directive for now
909     Parser.Lex();
910     return false;
911   }
912
913   if (DirectiveID.getString() == ".frame") {
914     //ignore this directive for now
915     Parser.EatToEndOfStatement();
916     return false;
917   }
918
919   if (DirectiveID.getString() == ".set") {
920     //ignore this directive for now
921     Parser.EatToEndOfStatement();
922     return false;
923   }
924
925   if (DirectiveID.getString() == ".fmask") {
926     //ignore this directive for now
927     Parser.EatToEndOfStatement();
928     return false;
929   }
930
931   if (DirectiveID.getString() == ".mask") {
932     //ignore this directive for now
933     Parser.EatToEndOfStatement();
934     return false;
935   }
936
937   if (DirectiveID.getString() == ".gpword") {
938     //ignore this directive for now
939     Parser.EatToEndOfStatement();
940     return false;
941   }
942
943   return true;
944 }
945
946 extern "C" void LLVMInitializeMipsAsmParser() {
947   RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
948   RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
949   RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
950   RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
951 }
952
953 #define GET_REGISTER_MATCHER
954 #define GET_MATCHER_IMPLEMENTATION
955 #include "MipsGenAsmMatcher.inc"