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