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