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/MCParser/MCAsmLexer.h"
17 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18 #include "llvm/MC/MCStreamer.h"
19 #include "llvm/MC/MCSubtargetInfo.h"
20 #include "llvm/MC/MCSymbol.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, unsigned &Opcode,
71                                SmallVectorImpl<MCParsedAsmOperand*> &Operands,
72                                MCStreamer &Out, unsigned &ErrorInfo,
73                                bool MatchingInlineAsm);
74 
75   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
76 
77   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
78                         SMLoc NameLoc,
79                         SmallVectorImpl<MCParsedAsmOperand*> &Operands);
80 
81   bool parseMathOperation(StringRef Name, SMLoc NameLoc,
82                         SmallVectorImpl<MCParsedAsmOperand*> &Operands);
83 
84   bool ParseDirective(AsmToken DirectiveID);
85 
86   MipsAsmParser::OperandMatchResultTy
87   parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
88 
89   MipsAsmParser::OperandMatchResultTy
90   parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
91 
92   MipsAsmParser::OperandMatchResultTy
93   parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
94 
95   MipsAsmParser::OperandMatchResultTy
96   parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
97 
98   MipsAsmParser::OperandMatchResultTy
99   parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
100 
101   MipsAsmParser::OperandMatchResultTy
102   parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
103 
104   bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
105                     StringRef Mnemonic);
106 
107   int tryParseRegister(bool is64BitReg);
108 
109   bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
110                                bool is64BitReg);
111 
112   bool needsExpansion(MCInst &Inst);
113 
114   void expandInstruction(MCInst &Inst, SMLoc IDLoc,
115                          SmallVectorImpl<MCInst> &Instructions);
116   void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
117                      SmallVectorImpl<MCInst> &Instructions);
118   void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
119                             SmallVectorImpl<MCInst> &Instructions);
120   void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
121                             SmallVectorImpl<MCInst> &Instructions);
122   bool reportParseError(StringRef ErrorMsg);
123 
124   bool parseMemOffset(const MCExpr *&Res);
125   bool parseRelocOperand(const MCExpr *&Res);
126 
127   bool parseDirectiveSet();
128 
129   bool parseSetAtDirective();
130   bool parseSetNoAtDirective();
131   bool parseSetMacroDirective();
132   bool parseSetNoMacroDirective();
133   bool parseSetReorderDirective();
134   bool parseSetNoReorderDirective();
135 
136   MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
137 
138   bool isMips64() const {
139     return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
140   }
141 
142   bool isFP64() const {
143     return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
144   }
145 
146   int matchRegisterName(StringRef Symbol, bool is64BitReg);
147 
148   int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
149 
150   void setFpFormat(FpFormatTy Format) {
151     FpFormat = Format;
152   }
153 
154   void setDefaultFpFormat();
155 
156   void setFpFormat(StringRef Format);
157 
158   FpFormatTy getFpFormat() {return FpFormat;}
159 
160   bool requestsDoubleOperand(StringRef Mnemonic);
161 
162   unsigned getReg(int RC,int RegNo);
163 
164   unsigned getATReg();
165 public:
166   MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
167     : MCTargetAsmParser(), STI(sti), Parser(parser) {
168     // Initialize the set of available features.
169     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
170   }
171 
172   MCAsmParser &getParser() const { return Parser; }
173   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
174 
175 };
176 }
177 
178 namespace {
179 
180 /// MipsOperand - Instances of this class represent a parsed Mips machine
181 /// instruction.
182 class MipsOperand : public MCParsedAsmOperand {
183 
184 public:
185   enum RegisterKind {
186     Kind_None,
187     Kind_CPURegs,
188     Kind_CPU64Regs,
189     Kind_HWRegs,
190     Kind_HW64Regs,
191     Kind_FGR32Regs,
192     Kind_FGR64Regs,
193     Kind_AFGR32Regs,
194     Kind_CCRRegs
195   };
196 
197 private:
198   enum KindTy {
199     k_CondCode,
200     k_CoprocNum,
201     k_Immediate,
202     k_Memory,
203     k_PostIndexRegister,
204     k_Register,
205     k_Token
206   } Kind;
207 
208   MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
209 
210   union {
211     struct {
212       const char *Data;
213       unsigned Length;
214     } Tok;
215 
216     struct {
217       unsigned RegNum;
218       RegisterKind Kind;
219     } Reg;
220 
221     struct {
222       const MCExpr *Val;
223     } Imm;
224 
225     struct {
226       unsigned Base;
227       const MCExpr *Off;
228     } Mem;
229   };
230 
231   SMLoc StartLoc, EndLoc;
232 
233 public:
234   void addRegOperands(MCInst &Inst, unsigned N) const {
235     assert(N == 1 && "Invalid number of operands!");
236     Inst.addOperand(MCOperand::CreateReg(getReg()));
237   }
238 
239   void addExpr(MCInst &Inst, const MCExpr *Expr) const{
240     // Add as immediate when possible.  Null MCExpr = 0.
241     if (Expr == 0)
242       Inst.addOperand(MCOperand::CreateImm(0));
243     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
244       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
245     else
246       Inst.addOperand(MCOperand::CreateExpr(Expr));
247   }
248 
249   void addImmOperands(MCInst &Inst, unsigned N) const {
250     assert(N == 1 && "Invalid number of operands!");
251     const MCExpr *Expr = getImm();
252     addExpr(Inst,Expr);
253   }
254 
255   void addMemOperands(MCInst &Inst, unsigned N) const {
256     assert(N == 2 && "Invalid number of operands!");
257 
258     Inst.addOperand(MCOperand::CreateReg(getMemBase()));
259 
260     const MCExpr *Expr = getMemOff();
261     addExpr(Inst,Expr);
262   }
263 
264   bool isReg() const { return Kind == k_Register; }
265   bool isImm() const { return Kind == k_Immediate; }
266   bool isToken() const { return Kind == k_Token; }
267   bool isMem() const { return Kind == k_Memory; }
268 
269   StringRef getToken() const {
270     assert(Kind == k_Token && "Invalid access!");
271     return StringRef(Tok.Data, Tok.Length);
272   }
273 
274   unsigned getReg() const {
275     assert((Kind == k_Register) && "Invalid access!");
276     return Reg.RegNum;
277   }
278 
279   void setRegKind(RegisterKind RegKind) {
280     assert((Kind == k_Register) && "Invalid access!");
281     Reg.Kind = RegKind;
282   }
283 
284   const MCExpr *getImm() const {
285     assert((Kind == k_Immediate) && "Invalid access!");
286     return Imm.Val;
287   }
288 
289   unsigned getMemBase() const {
290     assert((Kind == k_Memory) && "Invalid access!");
291     return Mem.Base;
292   }
293 
294   const MCExpr *getMemOff() const {
295     assert((Kind == k_Memory) && "Invalid access!");
296     return Mem.Off;
297   }
298 
299   static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
300     MipsOperand *Op = new MipsOperand(k_Token);
301     Op->Tok.Data = Str.data();
302     Op->Tok.Length = Str.size();
303     Op->StartLoc = S;
304     Op->EndLoc = S;
305     return Op;
306   }
307 
308   static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
309     MipsOperand *Op = new MipsOperand(k_Register);
310     Op->Reg.RegNum = RegNum;
311     Op->StartLoc = S;
312     Op->EndLoc = E;
313     return Op;
314   }
315 
316   static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
317     MipsOperand *Op = new MipsOperand(k_Immediate);
318     Op->Imm.Val = Val;
319     Op->StartLoc = S;
320     Op->EndLoc = E;
321     return Op;
322   }
323 
324   static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
325                                  SMLoc S, SMLoc E) {
326     MipsOperand *Op = new MipsOperand(k_Memory);
327     Op->Mem.Base = Base;
328     Op->Mem.Off = Off;
329     Op->StartLoc = S;
330     Op->EndLoc = E;
331     return Op;
332   }
333 
334   bool isCPURegsAsm() const {
335     return Kind == k_Register && Reg.Kind == Kind_CPURegs;
336   }
337   void addCPURegsAsmOperands(MCInst &Inst, unsigned N) const {
338     Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
339   }
340 
341   bool isCPU64RegsAsm() const {
342     return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
343   }
344   void addCPU64RegsAsmOperands(MCInst &Inst, unsigned N) const {
345     Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
346   }
347 
348   bool isHWRegsAsm() const {
349     assert((Kind == k_Register) && "Invalid access!");
350     return Reg.Kind == Kind_HWRegs;
351   }
352   void addHWRegsAsmOperands(MCInst &Inst, unsigned N) const {
353     Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
354   }
355 
356   bool isHW64RegsAsm() const {
357     assert((Kind == k_Register) && "Invalid access!");
358     return Reg.Kind == Kind_HW64Regs;
359   }
360   void addHW64RegsAsmOperands(MCInst &Inst, unsigned N) const {
361     Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
362   }
363 
364   void addCCRAsmOperands(MCInst &Inst, unsigned N) const {
365     Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
366   }
367 
368   bool isCCRAsm() const {
369     assert((Kind == k_Register) && "Invalid access!");
370     return Reg.Kind == Kind_CCRRegs;
371   }
372 
373   /// getStartLoc - Get the location of the first token of this operand.
374   SMLoc getStartLoc() const { return StartLoc; }
375   /// getEndLoc - Get the location of the last token of this operand.
376   SMLoc getEndLoc() const { return EndLoc; }
377 
378   virtual void print(raw_ostream &OS) const {
379     llvm_unreachable("unimplemented!");
380   }
381 };
382 }
383 
384 bool MipsAsmParser::needsExpansion(MCInst &Inst) {
385 
386   switch(Inst.getOpcode()) {
387     case Mips::LoadImm32Reg:
388     case Mips::LoadAddr32Imm:
389     case Mips::LoadAddr32Reg:
390       return true;
391     default:
392       return false;
393   }
394 }
395 
396 void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
397                         SmallVectorImpl<MCInst> &Instructions){
398   switch(Inst.getOpcode()) {
399     case Mips::LoadImm32Reg:
400       return expandLoadImm(Inst, IDLoc, Instructions);
401     case Mips::LoadAddr32Imm:
402       return expandLoadAddressImm(Inst,IDLoc,Instructions);
403     case Mips::LoadAddr32Reg:
404       return expandLoadAddressReg(Inst,IDLoc,Instructions);
405     }
406 }
407 
408 void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
409                                   SmallVectorImpl<MCInst> &Instructions){
410   MCInst tmpInst;
411   const MCOperand &ImmOp = Inst.getOperand(1);
412   assert(ImmOp.isImm() && "expected immediate operand kind");
413   const MCOperand &RegOp = Inst.getOperand(0);
414   assert(RegOp.isReg() && "expected register operand kind");
415 
416   int ImmValue = ImmOp.getImm();
417   tmpInst.setLoc(IDLoc);
418   if ( 0 <= ImmValue && ImmValue <= 65535) {
419     // for 0 <= j <= 65535.
420     // li d,j => ori d,$zero,j
421     tmpInst.setOpcode(Mips::ORi);
422     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
423     tmpInst.addOperand(
424               MCOperand::CreateReg(Mips::ZERO));
425     tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
426     Instructions.push_back(tmpInst);
427   } else if ( ImmValue < 0 && ImmValue >= -32768) {
428     // for -32768 <= j < 0.
429     // li d,j => addiu d,$zero,j
430     tmpInst.setOpcode(Mips::ADDiu);
431     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
432     tmpInst.addOperand(
433               MCOperand::CreateReg(Mips::ZERO));
434     tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
435     Instructions.push_back(tmpInst);
436   } else {
437     // for any other value of j that is representable as a 32-bit integer.
438     // li d,j => lui d,hi16(j)
439     //           ori d,d,lo16(j)
440     tmpInst.setOpcode(Mips::LUi);
441     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
442     tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
443     Instructions.push_back(tmpInst);
444     tmpInst.clear();
445     tmpInst.setOpcode(Mips::ORi);
446     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
447     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
448     tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
449     tmpInst.setLoc(IDLoc);
450     Instructions.push_back(tmpInst);
451   }
452 }
453 
454 void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
455                                          SmallVectorImpl<MCInst> &Instructions){
456   MCInst tmpInst;
457   const MCOperand &ImmOp = Inst.getOperand(2);
458   assert(ImmOp.isImm() && "expected immediate operand kind");
459   const MCOperand &SrcRegOp = Inst.getOperand(1);
460   assert(SrcRegOp.isReg() && "expected register operand kind");
461   const MCOperand &DstRegOp = Inst.getOperand(0);
462   assert(DstRegOp.isReg() && "expected register operand kind");
463   int ImmValue = ImmOp.getImm();
464   if ( -32768 <= ImmValue && ImmValue <= 65535) {
465     //for -32768 <= j <= 65535.
466     //la d,j(s) => addiu d,s,j
467     tmpInst.setOpcode(Mips::ADDiu);
468     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
469     tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
470     tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
471     Instructions.push_back(tmpInst);
472   } else {
473     //for any other value of j that is representable as a 32-bit integer.
474     //la d,j(s) => lui d,hi16(j)
475     //             ori d,d,lo16(j)
476     //             addu d,d,s
477     tmpInst.setOpcode(Mips::LUi);
478     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
479     tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
480     Instructions.push_back(tmpInst);
481     tmpInst.clear();
482     tmpInst.setOpcode(Mips::ORi);
483     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
484     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
485     tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
486     Instructions.push_back(tmpInst);
487     tmpInst.clear();
488     tmpInst.setOpcode(Mips::ADDu);
489     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
490     tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
491     tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
492     Instructions.push_back(tmpInst);
493   }
494 }
495 
496 void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
497                                          SmallVectorImpl<MCInst> &Instructions){
498   MCInst tmpInst;
499   const MCOperand &ImmOp = Inst.getOperand(1);
500   assert(ImmOp.isImm() && "expected immediate operand kind");
501   const MCOperand &RegOp = Inst.getOperand(0);
502   assert(RegOp.isReg() && "expected register operand kind");
503   int ImmValue = ImmOp.getImm();
504   if ( -32768 <= ImmValue && ImmValue <= 65535) {
505     //for -32768 <= j <= 65535.
506     //la d,j => addiu d,$zero,j
507     tmpInst.setOpcode(Mips::ADDiu);
508     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
509     tmpInst.addOperand(
510               MCOperand::CreateReg(Mips::ZERO));
511     tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
512     Instructions.push_back(tmpInst);
513   } else {
514     //for any other value of j that is representable as a 32-bit integer.
515     //la d,j => lui d,hi16(j)
516     //          ori d,d,lo16(j)
517     tmpInst.setOpcode(Mips::LUi);
518     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
519     tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
520     Instructions.push_back(tmpInst);
521     tmpInst.clear();
522     tmpInst.setOpcode(Mips::ORi);
523     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
524     tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
525     tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
526     Instructions.push_back(tmpInst);
527   }
528 }
529 
530 bool MipsAsmParser::
531 MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
532                         SmallVectorImpl<MCParsedAsmOperand*> &Operands,
533                         MCStreamer &Out, unsigned &ErrorInfo,
534                         bool MatchingInlineAsm) {
535   MCInst Inst;
536   unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
537                                               MatchingInlineAsm);
538 
539   switch (MatchResult) {
540   default: break;
541   case Match_Success: {
542     if (needsExpansion(Inst)) {
543       SmallVector<MCInst, 4> Instructions;
544       expandInstruction(Inst, IDLoc, Instructions);
545       for(unsigned i =0; i < Instructions.size(); i++){
546         Out.EmitInstruction(Instructions[i]);
547       }
548     } else {
549         Inst.setLoc(IDLoc);
550         Out.EmitInstruction(Inst);
551       }
552     return false;
553   }
554   case Match_MissingFeature:
555     Error(IDLoc, "instruction requires a CPU feature not currently enabled");
556     return true;
557   case Match_InvalidOperand: {
558     SMLoc ErrorLoc = IDLoc;
559     if (ErrorInfo != ~0U) {
560       if (ErrorInfo >= Operands.size())
561         return Error(IDLoc, "too few operands for instruction");
562 
563       ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
564       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
565     }
566 
567     return Error(ErrorLoc, "invalid operand for instruction");
568   }
569   case Match_MnemonicFail:
570     return Error(IDLoc, "invalid instruction");
571   }
572   return true;
573 }
574 
575 int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
576 
577    int CC;
578    if (!is64BitReg)
579     CC = StringSwitch<unsigned>(Name)
580       .Case("zero",  Mips::ZERO)
581       .Case("a0",  Mips::A0)
582       .Case("a1",  Mips::A1)
583       .Case("a2",  Mips::A2)
584       .Case("a3",  Mips::A3)
585       .Case("v0",  Mips::V0)
586       .Case("v1",  Mips::V1)
587       .Case("s0",  Mips::S0)
588       .Case("s1",  Mips::S1)
589       .Case("s2",  Mips::S2)
590       .Case("s3",  Mips::S3)
591       .Case("s4",  Mips::S4)
592       .Case("s5",  Mips::S5)
593       .Case("s6",  Mips::S6)
594       .Case("s7",  Mips::S7)
595       .Case("k0",  Mips::K0)
596       .Case("k1",  Mips::K1)
597       .Case("sp",  Mips::SP)
598       .Case("fp",  Mips::FP)
599       .Case("gp",  Mips::GP)
600       .Case("ra",  Mips::RA)
601       .Case("t0",  Mips::T0)
602       .Case("t1",  Mips::T1)
603       .Case("t2",  Mips::T2)
604       .Case("t3",  Mips::T3)
605       .Case("t4",  Mips::T4)
606       .Case("t5",  Mips::T5)
607       .Case("t6",  Mips::T6)
608       .Case("t7",  Mips::T7)
609       .Case("t8",  Mips::T8)
610       .Case("t9",  Mips::T9)
611       .Case("at",  Mips::AT)
612       .Case("fcc0",  Mips::FCC0)
613       .Default(-1);
614    else
615     CC = StringSwitch<unsigned>(Name)
616       .Case("zero", Mips::ZERO_64)
617       .Case("at", Mips::AT_64)
618       .Case("v0", Mips::V0_64)
619       .Case("v1", Mips::V1_64)
620       .Case("a0", Mips::A0_64)
621       .Case("a1", Mips::A1_64)
622       .Case("a2", Mips::A2_64)
623       .Case("a3", Mips::A3_64)
624       .Case("a4", Mips::T0_64)
625       .Case("a5", Mips::T1_64)
626       .Case("a6", Mips::T2_64)
627       .Case("a7", Mips::T3_64)
628       .Case("t4", Mips::T4_64)
629       .Case("t5", Mips::T5_64)
630       .Case("t6", Mips::T6_64)
631       .Case("t7", Mips::T7_64)
632       .Case("s0", Mips::S0_64)
633       .Case("s1", Mips::S1_64)
634       .Case("s2", Mips::S2_64)
635       .Case("s3", Mips::S3_64)
636       .Case("s4", Mips::S4_64)
637       .Case("s5", Mips::S5_64)
638       .Case("s6", Mips::S6_64)
639       .Case("s7", Mips::S7_64)
640       .Case("t8", Mips::T8_64)
641       .Case("t9", Mips::T9_64)
642       .Case("kt0", Mips::K0_64)
643       .Case("kt1", Mips::K1_64)
644       .Case("gp", Mips::GP_64)
645       .Case("sp", Mips::SP_64)
646       .Case("fp", Mips::FP_64)
647       .Case("s8", Mips::FP_64)
648       .Case("ra", Mips::RA_64)
649       .Default(-1);
650 
651   if (CC != -1)
652     return CC;
653 
654   if (Name[0] == 'f') {
655     StringRef NumString = Name.substr(1);
656     unsigned IntVal;
657     if( NumString.getAsInteger(10, IntVal))
658       return -1; // not integer
659     if (IntVal > 31)
660       return -1;
661 
662     FpFormatTy Format = getFpFormat();
663 
664     if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
665       return getReg(Mips::FGR32RegClassID, IntVal);
666     if (Format == FP_FORMAT_D) {
667       if(isFP64()) {
668         return getReg(Mips::FGR64RegClassID, IntVal);
669       }
670       // only even numbers available as register pairs
671       if (( IntVal > 31) || (IntVal%2 !=  0))
672         return -1;
673       return getReg(Mips::AFGR64RegClassID, IntVal/2);
674     }
675   }
676 
677   return -1;
678 }
679 void MipsAsmParser::setDefaultFpFormat() {
680 
681   if (isMips64() || isFP64())
682     FpFormat = FP_FORMAT_D;
683   else
684     FpFormat = FP_FORMAT_S;
685 }
686 
687 bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
688 
689   bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
690     .Case("ldxc1", true)
691     .Case("ldc1",  true)
692     .Case("sdxc1", true)
693     .Case("sdc1",  true)
694     .Default(false);
695 
696   return IsDouble;
697 }
698 void MipsAsmParser::setFpFormat(StringRef Format) {
699 
700   FpFormat = StringSwitch<FpFormatTy>(Format.lower())
701     .Case(".s",  FP_FORMAT_S)
702     .Case(".d",  FP_FORMAT_D)
703     .Case(".l",  FP_FORMAT_L)
704     .Case(".w",  FP_FORMAT_W)
705     .Default(FP_FORMAT_NONE);
706 }
707 
708 bool MipsAssemblerOptions::setATReg(unsigned Reg) {
709   if (Reg > 31)
710     return false;
711 
712   aTReg = Reg;
713   return true;
714 }
715 
716 unsigned MipsAsmParser::getATReg() {
717   unsigned Reg = Options.getATRegNum();
718   if (isMips64())
719     return getReg(Mips::CPU64RegsRegClassID,Reg);
720 
721   return getReg(Mips::CPURegsRegClassID,Reg);
722 }
723 
724 unsigned MipsAsmParser::getReg(int RC,int RegNo) {
725   return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
726 }
727 
728 int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
729 
730   if (RegNum > 31)
731     return -1;
732 
733   return getReg(RegClass, RegNum);
734 }
735 
736 int MipsAsmParser::tryParseRegister(bool is64BitReg) {
737   const AsmToken &Tok = Parser.getTok();
738   int RegNum = -1;
739 
740   if (Tok.is(AsmToken::Identifier)) {
741     std::string lowerCase = Tok.getString().lower();
742     RegNum = matchRegisterName(lowerCase, is64BitReg);
743   } else if (Tok.is(AsmToken::Integer))
744     RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
745                                    is64BitReg ? Mips::CPU64RegsRegClassID
746                                               : Mips::CPURegsRegClassID);
747   return RegNum;
748 }
749 
750 bool MipsAsmParser::
751   tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
752                           bool is64BitReg){
753 
754   SMLoc S = Parser.getTok().getLoc();
755   int RegNo = -1;
756 
757   RegNo = tryParseRegister(is64BitReg);
758   if (RegNo == -1)
759     return true;
760 
761   Operands.push_back(MipsOperand::CreateReg(RegNo, S,
762       Parser.getTok().getLoc()));
763   Parser.Lex(); // Eat register token.
764   return false;
765 }
766 
767 bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
768                                  StringRef Mnemonic) {
769   // Check if the current operand has a custom associated parser, if so, try to
770   // custom parse the operand, or fallback to the general approach.
771   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
772   if (ResTy == MatchOperand_Success)
773     return false;
774   // If there wasn't a custom match, try the generic matcher below. Otherwise,
775   // there was a match, but an error occurred, in which case, just return that
776   // the operand parsing failed.
777   if (ResTy == MatchOperand_ParseFail)
778     return true;
779 
780   switch (getLexer().getKind()) {
781   default:
782     Error(Parser.getTok().getLoc(), "unexpected token in operand");
783     return true;
784   case AsmToken::Dollar: {
785     // parse register
786     SMLoc S = Parser.getTok().getLoc();
787     Parser.Lex(); // Eat dollar token.
788     // parse register operand
789     if (!tryParseRegisterOperand(Operands, isMips64())) {
790       if (getLexer().is(AsmToken::LParen)) {
791         // check if it is indexed addressing operand
792         Operands.push_back(MipsOperand::CreateToken("(", S));
793         Parser.Lex(); // eat parenthesis
794         if (getLexer().isNot(AsmToken::Dollar))
795           return true;
796 
797         Parser.Lex(); // eat dollar
798         if (tryParseRegisterOperand(Operands, isMips64()))
799           return true;
800 
801         if (!getLexer().is(AsmToken::RParen))
802           return true;
803 
804         S = Parser.getTok().getLoc();
805         Operands.push_back(MipsOperand::CreateToken(")", S));
806         Parser.Lex();
807       }
808       return false;
809     }
810     // maybe it is a symbol reference
811     StringRef Identifier;
812     if (Parser.ParseIdentifier(Identifier))
813       return true;
814 
815     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
816 
817     MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
818 
819     // Otherwise create a symbol ref.
820     const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
821                                                 getContext());
822 
823     Operands.push_back(MipsOperand::CreateImm(Res, S, E));
824     return false;
825   }
826   case AsmToken::Identifier:
827   case AsmToken::LParen:
828   case AsmToken::Minus:
829   case AsmToken::Plus:
830   case AsmToken::Integer:
831   case AsmToken::String: {
832      // quoted label names
833     const MCExpr *IdVal;
834     SMLoc S = Parser.getTok().getLoc();
835     if (getParser().ParseExpression(IdVal))
836       return true;
837     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
838     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
839     return false;
840   }
841   case AsmToken::Percent: {
842     // it is a symbol reference or constant expression
843     const MCExpr *IdVal;
844     SMLoc S = Parser.getTok().getLoc(); // start location of the operand
845     if (parseRelocOperand(IdVal))
846       return true;
847 
848     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
849 
850     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
851     return false;
852   } // case AsmToken::Percent
853   } // switch(getLexer().getKind())
854   return true;
855 }
856 
857 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
858 
859   Parser.Lex(); // eat % token
860   const AsmToken &Tok = Parser.getTok(); // get next token, operation
861   if (Tok.isNot(AsmToken::Identifier))
862     return true;
863 
864   std::string Str = Tok.getIdentifier().str();
865 
866   Parser.Lex(); // eat identifier
867   // now make expression from the rest of the operand
868   const MCExpr *IdVal;
869   SMLoc EndLoc;
870 
871   if (getLexer().getKind() == AsmToken::LParen) {
872     while (1) {
873       Parser.Lex(); // eat '(' token
874       if (getLexer().getKind() == AsmToken::Percent) {
875         Parser.Lex(); // eat % token
876         const AsmToken &nextTok = Parser.getTok();
877         if (nextTok.isNot(AsmToken::Identifier))
878           return true;
879         Str += "(%";
880         Str += nextTok.getIdentifier();
881         Parser.Lex(); // eat identifier
882         if (getLexer().getKind() != AsmToken::LParen)
883           return true;
884       } else
885         break;
886     }
887     if (getParser().ParseParenExpression(IdVal,EndLoc))
888       return true;
889 
890     while (getLexer().getKind() == AsmToken::RParen)
891       Parser.Lex(); // eat ')' token
892 
893   } else
894     return true; // parenthesis must follow reloc operand
895 
896   // Check the type of the expression
897   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
898     // it's a constant, evaluate lo or hi value
899     int Val = MCE->getValue();
900     if (Str == "lo") {
901       Val = Val & 0xffff;
902     } else if (Str == "hi") {
903       Val = (Val & 0xffff0000) >> 16;
904     }
905     Res = MCConstantExpr::Create(Val, getContext());
906     return false;
907   }
908 
909   if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
910     // it's a symbol, create symbolic expression from symbol
911     StringRef Symbol = MSRE->getSymbol().getName();
912     MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
913     Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
914     return false;
915   }
916   return true;
917 }
918 
919 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
920                                   SMLoc &EndLoc) {
921 
922   StartLoc = Parser.getTok().getLoc();
923   RegNo = tryParseRegister(isMips64());
924   EndLoc = Parser.getTok().getLoc();
925   return (RegNo == (unsigned)-1);
926 }
927 
928 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
929 
930   SMLoc S;
931 
932   switch(getLexer().getKind()) {
933   default:
934     return true;
935   case AsmToken::Integer:
936   case AsmToken::Minus:
937   case AsmToken::Plus:
938     return (getParser().ParseExpression(Res));
939   case AsmToken::Percent:
940     return parseRelocOperand(Res);
941   case AsmToken::LParen:
942     return false;  // it's probably assuming 0
943   }
944   return true;
945 }
946 
947 MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
948                SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
949 
950   const MCExpr *IdVal = 0;
951   SMLoc S;
952   // first operand is the offset
953   S = Parser.getTok().getLoc();
954 
955   if (parseMemOffset(IdVal))
956     return MatchOperand_ParseFail;
957 
958   const AsmToken &Tok = Parser.getTok(); // get next token
959   if (Tok.isNot(AsmToken::LParen)) {
960     MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
961     if (Mnemonic->getToken() == "la") {
962       SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
963       Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
964       return MatchOperand_Success;
965     }
966     Error(Parser.getTok().getLoc(), "'(' expected");
967     return MatchOperand_ParseFail;
968   }
969 
970   Parser.Lex(); // Eat '(' token.
971 
972   const AsmToken &Tok1 = Parser.getTok(); // get next token
973   if (Tok1.is(AsmToken::Dollar)) {
974     Parser.Lex(); // Eat '$' token.
975     if (tryParseRegisterOperand(Operands, isMips64())) {
976       Error(Parser.getTok().getLoc(), "unexpected token in operand");
977       return MatchOperand_ParseFail;
978     }
979 
980   } else {
981     Error(Parser.getTok().getLoc(), "unexpected token in operand");
982     return MatchOperand_ParseFail;
983   }
984 
985   const AsmToken &Tok2 = Parser.getTok(); // get next token
986   if (Tok2.isNot(AsmToken::RParen)) {
987     Error(Parser.getTok().getLoc(), "')' expected");
988     return MatchOperand_ParseFail;
989   }
990 
991   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
992 
993   Parser.Lex(); // Eat ')' token.
994 
995   if (IdVal == 0)
996     IdVal = MCConstantExpr::Create(0, getContext());
997 
998   // now replace register operand with the mem operand
999   MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1000   int RegNo = op->getReg();
1001   // remove register from operands
1002   Operands.pop_back();
1003   // and add memory operand
1004   Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1005   delete op;
1006   return MatchOperand_Success;
1007 }
1008 
1009 MipsAsmParser::OperandMatchResultTy
1010 MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1011 
1012   if (!isMips64())
1013     return MatchOperand_NoMatch;
1014   // if the first token is not '$' we have an error
1015   if (Parser.getTok().isNot(AsmToken::Dollar))
1016     return MatchOperand_NoMatch;
1017 
1018   Parser.Lex(); // Eat $
1019   if(!tryParseRegisterOperand(Operands, true)) {
1020     // set the proper register kind
1021     MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1022     op->setRegKind(MipsOperand::Kind_CPU64Regs);
1023     return MatchOperand_Success;
1024   }
1025   return MatchOperand_NoMatch;
1026 }
1027 
1028 MipsAsmParser::OperandMatchResultTy
1029 MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1030 
1031   // if the first token is not '$' we have an error
1032   if (Parser.getTok().isNot(AsmToken::Dollar))
1033     return MatchOperand_NoMatch;
1034 
1035   Parser.Lex(); // Eat $
1036   if(!tryParseRegisterOperand(Operands, false)) {
1037     // set the propper register kind
1038     MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1039     op->setRegKind(MipsOperand::Kind_CPURegs);
1040     return MatchOperand_Success;
1041   }
1042   return MatchOperand_NoMatch;
1043 }
1044 
1045 MipsAsmParser::OperandMatchResultTy
1046 MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1047 
1048   // if the first token is not '$' we have error
1049   if (Parser.getTok().isNot(AsmToken::Dollar))
1050     return MatchOperand_NoMatch;
1051   SMLoc S = Parser.getTok().getLoc();
1052   Parser.Lex(); // Eat $
1053 
1054   const AsmToken &Tok = Parser.getTok(); // get next token
1055   if (Tok.isNot(AsmToken::Integer))
1056     return MatchOperand_NoMatch;
1057 
1058   unsigned RegNum = Tok.getIntVal();
1059   // at the moment only hwreg29 is supported
1060   if (RegNum != 29)
1061     return MatchOperand_ParseFail;
1062 
1063   MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
1064         Parser.getTok().getLoc());
1065   op->setRegKind(MipsOperand::Kind_HWRegs);
1066   Operands.push_back(op);
1067 
1068   Parser.Lex(); // Eat reg number
1069   return MatchOperand_Success;
1070 }
1071 
1072 MipsAsmParser::OperandMatchResultTy
1073 MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1074     //if the first token is not '$' we have error
1075   if (Parser.getTok().isNot(AsmToken::Dollar))
1076     return MatchOperand_NoMatch;
1077   SMLoc S = Parser.getTok().getLoc();
1078   Parser.Lex(); // Eat $
1079 
1080   const AsmToken &Tok = Parser.getTok(); // get next token
1081   if (Tok.isNot(AsmToken::Integer))
1082     return MatchOperand_NoMatch;
1083 
1084   unsigned RegNum = Tok.getIntVal();
1085   // at the moment only hwreg29 is supported
1086   if (RegNum != 29)
1087     return MatchOperand_ParseFail;
1088 
1089   MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
1090         Parser.getTok().getLoc());
1091   op->setRegKind(MipsOperand::Kind_HWRegs);
1092   Operands.push_back(op);
1093 
1094   Parser.Lex(); // Eat reg number
1095   return MatchOperand_Success;
1096 }
1097 
1098 MipsAsmParser::OperandMatchResultTy
1099 MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1100   unsigned RegNum;
1101   //if the first token is not '$' we have error
1102   if (Parser.getTok().isNot(AsmToken::Dollar))
1103     return MatchOperand_NoMatch;
1104   SMLoc S = Parser.getTok().getLoc();
1105   Parser.Lex(); // Eat $
1106 
1107   const AsmToken &Tok = Parser.getTok(); // get next token
1108   if (Tok.is(AsmToken::Integer)) {
1109     RegNum = Tok.getIntVal();
1110     // at the moment only fcc0 is supported
1111     if (RegNum != 0)
1112       return MatchOperand_ParseFail;
1113   } else if (Tok.is(AsmToken::Identifier)) {
1114     // at the moment only fcc0 is supported
1115     if (Tok.getIdentifier() != "fcc0")
1116       return MatchOperand_ParseFail;
1117   } else
1118     return MatchOperand_NoMatch;
1119 
1120   MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
1121         Parser.getTok().getLoc());
1122   op->setRegKind(MipsOperand::Kind_CCRRegs);
1123   Operands.push_back(op);
1124 
1125   Parser.Lex(); // Eat reg number
1126   return MatchOperand_Success;
1127 }
1128 
1129 MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1130 
1131   MCSymbolRefExpr::VariantKind VK
1132                    = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1133     .Case("hi",          MCSymbolRefExpr::VK_Mips_ABS_HI)
1134     .Case("lo",          MCSymbolRefExpr::VK_Mips_ABS_LO)
1135     .Case("gp_rel",      MCSymbolRefExpr::VK_Mips_GPREL)
1136     .Case("call16",      MCSymbolRefExpr::VK_Mips_GOT_CALL)
1137     .Case("got",         MCSymbolRefExpr::VK_Mips_GOT)
1138     .Case("tlsgd",       MCSymbolRefExpr::VK_Mips_TLSGD)
1139     .Case("tlsldm",      MCSymbolRefExpr::VK_Mips_TLSLDM)
1140     .Case("dtprel_hi",   MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1141     .Case("dtprel_lo",   MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1142     .Case("gottprel",    MCSymbolRefExpr::VK_Mips_GOTTPREL)
1143     .Case("tprel_hi",    MCSymbolRefExpr::VK_Mips_TPREL_HI)
1144     .Case("tprel_lo",    MCSymbolRefExpr::VK_Mips_TPREL_LO)
1145     .Case("got_disp",    MCSymbolRefExpr::VK_Mips_GOT_DISP)
1146     .Case("got_page",    MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1147     .Case("got_ofst",    MCSymbolRefExpr::VK_Mips_GOT_OFST)
1148     .Case("hi(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1149     .Case("lo(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1150     .Default(MCSymbolRefExpr::VK_None);
1151 
1152   return VK;
1153 }
1154 
1155 static int ConvertCcString(StringRef CondString) {
1156   int CC = StringSwitch<unsigned>(CondString)
1157       .Case(".f",    0)
1158       .Case(".un",   1)
1159       .Case(".eq",   2)
1160       .Case(".ueq",  3)
1161       .Case(".olt",  4)
1162       .Case(".ult",  5)
1163       .Case(".ole",  6)
1164       .Case(".ule",  7)
1165       .Case(".sf",   8)
1166       .Case(".ngle", 9)
1167       .Case(".seq",  10)
1168       .Case(".ngl",  11)
1169       .Case(".lt",   12)
1170       .Case(".nge",  13)
1171       .Case(".le",   14)
1172       .Case(".ngt",  15)
1173       .Default(-1);
1174 
1175   return CC;
1176 }
1177 
1178 bool MipsAsmParser::
1179 parseMathOperation(StringRef Name, SMLoc NameLoc,
1180                    SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1181   // split the format
1182   size_t Start = Name.find('.'), Next = Name.rfind('.');
1183   StringRef Format1 = Name.slice(Start, Next);
1184   // and add the first format to the operands
1185   Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
1186   // now for the second format
1187   StringRef Format2 = Name.slice(Next, StringRef::npos);
1188   Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1189 
1190   // set the format for the first register
1191   setFpFormat(Format1);
1192 
1193   // Read the remaining operands.
1194   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1195     // Read the first operand.
1196     if (ParseOperand(Operands, Name)) {
1197       SMLoc Loc = getLexer().getLoc();
1198       Parser.EatToEndOfStatement();
1199       return Error(Loc, "unexpected token in argument list");
1200     }
1201 
1202     if (getLexer().isNot(AsmToken::Comma)) {
1203       SMLoc Loc = getLexer().getLoc();
1204       Parser.EatToEndOfStatement();
1205       return Error(Loc, "unexpected token in argument list");
1206 
1207     }
1208     Parser.Lex();  // Eat the comma.
1209 
1210     //set the format for the first register
1211     setFpFormat(Format2);
1212 
1213     // Parse and remember the operand.
1214     if (ParseOperand(Operands, Name)) {
1215       SMLoc Loc = getLexer().getLoc();
1216       Parser.EatToEndOfStatement();
1217       return Error(Loc, "unexpected token in argument list");
1218     }
1219   }
1220 
1221   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1222     SMLoc Loc = getLexer().getLoc();
1223     Parser.EatToEndOfStatement();
1224     return Error(Loc, "unexpected token in argument list");
1225   }
1226 
1227   Parser.Lex(); // Consume the EndOfStatement
1228   return false;
1229 }
1230 
1231 bool MipsAsmParser::
1232 ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
1233                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1234   // floating point instructions: should register be treated as double?
1235   if (requestsDoubleOperand(Name)) {
1236     setFpFormat(FP_FORMAT_D);
1237   Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1238   }
1239   else {
1240     setDefaultFpFormat();
1241     // Create the leading tokens for the mnemonic, split by '.' characters.
1242     size_t Start = 0, Next = Name.find('.');
1243     StringRef Mnemonic = Name.slice(Start, Next);
1244 
1245     Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1246 
1247     if (Next != StringRef::npos) {
1248       // there is a format token in mnemonic
1249       // StringRef Rest = Name.slice(Next, StringRef::npos);
1250       size_t Dot = Name.find('.', Next+1);
1251       StringRef Format = Name.slice(Next, Dot);
1252       if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1253         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1254       else {
1255         if (Name.startswith("c.")){
1256           // floating point compare, add '.' and immediate represent for cc
1257           Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1258           int Cc = ConvertCcString(Format);
1259           if (Cc == -1) {
1260             return Error(NameLoc, "Invalid conditional code");
1261           }
1262           SMLoc E = SMLoc::getFromPointer(
1263               Parser.getTok().getLoc().getPointer() -1 );
1264           Operands.push_back(MipsOperand::CreateImm(
1265               MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1266         } else {
1267           // trunc, ceil, floor ...
1268           return parseMathOperation(Name, NameLoc, Operands);
1269         }
1270 
1271         // the rest is a format
1272         Format = Name.slice(Dot, StringRef::npos);
1273         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1274       }
1275 
1276       setFpFormat(Format);
1277     }
1278   }
1279 
1280   // Read the remaining operands.
1281   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1282     // Read the first operand.
1283     if (ParseOperand(Operands, Name)) {
1284       SMLoc Loc = getLexer().getLoc();
1285       Parser.EatToEndOfStatement();
1286       return Error(Loc, "unexpected token in argument list");
1287     }
1288 
1289     while (getLexer().is(AsmToken::Comma) ) {
1290       Parser.Lex();  // Eat the comma.
1291 
1292       // Parse and remember the operand.
1293       if (ParseOperand(Operands, Name)) {
1294         SMLoc Loc = getLexer().getLoc();
1295         Parser.EatToEndOfStatement();
1296         return Error(Loc, "unexpected token in argument list");
1297       }
1298     }
1299   }
1300 
1301   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1302     SMLoc Loc = getLexer().getLoc();
1303     Parser.EatToEndOfStatement();
1304     return Error(Loc, "unexpected token in argument list");
1305   }
1306 
1307   Parser.Lex(); // Consume the EndOfStatement
1308   return false;
1309 }
1310 
1311 bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1312    SMLoc Loc = getLexer().getLoc();
1313    Parser.EatToEndOfStatement();
1314    return Error(Loc, ErrorMsg);
1315 }
1316 
1317 bool MipsAsmParser::parseSetNoAtDirective() {
1318   // line should look like:
1319   //  .set noat
1320   // set at reg to 0
1321   Options.setATReg(0);
1322   // eat noat
1323   Parser.Lex();
1324   // if this is not the end of the statement, report error
1325   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1326     reportParseError("unexpected token in statement");
1327     return false;
1328   }
1329   Parser.Lex(); // Consume the EndOfStatement
1330   return false;
1331 }
1332 bool MipsAsmParser::parseSetAtDirective() {
1333   // line can be
1334   //  .set at - defaults to $1
1335   // or .set at=$reg
1336   getParser().Lex();
1337   if (getLexer().is(AsmToken::EndOfStatement)) {
1338     Options.setATReg(1);
1339     Parser.Lex(); // Consume the EndOfStatement
1340     return false;
1341   } else if (getLexer().is(AsmToken::Equal)) {
1342     getParser().Lex(); //eat '='
1343     if (getLexer().isNot(AsmToken::Dollar)) {
1344       reportParseError("unexpected token in statement");
1345       return false;
1346     }
1347     Parser.Lex(); // eat '$'
1348     if (getLexer().isNot(AsmToken::Integer)) {
1349       reportParseError("unexpected token in statement");
1350       return false;
1351     }
1352     const AsmToken &Reg = Parser.getTok();
1353     if (!Options.setATReg(Reg.getIntVal())) {
1354       reportParseError("unexpected token in statement");
1355       return false;
1356     }
1357     getParser().Lex(); //eat reg
1358 
1359     if (getLexer().isNot(AsmToken::EndOfStatement)) {
1360       reportParseError("unexpected token in statement");
1361       return false;
1362      }
1363     Parser.Lex(); // Consume the EndOfStatement
1364     return false;
1365   } else {
1366     reportParseError("unexpected token in statement");
1367     return false;
1368   }
1369 }
1370 
1371 bool MipsAsmParser::parseSetReorderDirective() {
1372   Parser.Lex();
1373   // if this is not the end of the statement, report error
1374   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1375     reportParseError("unexpected token in statement");
1376     return false;
1377   }
1378   Options.setReorder();
1379   Parser.Lex(); // Consume the EndOfStatement
1380   return false;
1381 }
1382 
1383 bool MipsAsmParser::parseSetNoReorderDirective() {
1384     Parser.Lex();
1385     // if this is not the end of the statement, report error
1386     if (getLexer().isNot(AsmToken::EndOfStatement)) {
1387       reportParseError("unexpected token in statement");
1388       return false;
1389     }
1390     Options.setNoreorder();
1391     Parser.Lex(); // Consume the EndOfStatement
1392     return false;
1393 }
1394 
1395 bool MipsAsmParser::parseSetMacroDirective() {
1396   Parser.Lex();
1397   // if this is not the end of the statement, report error
1398   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1399     reportParseError("unexpected token in statement");
1400     return false;
1401   }
1402   Options.setMacro();
1403   Parser.Lex(); // Consume the EndOfStatement
1404   return false;
1405 }
1406 
1407 bool MipsAsmParser::parseSetNoMacroDirective() {
1408   Parser.Lex();
1409   // if this is not the end of the statement, report error
1410   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1411     reportParseError("`noreorder' must be set before `nomacro'");
1412     return false;
1413   }
1414   if (Options.isReorder()) {
1415     reportParseError("`noreorder' must be set before `nomacro'");
1416     return false;
1417   }
1418   Options.setNomacro();
1419   Parser.Lex(); // Consume the EndOfStatement
1420   return false;
1421 }
1422 bool MipsAsmParser::parseDirectiveSet() {
1423 
1424   // get next token
1425   const AsmToken &Tok = Parser.getTok();
1426 
1427   if (Tok.getString() == "noat") {
1428     return parseSetNoAtDirective();
1429   } else if (Tok.getString() == "at") {
1430     return parseSetAtDirective();
1431   } else if (Tok.getString() == "reorder") {
1432     return parseSetReorderDirective();
1433   } else if (Tok.getString() == "noreorder") {
1434     return parseSetNoReorderDirective();
1435   } else if (Tok.getString() == "macro") {
1436     return parseSetMacroDirective();
1437   } else if (Tok.getString() == "nomacro") {
1438     return parseSetNoMacroDirective();
1439   } else if (Tok.getString() == "nomips16") {
1440     // ignore this directive for now
1441     Parser.EatToEndOfStatement();
1442     return false;
1443   } else if (Tok.getString() == "nomicromips") {
1444     // ignore this directive for now
1445     Parser.EatToEndOfStatement();
1446     return false;
1447   }
1448   return true;
1449 }
1450 
1451 bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
1452 
1453   if (DirectiveID.getString() == ".ent") {
1454     // ignore this directive for now
1455     Parser.Lex();
1456     return false;
1457   }
1458 
1459   if (DirectiveID.getString() == ".end") {
1460     // ignore this directive for now
1461     Parser.Lex();
1462     return false;
1463   }
1464 
1465   if (DirectiveID.getString() == ".frame") {
1466     // ignore this directive for now
1467     Parser.EatToEndOfStatement();
1468     return false;
1469   }
1470 
1471   if (DirectiveID.getString() == ".set") {
1472     return parseDirectiveSet();
1473   }
1474 
1475   if (DirectiveID.getString() == ".fmask") {
1476     // ignore this directive for now
1477     Parser.EatToEndOfStatement();
1478     return false;
1479   }
1480 
1481   if (DirectiveID.getString() == ".mask") {
1482     // ignore this directive for now
1483     Parser.EatToEndOfStatement();
1484     return false;
1485   }
1486 
1487   if (DirectiveID.getString() == ".gpword") {
1488     // ignore this directive for now
1489     Parser.EatToEndOfStatement();
1490     return false;
1491   }
1492 
1493   return true;
1494 }
1495 
1496 extern "C" void LLVMInitializeMipsAsmParser() {
1497   RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1498   RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1499   RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1500   RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1501 }
1502 
1503 #define GET_REGISTER_MATCHER
1504 #define GET_MATCHER_IMPLEMENTATION
1505 #include "MipsGenAsmMatcher.inc"
1506