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