Rather then have a wrapper function, have tblgen instantiate the implementation.
[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     MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
527
528     // Otherwise create a symbol ref.
529     const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
530                                                 getContext());
531
532     Operands.push_back(MipsOperand::CreateImm(Res, S, E));
533     return false;
534   }
535   case AsmToken::Identifier:
536   case AsmToken::LParen:
537   case AsmToken::Minus:
538   case AsmToken::Plus:
539   case AsmToken::Integer:
540   case AsmToken::String: {
541      // quoted label names
542     const MCExpr *IdVal;
543     SMLoc S = Parser.getTok().getLoc();
544     if (getParser().ParseExpression(IdVal))
545       return true;
546     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
547     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
548     return false;
549   }
550   case AsmToken::Percent: {
551     //it is a symbol reference or constant expression
552     const MCExpr *IdVal;
553     SMLoc S = Parser.getTok().getLoc(); //start location of the operand
554     if (parseRelocOperand(IdVal))
555       return true;
556
557     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
558
559     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
560     return false;
561   }//case AsmToken::Percent
562   }//switch(getLexer().getKind())
563   return true;
564 }
565
566 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
567
568   Parser.Lex(); //eat % token
569   const AsmToken &Tok = Parser.getTok(); //get next token, operation
570   if (Tok.isNot(AsmToken::Identifier))
571     return true;
572
573   std::string Str = Tok.getIdentifier().str();
574
575   Parser.Lex(); //eat identifier
576   //now make expression from the rest of the operand
577   const MCExpr *IdVal;
578   SMLoc EndLoc;
579
580   if (getLexer().getKind() == AsmToken::LParen) {
581     while (1) {
582       Parser.Lex(); //eat '(' token
583       if (getLexer().getKind() == AsmToken::Percent) {
584         Parser.Lex(); //eat % token
585         const AsmToken &nextTok = Parser.getTok();
586         if (nextTok.isNot(AsmToken::Identifier))
587           return true;
588         Str += "(%";
589         Str += nextTok.getIdentifier();
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 (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
607     //it's a constant, evaluate lo or hi value
608     int Val = MCE->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 (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
619     //it's a symbol, create symbolic expression from symbol
620     StringRef Symbol = MSRE->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 static int ConvertCcString(StringRef CondString) {
739   int CC = StringSwitch<unsigned>(CondString)
740       .Case(".f",    0)
741       .Case(".un",   1)
742       .Case(".eq",   2)
743       .Case(".ueq",  3)
744       .Case(".olt",  4)
745       .Case(".ult",  5)
746       .Case(".ole",  6)
747       .Case(".ule",  7)
748       .Case(".sf",   8)
749       .Case(".ngle", 9)
750       .Case(".seq",  10)
751       .Case(".ngl",  11)
752       .Case(".lt",   12)
753       .Case(".nge",  13)
754       .Case(".le",   14)
755       .Case(".ngt",  15)
756       .Default(-1);
757
758   return CC;
759 }
760
761 bool MipsAsmParser::
762 parseMathOperation(StringRef Name, SMLoc NameLoc,
763                         SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
764   //split the format
765   size_t Start = Name.find('.'), Next = Name.rfind('.');
766   StringRef Format1 = Name.slice(Start, Next);
767   //and add the first format to the operands
768   Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
769   //now for the second format
770   StringRef Format2 = Name.slice(Next, StringRef::npos);
771   Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
772
773   //set the format for the first register
774   setFpFormat(Format1);
775
776   // Read the remaining operands.
777   if (getLexer().isNot(AsmToken::EndOfStatement)) {
778     // Read the first operand.
779     if (ParseOperand(Operands, Name)) {
780       SMLoc Loc = getLexer().getLoc();
781       Parser.EatToEndOfStatement();
782       return Error(Loc, "unexpected token in argument list");
783     }
784
785     if (getLexer().isNot(AsmToken::Comma)) {
786       SMLoc Loc = getLexer().getLoc();
787       Parser.EatToEndOfStatement();
788       return Error(Loc, "unexpected token in argument list");
789
790     }
791     Parser.Lex();  // Eat the comma.
792
793     //set the format for the first register
794     setFpFormat(Format2);
795
796     // Parse and remember the operand.
797     if (ParseOperand(Operands, Name)) {
798       SMLoc Loc = getLexer().getLoc();
799       Parser.EatToEndOfStatement();
800       return Error(Loc, "unexpected token in argument list");
801     }
802   }
803
804   if (getLexer().isNot(AsmToken::EndOfStatement)) {
805     SMLoc Loc = getLexer().getLoc();
806     Parser.EatToEndOfStatement();
807     return Error(Loc, "unexpected token in argument list");
808   }
809
810   Parser.Lex(); // Consume the EndOfStatement
811   return false;
812 }
813
814 bool MipsAsmParser::
815 ParseInstruction(StringRef Name, SMLoc NameLoc,
816                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
817   //floating point instructions: should register be treated as double?
818   if (requestsDoubleOperand(Name)) {
819     setFpFormat(FP_FORMAT_D);
820   Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
821   }
822   else {
823     setDefaultFpFormat();
824     // Create the leading tokens for the mnemonic, split by '.' characters.
825     size_t Start = 0, Next = Name.find('.');
826     StringRef Mnemonic = Name.slice(Start, Next);
827
828     Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
829
830     if (Next != StringRef::npos) {
831       //there is a format token in mnemonic
832       //StringRef Rest = Name.slice(Next, StringRef::npos);
833       size_t Dot = Name.find('.', Next+1);
834       StringRef Format = Name.slice(Next, Dot);
835       if (Dot == StringRef::npos) //only one '.' in a string, it's a format
836         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
837       else {
838         if (Name.startswith("c.")){
839           // floating point compare, add '.' and immediate represent for cc
840           Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
841           int Cc = ConvertCcString(Format);
842           if (Cc == -1) {
843             return Error(NameLoc, "Invalid conditional code");
844           }
845           SMLoc E = SMLoc::getFromPointer(
846               Parser.getTok().getLoc().getPointer() -1 );
847           Operands.push_back(MipsOperand::CreateImm(
848               MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
849         } else {
850           //trunc, ceil, floor ...
851           return parseMathOperation(Name, NameLoc, Operands);
852         }
853
854         //the rest is a format
855         Format = Name.slice(Dot, StringRef::npos);
856         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
857       }
858
859       setFpFormat(Format);
860     }
861   }
862
863   // Read the remaining operands.
864   if (getLexer().isNot(AsmToken::EndOfStatement)) {
865     // Read the first operand.
866     if (ParseOperand(Operands, Name)) {
867       SMLoc Loc = getLexer().getLoc();
868       Parser.EatToEndOfStatement();
869       return Error(Loc, "unexpected token in argument list");
870     }
871
872     while (getLexer().is(AsmToken::Comma) ) {
873       Parser.Lex();  // Eat the comma.
874
875       // Parse and remember the operand.
876       if (ParseOperand(Operands, Name)) {
877         SMLoc Loc = getLexer().getLoc();
878         Parser.EatToEndOfStatement();
879         return Error(Loc, "unexpected token in argument list");
880       }
881     }
882   }
883
884   if (getLexer().isNot(AsmToken::EndOfStatement)) {
885     SMLoc Loc = getLexer().getLoc();
886     Parser.EatToEndOfStatement();
887     return Error(Loc, "unexpected token in argument list");
888   }
889
890   Parser.Lex(); // Consume the EndOfStatement
891   return false;
892 }
893
894 bool MipsAsmParser::
895 ParseDirective(AsmToken DirectiveID) {
896
897   if (DirectiveID.getString() == ".ent") {
898     //ignore this directive for now
899     Parser.Lex();
900     return false;
901   }
902
903   if (DirectiveID.getString() == ".end") {
904     //ignore this directive for now
905     Parser.Lex();
906     return false;
907   }
908
909   if (DirectiveID.getString() == ".frame") {
910     //ignore this directive for now
911     Parser.EatToEndOfStatement();
912     return false;
913   }
914
915   if (DirectiveID.getString() == ".set") {
916     //ignore this directive for now
917     Parser.EatToEndOfStatement();
918     return false;
919   }
920
921   if (DirectiveID.getString() == ".fmask") {
922     //ignore this directive for now
923     Parser.EatToEndOfStatement();
924     return false;
925   }
926
927   if (DirectiveID.getString() == ".mask") {
928     //ignore this directive for now
929     Parser.EatToEndOfStatement();
930     return false;
931   }
932
933   if (DirectiveID.getString() == ".gpword") {
934     //ignore this directive for now
935     Parser.EatToEndOfStatement();
936     return false;
937   }
938
939   return true;
940 }
941
942 extern "C" void LLVMInitializeMipsAsmParser() {
943   RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
944   RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
945   RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
946   RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
947 }
948
949 #define GET_REGISTER_MATCHER
950 #define GET_MATCHER_IMPLEMENTATION
951 #include "MipsGenAsmMatcher.inc"