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