Initial assembler implementation of Mips load address macro
[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 Kind;
460   unsigned ErrorInfo;
461   MatchInstMapAndConstraints MapAndConstraints;
462   unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
463                                               MapAndConstraints, ErrorInfo,
464                                               /*matchingInlineAsm*/ false);
465
466   switch (MatchResult) {
467   default: break;
468   case Match_Success: {
469     if (needsExpansion(Inst)) {
470       SmallVector<MCInst, 4> Instructions;
471       expandInstruction(Inst, IDLoc, Instructions);
472       for(unsigned i =0; i < Instructions.size(); i++){
473         Out.EmitInstruction(Instructions[i]);
474       }
475     } else {
476         Inst.setLoc(IDLoc);
477         Out.EmitInstruction(Inst);
478       }
479     return false;
480   }
481   case Match_MissingFeature:
482     Error(IDLoc, "instruction requires a CPU feature not currently enabled");
483     return true;
484   case Match_InvalidOperand: {
485     SMLoc ErrorLoc = IDLoc;
486     if (ErrorInfo != ~0U) {
487       if (ErrorInfo >= Operands.size())
488         return Error(IDLoc, "too few operands for instruction");
489
490       ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
491       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
492     }
493
494     return Error(ErrorLoc, "invalid operand for instruction");
495   }
496   case Match_MnemonicFail:
497     return Error(IDLoc, "invalid instruction");
498   }
499   return true;
500 }
501
502 int MipsAsmParser::matchRegisterName(StringRef Name) {
503
504    int CC;
505    if (!isMips64())
506     CC = StringSwitch<unsigned>(Name)
507       .Case("zero",  Mips::ZERO)
508       .Case("a0",  Mips::A0)
509       .Case("a1",  Mips::A1)
510       .Case("a2",  Mips::A2)
511       .Case("a3",  Mips::A3)
512       .Case("v0",  Mips::V0)
513       .Case("v1",  Mips::V1)
514       .Case("s0",  Mips::S0)
515       .Case("s1",  Mips::S1)
516       .Case("s2",  Mips::S2)
517       .Case("s3",  Mips::S3)
518       .Case("s4",  Mips::S4)
519       .Case("s5",  Mips::S5)
520       .Case("s6",  Mips::S6)
521       .Case("s7",  Mips::S7)
522       .Case("k0",  Mips::K0)
523       .Case("k1",  Mips::K1)
524       .Case("sp",  Mips::SP)
525       .Case("fp",  Mips::FP)
526       .Case("gp",  Mips::GP)
527       .Case("ra",  Mips::RA)
528       .Case("t0",  Mips::T0)
529       .Case("t1",  Mips::T1)
530       .Case("t2",  Mips::T2)
531       .Case("t3",  Mips::T3)
532       .Case("t4",  Mips::T4)
533       .Case("t5",  Mips::T5)
534       .Case("t6",  Mips::T6)
535       .Case("t7",  Mips::T7)
536       .Case("t8",  Mips::T8)
537       .Case("t9",  Mips::T9)
538       .Case("at",  Mips::AT)
539       .Case("fcc0",  Mips::FCC0)
540       .Default(-1);
541    else
542     CC = StringSwitch<unsigned>(Name)
543       .Case("zero", Mips::ZERO_64)
544       .Case("at", Mips::AT_64)
545       .Case("v0", Mips::V0_64)
546       .Case("v1", Mips::V1_64)
547       .Case("a0", Mips::A0_64)
548       .Case("a1", Mips::A1_64)
549       .Case("a2", Mips::A2_64)
550       .Case("a3", Mips::A3_64)
551       .Case("a4", Mips::T0_64)
552       .Case("a5", Mips::T1_64)
553       .Case("a6", Mips::T2_64)
554       .Case("a7", Mips::T3_64)
555       .Case("t4", Mips::T4_64)
556       .Case("t5", Mips::T5_64)
557       .Case("t6", Mips::T6_64)
558       .Case("t7", Mips::T7_64)
559       .Case("s0", Mips::S0_64)
560       .Case("s1", Mips::S1_64)
561       .Case("s2", Mips::S2_64)
562       .Case("s3", Mips::S3_64)
563       .Case("s4", Mips::S4_64)
564       .Case("s5", Mips::S5_64)
565       .Case("s6", Mips::S6_64)
566       .Case("s7", Mips::S7_64)
567       .Case("t8", Mips::T8_64)
568       .Case("t9", Mips::T9_64)
569       .Case("kt0", Mips::K0_64)
570       .Case("kt1", Mips::K1_64)
571       .Case("gp", Mips::GP_64)
572       .Case("sp", Mips::SP_64)
573       .Case("fp", Mips::FP_64)
574       .Case("s8", Mips::FP_64)
575       .Case("ra", Mips::RA_64)
576       .Default(-1);
577
578   if (CC != -1)
579     return CC;
580
581   if (Name[0] == 'f') {
582     StringRef NumString = Name.substr(1);
583     unsigned IntVal;
584     if( NumString.getAsInteger(10, IntVal))
585       return -1; // not integer
586     if (IntVal > 31)
587       return -1;
588
589     FpFormatTy Format = getFpFormat();
590
591     if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
592       return getReg(Mips::FGR32RegClassID, IntVal);
593     if (Format == FP_FORMAT_D) {
594       if(isFP64()) {
595         return getReg(Mips::FGR64RegClassID, IntVal);
596       }
597       // only even numbers available as register pairs
598       if (( IntVal > 31) || (IntVal%2 !=  0))
599         return -1;
600       return getReg(Mips::AFGR64RegClassID, IntVal/2);
601     }
602   }
603
604   return -1;
605 }
606 void MipsAsmParser::setDefaultFpFormat() {
607
608   if (isMips64() || isFP64())
609     FpFormat = FP_FORMAT_D;
610   else
611     FpFormat = FP_FORMAT_S;
612 }
613
614 bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
615
616   bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
617     .Case("ldxc1", true)
618     .Case("ldc1",  true)
619     .Case("sdxc1", true)
620     .Case("sdc1",  true)
621     .Default(false);
622
623   return IsDouble;
624 }
625 void MipsAsmParser::setFpFormat(StringRef Format) {
626
627   FpFormat = StringSwitch<FpFormatTy>(Format.lower())
628     .Case(".s",  FP_FORMAT_S)
629     .Case(".d",  FP_FORMAT_D)
630     .Case(".l",  FP_FORMAT_L)
631     .Case(".w",  FP_FORMAT_W)
632     .Default(FP_FORMAT_NONE);
633 }
634
635 bool MipsAssemblerOptions::setATReg(unsigned Reg) {
636   if (Reg > 31)
637     return false;
638
639   aTReg = Reg;
640   return true;
641 }
642
643 unsigned MipsAsmParser::getATReg() {
644   unsigned Reg = Options.getATRegNum();
645   if (isMips64())
646     return getReg(Mips::CPU64RegsRegClassID,Reg);
647   
648   return getReg(Mips::CPURegsRegClassID,Reg);
649 }
650
651 unsigned MipsAsmParser::getReg(int RC,int RegNo) {
652   return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
653 }
654
655 int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic) {
656
657   if (Mnemonic.lower() == "rdhwr") {
658     // at the moment only hwreg29 is supported
659     if (RegNum != 29)
660       return -1;
661     return Mips::HWR29;
662   }
663
664   if (RegNum > 31)
665     return -1;
666
667   // MIPS64 registers are numbered 1 after the 32-bit equivalents
668   return getReg(Mips::CPURegsRegClassID, RegNum) + isMips64();
669 }
670
671 int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
672   const AsmToken &Tok = Parser.getTok();
673   int RegNum = -1;
674
675   if (Tok.is(AsmToken::Identifier)) {
676     std::string lowerCase = Tok.getString().lower();
677     RegNum = matchRegisterName(lowerCase);
678   } else if (Tok.is(AsmToken::Integer))
679     RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
680                                    Mnemonic.lower());
681     else
682       return RegNum;  //error
683   // 64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
684   if (isMips64() && RegNum == Mips::ZERO_64) {
685     if (Mnemonic.find("ddiv") != StringRef::npos)
686       RegNum = Mips::ZERO;
687   }
688   return RegNum;
689 }
690
691 bool MipsAsmParser::
692   tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
693                           StringRef Mnemonic){
694
695   SMLoc S = Parser.getTok().getLoc();
696   int RegNo = -1;
697
698   // FIXME: we should make a more generic method for CCR
699   if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
700       && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
701     RegNo = Parser.getTok().getIntVal();  // get the int value
702     // at the moment only fcc0 is supported
703     if (RegNo ==  0)
704       RegNo = Mips::FCC0;
705   } else
706     RegNo = tryParseRegister(Mnemonic);
707   if (RegNo == -1)
708     return true;
709
710   Operands.push_back(MipsOperand::CreateReg(RegNo, S,
711       Parser.getTok().getLoc()));
712   Parser.Lex(); // Eat register token.
713   return false;
714 }
715
716 bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
717                                  StringRef Mnemonic) {
718   // Check if the current operand has a custom associated parser, if so, try to
719   // custom parse the operand, or fallback to the general approach.
720   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
721   if (ResTy == MatchOperand_Success)
722     return false;
723   // If there wasn't a custom match, try the generic matcher below. Otherwise,
724   // there was a match, but an error occurred, in which case, just return that
725   // the operand parsing failed.
726   if (ResTy == MatchOperand_ParseFail)
727     return true;
728
729   switch (getLexer().getKind()) {
730   default:
731     Error(Parser.getTok().getLoc(), "unexpected token in operand");
732     return true;
733   case AsmToken::Dollar: {
734     // parse register
735     SMLoc S = Parser.getTok().getLoc();
736     Parser.Lex(); // Eat dollar token.
737     // parse register operand
738     if (!tryParseRegisterOperand(Operands, Mnemonic)) {
739       if (getLexer().is(AsmToken::LParen)) {
740         // check if it is indexed addressing operand
741         Operands.push_back(MipsOperand::CreateToken("(", S));
742         Parser.Lex(); // eat parenthesis
743         if (getLexer().isNot(AsmToken::Dollar))
744           return true;
745
746         Parser.Lex(); // eat dollar
747         if (tryParseRegisterOperand(Operands, Mnemonic))
748           return true;
749
750         if (!getLexer().is(AsmToken::RParen))
751           return true;
752
753         S = Parser.getTok().getLoc();
754         Operands.push_back(MipsOperand::CreateToken(")", S));
755         Parser.Lex();
756       }
757       return false;
758     }
759     // maybe it is a symbol reference
760     StringRef Identifier;
761     if (Parser.ParseIdentifier(Identifier))
762       return true;
763
764     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
765
766     MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
767
768     // Otherwise create a symbol ref.
769     const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
770                                                 getContext());
771
772     Operands.push_back(MipsOperand::CreateImm(Res, S, E));
773     return false;
774   }
775   case AsmToken::Identifier:
776   case AsmToken::LParen:
777   case AsmToken::Minus:
778   case AsmToken::Plus:
779   case AsmToken::Integer:
780   case AsmToken::String: {
781      // quoted label names
782     const MCExpr *IdVal;
783     SMLoc S = Parser.getTok().getLoc();
784     if (getParser().ParseExpression(IdVal))
785       return true;
786     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
787     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
788     return false;
789   }
790   case AsmToken::Percent: {
791     // it is a symbol reference or constant expression
792     const MCExpr *IdVal;
793     SMLoc S = Parser.getTok().getLoc(); // start location of the operand
794     if (parseRelocOperand(IdVal))
795       return true;
796
797     SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
798
799     Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
800     return false;
801   } // case AsmToken::Percent
802   } // switch(getLexer().getKind())
803   return true;
804 }
805
806 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
807
808   Parser.Lex(); // eat % token
809   const AsmToken &Tok = Parser.getTok(); // get next token, operation
810   if (Tok.isNot(AsmToken::Identifier))
811     return true;
812
813   std::string Str = Tok.getIdentifier().str();
814
815   Parser.Lex(); // eat identifier
816   // now make expression from the rest of the operand
817   const MCExpr *IdVal;
818   SMLoc EndLoc;
819
820   if (getLexer().getKind() == AsmToken::LParen) {
821     while (1) {
822       Parser.Lex(); // eat '(' token
823       if (getLexer().getKind() == AsmToken::Percent) {
824         Parser.Lex(); // eat % token
825         const AsmToken &nextTok = Parser.getTok();
826         if (nextTok.isNot(AsmToken::Identifier))
827           return true;
828         Str += "(%";
829         Str += nextTok.getIdentifier();
830         Parser.Lex(); // eat identifier
831         if (getLexer().getKind() != AsmToken::LParen)
832           return true;
833       } else
834         break;
835     }
836     if (getParser().ParseParenExpression(IdVal,EndLoc))
837       return true;
838
839     while (getLexer().getKind() == AsmToken::RParen)
840       Parser.Lex(); // eat ')' token
841
842   } else
843     return true; // parenthesis must follow reloc operand
844
845   // Check the type of the expression
846   if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
847     // it's a constant, evaluate lo or hi value
848     int Val = MCE->getValue();
849     if (Str == "lo") {
850       Val = Val & 0xffff;
851     } else if (Str == "hi") {
852       Val = (Val & 0xffff0000) >> 16;
853     }
854     Res = MCConstantExpr::Create(Val, getContext());
855     return false;
856   }
857
858   if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
859     // it's a symbol, create symbolic expression from symbol
860     StringRef Symbol = MSRE->getSymbol().getName();
861     MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
862     Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
863     return false;
864   }
865   return true;
866 }
867
868 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
869                                   SMLoc &EndLoc) {
870
871   StartLoc = Parser.getTok().getLoc();
872   RegNo = tryParseRegister("");
873   EndLoc = Parser.getTok().getLoc();
874   return (RegNo == (unsigned)-1);
875 }
876
877 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
878
879   SMLoc S;
880
881   switch(getLexer().getKind()) {
882   default:
883     return true;
884   case AsmToken::Integer:
885   case AsmToken::Minus:
886   case AsmToken::Plus:
887     return (getParser().ParseExpression(Res));
888   case AsmToken::Percent:
889     return parseRelocOperand(Res);
890   case AsmToken::LParen:
891     return false;  // it's probably assuming 0
892   }
893   return true;
894 }
895
896 MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
897                SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
898
899   const MCExpr *IdVal = 0;
900   SMLoc S;
901   // first operand is the offset
902   S = Parser.getTok().getLoc();
903
904   if (parseMemOffset(IdVal))
905     return MatchOperand_ParseFail;
906
907   const AsmToken &Tok = Parser.getTok(); // get next token
908   if (Tok.isNot(AsmToken::LParen)) {
909     MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
910     if (Mnemonic->getToken() == "la") {
911       SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
912       Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
913       return MatchOperand_Success;
914     }
915     Error(Parser.getTok().getLoc(), "'(' expected");
916     return MatchOperand_ParseFail;
917   }
918
919   Parser.Lex(); // Eat '(' token.
920
921   const AsmToken &Tok1 = Parser.getTok(); // get next token
922   if (Tok1.is(AsmToken::Dollar)) {
923     Parser.Lex(); // Eat '$' token.
924     if (tryParseRegisterOperand(Operands,"")) {
925       Error(Parser.getTok().getLoc(), "unexpected token in operand");
926       return MatchOperand_ParseFail;
927     }
928
929   } else {
930     Error(Parser.getTok().getLoc(), "unexpected token in operand");
931     return MatchOperand_ParseFail;
932   }
933
934   const AsmToken &Tok2 = Parser.getTok(); // get next token
935   if (Tok2.isNot(AsmToken::RParen)) {
936     Error(Parser.getTok().getLoc(), "')' expected");
937     return MatchOperand_ParseFail;
938   }
939
940   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
941
942   Parser.Lex(); // Eat ')' token.
943
944   if (IdVal == 0)
945     IdVal = MCConstantExpr::Create(0, getContext());
946
947   // now replace register operand with the mem operand
948   MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
949   int RegNo = op->getReg();
950   // remove register from operands
951   Operands.pop_back();
952   // and add memory operand
953   Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
954   delete op;
955   return MatchOperand_Success;
956 }
957
958 MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
959
960   MCSymbolRefExpr::VariantKind VK
961                    = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
962     .Case("hi",          MCSymbolRefExpr::VK_Mips_ABS_HI)
963     .Case("lo",          MCSymbolRefExpr::VK_Mips_ABS_LO)
964     .Case("gp_rel",      MCSymbolRefExpr::VK_Mips_GPREL)
965     .Case("call16",      MCSymbolRefExpr::VK_Mips_GOT_CALL)
966     .Case("got",         MCSymbolRefExpr::VK_Mips_GOT)
967     .Case("tlsgd",       MCSymbolRefExpr::VK_Mips_TLSGD)
968     .Case("tlsldm",      MCSymbolRefExpr::VK_Mips_TLSLDM)
969     .Case("dtprel_hi",   MCSymbolRefExpr::VK_Mips_DTPREL_HI)
970     .Case("dtprel_lo",   MCSymbolRefExpr::VK_Mips_DTPREL_LO)
971     .Case("gottprel",    MCSymbolRefExpr::VK_Mips_GOTTPREL)
972     .Case("tprel_hi",    MCSymbolRefExpr::VK_Mips_TPREL_HI)
973     .Case("tprel_lo",    MCSymbolRefExpr::VK_Mips_TPREL_LO)
974     .Case("got_disp",    MCSymbolRefExpr::VK_Mips_GOT_DISP)
975     .Case("got_page",    MCSymbolRefExpr::VK_Mips_GOT_PAGE)
976     .Case("got_ofst",    MCSymbolRefExpr::VK_Mips_GOT_OFST)
977     .Case("hi(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_HI)
978     .Case("lo(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_LO)
979     .Default(MCSymbolRefExpr::VK_None);
980
981   return VK;
982 }
983
984 static int ConvertCcString(StringRef CondString) {
985   int CC = StringSwitch<unsigned>(CondString)
986       .Case(".f",    0)
987       .Case(".un",   1)
988       .Case(".eq",   2)
989       .Case(".ueq",  3)
990       .Case(".olt",  4)
991       .Case(".ult",  5)
992       .Case(".ole",  6)
993       .Case(".ule",  7)
994       .Case(".sf",   8)
995       .Case(".ngle", 9)
996       .Case(".seq",  10)
997       .Case(".ngl",  11)
998       .Case(".lt",   12)
999       .Case(".nge",  13)
1000       .Case(".le",   14)
1001       .Case(".ngt",  15)
1002       .Default(-1);
1003
1004   return CC;
1005 }
1006
1007 bool MipsAsmParser::
1008 parseMathOperation(StringRef Name, SMLoc NameLoc,
1009                    SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1010   // split the format
1011   size_t Start = Name.find('.'), Next = Name.rfind('.');
1012   StringRef Format1 = Name.slice(Start, Next);
1013   // and add the first format to the operands
1014   Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
1015   // now for the second format
1016   StringRef Format2 = Name.slice(Next, StringRef::npos);
1017   Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1018
1019   // set the format for the first register
1020   setFpFormat(Format1);
1021
1022   // Read the remaining operands.
1023   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1024     // Read the first operand.
1025     if (ParseOperand(Operands, Name)) {
1026       SMLoc Loc = getLexer().getLoc();
1027       Parser.EatToEndOfStatement();
1028       return Error(Loc, "unexpected token in argument list");
1029     }
1030
1031     if (getLexer().isNot(AsmToken::Comma)) {
1032       SMLoc Loc = getLexer().getLoc();
1033       Parser.EatToEndOfStatement();
1034       return Error(Loc, "unexpected token in argument list");
1035
1036     }
1037     Parser.Lex();  // Eat the comma.
1038
1039     //set the format for the first register
1040     setFpFormat(Format2);
1041
1042     // Parse and remember the operand.
1043     if (ParseOperand(Operands, Name)) {
1044       SMLoc Loc = getLexer().getLoc();
1045       Parser.EatToEndOfStatement();
1046       return Error(Loc, "unexpected token in argument list");
1047     }
1048   }
1049
1050   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1051     SMLoc Loc = getLexer().getLoc();
1052     Parser.EatToEndOfStatement();
1053     return Error(Loc, "unexpected token in argument list");
1054   }
1055
1056   Parser.Lex(); // Consume the EndOfStatement
1057   return false;
1058 }
1059
1060 bool MipsAsmParser::
1061 ParseInstruction(StringRef Name, SMLoc NameLoc,
1062                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1063   // floating point instructions: should register be treated as double?
1064   if (requestsDoubleOperand(Name)) {
1065     setFpFormat(FP_FORMAT_D);
1066   Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1067   }
1068   else {
1069     setDefaultFpFormat();
1070     // Create the leading tokens for the mnemonic, split by '.' characters.
1071     size_t Start = 0, Next = Name.find('.');
1072     StringRef Mnemonic = Name.slice(Start, Next);
1073
1074     Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1075
1076     if (Next != StringRef::npos) {
1077       // there is a format token in mnemonic
1078       // StringRef Rest = Name.slice(Next, StringRef::npos);
1079       size_t Dot = Name.find('.', Next+1);
1080       StringRef Format = Name.slice(Next, Dot);
1081       if (Dot == StringRef::npos) //only one '.' in a string, it's a format
1082         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1083       else {
1084         if (Name.startswith("c.")){
1085           // floating point compare, add '.' and immediate represent for cc
1086           Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1087           int Cc = ConvertCcString(Format);
1088           if (Cc == -1) {
1089             return Error(NameLoc, "Invalid conditional code");
1090           }
1091           SMLoc E = SMLoc::getFromPointer(
1092               Parser.getTok().getLoc().getPointer() -1 );
1093           Operands.push_back(MipsOperand::CreateImm(
1094               MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
1095         } else {
1096           // trunc, ceil, floor ...
1097           return parseMathOperation(Name, NameLoc, Operands);
1098         }
1099
1100         // the rest is a format
1101         Format = Name.slice(Dot, StringRef::npos);
1102         Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1103       }
1104
1105       setFpFormat(Format);
1106     }
1107   }
1108
1109   // Read the remaining operands.
1110   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1111     // Read the first operand.
1112     if (ParseOperand(Operands, Name)) {
1113       SMLoc Loc = getLexer().getLoc();
1114       Parser.EatToEndOfStatement();
1115       return Error(Loc, "unexpected token in argument list");
1116     }
1117
1118     while (getLexer().is(AsmToken::Comma) ) {
1119       Parser.Lex();  // Eat the comma.
1120
1121       // Parse and remember the operand.
1122       if (ParseOperand(Operands, Name)) {
1123         SMLoc Loc = getLexer().getLoc();
1124         Parser.EatToEndOfStatement();
1125         return Error(Loc, "unexpected token in argument list");
1126       }
1127     }
1128   }
1129
1130   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1131     SMLoc Loc = getLexer().getLoc();
1132     Parser.EatToEndOfStatement();
1133     return Error(Loc, "unexpected token in argument list");
1134   }
1135
1136   Parser.Lex(); // Consume the EndOfStatement
1137   return false;
1138 }
1139
1140 bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1141    SMLoc Loc = getLexer().getLoc();
1142    Parser.EatToEndOfStatement();
1143    return Error(Loc, ErrorMsg);
1144 }
1145
1146 bool MipsAsmParser::parseSetNoAtDirective() {
1147   // line should look like:
1148   //  .set noat
1149   // set at reg to 0
1150   Options.setATReg(0);
1151   // eat noat
1152   Parser.Lex();
1153   // if this is not the end of the statement, report error
1154   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1155     reportParseError("unexpected token in statement");
1156     return false;
1157   }
1158   Parser.Lex(); // Consume the EndOfStatement
1159   return false;
1160 }
1161 bool MipsAsmParser::parseSetAtDirective() {
1162   // line can be
1163   //  .set at - defaults to $1
1164   // or .set at=$reg
1165   getParser().Lex();
1166   if (getLexer().is(AsmToken::EndOfStatement)) {
1167     Options.setATReg(1);
1168     Parser.Lex(); // Consume the EndOfStatement
1169     return false;
1170   } else if (getLexer().is(AsmToken::Equal)) {
1171     getParser().Lex(); //eat '='
1172     if (getLexer().isNot(AsmToken::Dollar)) {
1173       reportParseError("unexpected token in statement");
1174       return false;
1175     }
1176     Parser.Lex(); // eat '$'
1177     if (getLexer().isNot(AsmToken::Integer)) {
1178       reportParseError("unexpected token in statement");
1179       return false;
1180     }
1181     const AsmToken &Reg = Parser.getTok();
1182     if (!Options.setATReg(Reg.getIntVal())) {
1183       reportParseError("unexpected token in statement");
1184       return false;
1185     }
1186     getParser().Lex(); //eat reg
1187
1188     if (getLexer().isNot(AsmToken::EndOfStatement)) {
1189       reportParseError("unexpected token in statement");
1190       return false;
1191      }
1192     Parser.Lex(); // Consume the EndOfStatement
1193     return false;
1194   } else {
1195     reportParseError("unexpected token in statement");
1196     return false;
1197   }
1198 }
1199
1200 bool MipsAsmParser::parseSetReorderDirective() {
1201   Parser.Lex();
1202   // if this is not the end of the statement, report error
1203   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1204     reportParseError("unexpected token in statement");
1205     return false;
1206   }
1207   Options.setReorder();
1208   Parser.Lex(); // Consume the EndOfStatement
1209   return false;
1210 }
1211
1212 bool MipsAsmParser::parseSetNoReorderDirective() {
1213     Parser.Lex();
1214     // if this is not the end of the statement, report error
1215     if (getLexer().isNot(AsmToken::EndOfStatement)) {
1216       reportParseError("unexpected token in statement");
1217       return false;
1218     }
1219     Options.setNoreorder();
1220     Parser.Lex(); // Consume the EndOfStatement
1221     return false;
1222 }
1223
1224 bool MipsAsmParser::parseSetMacroDirective() {
1225   Parser.Lex();
1226   // if this is not the end of the statement, report error
1227   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1228     reportParseError("unexpected token in statement");
1229     return false;
1230   }
1231   Options.setMacro();
1232   Parser.Lex(); // Consume the EndOfStatement
1233   return false;
1234 }
1235
1236 bool MipsAsmParser::parseSetNoMacroDirective() {
1237   Parser.Lex();
1238   // if this is not the end of the statement, report error
1239   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1240     reportParseError("`noreorder' must be set before `nomacro'");
1241     return false;
1242   }
1243   if (Options.isReorder()) {
1244     reportParseError("`noreorder' must be set before `nomacro'");
1245     return false;
1246   }
1247   Options.setNomacro();
1248   Parser.Lex(); // Consume the EndOfStatement
1249   return false;
1250 }
1251 bool MipsAsmParser::parseDirectiveSet() {
1252
1253   // get next token
1254   const AsmToken &Tok = Parser.getTok();
1255
1256   if (Tok.getString() == "noat") {
1257     return parseSetNoAtDirective();
1258   } else if (Tok.getString() == "at") {
1259     return parseSetAtDirective();
1260   } else if (Tok.getString() == "reorder") {
1261     return parseSetReorderDirective();
1262   } else if (Tok.getString() == "noreorder") {
1263     return parseSetNoReorderDirective();
1264   } else if (Tok.getString() == "macro") {
1265     return parseSetMacroDirective();
1266   } else if (Tok.getString() == "nomacro") {
1267     return parseSetNoMacroDirective();
1268   } else if (Tok.getString() == "nomips16") {
1269     // ignore this directive for now
1270     Parser.EatToEndOfStatement();
1271     return false;
1272   } else if (Tok.getString() == "nomicromips") {
1273     // ignore this directive for now
1274     Parser.EatToEndOfStatement();
1275     return false;
1276   }
1277   return true;
1278 }
1279
1280 bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
1281
1282   if (DirectiveID.getString() == ".ent") {
1283     // ignore this directive for now
1284     Parser.Lex();
1285     return false;
1286   }
1287
1288   if (DirectiveID.getString() == ".end") {
1289     // ignore this directive for now
1290     Parser.Lex();
1291     return false;
1292   }
1293
1294   if (DirectiveID.getString() == ".frame") {
1295     // ignore this directive for now
1296     Parser.EatToEndOfStatement();
1297     return false;
1298   }
1299
1300   if (DirectiveID.getString() == ".set") {
1301     return parseDirectiveSet();
1302   }
1303
1304   if (DirectiveID.getString() == ".fmask") {
1305     // ignore this directive for now
1306     Parser.EatToEndOfStatement();
1307     return false;
1308   }
1309
1310   if (DirectiveID.getString() == ".mask") {
1311     // ignore this directive for now
1312     Parser.EatToEndOfStatement();
1313     return false;
1314   }
1315
1316   if (DirectiveID.getString() == ".gpword") {
1317     // ignore this directive for now
1318     Parser.EatToEndOfStatement();
1319     return false;
1320   }
1321
1322   return true;
1323 }
1324
1325 extern "C" void LLVMInitializeMipsAsmParser() {
1326   RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1327   RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1328   RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1329   RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1330 }
1331
1332 #define GET_REGISTER_MATCHER
1333 #define GET_MATCHER_IMPLEMENTATION
1334 #include "MipsGenAsmMatcher.inc"