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