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