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