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    MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
527
528    // Otherwise create a symbol ref.
529    const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
530                                                getContext());
531
532    Operands.push_back(MipsOperand::CreateImm(Res, S, E));
533    return false;
534  }
535  case AsmToken::Identifier:
536  case AsmToken::LParen:
537  case AsmToken::Minus:
538  case AsmToken::Plus:
539  case AsmToken::Integer:
540  case AsmToken::String: {
541     // quoted label names
542    const MCExpr *IdVal;
543    SMLoc S = Parser.getTok().getLoc();
544    if (getParser().ParseExpression(IdVal))
545      return true;
546    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
547    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
548    return false;
549  }
550  case AsmToken::Percent: {
551    //it is a symbol reference or constant expression
552    const MCExpr *IdVal;
553    SMLoc S = Parser.getTok().getLoc(); //start location of the operand
554    if (parseRelocOperand(IdVal))
555      return true;
556
557    SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
558
559    Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
560    return false;
561  }//case AsmToken::Percent
562  }//switch(getLexer().getKind())
563  return true;
564}
565
566bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
567
568  Parser.Lex(); //eat % token
569  const AsmToken &Tok = Parser.getTok(); //get next token, operation
570  if (Tok.isNot(AsmToken::Identifier))
571    return true;
572
573  std::string Str = Tok.getIdentifier().str();
574
575  Parser.Lex(); //eat identifier
576  //now make expression from the rest of the operand
577  const MCExpr *IdVal;
578  SMLoc EndLoc;
579
580  if (getLexer().getKind() == AsmToken::LParen) {
581    while (1) {
582      Parser.Lex(); //eat '(' token
583      if (getLexer().getKind() == AsmToken::Percent) {
584        Parser.Lex(); //eat % token
585        const AsmToken &nextTok = Parser.getTok();
586        if (nextTok.isNot(AsmToken::Identifier))
587          return true;
588        Str += "(%";
589        Str += nextTok.getIdentifier();
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 (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
607    //it's a constant, evaluate lo or hi value
608    int Val = MCE->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 (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
619    //it's a symbol, create symbolic expression from symbol
620    StringRef Symbol = MSRE->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
738static int ConvertCcString(StringRef CondString) {
739  int CC = StringSwitch<unsigned>(CondString)
740      .Case(".f",    0)
741      .Case(".un",   1)
742      .Case(".eq",   2)
743      .Case(".ueq",  3)
744      .Case(".olt",  4)
745      .Case(".ult",  5)
746      .Case(".ole",  6)
747      .Case(".ule",  7)
748      .Case(".sf",   8)
749      .Case(".ngle", 9)
750      .Case(".seq",  10)
751      .Case(".ngl",  11)
752      .Case(".lt",   12)
753      .Case(".nge",  13)
754      .Case(".le",   14)
755      .Case(".ngt",  15)
756      .Default(-1);
757
758  return CC;
759}
760
761bool MipsAsmParser::
762parseMathOperation(StringRef Name, SMLoc NameLoc,
763                        SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
764  //split the format
765  size_t Start = Name.find('.'), Next = Name.rfind('.');
766  StringRef Format1 = Name.slice(Start, Next);
767  //and add the first format to the operands
768  Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
769  //now for the second format
770  StringRef Format2 = Name.slice(Next, StringRef::npos);
771  Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
772
773  //set the format for the first register
774  setFpFormat(Format1);
775
776  // Read the remaining operands.
777  if (getLexer().isNot(AsmToken::EndOfStatement)) {
778    // Read the first operand.
779    if (ParseOperand(Operands, Name)) {
780      SMLoc Loc = getLexer().getLoc();
781      Parser.EatToEndOfStatement();
782      return Error(Loc, "unexpected token in argument list");
783    }
784
785    if (getLexer().isNot(AsmToken::Comma)) {
786      SMLoc Loc = getLexer().getLoc();
787      Parser.EatToEndOfStatement();
788      return Error(Loc, "unexpected token in argument list");
789
790    }
791    Parser.Lex();  // Eat the comma.
792
793    //set the format for the first register
794    setFpFormat(Format2);
795
796    // Parse and remember the operand.
797    if (ParseOperand(Operands, Name)) {
798      SMLoc Loc = getLexer().getLoc();
799      Parser.EatToEndOfStatement();
800      return Error(Loc, "unexpected token in argument list");
801    }
802  }
803
804  if (getLexer().isNot(AsmToken::EndOfStatement)) {
805    SMLoc Loc = getLexer().getLoc();
806    Parser.EatToEndOfStatement();
807    return Error(Loc, "unexpected token in argument list");
808  }
809
810  Parser.Lex(); // Consume the EndOfStatement
811  return false;
812}
813
814bool MipsAsmParser::
815ParseInstruction(StringRef Name, SMLoc NameLoc,
816                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
817  //floating point instructions: should register be treated as double?
818  if (requestsDoubleOperand(Name)) {
819    setFpFormat(FP_FORMAT_D);
820  Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
821  }
822  else {
823    setDefaultFpFormat();
824    // Create the leading tokens for the mnemonic, split by '.' characters.
825    size_t Start = 0, Next = Name.find('.');
826    StringRef Mnemonic = Name.slice(Start, Next);
827
828    Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
829
830    if (Next != StringRef::npos) {
831      //there is a format token in mnemonic
832      //StringRef Rest = Name.slice(Next, StringRef::npos);
833      size_t Dot = Name.find('.', Next+1);
834      StringRef Format = Name.slice(Next, Dot);
835      if (Dot == StringRef::npos) //only one '.' in a string, it's a format
836        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
837      else {
838        if (Name.startswith("c.")){
839          // floating point compare, add '.' and immediate represent for cc
840          Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
841          int Cc = ConvertCcString(Format);
842          if (Cc == -1) {
843            return Error(NameLoc, "Invalid conditional code");
844          }
845          SMLoc E = SMLoc::getFromPointer(
846              Parser.getTok().getLoc().getPointer() -1 );
847          Operands.push_back(MipsOperand::CreateImm(
848              MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
849        } else {
850          //trunc, ceil, floor ...
851          return parseMathOperation(Name, NameLoc, Operands);
852        }
853
854        //the rest is a format
855        Format = Name.slice(Dot, StringRef::npos);
856        Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
857      }
858
859      setFpFormat(Format);
860    }
861  }
862
863  // Read the remaining operands.
864  if (getLexer().isNot(AsmToken::EndOfStatement)) {
865    // Read the first operand.
866    if (ParseOperand(Operands, Name)) {
867      SMLoc Loc = getLexer().getLoc();
868      Parser.EatToEndOfStatement();
869      return Error(Loc, "unexpected token in argument list");
870    }
871
872    while (getLexer().is(AsmToken::Comma) ) {
873      Parser.Lex();  // Eat the comma.
874
875      // Parse and remember the operand.
876      if (ParseOperand(Operands, Name)) {
877        SMLoc Loc = getLexer().getLoc();
878        Parser.EatToEndOfStatement();
879        return Error(Loc, "unexpected token in argument list");
880      }
881    }
882  }
883
884  if (getLexer().isNot(AsmToken::EndOfStatement)) {
885    SMLoc Loc = getLexer().getLoc();
886    Parser.EatToEndOfStatement();
887    return Error(Loc, "unexpected token in argument list");
888  }
889
890  Parser.Lex(); // Consume the EndOfStatement
891  return false;
892}
893
894bool MipsAsmParser::
895ParseDirective(AsmToken DirectiveID) {
896
897  if (DirectiveID.getString() == ".ent") {
898    //ignore this directive for now
899    Parser.Lex();
900    return false;
901  }
902
903  if (DirectiveID.getString() == ".end") {
904    //ignore this directive for now
905    Parser.Lex();
906    return false;
907  }
908
909  if (DirectiveID.getString() == ".frame") {
910    //ignore this directive for now
911    Parser.EatToEndOfStatement();
912    return false;
913  }
914
915  if (DirectiveID.getString() == ".set") {
916    //ignore this directive for now
917    Parser.EatToEndOfStatement();
918    return false;
919  }
920
921  if (DirectiveID.getString() == ".fmask") {
922    //ignore this directive for now
923    Parser.EatToEndOfStatement();
924    return false;
925  }
926
927  if (DirectiveID.getString() == ".mask") {
928    //ignore this directive for now
929    Parser.EatToEndOfStatement();
930    return false;
931  }
932
933  if (DirectiveID.getString() == ".gpword") {
934    //ignore this directive for now
935    Parser.EatToEndOfStatement();
936    return false;
937  }
938
939  return true;
940}
941
942extern "C" void LLVMInitializeMipsAsmParser() {
943  RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
944  RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
945  RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
946  RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
947}
948
949#define GET_REGISTER_MATCHER
950#define GET_MATCHER_IMPLEMENTATION
951#include "MipsGenAsmMatcher.inc"
952