1 //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
28 class MipsAsmParser : public MCTargetAsmParser {
41 #define GET_ASSEMBLER_HEADER
42 #include "MipsGenAsmMatcher.inc"
44 bool MatchAndEmitInstruction(SMLoc IDLoc,
45 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
48 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
50 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
51 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
53 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
54 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
56 bool ParseDirective(AsmToken DirectiveID);
58 MipsAsmParser::OperandMatchResultTy
59 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
61 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
64 int tryParseRegister(StringRef Mnemonic);
66 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
69 bool parseMemOffset(const MCExpr *&Res);
70 bool parseRelocOperand(const MCExpr *&Res);
71 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
73 bool isMips64() const {
74 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
78 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
81 int matchRegisterName(StringRef Symbol);
83 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
85 void setFpFormat(FpFormatTy Format) {
89 void setDefaultFpFormat();
91 void setFpFormat(StringRef Format);
93 FpFormatTy getFpFormat() {return FpFormat;}
95 bool requestsDoubleOperand(StringRef Mnemonic);
97 unsigned getReg(int RC,int RegNo);
100 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
101 : MCTargetAsmParser(), STI(sti), Parser(parser) {
102 // Initialize the set of available features.
103 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
106 MCAsmParser &getParser() const { return Parser; }
107 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
114 /// MipsOperand - Instances of this class represent a parsed Mips machine
116 class MipsOperand : public MCParsedAsmOperand {
128 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
150 SMLoc StartLoc, EndLoc;
153 void addRegOperands(MCInst &Inst, unsigned N) const {
154 assert(N == 1 && "Invalid number of operands!");
155 Inst.addOperand(MCOperand::CreateReg(getReg()));
158 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
159 // Add as immediate when possible. Null MCExpr = 0.
161 Inst.addOperand(MCOperand::CreateImm(0));
162 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
163 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
165 Inst.addOperand(MCOperand::CreateExpr(Expr));
168 void addImmOperands(MCInst &Inst, unsigned N) const {
169 assert(N == 1 && "Invalid number of operands!");
170 const MCExpr *Expr = getImm();
174 void addMemOperands(MCInst &Inst, unsigned N) const {
175 assert(N == 2 && "Invalid number of operands!");
177 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
179 const MCExpr *Expr = getMemOff();
183 bool isReg() const { return Kind == k_Register; }
184 bool isImm() const { return Kind == k_Immediate; }
185 bool isToken() const { return Kind == k_Token; }
186 bool isMem() const { return Kind == k_Memory; }
188 StringRef getToken() const {
189 assert(Kind == k_Token && "Invalid access!");
190 return StringRef(Tok.Data, Tok.Length);
193 unsigned getReg() const {
194 assert((Kind == k_Register) && "Invalid access!");
198 const MCExpr *getImm() const {
199 assert((Kind == k_Immediate) && "Invalid access!");
203 unsigned getMemBase() const {
204 assert((Kind == k_Memory) && "Invalid access!");
208 const MCExpr *getMemOff() const {
209 assert((Kind == k_Memory) && "Invalid access!");
213 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
214 MipsOperand *Op = new MipsOperand(k_Token);
215 Op->Tok.Data = Str.data();
216 Op->Tok.Length = Str.size();
222 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
223 MipsOperand *Op = new MipsOperand(k_Register);
224 Op->Reg.RegNum = RegNum;
230 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
231 MipsOperand *Op = new MipsOperand(k_Immediate);
238 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
240 MipsOperand *Op = new MipsOperand(k_Memory);
248 /// getStartLoc - Get the location of the first token of this operand.
249 SMLoc getStartLoc() const { return StartLoc; }
250 /// getEndLoc - Get the location of the last token of this operand.
251 SMLoc getEndLoc() const { return EndLoc; }
253 virtual void print(raw_ostream &OS) const {
254 llvm_unreachable("unimplemented!");
260 MatchAndEmitInstruction(SMLoc IDLoc,
261 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
266 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst, ErrorInfo);
268 switch (MatchResult) {
270 case Match_Success: {
272 Out.EmitInstruction(Inst);
275 case Match_MissingFeature:
276 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
278 case Match_InvalidOperand: {
279 SMLoc ErrorLoc = IDLoc;
280 if (ErrorInfo != ~0U) {
281 if (ErrorInfo >= Operands.size())
282 return Error(IDLoc, "too few operands for instruction");
284 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
285 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
288 return Error(ErrorLoc, "invalid operand for instruction");
290 case Match_MnemonicFail:
291 return Error(IDLoc, "invalid instruction");
296 int MipsAsmParser::matchRegisterName(StringRef Name) {
298 int CC = StringSwitch<unsigned>(Name)
299 .Case("zero", Mips::ZERO)
300 .Case("a0", Mips::A0)
301 .Case("a1", Mips::A1)
302 .Case("a2", Mips::A2)
303 .Case("a3", Mips::A3)
304 .Case("v0", Mips::V0)
305 .Case("v1", Mips::V1)
306 .Case("s0", Mips::S0)
307 .Case("s1", Mips::S1)
308 .Case("s2", Mips::S2)
309 .Case("s3", Mips::S3)
310 .Case("s4", Mips::S4)
311 .Case("s5", Mips::S5)
312 .Case("s6", Mips::S6)
313 .Case("s7", Mips::S7)
314 .Case("k0", Mips::K0)
315 .Case("k1", Mips::K1)
316 .Case("sp", Mips::SP)
317 .Case("fp", Mips::FP)
318 .Case("gp", Mips::GP)
319 .Case("ra", Mips::RA)
320 .Case("t0", Mips::T0)
321 .Case("t1", Mips::T1)
322 .Case("t2", Mips::T2)
323 .Case("t3", Mips::T3)
324 .Case("t4", Mips::T4)
325 .Case("t5", Mips::T5)
326 .Case("t6", Mips::T6)
327 .Case("t7", Mips::T7)
328 .Case("t8", Mips::T8)
329 .Case("t9", Mips::T9)
330 .Case("at", Mips::AT)
331 .Case("fcc0", Mips::FCC0)
335 //64 bit register in Mips are following 32 bit definitions.
341 if (Name[0] == 'f') {
342 StringRef NumString = Name.substr(1);
344 if( NumString.getAsInteger(10, IntVal))
345 return -1; //not integer
349 FpFormatTy Format = getFpFormat();
351 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
352 return getReg(Mips::FGR32RegClassID, IntVal);
353 if (Format == FP_FORMAT_D) {
355 return getReg(Mips::FGR64RegClassID, IntVal);
357 //only even numbers available as register pairs
358 if (( IntVal > 31) || (IntVal%2 != 0))
360 return getReg(Mips::AFGR64RegClassID, IntVal/2);
366 void MipsAsmParser::setDefaultFpFormat() {
368 if (isMips64() || isFP64())
369 FpFormat = FP_FORMAT_D;
371 FpFormat = FP_FORMAT_S;
374 bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
376 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
385 void MipsAsmParser::setFpFormat(StringRef Format) {
387 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
388 .Case(".s", FP_FORMAT_S)
389 .Case(".d", FP_FORMAT_D)
390 .Case(".l", FP_FORMAT_L)
391 .Case(".w", FP_FORMAT_W)
392 .Default(FP_FORMAT_NONE);
395 unsigned MipsAsmParser::getReg(int RC,int RegNo){
396 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
399 int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
401 if (Mnemonic.lower() == "rdhwr") {
402 //at the moment only hwreg29 is supported
411 return getReg(Mips::CPURegsRegClassID,RegNum);
414 int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
415 const AsmToken &Tok = Parser.getTok();
418 if (Tok.is(AsmToken::Identifier)) {
419 std::string lowerCase = Tok.getString().lower();
420 RegNum = matchRegisterName(lowerCase);
421 } else if (Tok.is(AsmToken::Integer))
422 RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()),
425 return RegNum; //error
426 //64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
427 if (isMips64() && RegNum == Mips::ZERO_64) {
428 if (Mnemonic.find("ddiv") != StringRef::npos)
435 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
438 SMLoc S = Parser.getTok().getLoc();
441 //FIXME: we should make a more generic method for CCR
442 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
443 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
444 RegNo = Parser.getTok().getIntVal(); //get the int value
445 //at the moment only fcc0 is supported
449 RegNo = tryParseRegister(Mnemonic);
453 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
454 Parser.getTok().getLoc()));
455 Parser.Lex(); // Eat register token.
459 bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
460 StringRef Mnemonic) {
461 //Check if the current operand has a custom associated parser, if so, try to
462 //custom parse the operand, or fallback to the general approach.
463 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
464 if (ResTy == MatchOperand_Success)
466 // If there wasn't a custom match, try the generic matcher below. Otherwise,
467 // there was a match, but an error occurred, in which case, just return that
468 // the operand parsing failed.
469 if (ResTy == MatchOperand_ParseFail)
472 switch (getLexer().getKind()) {
474 Error(Parser.getTok().getLoc(), "unexpected token in operand");
476 case AsmToken::Dollar: {
478 SMLoc S = Parser.getTok().getLoc();
479 Parser.Lex(); // Eat dollar token.
480 //parse register operand
481 if (!tryParseRegisterOperand(Operands,Mnemonic)) {
482 if (getLexer().is(AsmToken::LParen)) {
483 //check if it is indexed addressing operand
484 Operands.push_back(MipsOperand::CreateToken("(", S));
485 Parser.Lex(); //eat parenthesis
486 if (getLexer().isNot(AsmToken::Dollar))
489 Parser.Lex(); //eat dollar
490 if (tryParseRegisterOperand(Operands,Mnemonic))
493 if (!getLexer().is(AsmToken::RParen))
496 S = Parser.getTok().getLoc();
497 Operands.push_back(MipsOperand::CreateToken(")", S));
502 //maybe it is a symbol reference
503 StringRef Identifier;
504 if (Parser.ParseIdentifier(Identifier))
507 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
509 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
511 // Otherwise create a symbol ref.
512 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
515 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
518 case AsmToken::Identifier:
519 case AsmToken::LParen:
520 case AsmToken::Minus:
522 case AsmToken::Integer:
523 case AsmToken::String: {
524 // quoted label names
526 SMLoc S = Parser.getTok().getLoc();
527 if (getParser().ParseExpression(IdVal))
529 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
530 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
533 case AsmToken::Percent: {
534 //it is a symbol reference or constant expression
536 SMLoc S = Parser.getTok().getLoc(); //start location of the operand
537 if (parseRelocOperand(IdVal))
540 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
542 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
544 }//case AsmToken::Percent
545 }//switch(getLexer().getKind())
549 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
551 Parser.Lex(); //eat % token
552 const AsmToken &Tok = Parser.getTok(); //get next token, operation
553 if (Tok.isNot(AsmToken::Identifier))
556 std::string Str = Tok.getIdentifier().str();
558 Parser.Lex(); //eat identifier
559 //now make expression from the rest of the operand
563 if (getLexer().getKind() == AsmToken::LParen) {
565 Parser.Lex(); //eat '(' token
566 if (getLexer().getKind() == AsmToken::Percent) {
567 Parser.Lex(); //eat % token
568 const AsmToken &nextTok = Parser.getTok();
569 if (nextTok.isNot(AsmToken::Identifier))
572 Str += nextTok.getIdentifier();
573 Parser.Lex(); //eat identifier
574 if (getLexer().getKind() != AsmToken::LParen)
579 if (getParser().ParseParenExpression(IdVal,EndLoc))
582 while (getLexer().getKind() == AsmToken::RParen)
583 Parser.Lex(); //eat ')' token
586 return true; //parenthesis must follow reloc operand
588 //Check the type of the expression
589 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
590 //it's a constant, evaluate lo or hi value
591 int Val = MCE->getValue();
594 } else if (Str == "hi") {
595 Val = (Val & 0xffff0000) >> 16;
597 Res = MCConstantExpr::Create(Val, getContext());
601 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
602 //it's a symbol, create symbolic expression from symbol
603 StringRef Symbol = MSRE->getSymbol().getName();
604 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
605 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
611 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
614 StartLoc = Parser.getTok().getLoc();
615 RegNo = tryParseRegister("");
616 EndLoc = Parser.getTok().getLoc();
617 return (RegNo == (unsigned)-1);
620 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
624 switch(getLexer().getKind()) {
627 case AsmToken::Integer:
628 case AsmToken::Minus:
630 return (getParser().ParseExpression(Res));
631 case AsmToken::Percent:
632 return parseRelocOperand(Res);
633 case AsmToken::LParen:
634 return false; //it's probably assuming 0
639 MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
640 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
642 const MCExpr *IdVal = 0;
644 //first operand is the offset
645 S = Parser.getTok().getLoc();
647 if (parseMemOffset(IdVal))
648 return MatchOperand_ParseFail;
650 const AsmToken &Tok = Parser.getTok(); //get next token
651 if (Tok.isNot(AsmToken::LParen)) {
652 Error(Parser.getTok().getLoc(), "'(' expected");
653 return MatchOperand_ParseFail;
656 Parser.Lex(); // Eat '(' token.
658 const AsmToken &Tok1 = Parser.getTok(); //get next token
659 if (Tok1.is(AsmToken::Dollar)) {
660 Parser.Lex(); // Eat '$' token.
661 if (tryParseRegisterOperand(Operands,"")) {
662 Error(Parser.getTok().getLoc(), "unexpected token in operand");
663 return MatchOperand_ParseFail;
667 Error(Parser.getTok().getLoc(),"unexpected token in operand");
668 return MatchOperand_ParseFail;
671 const AsmToken &Tok2 = Parser.getTok(); //get next token
672 if (Tok2.isNot(AsmToken::RParen)) {
673 Error(Parser.getTok().getLoc(), "')' expected");
674 return MatchOperand_ParseFail;
677 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
679 Parser.Lex(); // Eat ')' token.
682 IdVal = MCConstantExpr::Create(0, getContext());
684 //now replace register operand with the mem operand
685 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
686 int RegNo = op->getReg();
687 //remove register from operands
689 //and add memory operand
690 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
692 return MatchOperand_Success;
695 MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
697 MCSymbolRefExpr::VariantKind VK
698 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
699 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
700 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
701 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
702 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
703 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
704 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
705 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
706 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
707 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
708 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
709 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
710 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
711 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
712 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
713 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
714 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
715 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
716 .Default(MCSymbolRefExpr::VK_None);
721 static int ConvertCcString(StringRef CondString) {
722 int CC = StringSwitch<unsigned>(CondString)
745 parseMathOperation(StringRef Name, SMLoc NameLoc,
746 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
748 size_t Start = Name.find('.'), Next = Name.rfind('.');
749 StringRef Format1 = Name.slice(Start, Next);
750 //and add the first format to the operands
751 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
752 //now for the second format
753 StringRef Format2 = Name.slice(Next, StringRef::npos);
754 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
756 //set the format for the first register
757 setFpFormat(Format1);
759 // Read the remaining operands.
760 if (getLexer().isNot(AsmToken::EndOfStatement)) {
761 // Read the first operand.
762 if (ParseOperand(Operands, Name)) {
763 SMLoc Loc = getLexer().getLoc();
764 Parser.EatToEndOfStatement();
765 return Error(Loc, "unexpected token in argument list");
768 if (getLexer().isNot(AsmToken::Comma)) {
769 SMLoc Loc = getLexer().getLoc();
770 Parser.EatToEndOfStatement();
771 return Error(Loc, "unexpected token in argument list");
774 Parser.Lex(); // Eat the comma.
776 //set the format for the first register
777 setFpFormat(Format2);
779 // Parse and remember the operand.
780 if (ParseOperand(Operands, Name)) {
781 SMLoc Loc = getLexer().getLoc();
782 Parser.EatToEndOfStatement();
783 return Error(Loc, "unexpected token in argument list");
787 if (getLexer().isNot(AsmToken::EndOfStatement)) {
788 SMLoc Loc = getLexer().getLoc();
789 Parser.EatToEndOfStatement();
790 return Error(Loc, "unexpected token in argument list");
793 Parser.Lex(); // Consume the EndOfStatement
798 ParseInstruction(StringRef Name, SMLoc NameLoc,
799 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
800 //floating point instructions: should register be treated as double?
801 if (requestsDoubleOperand(Name)) {
802 setFpFormat(FP_FORMAT_D);
803 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
806 setDefaultFpFormat();
807 // Create the leading tokens for the mnemonic, split by '.' characters.
808 size_t Start = 0, Next = Name.find('.');
809 StringRef Mnemonic = Name.slice(Start, Next);
811 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
813 if (Next != StringRef::npos) {
814 //there is a format token in mnemonic
815 //StringRef Rest = Name.slice(Next, StringRef::npos);
816 size_t Dot = Name.find('.', Next+1);
817 StringRef Format = Name.slice(Next, Dot);
818 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
819 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
821 if (Name.startswith("c.")){
822 // floating point compare, add '.' and immediate represent for cc
823 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
824 int Cc = ConvertCcString(Format);
826 return Error(NameLoc, "Invalid conditional code");
828 SMLoc E = SMLoc::getFromPointer(
829 Parser.getTok().getLoc().getPointer() -1 );
830 Operands.push_back(MipsOperand::CreateImm(
831 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
833 //trunc, ceil, floor ...
834 return parseMathOperation(Name, NameLoc, Operands);
837 //the rest is a format
838 Format = Name.slice(Dot, StringRef::npos);
839 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
846 // Read the remaining operands.
847 if (getLexer().isNot(AsmToken::EndOfStatement)) {
848 // Read the first operand.
849 if (ParseOperand(Operands, Name)) {
850 SMLoc Loc = getLexer().getLoc();
851 Parser.EatToEndOfStatement();
852 return Error(Loc, "unexpected token in argument list");
855 while (getLexer().is(AsmToken::Comma) ) {
856 Parser.Lex(); // Eat the comma.
858 // Parse and remember the operand.
859 if (ParseOperand(Operands, Name)) {
860 SMLoc Loc = getLexer().getLoc();
861 Parser.EatToEndOfStatement();
862 return Error(Loc, "unexpected token in argument list");
867 if (getLexer().isNot(AsmToken::EndOfStatement)) {
868 SMLoc Loc = getLexer().getLoc();
869 Parser.EatToEndOfStatement();
870 return Error(Loc, "unexpected token in argument list");
873 Parser.Lex(); // Consume the EndOfStatement
878 ParseDirective(AsmToken DirectiveID) {
880 if (DirectiveID.getString() == ".ent") {
881 //ignore this directive for now
886 if (DirectiveID.getString() == ".end") {
887 //ignore this directive for now
892 if (DirectiveID.getString() == ".frame") {
893 //ignore this directive for now
894 Parser.EatToEndOfStatement();
898 if (DirectiveID.getString() == ".set") {
899 //ignore this directive for now
900 Parser.EatToEndOfStatement();
904 if (DirectiveID.getString() == ".fmask") {
905 //ignore this directive for now
906 Parser.EatToEndOfStatement();
910 if (DirectiveID.getString() == ".mask") {
911 //ignore this directive for now
912 Parser.EatToEndOfStatement();
916 if (DirectiveID.getString() == ".gpword") {
917 //ignore this directive for now
918 Parser.EatToEndOfStatement();
925 extern "C" void LLVMInitializeMipsAsmParser() {
926 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
927 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
928 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
929 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
932 #define GET_REGISTER_MATCHER
933 #define GET_MATCHER_IMPLEMENTATION
934 #include "MipsGenAsmMatcher.inc"