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 SmallVector<std::pair< unsigned, std::string >, 4> MapAndConstraints;
267 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
268 MapAndConstraints, ErrorInfo,
269 /*matchingInlineAsm*/ false);
271 switch (MatchResult) {
273 case Match_Success: {
275 Out.EmitInstruction(Inst);
278 case Match_MissingFeature:
279 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
281 case Match_InvalidOperand: {
282 SMLoc ErrorLoc = IDLoc;
283 if (ErrorInfo != ~0U) {
284 if (ErrorInfo >= Operands.size())
285 return Error(IDLoc, "too few operands for instruction");
287 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
288 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
291 return Error(ErrorLoc, "invalid operand for instruction");
293 case Match_MnemonicFail:
294 return Error(IDLoc, "invalid instruction");
299 int MipsAsmParser::matchRegisterName(StringRef Name) {
301 int CC = StringSwitch<unsigned>(Name)
302 .Case("zero", Mips::ZERO)
303 .Case("a0", Mips::A0)
304 .Case("a1", Mips::A1)
305 .Case("a2", Mips::A2)
306 .Case("a3", Mips::A3)
307 .Case("v0", Mips::V0)
308 .Case("v1", Mips::V1)
309 .Case("s0", Mips::S0)
310 .Case("s1", Mips::S1)
311 .Case("s2", Mips::S2)
312 .Case("s3", Mips::S3)
313 .Case("s4", Mips::S4)
314 .Case("s5", Mips::S5)
315 .Case("s6", Mips::S6)
316 .Case("s7", Mips::S7)
317 .Case("k0", Mips::K0)
318 .Case("k1", Mips::K1)
319 .Case("sp", Mips::SP)
320 .Case("fp", Mips::FP)
321 .Case("gp", Mips::GP)
322 .Case("ra", Mips::RA)
323 .Case("t0", Mips::T0)
324 .Case("t1", Mips::T1)
325 .Case("t2", Mips::T2)
326 .Case("t3", Mips::T3)
327 .Case("t4", Mips::T4)
328 .Case("t5", Mips::T5)
329 .Case("t6", Mips::T6)
330 .Case("t7", Mips::T7)
331 .Case("t8", Mips::T8)
332 .Case("t9", Mips::T9)
333 .Case("at", Mips::AT)
334 .Case("fcc0", Mips::FCC0)
338 //64 bit register in Mips are following 32 bit definitions.
344 if (Name[0] == 'f') {
345 StringRef NumString = Name.substr(1);
347 if( NumString.getAsInteger(10, IntVal))
348 return -1; //not integer
352 FpFormatTy Format = getFpFormat();
354 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
355 return getReg(Mips::FGR32RegClassID, IntVal);
356 if (Format == FP_FORMAT_D) {
358 return getReg(Mips::FGR64RegClassID, IntVal);
360 //only even numbers available as register pairs
361 if (( IntVal > 31) || (IntVal%2 != 0))
363 return getReg(Mips::AFGR64RegClassID, IntVal/2);
369 void MipsAsmParser::setDefaultFpFormat() {
371 if (isMips64() || isFP64())
372 FpFormat = FP_FORMAT_D;
374 FpFormat = FP_FORMAT_S;
377 bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
379 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
388 void MipsAsmParser::setFpFormat(StringRef Format) {
390 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
391 .Case(".s", FP_FORMAT_S)
392 .Case(".d", FP_FORMAT_D)
393 .Case(".l", FP_FORMAT_L)
394 .Case(".w", FP_FORMAT_W)
395 .Default(FP_FORMAT_NONE);
398 unsigned MipsAsmParser::getReg(int RC,int RegNo){
399 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
402 int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
404 if (Mnemonic.lower() == "rdhwr") {
405 //at the moment only hwreg29 is supported
414 return getReg(Mips::CPURegsRegClassID,RegNum);
417 int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
418 const AsmToken &Tok = Parser.getTok();
421 if (Tok.is(AsmToken::Identifier)) {
422 std::string lowerCase = Tok.getString().lower();
423 RegNum = matchRegisterName(lowerCase);
424 } else if (Tok.is(AsmToken::Integer))
425 RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()),
428 return RegNum; //error
429 //64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
430 if (isMips64() && RegNum == Mips::ZERO_64) {
431 if (Mnemonic.find("ddiv") != StringRef::npos)
438 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
441 SMLoc S = Parser.getTok().getLoc();
444 //FIXME: we should make a more generic method for CCR
445 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
446 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
447 RegNo = Parser.getTok().getIntVal(); //get the int value
448 //at the moment only fcc0 is supported
452 RegNo = tryParseRegister(Mnemonic);
456 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
457 Parser.getTok().getLoc()));
458 Parser.Lex(); // Eat register token.
462 bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
463 StringRef Mnemonic) {
464 //Check if the current operand has a custom associated parser, if so, try to
465 //custom parse the operand, or fallback to the general approach.
466 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
467 if (ResTy == MatchOperand_Success)
469 // If there wasn't a custom match, try the generic matcher below. Otherwise,
470 // there was a match, but an error occurred, in which case, just return that
471 // the operand parsing failed.
472 if (ResTy == MatchOperand_ParseFail)
475 switch (getLexer().getKind()) {
477 Error(Parser.getTok().getLoc(), "unexpected token in operand");
479 case AsmToken::Dollar: {
481 SMLoc S = Parser.getTok().getLoc();
482 Parser.Lex(); // Eat dollar token.
483 //parse register operand
484 if (!tryParseRegisterOperand(Operands,Mnemonic)) {
485 if (getLexer().is(AsmToken::LParen)) {
486 //check if it is indexed addressing operand
487 Operands.push_back(MipsOperand::CreateToken("(", S));
488 Parser.Lex(); //eat parenthesis
489 if (getLexer().isNot(AsmToken::Dollar))
492 Parser.Lex(); //eat dollar
493 if (tryParseRegisterOperand(Operands,Mnemonic))
496 if (!getLexer().is(AsmToken::RParen))
499 S = Parser.getTok().getLoc();
500 Operands.push_back(MipsOperand::CreateToken(")", S));
505 //maybe it is a symbol reference
506 StringRef Identifier;
507 if (Parser.ParseIdentifier(Identifier))
510 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
512 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
514 // Otherwise create a symbol ref.
515 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
518 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
521 case AsmToken::Identifier:
522 case AsmToken::LParen:
523 case AsmToken::Minus:
525 case AsmToken::Integer:
526 case AsmToken::String: {
527 // quoted label names
529 SMLoc S = Parser.getTok().getLoc();
530 if (getParser().ParseExpression(IdVal))
532 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
533 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
536 case AsmToken::Percent: {
537 //it is a symbol reference or constant expression
539 SMLoc S = Parser.getTok().getLoc(); //start location of the operand
540 if (parseRelocOperand(IdVal))
543 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
545 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
547 }//case AsmToken::Percent
548 }//switch(getLexer().getKind())
552 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
554 Parser.Lex(); //eat % token
555 const AsmToken &Tok = Parser.getTok(); //get next token, operation
556 if (Tok.isNot(AsmToken::Identifier))
559 std::string Str = Tok.getIdentifier().str();
561 Parser.Lex(); //eat identifier
562 //now make expression from the rest of the operand
566 if (getLexer().getKind() == AsmToken::LParen) {
568 Parser.Lex(); //eat '(' token
569 if (getLexer().getKind() == AsmToken::Percent) {
570 Parser.Lex(); //eat % token
571 const AsmToken &nextTok = Parser.getTok();
572 if (nextTok.isNot(AsmToken::Identifier))
575 Str += nextTok.getIdentifier();
576 Parser.Lex(); //eat identifier
577 if (getLexer().getKind() != AsmToken::LParen)
582 if (getParser().ParseParenExpression(IdVal,EndLoc))
585 while (getLexer().getKind() == AsmToken::RParen)
586 Parser.Lex(); //eat ')' token
589 return true; //parenthesis must follow reloc operand
591 //Check the type of the expression
592 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
593 //it's a constant, evaluate lo or hi value
594 int Val = MCE->getValue();
597 } else if (Str == "hi") {
598 Val = (Val & 0xffff0000) >> 16;
600 Res = MCConstantExpr::Create(Val, getContext());
604 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
605 //it's a symbol, create symbolic expression from symbol
606 StringRef Symbol = MSRE->getSymbol().getName();
607 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
608 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
614 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
617 StartLoc = Parser.getTok().getLoc();
618 RegNo = tryParseRegister("");
619 EndLoc = Parser.getTok().getLoc();
620 return (RegNo == (unsigned)-1);
623 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
627 switch(getLexer().getKind()) {
630 case AsmToken::Integer:
631 case AsmToken::Minus:
633 return (getParser().ParseExpression(Res));
634 case AsmToken::Percent:
635 return parseRelocOperand(Res);
636 case AsmToken::LParen:
637 return false; //it's probably assuming 0
642 MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
643 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
645 const MCExpr *IdVal = 0;
647 //first operand is the offset
648 S = Parser.getTok().getLoc();
650 if (parseMemOffset(IdVal))
651 return MatchOperand_ParseFail;
653 const AsmToken &Tok = Parser.getTok(); //get next token
654 if (Tok.isNot(AsmToken::LParen)) {
655 Error(Parser.getTok().getLoc(), "'(' expected");
656 return MatchOperand_ParseFail;
659 Parser.Lex(); // Eat '(' token.
661 const AsmToken &Tok1 = Parser.getTok(); //get next token
662 if (Tok1.is(AsmToken::Dollar)) {
663 Parser.Lex(); // Eat '$' token.
664 if (tryParseRegisterOperand(Operands,"")) {
665 Error(Parser.getTok().getLoc(), "unexpected token in operand");
666 return MatchOperand_ParseFail;
670 Error(Parser.getTok().getLoc(),"unexpected token in operand");
671 return MatchOperand_ParseFail;
674 const AsmToken &Tok2 = Parser.getTok(); //get next token
675 if (Tok2.isNot(AsmToken::RParen)) {
676 Error(Parser.getTok().getLoc(), "')' expected");
677 return MatchOperand_ParseFail;
680 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
682 Parser.Lex(); // Eat ')' token.
685 IdVal = MCConstantExpr::Create(0, getContext());
687 //now replace register operand with the mem operand
688 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
689 int RegNo = op->getReg();
690 //remove register from operands
692 //and add memory operand
693 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
695 return MatchOperand_Success;
698 MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
700 MCSymbolRefExpr::VariantKind VK
701 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
702 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
703 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
704 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
705 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
706 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
707 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
708 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
709 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
710 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
711 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
712 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
713 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
714 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
715 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
716 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
717 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
718 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
719 .Default(MCSymbolRefExpr::VK_None);
724 static int ConvertCcString(StringRef CondString) {
725 int CC = StringSwitch<unsigned>(CondString)
748 parseMathOperation(StringRef Name, SMLoc NameLoc,
749 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
751 size_t Start = Name.find('.'), Next = Name.rfind('.');
752 StringRef Format1 = Name.slice(Start, Next);
753 //and add the first format to the operands
754 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
755 //now for the second format
756 StringRef Format2 = Name.slice(Next, StringRef::npos);
757 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
759 //set the format for the first register
760 setFpFormat(Format1);
762 // Read the remaining operands.
763 if (getLexer().isNot(AsmToken::EndOfStatement)) {
764 // Read the first operand.
765 if (ParseOperand(Operands, Name)) {
766 SMLoc Loc = getLexer().getLoc();
767 Parser.EatToEndOfStatement();
768 return Error(Loc, "unexpected token in argument list");
771 if (getLexer().isNot(AsmToken::Comma)) {
772 SMLoc Loc = getLexer().getLoc();
773 Parser.EatToEndOfStatement();
774 return Error(Loc, "unexpected token in argument list");
777 Parser.Lex(); // Eat the comma.
779 //set the format for the first register
780 setFpFormat(Format2);
782 // Parse and remember the operand.
783 if (ParseOperand(Operands, Name)) {
784 SMLoc Loc = getLexer().getLoc();
785 Parser.EatToEndOfStatement();
786 return Error(Loc, "unexpected token in argument list");
790 if (getLexer().isNot(AsmToken::EndOfStatement)) {
791 SMLoc Loc = getLexer().getLoc();
792 Parser.EatToEndOfStatement();
793 return Error(Loc, "unexpected token in argument list");
796 Parser.Lex(); // Consume the EndOfStatement
801 ParseInstruction(StringRef Name, SMLoc NameLoc,
802 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
803 //floating point instructions: should register be treated as double?
804 if (requestsDoubleOperand(Name)) {
805 setFpFormat(FP_FORMAT_D);
806 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
809 setDefaultFpFormat();
810 // Create the leading tokens for the mnemonic, split by '.' characters.
811 size_t Start = 0, Next = Name.find('.');
812 StringRef Mnemonic = Name.slice(Start, Next);
814 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
816 if (Next != StringRef::npos) {
817 //there is a format token in mnemonic
818 //StringRef Rest = Name.slice(Next, StringRef::npos);
819 size_t Dot = Name.find('.', Next+1);
820 StringRef Format = Name.slice(Next, Dot);
821 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
822 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
824 if (Name.startswith("c.")){
825 // floating point compare, add '.' and immediate represent for cc
826 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
827 int Cc = ConvertCcString(Format);
829 return Error(NameLoc, "Invalid conditional code");
831 SMLoc E = SMLoc::getFromPointer(
832 Parser.getTok().getLoc().getPointer() -1 );
833 Operands.push_back(MipsOperand::CreateImm(
834 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
836 //trunc, ceil, floor ...
837 return parseMathOperation(Name, NameLoc, Operands);
840 //the rest is a format
841 Format = Name.slice(Dot, StringRef::npos);
842 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
849 // Read the remaining operands.
850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
851 // Read the first operand.
852 if (ParseOperand(Operands, Name)) {
853 SMLoc Loc = getLexer().getLoc();
854 Parser.EatToEndOfStatement();
855 return Error(Loc, "unexpected token in argument list");
858 while (getLexer().is(AsmToken::Comma) ) {
859 Parser.Lex(); // Eat the comma.
861 // Parse and remember the operand.
862 if (ParseOperand(Operands, Name)) {
863 SMLoc Loc = getLexer().getLoc();
864 Parser.EatToEndOfStatement();
865 return Error(Loc, "unexpected token in argument list");
870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
871 SMLoc Loc = getLexer().getLoc();
872 Parser.EatToEndOfStatement();
873 return Error(Loc, "unexpected token in argument list");
876 Parser.Lex(); // Consume the EndOfStatement
881 ParseDirective(AsmToken DirectiveID) {
883 if (DirectiveID.getString() == ".ent") {
884 //ignore this directive for now
889 if (DirectiveID.getString() == ".end") {
890 //ignore this directive for now
895 if (DirectiveID.getString() == ".frame") {
896 //ignore this directive for now
897 Parser.EatToEndOfStatement();
901 if (DirectiveID.getString() == ".set") {
902 //ignore this directive for now
903 Parser.EatToEndOfStatement();
907 if (DirectiveID.getString() == ".fmask") {
908 //ignore this directive for now
909 Parser.EatToEndOfStatement();
913 if (DirectiveID.getString() == ".mask") {
914 //ignore this directive for now
915 Parser.EatToEndOfStatement();
919 if (DirectiveID.getString() == ".gpword") {
920 //ignore this directive for now
921 Parser.EatToEndOfStatement();
928 extern "C" void LLVMInitializeMipsAsmParser() {
929 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
930 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
931 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
932 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
935 #define GET_REGISTER_MATCHER
936 #define GET_MATCHER_IMPLEMENTATION
937 #include "MipsGenAsmMatcher.inc"