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