59fefa1268e158ff0c33a2b9df858d496f6147a5
[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);
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   int RegNo = -1;
696
697   // FIXME: we should make a more generic method for CCR
698   if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
699       && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
700     RegNo = Parser.getTok().getIntVal();  // get the int value
701     // at the moment only fcc0 is supported
702     if (RegNo ==  0)
703       RegNo = Mips::FCC0;
704   } else
705     RegNo = tryParseRegister(Mnemonic);
706   if (RegNo == -1)
707     return true;
708
709   Operands.push_back(MipsOperand::CreateReg(RegNo, S,
710       Parser.getTok().getLoc()));
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(Parser.getTok().getLoc().getPointer() - 1);
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     if (getParser().ParseExpression(IdVal))
784       return true;
785     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
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     if (parseRelocOperand(IdVal))
794       return true;
795
796     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
797
798     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
799     return false;
800   } // case AsmToken::Percent
801   } // switch(getLexer().getKind())
802   return true;
803 }
804
805 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
806
807   Parser.Lex(); // eat % token
808   const AsmToken &Tok = Parser.getTok(); // get next token, operation
809   if (Tok.isNot(AsmToken::Identifier))
810     return true;
811
812   std::string Str = Tok.getIdentifier().str();
813
814   Parser.Lex(); // eat identifier
815   // now make expression from the rest of the operand
816   const MCExpr *IdVal;
817   SMLoc EndLoc;
818
819   if (getLexer().getKind() == AsmToken::LParen) {
820     while (1) {
821       Parser.Lex(); // eat '(' token
822       if (getLexer().getKind() == AsmToken::Percent) {
823         Parser.Lex(); // eat % token
824         const AsmToken &nextTok = Parser.getTok();
825         if (nextTok.isNot(AsmToken::Identifier))
826           return true;
827         Str += "(%";
828         Str += nextTok.getIdentifier();
829         Parser.Lex(); // eat identifier
830         if (getLexer().getKind() != AsmToken::LParen)
831           return true;
832       } else
833         break;
834     }
835     if (getParser().ParseParenExpression(IdVal,EndLoc))
836       return true;
837
838     while (getLexer().getKind() == AsmToken::RParen)
839       Parser.Lex(); // eat ')' token
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   RegNo = tryParseRegister("");
872   EndLoc = Parser.getTok().getLoc();
873   return (RegNo == (unsigned)-1);
874 }
875
876 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
877
878   SMLoc S;
879
880   switch(getLexer().getKind()) {
881   default:
882     return true;
883   case AsmToken::Integer:
884   case AsmToken::Minus:
885   case AsmToken::Plus:
886     return (getParser().ParseExpression(Res));
887   case AsmToken::Percent:
888     return parseRelocOperand(Res);
889   case AsmToken::LParen:
890     return false;  // it's probably assuming 0
891   }
892   return true;
893 }
894
895 MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
896                SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
897
898   const MCExpr *IdVal = 0;
899   SMLoc S;
900   // first operand is the offset
901   S = Parser.getTok().getLoc();
902
903   if (parseMemOffset(IdVal))
904     return MatchOperand_ParseFail;
905
906   const AsmToken &Tok = Parser.getTok(); // get next token
907   if (Tok.isNot(AsmToken::LParen)) {
908     MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
909     if (Mnemonic->getToken() == "la") {
910       SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
911       Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
912       return MatchOperand_Success;
913     }
914     Error(Parser.getTok().getLoc(), "'(' expected");
915     return MatchOperand_ParseFail;
916   }
917
918   Parser.Lex(); // Eat '(' token.
919
920   const AsmToken &Tok1 = Parser.getTok(); // get next token
921   if (Tok1.is(AsmToken::Dollar)) {
922     Parser.Lex(); // Eat '$' token.
923     if (tryParseRegisterOperand(Operands,"")) {
924       Error(Parser.getTok().getLoc(), "unexpected token in operand");
925       return MatchOperand_ParseFail;
926     }
927
928   } else {
929     Error(Parser.getTok().getLoc(), "unexpected token in operand");
930     return MatchOperand_ParseFail;
931   }
932
933   const AsmToken &Tok2 = Parser.getTok(); // get next token
934   if (Tok2.isNot(AsmToken::RParen)) {
935     Error(Parser.getTok().getLoc(), "')' expected");
936     return MatchOperand_ParseFail;
937   }
938
939   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
940
941   Parser.Lex(); // Eat ')' token.
942
943   if (IdVal == 0)
944     IdVal = MCConstantExpr::Create(0, getContext());
945
946   // now replace register operand with the mem operand
947   MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
948   int RegNo = op->getReg();
949   // remove register from operands
950   Operands.pop_back();
951   // and add memory operand
952   Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
953   delete op;
954   return MatchOperand_Success;
955 }
956
957 MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
958
959   MCSymbolRefExpr::VariantKind VK
960                    = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
961     .Case("hi",          MCSymbolRefExpr::VK_Mips_ABS_HI)
962     .Case("lo",          MCSymbolRefExpr::VK_Mips_ABS_LO)
963     .Case("gp_rel",      MCSymbolRefExpr::VK_Mips_GPREL)
964     .Case("call16",      MCSymbolRefExpr::VK_Mips_GOT_CALL)
965     .Case("got",         MCSymbolRefExpr::VK_Mips_GOT)
966     .Case("tlsgd",       MCSymbolRefExpr::VK_Mips_TLSGD)
967     .Case("tlsldm",      MCSymbolRefExpr::VK_Mips_TLSLDM)
968     .Case("dtprel_hi",   MCSymbolRefExpr::VK_Mips_DTPREL_HI)
969     .Case("dtprel_lo",   MCSymbolRefExpr::VK_Mips_DTPREL_LO)
970     .Case("gottprel",    MCSymbolRefExpr::VK_Mips_GOTTPREL)
971     .Case("tprel_hi",    MCSymbolRefExpr::VK_Mips_TPREL_HI)
972     .Case("tprel_lo",    MCSymbolRefExpr::VK_Mips_TPREL_LO)
973     .Case("got_disp",    MCSymbolRefExpr::VK_Mips_GOT_DISP)
974     .Case("got_page",    MCSymbolRefExpr::VK_Mips_GOT_PAGE)
975     .Case("got_ofst",    MCSymbolRefExpr::VK_Mips_GOT_OFST)
976     .Case("hi(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_HI)
977     .Case("lo(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_LO)
978     .Default(MCSymbolRefExpr::VK_None);
979
980   return VK;
981 }
982
983 static int ConvertCcString(StringRef CondString) {
984   int CC = StringSwitch<unsigned>(CondString)
985       .Case(".f",    0)
986       .Case(".un",   1)
987       .Case(".eq",   2)
988       .Case(".ueq",  3)
989       .Case(".olt",  4)
990       .Case(".ult",  5)
991       .Case(".ole",  6)
992       .Case(".ule",  7)
993       .Case(".sf",   8)
994       .Case(".ngle", 9)
995       .Case(".seq",  10)
996       .Case(".ngl",  11)
997       .Case(".lt",   12)
998       .Case(".nge",  13)
999       .Case(".le",   14)
1000       .Case(".ngt",  15)
1001       .Default(-1);
1002
1003   return CC;
1004 }
1005
1006 bool MipsAsmParser::
1007 parseMathOperation(StringRef Name, SMLoc NameLoc,
1008                    SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1009   // split the format
1010   size_t Start = Name.find('.'), Next = Name.rfind('.');
1011   StringRef Format1 = Name.slice(Start, Next);
1012   // and add the first format to the operands
1013   Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
1014   // now for the second format
1015   StringRef Format2 = Name.slice(Next, StringRef::npos);
1016   Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1017
1018   // set the format for the first register
1019   setFpFormat(Format1);
1020
1021   // Read the remaining operands.
1022   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1023     // Read the first operand.
1024     if (ParseOperand(Operands, Name)) {
1025       SMLoc Loc = getLexer().getLoc();
1026       Parser.EatToEndOfStatement();
1027       return Error(Loc, "unexpected token in argument list");
1028     }
1029
1030     if (getLexer().isNot(AsmToken::Comma)) {
1031       SMLoc Loc = getLexer().getLoc();
1032       Parser.EatToEndOfStatement();
1033       return Error(Loc, "unexpected token in argument list");
1034
1035     }
1036     Parser.Lex();  // Eat the comma.
1037
1038     //set the format for the first register
1039     setFpFormat(Format2);
1040
1041     // Parse and remember the operand.
1042     if (ParseOperand(Operands, Name)) {
1043       SMLoc Loc = getLexer().getLoc();
1044       Parser.EatToEndOfStatement();
1045       return Error(Loc, "unexpected token in argument list");
1046     }
1047   }
1048
1049   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1050     SMLoc Loc = getLexer().getLoc();
1051     Parser.EatToEndOfStatement();
1052     return Error(Loc, "unexpected token in argument list");
1053   }
1054
1055   Parser.Lex(); // Consume the EndOfStatement
1056   return false;
1057 }
1058
1059 bool MipsAsmParser::
1060 ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
1061                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1062   // floating point instructions: should register be treated as double?
1063   if (requestsDoubleOperand(Name)) {
1064     setFpFormat(FP_FORMAT_D);
1065   Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1066   }
1067   else {
1068     setDefaultFpFormat();
1069     // Create the leading tokens for the mnemonic, split by '.' characters.
1070     size_t Start = 0, Next = Name.find('.');
1071     StringRef Mnemonic = Name.slice(Start, Next);
1072
1073     Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1074
1075     if (Next != StringRef::npos) {
1076       // there is a format token in mnemonic
1077       // StringRef Rest = Name.slice(Next, StringRef::npos);
1078       size_t Dot = Name.find('.', Next+1);
1079       StringRef Format = Name.slice(Next, Dot);
1080       if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1081         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1082       else {
1083         if (Name.startswith("c.")){
1084           // floating point compare, add '.' and immediate represent for cc
1085           Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1086           int Cc = ConvertCcString(Format);
1087           if (Cc == -1) {
1088             return Error(NameLoc, "Invalid conditional code");
1089           }
1090           SMLoc E = SMLoc::getFromPointer(
1091               Parser.getTok().getLoc().getPointer() -1 );
1092           Operands.push_back(MipsOperand::CreateImm(
1093               MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1094         } else {
1095           // trunc, ceil, floor ...
1096           return parseMathOperation(Name, NameLoc, Operands);
1097         }
1098
1099         // the rest is a format
1100         Format = Name.slice(Dot, StringRef::npos);
1101         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1102       }
1103
1104       setFpFormat(Format);
1105     }
1106   }
1107
1108   // Read the remaining operands.
1109   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1110     // Read the first operand.
1111     if (ParseOperand(Operands, Name)) {
1112       SMLoc Loc = getLexer().getLoc();
1113       Parser.EatToEndOfStatement();
1114       return Error(Loc, "unexpected token in argument list");
1115     }
1116
1117     while (getLexer().is(AsmToken::Comma) ) {
1118       Parser.Lex();  // Eat the comma.
1119
1120       // Parse and remember the operand.
1121       if (ParseOperand(Operands, Name)) {
1122         SMLoc Loc = getLexer().getLoc();
1123         Parser.EatToEndOfStatement();
1124         return Error(Loc, "unexpected token in argument list");
1125       }
1126     }
1127   }
1128
1129   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1130     SMLoc Loc = getLexer().getLoc();
1131     Parser.EatToEndOfStatement();
1132     return Error(Loc, "unexpected token in argument list");
1133   }
1134
1135   Parser.Lex(); // Consume the EndOfStatement
1136   return false;
1137 }
1138
1139 bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1140    SMLoc Loc = getLexer().getLoc();
1141    Parser.EatToEndOfStatement();
1142    return Error(Loc, ErrorMsg);
1143 }
1144
1145 bool MipsAsmParser::parseSetNoAtDirective() {
1146   // line should look like:
1147   //  .set noat
1148   // set at reg to 0
1149   Options.setATReg(0);
1150   // eat noat
1151   Parser.Lex();
1152   // if this is not the end of the statement, report error
1153   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1154     reportParseError("unexpected token in statement");
1155     return false;
1156   }
1157   Parser.Lex(); // Consume the EndOfStatement
1158   return false;
1159 }
1160 bool MipsAsmParser::parseSetAtDirective() {
1161   // line can be
1162   //  .set at - defaults to $1
1163   // or .set at=$reg
1164   getParser().Lex();
1165   if (getLexer().is(AsmToken::EndOfStatement)) {
1166     Options.setATReg(1);
1167     Parser.Lex(); // Consume the EndOfStatement
1168     return false;
1169   } else if (getLexer().is(AsmToken::Equal)) {
1170     getParser().Lex(); //eat '='
1171     if (getLexer().isNot(AsmToken::Dollar)) {
1172       reportParseError("unexpected token in statement");
1173       return false;
1174     }
1175     Parser.Lex(); // eat '$'
1176     if (getLexer().isNot(AsmToken::Integer)) {
1177       reportParseError("unexpected token in statement");
1178       return false;
1179     }
1180     const AsmToken &Reg = Parser.getTok();
1181     if (!Options.setATReg(Reg.getIntVal())) {
1182       reportParseError("unexpected token in statement");
1183       return false;
1184     }
1185     getParser().Lex(); //eat reg
1186
1187     if (getLexer().isNot(AsmToken::EndOfStatement)) {
1188       reportParseError("unexpected token in statement");
1189       return false;
1190      }
1191     Parser.Lex(); // Consume the EndOfStatement
1192     return false;
1193   } else {
1194     reportParseError("unexpected token in statement");
1195     return false;
1196   }
1197 }
1198
1199 bool MipsAsmParser::parseSetReorderDirective() {
1200   Parser.Lex();
1201   // if this is not the end of the statement, report error
1202   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1203     reportParseError("unexpected token in statement");
1204     return false;
1205   }
1206   Options.setReorder();
1207   Parser.Lex(); // Consume the EndOfStatement
1208   return false;
1209 }
1210
1211 bool MipsAsmParser::parseSetNoReorderDirective() {
1212     Parser.Lex();
1213     // if this is not the end of the statement, report error
1214     if (getLexer().isNot(AsmToken::EndOfStatement)) {
1215       reportParseError("unexpected token in statement");
1216       return false;
1217     }
1218     Options.setNoreorder();
1219     Parser.Lex(); // Consume the EndOfStatement
1220     return false;
1221 }
1222
1223 bool MipsAsmParser::parseSetMacroDirective() {
1224   Parser.Lex();
1225   // if this is not the end of the statement, report error
1226   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1227     reportParseError("unexpected token in statement");
1228     return false;
1229   }
1230   Options.setMacro();
1231   Parser.Lex(); // Consume the EndOfStatement
1232   return false;
1233 }
1234
1235 bool MipsAsmParser::parseSetNoMacroDirective() {
1236   Parser.Lex();
1237   // if this is not the end of the statement, report error
1238   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1239     reportParseError("`noreorder' must be set before `nomacro'");
1240     return false;
1241   }
1242   if (Options.isReorder()) {
1243     reportParseError("`noreorder' must be set before `nomacro'");
1244     return false;
1245   }
1246   Options.setNomacro();
1247   Parser.Lex(); // Consume the EndOfStatement
1248   return false;
1249 }
1250 bool MipsAsmParser::parseDirectiveSet() {
1251
1252   // get next token
1253   const AsmToken &Tok = Parser.getTok();
1254
1255   if (Tok.getString() == "noat") {
1256     return parseSetNoAtDirective();
1257   } else if (Tok.getString() == "at") {
1258     return parseSetAtDirective();
1259   } else if (Tok.getString() == "reorder") {
1260     return parseSetReorderDirective();
1261   } else if (Tok.getString() == "noreorder") {
1262     return parseSetNoReorderDirective();
1263   } else if (Tok.getString() == "macro") {
1264     return parseSetMacroDirective();
1265   } else if (Tok.getString() == "nomacro") {
1266     return parseSetNoMacroDirective();
1267   } else if (Tok.getString() == "nomips16") {
1268     // ignore this directive for now
1269     Parser.EatToEndOfStatement();
1270     return false;
1271   } else if (Tok.getString() == "nomicromips") {
1272     // ignore this directive for now
1273     Parser.EatToEndOfStatement();
1274     return false;
1275   }
1276   return true;
1277 }
1278
1279 bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
1280
1281   if (DirectiveID.getString() == ".ent") {
1282     // ignore this directive for now
1283     Parser.Lex();
1284     return false;
1285   }
1286
1287   if (DirectiveID.getString() == ".end") {
1288     // ignore this directive for now
1289     Parser.Lex();
1290     return false;
1291   }
1292
1293   if (DirectiveID.getString() == ".frame") {
1294     // ignore this directive for now
1295     Parser.EatToEndOfStatement();
1296     return false;
1297   }
1298
1299   if (DirectiveID.getString() == ".set") {
1300     return parseDirectiveSet();
1301   }
1302
1303   if (DirectiveID.getString() == ".fmask") {
1304     // ignore this directive for now
1305     Parser.EatToEndOfStatement();
1306     return false;
1307   }
1308
1309   if (DirectiveID.getString() == ".mask") {
1310     // ignore this directive for now
1311     Parser.EatToEndOfStatement();
1312     return false;
1313   }
1314
1315   if (DirectiveID.getString() == ".gpword") {
1316     // ignore this directive for now
1317     Parser.EatToEndOfStatement();
1318     return false;
1319   }
1320
1321   return true;
1322 }
1323
1324 extern "C" void LLVMInitializeMipsAsmParser() {
1325   RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1326   RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1327   RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1328   RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1329 }
1330
1331 #define GET_REGISTER_MATCHER
1332 #define GET_MATCHER_IMPLEMENTATION
1333 #include "MipsGenAsmMatcher.inc"