Home | History | Annotate | Download | only in AsmParser
      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 
     24 using namespace llvm;
     25 
     26 namespace {
     27 
     28 class 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 
    104 public:
    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 
    117 namespace {
    118 
    119 /// MipsOperand - Instances of this class represent a parsed Mips machine
    120 /// instruction.
    121 class 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 
    157 public:
    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 
    264 unsigned MipsAsmParser::
    265 getMCInstOperandNum(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 
    276 bool MipsAsmParser::
    277 MatchAndEmitInstruction(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 
    313 int 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 }
    383 void MipsAsmParser::setDefaultFpFormat() {
    384 
    385   if (isMips64() || isFP64())
    386     FpFormat = FP_FORMAT_D;
    387   else
    388     FpFormat = FP_FORMAT_S;
    389 }
    390 
    391 bool 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 }
    402 void 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 
    412 unsigned MipsAsmParser::getReg(int RC,int RegNo){
    413   return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
    414 }
    415 
    416 int 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 
    431 int 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 
    451 bool 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 
    476 bool 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 
    566 bool 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 
    628 bool 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 
    637 bool 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 
    656 MipsAsmParser::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 
    712 MCSymbolRefExpr::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 
    738 static 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 
    761 bool MipsAsmParser::
    762 parseMathOperation(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 
    814 bool MipsAsmParser::
    815 ParseInstruction(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 
    894 bool MipsAsmParser::
    895 ParseDirective(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 
    942 extern "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