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