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