1 //===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MCTargetDesc/MipsMCTargetDesc.h" 11 #include "MipsRegisterInfo.h" 12 #include "llvm/ADT/StringSwitch.h" 13 #include "llvm/MC/MCContext.h" 14 #include "llvm/MC/MCExpr.h" 15 #include "llvm/MC/MCInst.h" 16 #include "llvm/MC/MCStreamer.h" 17 #include "llvm/MC/MCSubtargetInfo.h" 18 #include "llvm/MC/MCSymbol.h" 19 #include "llvm/MC/MCParser/MCAsmLexer.h" 20 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 21 #include "llvm/MC/MCTargetAsmParser.h" 22 #include "llvm/Support/TargetRegistry.h" 23 24 using namespace llvm; 25 26 namespace { 27 28 class MipsAsmParser : public MCTargetAsmParser { 29 30 enum FpFormatTy { 31 FP_FORMAT_NONE = -1, 32 FP_FORMAT_S, 33 FP_FORMAT_D, 34 FP_FORMAT_L, 35 FP_FORMAT_W 36 } FpFormat; 37 38 MCSubtargetInfo &STI; 39 MCAsmParser &Parser; 40 41 #define GET_ASSEMBLER_HEADER 42 #include "MipsGenAsmMatcher.inc" 43 44 bool MatchAndEmitInstruction(SMLoc IDLoc, 45 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 46 MCStreamer &Out); 47 48 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); 49 50 bool ParseInstruction(StringRef Name, SMLoc NameLoc, 51 SmallVectorImpl<MCParsedAsmOperand*> &Operands); 52 53 bool parseMathOperation(StringRef Name, SMLoc NameLoc, 54 SmallVectorImpl<MCParsedAsmOperand*> &Operands); 55 56 bool ParseDirective(AsmToken DirectiveID); 57 58 MipsAsmParser::OperandMatchResultTy 59 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&); 60 61 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, 62 StringRef Mnemonic); 63 64 int tryParseRegister(StringRef Mnemonic); 65 66 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 67 StringRef Mnemonic); 68 69 bool parseMemOffset(const MCExpr *&Res); 70 bool parseRelocOperand(const MCExpr *&Res); 71 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol); 72 73 bool isMips64() const { 74 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0; 75 } 76 77 bool isFP64() const { 78 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0; 79 } 80 81 int matchRegisterName(StringRef Symbol); 82 83 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic); 84 85 void setFpFormat(FpFormatTy Format) { 86 FpFormat = Format; 87 } 88 89 void setDefaultFpFormat(); 90 91 void setFpFormat(StringRef Format); 92 93 FpFormatTy getFpFormat() {return FpFormat;} 94 95 bool requestsDoubleOperand(StringRef Mnemonic); 96 97 unsigned getReg(int RC,int RegNo); 98 99 public: 100 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser) 101 : MCTargetAsmParser(), STI(sti), Parser(parser) { 102 // Initialize the set of available features. 103 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 104 } 105 106 MCAsmParser &getParser() const { return Parser; } 107 MCAsmLexer &getLexer() const { return Parser.getLexer(); } 108 109 }; 110 } 111 112 namespace { 113 114 /// MipsOperand - Instances of this class represent a parsed Mips machine 115 /// instruction. 116 class MipsOperand : public MCParsedAsmOperand { 117 118 enum KindTy { 119 k_CondCode, 120 k_CoprocNum, 121 k_Immediate, 122 k_Memory, 123 k_PostIndexRegister, 124 k_Register, 125 k_Token 126 } Kind; 127 128 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 129 130 union { 131 struct { 132 const char *Data; 133 unsigned Length; 134 } Tok; 135 136 struct { 137 unsigned RegNum; 138 } Reg; 139 140 struct { 141 const MCExpr *Val; 142 } Imm; 143 144 struct { 145 unsigned Base; 146 const MCExpr *Off; 147 } Mem; 148 }; 149 150 SMLoc StartLoc, EndLoc; 151 152 public: 153 void addRegOperands(MCInst &Inst, unsigned N) const { 154 assert(N == 1 && "Invalid number of operands!"); 155 Inst.addOperand(MCOperand::CreateReg(getReg())); 156 } 157 158 void addExpr(MCInst &Inst, const MCExpr *Expr) const{ 159 // Add as immediate when possible. Null MCExpr = 0. 160 if (Expr == 0) 161 Inst.addOperand(MCOperand::CreateImm(0)); 162 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 163 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 164 else 165 Inst.addOperand(MCOperand::CreateExpr(Expr)); 166 } 167 168 void addImmOperands(MCInst &Inst, unsigned N) const { 169 assert(N == 1 && "Invalid number of operands!"); 170 const MCExpr *Expr = getImm(); 171 addExpr(Inst,Expr); 172 } 173 174 void addMemOperands(MCInst &Inst, unsigned N) const { 175 assert(N == 2 && "Invalid number of operands!"); 176 177 Inst.addOperand(MCOperand::CreateReg(getMemBase())); 178 179 const MCExpr *Expr = getMemOff(); 180 addExpr(Inst,Expr); 181 } 182 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; } 187 188 StringRef getToken() const { 189 assert(Kind == k_Token && "Invalid access!"); 190 return StringRef(Tok.Data, Tok.Length); 191 } 192 193 unsigned getReg() const { 194 assert((Kind == k_Register) && "Invalid access!"); 195 return Reg.RegNum; 196 } 197 198 const MCExpr *getImm() const { 199 assert((Kind == k_Immediate) && "Invalid access!"); 200 return Imm.Val; 201 } 202 203 unsigned getMemBase() const { 204 assert((Kind == k_Memory) && "Invalid access!"); 205 return Mem.Base; 206 } 207 208 const MCExpr *getMemOff() const { 209 assert((Kind == k_Memory) && "Invalid access!"); 210 return Mem.Off; 211 } 212 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(); 217 Op->StartLoc = S; 218 Op->EndLoc = S; 219 return Op; 220 } 221 222 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { 223 MipsOperand *Op = new MipsOperand(k_Register); 224 Op->Reg.RegNum = RegNum; 225 Op->StartLoc = S; 226 Op->EndLoc = E; 227 return Op; 228 } 229 230 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { 231 MipsOperand *Op = new MipsOperand(k_Immediate); 232 Op->Imm.Val = Val; 233 Op->StartLoc = S; 234 Op->EndLoc = E; 235 return Op; 236 } 237 238 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, 239 SMLoc S, SMLoc E) { 240 MipsOperand *Op = new MipsOperand(k_Memory); 241 Op->Mem.Base = Base; 242 Op->Mem.Off = Off; 243 Op->StartLoc = S; 244 Op->EndLoc = E; 245 return Op; 246 } 247 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; } 252 253 virtual void print(raw_ostream &OS) const { 254 llvm_unreachable("unimplemented!"); 255 } 256 }; 257 } 258 259 bool MipsAsmParser:: 260 MatchAndEmitInstruction(SMLoc IDLoc, 261 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 262 MCStreamer &Out) { 263 MCInst Inst; 264 unsigned Kind; 265 unsigned ErrorInfo; 266 SmallVector<std::pair< unsigned, std::string >, 4> MapAndConstraints; 267 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst, 268 MapAndConstraints, ErrorInfo, 269 /*matchingInlineAsm*/ false); 270 271 switch (MatchResult) { 272 default: break; 273 case Match_Success: { 274 Inst.setLoc(IDLoc); 275 Out.EmitInstruction(Inst); 276 return false; 277 } 278 case Match_MissingFeature: 279 Error(IDLoc, "instruction requires a CPU feature not currently enabled"); 280 return true; 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"); 286 287 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc(); 288 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 289 } 290 291 return Error(ErrorLoc, "invalid operand for instruction"); 292 } 293 case Match_MnemonicFail: 294 return Error(IDLoc, "invalid instruction"); 295 } 296 return true; 297 } 298 299 int MipsAsmParser::matchRegisterName(StringRef Name) { 300 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) 335 .Default(-1); 336 337 if (CC != -1) { 338 //64 bit register in Mips are following 32 bit definitions. 339 if (isMips64()) 340 CC++; 341 return CC; 342 } 343 344 if (Name[0] == 'f') { 345 StringRef NumString = Name.substr(1); 346 unsigned IntVal; 347 if( NumString.getAsInteger(10, IntVal)) 348 return -1; //not integer 349 if (IntVal > 31) 350 return -1; 351 352 FpFormatTy Format = getFpFormat(); 353 354 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W) 355 return getReg(Mips::FGR32RegClassID, IntVal); 356 if (Format == FP_FORMAT_D) { 357 if(isFP64()) { 358 return getReg(Mips::FGR64RegClassID, IntVal); 359 } 360 //only even numbers available as register pairs 361 if (( IntVal > 31) || (IntVal%2 != 0)) 362 return -1; 363 return getReg(Mips::AFGR64RegClassID, IntVal/2); 364 } 365 } 366 367 return -1; 368 } 369 void MipsAsmParser::setDefaultFpFormat() { 370 371 if (isMips64() || isFP64()) 372 FpFormat = FP_FORMAT_D; 373 else 374 FpFormat = FP_FORMAT_S; 375 } 376 377 bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){ 378 379 bool IsDouble = StringSwitch<bool>(Mnemonic.lower()) 380 .Case("ldxc1", true) 381 .Case("ldc1", true) 382 .Case("sdxc1", true) 383 .Case("sdc1", true) 384 .Default(false); 385 386 return IsDouble; 387 } 388 void MipsAsmParser::setFpFormat(StringRef Format) { 389 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); 396 } 397 398 unsigned MipsAsmParser::getReg(int RC,int RegNo){ 399 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo); 400 } 401 402 int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) { 403 404 if (Mnemonic.lower() == "rdhwr") { 405 //at the moment only hwreg29 is supported 406 if (RegNum != 29) 407 return -1; 408 return Mips::HWR29; 409 } 410 411 if (RegNum > 31) 412 return -1; 413 414 return getReg(Mips::CPURegsRegClassID,RegNum); 415 } 416 417 int MipsAsmParser::tryParseRegister(StringRef Mnemonic) { 418 const AsmToken &Tok = Parser.getTok(); 419 int RegNum = -1; 420 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()), 426 Mnemonic.lower()); 427 else 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) 432 RegNum = Mips::ZERO; 433 } 434 return RegNum; 435 } 436 437 bool MipsAsmParser:: 438 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 439 StringRef Mnemonic){ 440 441 SMLoc S = Parser.getTok().getLoc(); 442 int RegNo = -1; 443 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 449 if (RegNo == 0) 450 RegNo = Mips::FCC0; 451 } else 452 RegNo = tryParseRegister(Mnemonic); 453 if (RegNo == -1) 454 return true; 455 456 Operands.push_back(MipsOperand::CreateReg(RegNo, S, 457 Parser.getTok().getLoc())); 458 Parser.Lex(); // Eat register token. 459 return false; 460 } 461 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) 468 return false; 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) 473 return true; 474 475 switch (getLexer().getKind()) { 476 default: 477 Error(Parser.getTok().getLoc(), "unexpected token in operand"); 478 return true; 479 case AsmToken::Dollar: { 480 //parse register 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)) 490 return true; 491 492 Parser.Lex(); //eat dollar 493 if (tryParseRegisterOperand(Operands,Mnemonic)) 494 return true; 495 496 if (!getLexer().is(AsmToken::RParen)) 497 return true; 498 499 S = Parser.getTok().getLoc(); 500 Operands.push_back(MipsOperand::CreateToken(")", S)); 501 Parser.Lex(); 502 } 503 return false; 504 } 505 //maybe it is a symbol reference 506 StringRef Identifier; 507 if (Parser.ParseIdentifier(Identifier)) 508 return true; 509 510 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 511 512 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier); 513 514 // Otherwise create a symbol ref. 515 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, 516 getContext()); 517 518 Operands.push_back(MipsOperand::CreateImm(Res, S, E)); 519 return false; 520 } 521 case AsmToken::Identifier: 522 case AsmToken::LParen: 523 case AsmToken::Minus: 524 case AsmToken::Plus: 525 case AsmToken::Integer: 526 case AsmToken::String: { 527 // quoted label names 528 const MCExpr *IdVal; 529 SMLoc S = Parser.getTok().getLoc(); 530 if (getParser().ParseExpression(IdVal)) 531 return true; 532 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 533 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); 534 return false; 535 } 536 case AsmToken::Percent: { 537 //it is a symbol reference or constant expression 538 const MCExpr *IdVal; 539 SMLoc S = Parser.getTok().getLoc(); //start location of the operand 540 if (parseRelocOperand(IdVal)) 541 return true; 542 543 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 544 545 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); 546 return false; 547 }//case AsmToken::Percent 548 }//switch(getLexer().getKind()) 549 return true; 550 } 551 552 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { 553 554 Parser.Lex(); //eat % token 555 const AsmToken &Tok = Parser.getTok(); //get next token, operation 556 if (Tok.isNot(AsmToken::Identifier)) 557 return true; 558 559 std::string Str = Tok.getIdentifier().str(); 560 561 Parser.Lex(); //eat identifier 562 //now make expression from the rest of the operand 563 const MCExpr *IdVal; 564 SMLoc EndLoc; 565 566 if (getLexer().getKind() == AsmToken::LParen) { 567 while (1) { 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)) 573 return true; 574 Str += "(%"; 575 Str += nextTok.getIdentifier(); 576 Parser.Lex(); //eat identifier 577 if (getLexer().getKind() != AsmToken::LParen) 578 return true; 579 } else 580 break; 581 } 582 if (getParser().ParseParenExpression(IdVal,EndLoc)) 583 return true; 584 585 while (getLexer().getKind() == AsmToken::RParen) 586 Parser.Lex(); //eat ')' token 587 588 } else 589 return true; //parenthesis must follow reloc operand 590 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(); 595 if (Str == "lo") { 596 Val = Val & 0xffff; 597 } else if (Str == "hi") { 598 Val = (Val & 0xffff0000) >> 16; 599 } 600 Res = MCConstantExpr::Create(Val, getContext()); 601 return false; 602 } 603 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()); 609 return false; 610 } 611 return true; 612 } 613 614 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 615 SMLoc &EndLoc) { 616 617 StartLoc = Parser.getTok().getLoc(); 618 RegNo = tryParseRegister(""); 619 EndLoc = Parser.getTok().getLoc(); 620 return (RegNo == (unsigned)-1); 621 } 622 623 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) { 624 625 SMLoc S; 626 627 switch(getLexer().getKind()) { 628 default: 629 return true; 630 case AsmToken::Integer: 631 case AsmToken::Minus: 632 case AsmToken::Plus: 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 638 } 639 return true; 640 } 641 642 MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( 643 SmallVectorImpl<MCParsedAsmOperand*>&Operands) { 644 645 const MCExpr *IdVal = 0; 646 SMLoc S; 647 //first operand is the offset 648 S = Parser.getTok().getLoc(); 649 650 if (parseMemOffset(IdVal)) 651 return MatchOperand_ParseFail; 652 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; 657 } 658 659 Parser.Lex(); // Eat '(' token. 660 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; 667 } 668 669 } else { 670 Error(Parser.getTok().getLoc(),"unexpected token in operand"); 671 return MatchOperand_ParseFail; 672 } 673 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; 678 } 679 680 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 681 682 Parser.Lex(); // Eat ')' token. 683 684 if (IdVal == 0) 685 IdVal = MCConstantExpr::Create(0, getContext()); 686 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 691 Operands.pop_back(); 692 //and add memory operand 693 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E)); 694 delete op; 695 return MatchOperand_Success; 696 } 697 698 MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { 699 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); 720 721 return VK; 722 } 723 724 static int ConvertCcString(StringRef CondString) { 725 int CC = StringSwitch<unsigned>(CondString) 726 .Case(".f", 0) 727 .Case(".un", 1) 728 .Case(".eq", 2) 729 .Case(".ueq", 3) 730 .Case(".olt", 4) 731 .Case(".ult", 5) 732 .Case(".ole", 6) 733 .Case(".ule", 7) 734 .Case(".sf", 8) 735 .Case(".ngle", 9) 736 .Case(".seq", 10) 737 .Case(".ngl", 11) 738 .Case(".lt", 12) 739 .Case(".nge", 13) 740 .Case(".le", 14) 741 .Case(".ngt", 15) 742 .Default(-1); 743 744 return CC; 745 } 746 747 bool MipsAsmParser:: 748 parseMathOperation(StringRef Name, SMLoc NameLoc, 749 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 750 //split the format 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)); 758 759 //set the format for the first register 760 setFpFormat(Format1); 761 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"); 769 } 770 771 if (getLexer().isNot(AsmToken::Comma)) { 772 SMLoc Loc = getLexer().getLoc(); 773 Parser.EatToEndOfStatement(); 774 return Error(Loc, "unexpected token in argument list"); 775 776 } 777 Parser.Lex(); // Eat the comma. 778 779 //set the format for the first register 780 setFpFormat(Format2); 781 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"); 787 } 788 } 789 790 if (getLexer().isNot(AsmToken::EndOfStatement)) { 791 SMLoc Loc = getLexer().getLoc(); 792 Parser.EatToEndOfStatement(); 793 return Error(Loc, "unexpected token in argument list"); 794 } 795 796 Parser.Lex(); // Consume the EndOfStatement 797 return false; 798 } 799 800 bool MipsAsmParser:: 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)); 807 } 808 else { 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); 813 814 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc)); 815 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)); 823 else { 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); 828 if (Cc == -1) { 829 return Error(NameLoc, "Invalid conditional code"); 830 } 831 SMLoc E = SMLoc::getFromPointer( 832 Parser.getTok().getLoc().getPointer() -1 ); 833 Operands.push_back(MipsOperand::CreateImm( 834 MCConstantExpr::Create(Cc, getContext()), NameLoc, E)); 835 } else { 836 //trunc, ceil, floor ... 837 return parseMathOperation(Name, NameLoc, Operands); 838 } 839 840 //the rest is a format 841 Format = Name.slice(Dot, StringRef::npos); 842 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc)); 843 } 844 845 setFpFormat(Format); 846 } 847 } 848 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"); 856 } 857 858 while (getLexer().is(AsmToken::Comma) ) { 859 Parser.Lex(); // Eat the comma. 860 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"); 866 } 867 } 868 } 869 870 if (getLexer().isNot(AsmToken::EndOfStatement)) { 871 SMLoc Loc = getLexer().getLoc(); 872 Parser.EatToEndOfStatement(); 873 return Error(Loc, "unexpected token in argument list"); 874 } 875 876 Parser.Lex(); // Consume the EndOfStatement 877 return false; 878 } 879 880 bool MipsAsmParser:: 881 ParseDirective(AsmToken DirectiveID) { 882 883 if (DirectiveID.getString() == ".ent") { 884 //ignore this directive for now 885 Parser.Lex(); 886 return false; 887 } 888 889 if (DirectiveID.getString() == ".end") { 890 //ignore this directive for now 891 Parser.Lex(); 892 return false; 893 } 894 895 if (DirectiveID.getString() == ".frame") { 896 //ignore this directive for now 897 Parser.EatToEndOfStatement(); 898 return false; 899 } 900 901 if (DirectiveID.getString() == ".set") { 902 //ignore this directive for now 903 Parser.EatToEndOfStatement(); 904 return false; 905 } 906 907 if (DirectiveID.getString() == ".fmask") { 908 //ignore this directive for now 909 Parser.EatToEndOfStatement(); 910 return false; 911 } 912 913 if (DirectiveID.getString() == ".mask") { 914 //ignore this directive for now 915 Parser.EatToEndOfStatement(); 916 return false; 917 } 918 919 if (DirectiveID.getString() == ".gpword") { 920 //ignore this directive for now 921 Parser.EatToEndOfStatement(); 922 return false; 923 } 924 925 return true; 926 } 927 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); 933 } 934 935 #define GET_REGISTER_MATCHER 936 #define GET_MATCHER_IMPLEMENTATION 937 #include "MipsGenAsmMatcher.inc" 938