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