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