MipsAsmParser.cpp revision 99e98551bf8719764f9345ce856118f3f1a9c441
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 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();
169public:
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
182namespace {
183
184/// MipsOperand - Instances of this class represent a parsed Mips machine
185/// instruction.
186class MipsOperand : public MCParsedAsmOperand {
187
188public:
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
201private:
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
237public:
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
388bool 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
400void 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
412void 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
458void 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
500void 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
534bool MipsAsmParser::
535MatchAndEmitInstruction(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
579int 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}
638int 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}
671void MipsAsmParser::setDefaultFpFormat() {
672
673  if (isMips64() || isFP64())
674    FpFormat = FP_FORMAT_D;
675  else
676    FpFormat = FP_FORMAT_S;
677}
678
679bool 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}
690void 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
700bool MipsAssemblerOptions::setATReg(unsigned Reg) {
701  if (Reg > 31)
702    return false;
703
704  aTReg = Reg;
705  return true;
706}
707
708int MipsAsmParser::getATReg() {
709  return Options.getATRegNum();
710}
711
712unsigned MipsAsmParser::getReg(int RC,int RegNo) {
713  return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
714}
715
716int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
717
718  if (RegNum > 31)
719    return -1;
720
721  return getReg(RegClass, RegNum);
722}
723
724int 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
738bool 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
755bool 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
845bool 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
907bool 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
916bool 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
935MipsAsmParser::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
997MipsAsmParser::OperandMatchResultTy
998MipsAsmParser::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
1016MipsAsmParser::OperandMatchResultTy
1017MipsAsmParser::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
1033MipsAsmParser::OperandMatchResultTy
1034MipsAsmParser::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
1063MipsAsmParser::OperandMatchResultTy
1064MipsAsmParser::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
1092MipsAsmParser::OperandMatchResultTy
1093MipsAsmParser::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
1123MCSymbolRefExpr::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
1149static 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
1172bool MipsAsmParser::
1173parseMathOperation(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
1225bool MipsAsmParser::
1226ParseInstruction(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
1307bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
1308   SMLoc Loc = getLexer().getLoc();
1309   Parser.eatToEndOfStatement();
1310   return Error(Loc, ErrorMsg);
1311}
1312
1313bool 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}
1328bool 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
1378bool 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
1390bool 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
1402bool 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
1414bool 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}
1429bool 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)* ]
1461bool 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
1484bool 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
1536extern "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"
1546