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