MipsAsmParser.cpp revision acbea45573078631e116c2aa91e57d3a9cb2dde1
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/MCStreamer.h"
17#include "llvm/MC/MCSubtargetInfo.h"
18#include "llvm/MC/MCSymbol.h"
19#include "llvm/MC/MCParser/MCAsmLexer.h"
20#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCTargetAsmParser.h"
22#include "llvm/Support/TargetRegistry.h"
23
24using namespace llvm;
25
26namespace {
27
28class MipsAsmParser : public MCTargetAsmParser {
29
30  enum FpFormatTy {
31    FP_FORMAT_NONE = -1,
32    FP_FORMAT_S,
33    FP_FORMAT_D,
34    FP_FORMAT_L,
35    FP_FORMAT_W
36  } FpFormat;
37
38  MCSubtargetInfo &STI;
39  MCAsmParser &Parser;
40
41#define GET_ASSEMBLER_HEADER
42#include "MipsGenAsmMatcher.inc"
43
44  bool MatchAndEmitInstruction(SMLoc IDLoc,
45                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
46                               MCStreamer &Out);
47
48  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
49
50  bool ParseInstruction(StringRef Name, SMLoc NameLoc,
51                        SmallVectorImpl<MCParsedAsmOperand*> &Operands);
52
53  bool parseMathOperation(StringRef Name, SMLoc NameLoc,
54                        SmallVectorImpl<MCParsedAsmOperand*> &Operands);
55
56  bool ParseDirective(AsmToken DirectiveID);
57
58  MipsAsmParser::OperandMatchResultTy
59  parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
60
61  unsigned
62  getMCInstOperandNum(unsigned Kind, MCInst &Inst,
63                      const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
64                      unsigned OperandNum, unsigned &NumMCOperands);
65
66  bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
67                    StringRef Mnemonic);
68
69  int tryParseRegister(StringRef Mnemonic);
70
71  bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
72                               StringRef Mnemonic);
73
74  bool parseMemOffset(const MCExpr *&Res);
75  bool parseRelocOperand(const MCExpr *&Res);
76  MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
77
78  bool isMips64() const {
79    return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
80  }
81
82  bool isFP64() const {
83    return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
84  }
85
86  int matchRegisterName(StringRef Symbol);
87
88  int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
89
90  void setFpFormat(FpFormatTy Format) {
91    FpFormat = Format;
92  }
93
94  void setDefaultFpFormat();
95
96  void setFpFormat(StringRef Format);
97
98  FpFormatTy getFpFormat() {return FpFormat;}
99
100  bool requestsDoubleOperand(StringRef Mnemonic);
101
102  unsigned getReg(int RC,int RegNo);
103
104public:
105  MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
106    : MCTargetAsmParser(), STI(sti), Parser(parser) {
107    // Initialize the set of available features.
108    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
109  }
110
111  MCAsmParser &getParser() const { return Parser; }
112  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
113
114};
115}
116
117namespace {
118
119/// MipsOperand - Instances of this class represent a parsed Mips machine
120/// instruction.
121class MipsOperand : public MCParsedAsmOperand {
122
123  enum KindTy {
124    k_CondCode,
125    k_CoprocNum,
126    k_Immediate,
127    k_Memory,
128    k_PostIndexRegister,
129    k_Register,
130    k_Token
131  } Kind;
132
133  MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
134
135  union {
136    struct {
137      const char *Data;
138      unsigned Length;
139    } Tok;
140
141    struct {
142      unsigned RegNum;
143    } Reg;
144
145    struct {
146      const MCExpr *Val;
147    } Imm;
148
149    struct {
150      unsigned Base;
151      const MCExpr *Off;
152    } Mem;
153  };
154
155  SMLoc StartLoc, EndLoc;
156
157public:
158  void addRegOperands(MCInst &Inst, unsigned N) const {
159    assert(N == 1 && "Invalid number of operands!");
160    Inst.addOperand(MCOperand::CreateReg(getReg()));
161  }
162
163  void addExpr(MCInst &Inst, const MCExpr *Expr) const{
164    // Add as immediate when possible.  Null MCExpr = 0.
165    if (Expr == 0)
166      Inst.addOperand(MCOperand::CreateImm(0));
167    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
168      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
169    else
170      Inst.addOperand(MCOperand::CreateExpr(Expr));
171  }
172
173  void addImmOperands(MCInst &Inst, unsigned N) const {
174    assert(N == 1 && "Invalid number of operands!");
175    const MCExpr *Expr = getImm();
176    addExpr(Inst,Expr);
177  }
178
179  void addMemOperands(MCInst &Inst, unsigned N) const {
180    assert(N == 2 && "Invalid number of operands!");
181
182    Inst.addOperand(MCOperand::CreateReg(getMemBase()));
183
184    const MCExpr *Expr = getMemOff();
185    addExpr(Inst,Expr);
186  }
187
188  bool isReg() const { return Kind == k_Register; }
189  bool isImm() const { return Kind == k_Immediate; }
190  bool isToken() const { return Kind == k_Token; }
191  bool isMem() const { return Kind == k_Memory; }
192
193  StringRef getToken() const {
194    assert(Kind == k_Token && "Invalid access!");
195    return StringRef(Tok.Data, Tok.Length);
196  }
197
198  unsigned getReg() const {
199    assert((Kind == k_Register) && "Invalid access!");
200    return Reg.RegNum;
201  }
202
203  const MCExpr *getImm() const {
204    assert((Kind == k_Immediate) && "Invalid access!");
205    return Imm.Val;
206  }
207
208  unsigned getMemBase() const {
209    assert((Kind == k_Memory) && "Invalid access!");
210    return Mem.Base;
211  }
212
213  const MCExpr *getMemOff() const {
214    assert((Kind == k_Memory) && "Invalid access!");
215    return Mem.Off;
216  }
217
218  static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
219    MipsOperand *Op = new MipsOperand(k_Token);
220    Op->Tok.Data = Str.data();
221    Op->Tok.Length = Str.size();
222    Op->StartLoc = S;
223    Op->EndLoc = S;
224    return Op;
225  }
226
227  static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
228    MipsOperand *Op = new MipsOperand(k_Register);
229    Op->Reg.RegNum = RegNum;
230    Op->StartLoc = S;
231    Op->EndLoc = E;
232    return Op;
233  }
234
235  static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
236    MipsOperand *Op = new MipsOperand(k_Immediate);
237    Op->Imm.Val = Val;
238    Op->StartLoc = S;
239    Op->EndLoc = E;
240    return Op;
241  }
242
243  static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
244                                 SMLoc S, SMLoc E) {
245    MipsOperand *Op = new MipsOperand(k_Memory);
246    Op->Mem.Base = Base;
247    Op->Mem.Off = Off;
248    Op->StartLoc = S;
249    Op->EndLoc = E;
250    return Op;
251  }
252
253  /// getStartLoc - Get the location of the first token of this operand.
254  SMLoc getStartLoc() const { return StartLoc; }
255  /// getEndLoc - Get the location of the last token of this operand.
256  SMLoc getEndLoc() const { return EndLoc; }
257
258  virtual void print(raw_ostream &OS) const {
259    llvm_unreachable("unimplemented!");
260  }
261};
262}
263
264unsigned MipsAsmParser::
265getMCInstOperandNum(unsigned Kind, MCInst &Inst,
266                    const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
267                    unsigned OperandNum, unsigned &NumMCOperands) {
268  assert (0 && "getMCInstOperandNum() not supported by the Mips target.");
269  // The Mips backend doesn't currently include the matcher implementation, so
270  // the getMCInstOperandNumImpl() is undefined.  This is a temporary
271  // work around.
272  NumMCOperands = 0;
273  return 0;
274}
275
276bool MipsAsmParser::
277MatchAndEmitInstruction(SMLoc IDLoc,
278                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
279                        MCStreamer &Out) {
280  MCInst Inst;
281  unsigned ErrorInfo;
282  unsigned Kind;
283  unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst, ErrorInfo);
284
285  switch (MatchResult) {
286  default: break;
287  case Match_Success: {
288    Inst.setLoc(IDLoc);
289    Out.EmitInstruction(Inst);
290    return false;
291  }
292  case Match_MissingFeature:
293    Error(IDLoc, "instruction requires a CPU feature not currently enabled");
294    return true;
295  case Match_InvalidOperand: {
296    SMLoc ErrorLoc = IDLoc;
297    if (ErrorInfo != ~0U) {
298      if (ErrorInfo >= Operands.size())
299        return Error(IDLoc, "too few operands for instruction");
300
301      ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
302      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
303    }
304
305    return Error(ErrorLoc, "invalid operand for instruction");
306  }
307  case Match_MnemonicFail:
308    return Error(IDLoc, "invalid instruction");
309  }
310  return true;
311}
312
313int MipsAsmParser::matchRegisterName(StringRef Name) {
314
315   int CC = StringSwitch<unsigned>(Name)
316    .Case("zero",  Mips::ZERO)
317    .Case("a0",  Mips::A0)
318    .Case("a1",  Mips::A1)
319    .Case("a2",  Mips::A2)
320    .Case("a3",  Mips::A3)
321    .Case("v0",  Mips::V0)
322    .Case("v1",  Mips::V1)
323    .Case("s0",  Mips::S0)
324    .Case("s1",  Mips::S1)
325    .Case("s2",  Mips::S2)
326    .Case("s3",  Mips::S3)
327    .Case("s4",  Mips::S4)
328    .Case("s5",  Mips::S5)
329    .Case("s6",  Mips::S6)
330    .Case("s7",  Mips::S7)
331    .Case("k0",  Mips::K0)
332    .Case("k1",  Mips::K1)
333    .Case("sp",  Mips::SP)
334    .Case("fp",  Mips::FP)
335    .Case("gp",  Mips::GP)
336    .Case("ra",  Mips::RA)
337    .Case("t0",  Mips::T0)
338    .Case("t1",  Mips::T1)
339    .Case("t2",  Mips::T2)
340    .Case("t3",  Mips::T3)
341    .Case("t4",  Mips::T4)
342    .Case("t5",  Mips::T5)
343    .Case("t6",  Mips::T6)
344    .Case("t7",  Mips::T7)
345    .Case("t8",  Mips::T8)
346    .Case("t9",  Mips::T9)
347    .Case("at",  Mips::AT)
348    .Case("fcc0",  Mips::FCC0)
349    .Default(-1);
350
351  if (CC != -1) {
352    //64 bit register in Mips are following 32 bit definitions.
353    if (isMips64())
354      CC++;
355    return CC;
356  }
357
358  if (Name[0] == 'f') {
359    StringRef NumString = Name.substr(1);
360    unsigned IntVal;
361    if( NumString.getAsInteger(10, IntVal))
362      return -1; //not integer
363    if (IntVal > 31)
364      return -1;
365
366    FpFormatTy Format = getFpFormat();
367
368    if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
369      return getReg(Mips::FGR32RegClassID, IntVal);
370    if (Format == FP_FORMAT_D) {
371      if(isFP64()) {
372        return getReg(Mips::FGR64RegClassID, IntVal);
373      }
374      //only even numbers available as register pairs
375      if (( IntVal > 31) || (IntVal%2 !=  0))
376        return -1;
377      return getReg(Mips::AFGR64RegClassID, IntVal/2);
378    }
379  }
380
381  return -1;
382}
383void MipsAsmParser::setDefaultFpFormat() {
384
385  if (isMips64() || isFP64())
386    FpFormat = FP_FORMAT_D;
387  else
388    FpFormat = FP_FORMAT_S;
389}
390
391bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
392
393  bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
394    .Case("ldxc1", true)
395    .Case("ldc1",  true)
396    .Case("sdxc1", true)
397    .Case("sdc1",  true)
398    .Default(false);
399
400  return IsDouble;
401}
402void MipsAsmParser::setFpFormat(StringRef Format) {
403
404  FpFormat = StringSwitch<FpFormatTy>(Format.lower())
405    .Case(".s",  FP_FORMAT_S)
406    .Case(".d",  FP_FORMAT_D)
407    .Case(".l",  FP_FORMAT_L)
408    .Case(".w",  FP_FORMAT_W)
409    .Default(FP_FORMAT_NONE);
410}
411
412unsigned MipsAsmParser::getReg(int RC,int RegNo){
413  return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
414}
415
416int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
417
418  if (Mnemonic.lower() == "rdhwr") {
419    //at the moment only hwreg29 is supported
420    if (RegNum != 29)
421      return -1;
422    return Mips::HWR29;
423  }
424
425  if (RegNum > 31)
426    return -1;
427
428  return getReg(Mips::CPURegsRegClassID,RegNum);
429}
430
431int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
432  const AsmToken &Tok = Parser.getTok();
433  int RegNum = -1;
434
435  if (Tok.is(AsmToken::Identifier)) {
436    std::string lowerCase = Tok.getString().lower();
437    RegNum = matchRegisterName(lowerCase);
438  } else if (Tok.is(AsmToken::Integer))
439    RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()),
440                                   Mnemonic.lower());
441    else
442      return RegNum;  //error
443  //64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
444  if (isMips64() && RegNum == Mips::ZERO_64) {
445    if (Mnemonic.find("ddiv") != StringRef::npos)
446      RegNum = Mips::ZERO;
447  }
448  return RegNum;
449}
450
451bool MipsAsmParser::
452  tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
453                          StringRef Mnemonic){
454
455  SMLoc S = Parser.getTok().getLoc();
456  int RegNo = -1;
457
458  //FIXME: we should make a more generic method for CCR
459  if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
460      && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
461    RegNo = Parser.getTok().getIntVal();  //get the int value
462    //at the moment only fcc0 is supported
463    if (RegNo ==  0)
464      RegNo = Mips::FCC0;
465  } else
466    RegNo = tryParseRegister(Mnemonic);
467  if (RegNo == -1)
468    return true;
469
470  Operands.push_back(MipsOperand::CreateReg(RegNo, S,
471      Parser.getTok().getLoc()));
472  Parser.Lex(); // Eat register token.
473  return false;
474}
475
476bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
477                                 StringRef Mnemonic) {
478  //Check if the current operand has a custom associated parser, if so, try to
479  //custom parse the operand, or fallback to the general approach.
480  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
481  if (ResTy == MatchOperand_Success)
482    return false;
483  // If there wasn't a custom match, try the generic matcher below. Otherwise,
484  // there was a match, but an error occurred, in which case, just return that
485  // the operand parsing failed.
486  if (ResTy == MatchOperand_ParseFail)
487    return true;
488
489  switch (getLexer().getKind()) {
490  default:
491    Error(Parser.getTok().getLoc(), "unexpected token in operand");
492    return true;
493  case AsmToken::Dollar: {
494    //parse register
495    SMLoc S = Parser.getTok().getLoc();
496    Parser.Lex(); // Eat dollar token.
497    //parse register operand
498    if (!tryParseRegisterOperand(Operands,Mnemonic)) {
499      if (getLexer().is(AsmToken::LParen)) {
500        //check if it is indexed addressing operand
501        Operands.push_back(MipsOperand::CreateToken("(", S));
502        Parser.Lex(); //eat parenthesis
503        if (getLexer().isNot(AsmToken::Dollar))
504          return true;
505
506        Parser.Lex(); //eat dollar
507        if (tryParseRegisterOperand(Operands,Mnemonic))
508          return true;
509
510        if (!getLexer().is(AsmToken::RParen))
511          return true;
512
513        S = Parser.getTok().getLoc();
514        Operands.push_back(MipsOperand::CreateToken(")", S));
515        Parser.Lex();
516      }
517      return false;
518    }
519    //maybe it is a symbol reference
520    StringRef Identifier;
521    if (Parser.ParseIdentifier(Identifier))
522      return true;
523
524    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
525
526    StringRef Id = StringRef("$" + Identifier.str());
527    MCSymbol *Sym = getContext().GetOrCreateSymbol(Id);
528
529    // Otherwise create a symbol ref.
530    const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
531                                                getContext());
532
533    Operands.push_back(MipsOperand::CreateImm(Res, S, E));
534    return false;
535  }
536  case AsmToken::Identifier:
537  case AsmToken::LParen:
538  case AsmToken::Minus:
539  case AsmToken::Plus:
540  case AsmToken::Integer:
541  case AsmToken::String: {
542     // quoted label names
543    const MCExpr *IdVal;
544    SMLoc S = Parser.getTok().getLoc();
545    if (getParser().ParseExpression(IdVal))
546      return true;
547    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
548    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
549    return false;
550  }
551  case AsmToken::Percent: {
552    //it is a symbol reference or constant expression
553    const MCExpr *IdVal;
554    SMLoc S = Parser.getTok().getLoc(); //start location of the operand
555    if (parseRelocOperand(IdVal))
556      return true;
557
558    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
559
560    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
561    return false;
562  }//case AsmToken::Percent
563  }//switch(getLexer().getKind())
564  return true;
565}
566
567bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
568
569  Parser.Lex(); //eat % token
570  const AsmToken &Tok = Parser.getTok(); //get next token, operation
571  if (Tok.isNot(AsmToken::Identifier))
572    return true;
573
574  StringRef Str = Tok.getIdentifier();
575
576  Parser.Lex(); //eat identifier
577  //now make expression from the rest of the operand
578  const MCExpr *IdVal;
579  SMLoc EndLoc;
580
581  if (getLexer().getKind() == AsmToken::LParen) {
582    while (1) {
583      Parser.Lex(); //eat '(' token
584      if (getLexer().getKind() == AsmToken::Percent) {
585        Parser.Lex(); //eat % token
586        const AsmToken &nextTok = Parser.getTok();
587        if (nextTok.isNot(AsmToken::Identifier))
588          return true;
589        Str = StringRef(Str.str() + "(%" + nextTok.getIdentifier().str());
590        Parser.Lex(); //eat identifier
591        if (getLexer().getKind() != AsmToken::LParen)
592          return true;
593      } else
594        break;
595    }
596    if (getParser().ParseParenExpression(IdVal,EndLoc))
597      return true;
598
599    while (getLexer().getKind() == AsmToken::RParen)
600      Parser.Lex(); //eat ')' token
601
602  } else
603    return true; //parenthesis must follow reloc operand
604
605  //Check the type of the expression
606  if (MCConstantExpr::classof(IdVal)) {
607    //it's a constant, evaluate lo or hi value
608    int Val = ((const MCConstantExpr*)IdVal)->getValue();
609    if (Str == "lo") {
610      Val = Val & 0xffff;
611    } else if (Str == "hi") {
612      Val = (Val & 0xffff0000) >> 16;
613    }
614    Res = MCConstantExpr::Create(Val, getContext());
615    return false;
616  }
617
618  if (MCSymbolRefExpr::classof(IdVal)) {
619    //it's a symbol, create symbolic expression from symbol
620    StringRef Symbol = ((const MCSymbolRefExpr*)IdVal)->getSymbol().getName();
621    MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
622    Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
623    return false;
624  }
625  return true;
626}
627
628bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
629                                  SMLoc &EndLoc) {
630
631  StartLoc = Parser.getTok().getLoc();
632  RegNo = tryParseRegister("");
633  EndLoc = Parser.getTok().getLoc();
634  return (RegNo == (unsigned)-1);
635}
636
637bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
638
639  SMLoc S;
640
641  switch(getLexer().getKind()) {
642  default:
643    return true;
644  case AsmToken::Integer:
645  case AsmToken::Minus:
646  case AsmToken::Plus:
647    return (getParser().ParseExpression(Res));
648  case AsmToken::Percent:
649    return parseRelocOperand(Res);
650  case AsmToken::LParen:
651    return false;  //it's probably assuming 0
652  }
653  return true;
654}
655
656MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
657               SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
658
659  const MCExpr *IdVal = 0;
660  SMLoc S;
661  //first operand is the offset
662  S = Parser.getTok().getLoc();
663
664  if (parseMemOffset(IdVal))
665    return MatchOperand_ParseFail;
666
667  const AsmToken &Tok = Parser.getTok(); //get next token
668  if (Tok.isNot(AsmToken::LParen)) {
669    Error(Parser.getTok().getLoc(), "'(' expected");
670    return MatchOperand_ParseFail;
671  }
672
673  Parser.Lex(); // Eat '(' token.
674
675  const AsmToken &Tok1 = Parser.getTok(); //get next token
676  if (Tok1.is(AsmToken::Dollar)) {
677    Parser.Lex(); // Eat '$' token.
678    if (tryParseRegisterOperand(Operands,"")) {
679      Error(Parser.getTok().getLoc(), "unexpected token in operand");
680      return MatchOperand_ParseFail;
681    }
682
683  } else {
684    Error(Parser.getTok().getLoc(),"unexpected token in operand");
685    return MatchOperand_ParseFail;
686  }
687
688  const AsmToken &Tok2 = Parser.getTok(); //get next token
689  if (Tok2.isNot(AsmToken::RParen)) {
690    Error(Parser.getTok().getLoc(), "')' expected");
691    return MatchOperand_ParseFail;
692  }
693
694  SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
695
696  Parser.Lex(); // Eat ')' token.
697
698  if (IdVal == 0)
699    IdVal = MCConstantExpr::Create(0, getContext());
700
701  //now replace register operand with the mem operand
702  MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
703  int RegNo = op->getReg();
704  //remove register from operands
705  Operands.pop_back();
706  //and add memory operand
707  Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
708  delete op;
709  return MatchOperand_Success;
710}
711
712MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
713
714  MCSymbolRefExpr::VariantKind VK
715                   = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
716    .Case("hi",          MCSymbolRefExpr::VK_Mips_ABS_HI)
717    .Case("lo",          MCSymbolRefExpr::VK_Mips_ABS_LO)
718    .Case("gp_rel",      MCSymbolRefExpr::VK_Mips_GPREL)
719    .Case("call16",      MCSymbolRefExpr::VK_Mips_GOT_CALL)
720    .Case("got",         MCSymbolRefExpr::VK_Mips_GOT)
721    .Case("tlsgd",       MCSymbolRefExpr::VK_Mips_TLSGD)
722    .Case("tlsldm",      MCSymbolRefExpr::VK_Mips_TLSLDM)
723    .Case("dtprel_hi",   MCSymbolRefExpr::VK_Mips_DTPREL_HI)
724    .Case("dtprel_lo",   MCSymbolRefExpr::VK_Mips_DTPREL_LO)
725    .Case("gottprel",    MCSymbolRefExpr::VK_Mips_GOTTPREL)
726    .Case("tprel_hi",    MCSymbolRefExpr::VK_Mips_TPREL_HI)
727    .Case("tprel_lo",    MCSymbolRefExpr::VK_Mips_TPREL_LO)
728    .Case("got_disp",    MCSymbolRefExpr::VK_Mips_GOT_DISP)
729    .Case("got_page",    MCSymbolRefExpr::VK_Mips_GOT_PAGE)
730    .Case("got_ofst",    MCSymbolRefExpr::VK_Mips_GOT_OFST)
731    .Case("hi(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_HI)
732    .Case("lo(%neg(%gp_rel",    MCSymbolRefExpr::VK_Mips_GPOFF_LO)
733    .Default(MCSymbolRefExpr::VK_None);
734
735  return VK;
736}
737
738int ConvertCcString(StringRef CondString){
739
740  int CC = StringSwitch<unsigned>(CondString)
741      .Case(".f",    0)
742      .Case(".un",   1)
743      .Case(".eq",   2)
744      .Case(".ueq",  3)
745      .Case(".olt",  4)
746      .Case(".ult",  5)
747      .Case(".ole",  6)
748      .Case(".ule",  7)
749      .Case(".sf",   8)
750      .Case(".ngle", 9)
751      .Case(".seq",  10)
752      .Case(".ngl",  11)
753      .Case(".lt",   12)
754      .Case(".nge",  13)
755      .Case(".le",   14)
756      .Case(".ngt",  15)
757      .Default(-1);
758
759  return CC;
760}
761
762bool MipsAsmParser::
763parseMathOperation(StringRef Name, SMLoc NameLoc,
764                        SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
765  //split the format
766  size_t Start = Name.find('.'), Next = Name.rfind('.');
767  StringRef Format1 = Name.slice(Start, Next);
768  //and add the first format to the operands
769  Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
770  //now for the second format
771  StringRef Format2 = Name.slice(Next, StringRef::npos);
772  Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
773
774  //set the format for the first register
775  setFpFormat(Format1);
776
777  // Read the remaining operands.
778  if (getLexer().isNot(AsmToken::EndOfStatement)) {
779    // Read the first operand.
780    if (ParseOperand(Operands, Name)) {
781      SMLoc Loc = getLexer().getLoc();
782      Parser.EatToEndOfStatement();
783      return Error(Loc, "unexpected token in argument list");
784    }
785
786    if (getLexer().isNot(AsmToken::Comma)) {
787      SMLoc Loc = getLexer().getLoc();
788      Parser.EatToEndOfStatement();
789      return Error(Loc, "unexpected token in argument list");
790
791    }
792    Parser.Lex();  // Eat the comma.
793
794    //set the format for the first register
795    setFpFormat(Format2);
796
797    // Parse and remember the operand.
798    if (ParseOperand(Operands, Name)) {
799      SMLoc Loc = getLexer().getLoc();
800      Parser.EatToEndOfStatement();
801      return Error(Loc, "unexpected token in argument list");
802    }
803  }
804
805  if (getLexer().isNot(AsmToken::EndOfStatement)) {
806    SMLoc Loc = getLexer().getLoc();
807    Parser.EatToEndOfStatement();
808    return Error(Loc, "unexpected token in argument list");
809  }
810
811  Parser.Lex(); // Consume the EndOfStatement
812  return false;
813}
814
815bool MipsAsmParser::
816ParseInstruction(StringRef Name, SMLoc NameLoc,
817                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
818  //floating point instructions: should register be treated as double?
819  if (requestsDoubleOperand(Name)) {
820    setFpFormat(FP_FORMAT_D);
821  Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
822  }
823  else {
824    setDefaultFpFormat();
825    // Create the leading tokens for the mnemonic, split by '.' characters.
826    size_t Start = 0, Next = Name.find('.');
827    StringRef Mnemonic = Name.slice(Start, Next);
828
829    Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
830
831    if (Next != StringRef::npos) {
832      //there is a format token in mnemonic
833      //StringRef Rest = Name.slice(Next, StringRef::npos);
834      size_t Dot = Name.find('.', Next+1);
835      StringRef Format = Name.slice(Next, Dot);
836      if (Dot == StringRef::npos) //only one '.' in a string, it's a format
837        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
838      else {
839        if (Name.startswith("c.")){
840          // floating point compare, add '.' and immediate represent for cc
841          Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
842          int Cc = ConvertCcString(Format);
843          if (Cc == -1) {
844            return Error(NameLoc, "Invalid conditional code");
845          }
846          SMLoc E = SMLoc::getFromPointer(
847              Parser.getTok().getLoc().getPointer() -1 );
848          Operands.push_back(MipsOperand::CreateImm(
849              MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
850        } else {
851          //trunc, ceil, floor ...
852          return parseMathOperation(Name, NameLoc, Operands);
853        }
854
855        //the rest is a format
856        Format = Name.slice(Dot, StringRef::npos);
857        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
858      }
859
860      setFpFormat(Format);
861    }
862  }
863
864  // Read the remaining operands.
865  if (getLexer().isNot(AsmToken::EndOfStatement)) {
866    // Read the first operand.
867    if (ParseOperand(Operands, Name)) {
868      SMLoc Loc = getLexer().getLoc();
869      Parser.EatToEndOfStatement();
870      return Error(Loc, "unexpected token in argument list");
871    }
872
873    while (getLexer().is(AsmToken::Comma) ) {
874      Parser.Lex();  // Eat the comma.
875
876      // Parse and remember the operand.
877      if (ParseOperand(Operands, Name)) {
878        SMLoc Loc = getLexer().getLoc();
879        Parser.EatToEndOfStatement();
880        return Error(Loc, "unexpected token in argument list");
881      }
882    }
883  }
884
885  if (getLexer().isNot(AsmToken::EndOfStatement)) {
886    SMLoc Loc = getLexer().getLoc();
887    Parser.EatToEndOfStatement();
888    return Error(Loc, "unexpected token in argument list");
889  }
890
891  Parser.Lex(); // Consume the EndOfStatement
892  return false;
893}
894
895bool MipsAsmParser::
896ParseDirective(AsmToken DirectiveID) {
897
898  if (DirectiveID.getString() == ".ent") {
899    //ignore this directive for now
900    Parser.Lex();
901    return false;
902  }
903
904  if (DirectiveID.getString() == ".end") {
905    //ignore this directive for now
906    Parser.Lex();
907    return false;
908  }
909
910  if (DirectiveID.getString() == ".frame") {
911    //ignore this directive for now
912    Parser.EatToEndOfStatement();
913    return false;
914  }
915
916  if (DirectiveID.getString() == ".set") {
917    //ignore this directive for now
918    Parser.EatToEndOfStatement();
919    return false;
920  }
921
922  if (DirectiveID.getString() == ".fmask") {
923    //ignore this directive for now
924    Parser.EatToEndOfStatement();
925    return false;
926  }
927
928  if (DirectiveID.getString() == ".mask") {
929    //ignore this directive for now
930    Parser.EatToEndOfStatement();
931    return false;
932  }
933
934  if (DirectiveID.getString() == ".gpword") {
935    //ignore this directive for now
936    Parser.EatToEndOfStatement();
937    return false;
938  }
939
940  return true;
941}
942
943extern "C" void LLVMInitializeMipsAsmParser() {
944  RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
945  RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
946  RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
947  RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
948}
949
950#define GET_REGISTER_MATCHER
951#define GET_MATCHER_IMPLEMENTATION
952#include "MipsGenAsmMatcher.inc"
953