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