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