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 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier); 527 528 // Otherwise create a symbol ref. 529 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, 530 getContext()); 531 532 Operands.push_back(MipsOperand::CreateImm(Res, S, E)); 533 return false; 534 } 535 case AsmToken::Identifier: 536 case AsmToken::LParen: 537 case AsmToken::Minus: 538 case AsmToken::Plus: 539 case AsmToken::Integer: 540 case AsmToken::String: { 541 // quoted label names 542 const MCExpr *IdVal; 543 SMLoc S = Parser.getTok().getLoc(); 544 if (getParser().ParseExpression(IdVal)) 545 return true; 546 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 547 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); 548 return false; 549 } 550 case AsmToken::Percent: { 551 //it is a symbol reference or constant expression 552 const MCExpr *IdVal; 553 SMLoc S = Parser.getTok().getLoc(); //start location of the operand 554 if (parseRelocOperand(IdVal)) 555 return true; 556 557 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 558 559 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); 560 return false; 561 }//case AsmToken::Percent 562 }//switch(getLexer().getKind()) 563 return true; 564} 565 566bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { 567 568 Parser.Lex(); //eat % token 569 const AsmToken &Tok = Parser.getTok(); //get next token, operation 570 if (Tok.isNot(AsmToken::Identifier)) 571 return true; 572 573 std::string Str = Tok.getIdentifier().str(); 574 575 Parser.Lex(); //eat identifier 576 //now make expression from the rest of the operand 577 const MCExpr *IdVal; 578 SMLoc EndLoc; 579 580 if (getLexer().getKind() == AsmToken::LParen) { 581 while (1) { 582 Parser.Lex(); //eat '(' token 583 if (getLexer().getKind() == AsmToken::Percent) { 584 Parser.Lex(); //eat % token 585 const AsmToken &nextTok = Parser.getTok(); 586 if (nextTok.isNot(AsmToken::Identifier)) 587 return true; 588 Str += "(%"; 589 Str += nextTok.getIdentifier(); 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 (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) { 607 //it's a constant, evaluate lo or hi value 608 int Val = MCE->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 (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) { 619 //it's a symbol, create symbolic expression from symbol 620 StringRef Symbol = MSRE->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 738static int ConvertCcString(StringRef CondString) { 739 int CC = StringSwitch<unsigned>(CondString) 740 .Case(".f", 0) 741 .Case(".un", 1) 742 .Case(".eq", 2) 743 .Case(".ueq", 3) 744 .Case(".olt", 4) 745 .Case(".ult", 5) 746 .Case(".ole", 6) 747 .Case(".ule", 7) 748 .Case(".sf", 8) 749 .Case(".ngle", 9) 750 .Case(".seq", 10) 751 .Case(".ngl", 11) 752 .Case(".lt", 12) 753 .Case(".nge", 13) 754 .Case(".le", 14) 755 .Case(".ngt", 15) 756 .Default(-1); 757 758 return CC; 759} 760 761bool MipsAsmParser:: 762parseMathOperation(StringRef Name, SMLoc NameLoc, 763 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 764 //split the format 765 size_t Start = Name.find('.'), Next = Name.rfind('.'); 766 StringRef Format1 = Name.slice(Start, Next); 767 //and add the first format to the operands 768 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc)); 769 //now for the second format 770 StringRef Format2 = Name.slice(Next, StringRef::npos); 771 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc)); 772 773 //set the format for the first register 774 setFpFormat(Format1); 775 776 // Read the remaining operands. 777 if (getLexer().isNot(AsmToken::EndOfStatement)) { 778 // Read the first operand. 779 if (ParseOperand(Operands, Name)) { 780 SMLoc Loc = getLexer().getLoc(); 781 Parser.EatToEndOfStatement(); 782 return Error(Loc, "unexpected token in argument list"); 783 } 784 785 if (getLexer().isNot(AsmToken::Comma)) { 786 SMLoc Loc = getLexer().getLoc(); 787 Parser.EatToEndOfStatement(); 788 return Error(Loc, "unexpected token in argument list"); 789 790 } 791 Parser.Lex(); // Eat the comma. 792 793 //set the format for the first register 794 setFpFormat(Format2); 795 796 // Parse and remember the operand. 797 if (ParseOperand(Operands, Name)) { 798 SMLoc Loc = getLexer().getLoc(); 799 Parser.EatToEndOfStatement(); 800 return Error(Loc, "unexpected token in argument list"); 801 } 802 } 803 804 if (getLexer().isNot(AsmToken::EndOfStatement)) { 805 SMLoc Loc = getLexer().getLoc(); 806 Parser.EatToEndOfStatement(); 807 return Error(Loc, "unexpected token in argument list"); 808 } 809 810 Parser.Lex(); // Consume the EndOfStatement 811 return false; 812} 813 814bool MipsAsmParser:: 815ParseInstruction(StringRef Name, SMLoc NameLoc, 816 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 817 //floating point instructions: should register be treated as double? 818 if (requestsDoubleOperand(Name)) { 819 setFpFormat(FP_FORMAT_D); 820 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc)); 821 } 822 else { 823 setDefaultFpFormat(); 824 // Create the leading tokens for the mnemonic, split by '.' characters. 825 size_t Start = 0, Next = Name.find('.'); 826 StringRef Mnemonic = Name.slice(Start, Next); 827 828 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc)); 829 830 if (Next != StringRef::npos) { 831 //there is a format token in mnemonic 832 //StringRef Rest = Name.slice(Next, StringRef::npos); 833 size_t Dot = Name.find('.', Next+1); 834 StringRef Format = Name.slice(Next, Dot); 835 if (Dot == StringRef::npos) //only one '.' in a string, it's a format 836 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc)); 837 else { 838 if (Name.startswith("c.")){ 839 // floating point compare, add '.' and immediate represent for cc 840 Operands.push_back(MipsOperand::CreateToken(".", NameLoc)); 841 int Cc = ConvertCcString(Format); 842 if (Cc == -1) { 843 return Error(NameLoc, "Invalid conditional code"); 844 } 845 SMLoc E = SMLoc::getFromPointer( 846 Parser.getTok().getLoc().getPointer() -1 ); 847 Operands.push_back(MipsOperand::CreateImm( 848 MCConstantExpr::Create(Cc, getContext()), NameLoc, E)); 849 } else { 850 //trunc, ceil, floor ... 851 return parseMathOperation(Name, NameLoc, Operands); 852 } 853 854 //the rest is a format 855 Format = Name.slice(Dot, StringRef::npos); 856 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc)); 857 } 858 859 setFpFormat(Format); 860 } 861 } 862 863 // Read the remaining operands. 864 if (getLexer().isNot(AsmToken::EndOfStatement)) { 865 // Read the first operand. 866 if (ParseOperand(Operands, Name)) { 867 SMLoc Loc = getLexer().getLoc(); 868 Parser.EatToEndOfStatement(); 869 return Error(Loc, "unexpected token in argument list"); 870 } 871 872 while (getLexer().is(AsmToken::Comma) ) { 873 Parser.Lex(); // Eat the comma. 874 875 // Parse and remember the operand. 876 if (ParseOperand(Operands, Name)) { 877 SMLoc Loc = getLexer().getLoc(); 878 Parser.EatToEndOfStatement(); 879 return Error(Loc, "unexpected token in argument list"); 880 } 881 } 882 } 883 884 if (getLexer().isNot(AsmToken::EndOfStatement)) { 885 SMLoc Loc = getLexer().getLoc(); 886 Parser.EatToEndOfStatement(); 887 return Error(Loc, "unexpected token in argument list"); 888 } 889 890 Parser.Lex(); // Consume the EndOfStatement 891 return false; 892} 893 894bool MipsAsmParser:: 895ParseDirective(AsmToken DirectiveID) { 896 897 if (DirectiveID.getString() == ".ent") { 898 //ignore this directive for now 899 Parser.Lex(); 900 return false; 901 } 902 903 if (DirectiveID.getString() == ".end") { 904 //ignore this directive for now 905 Parser.Lex(); 906 return false; 907 } 908 909 if (DirectiveID.getString() == ".frame") { 910 //ignore this directive for now 911 Parser.EatToEndOfStatement(); 912 return false; 913 } 914 915 if (DirectiveID.getString() == ".set") { 916 //ignore this directive for now 917 Parser.EatToEndOfStatement(); 918 return false; 919 } 920 921 if (DirectiveID.getString() == ".fmask") { 922 //ignore this directive for now 923 Parser.EatToEndOfStatement(); 924 return false; 925 } 926 927 if (DirectiveID.getString() == ".mask") { 928 //ignore this directive for now 929 Parser.EatToEndOfStatement(); 930 return false; 931 } 932 933 if (DirectiveID.getString() == ".gpword") { 934 //ignore this directive for now 935 Parser.EatToEndOfStatement(); 936 return false; 937 } 938 939 return true; 940} 941 942extern "C" void LLVMInitializeMipsAsmParser() { 943 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget); 944 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget); 945 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target); 946 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget); 947} 948 949#define GET_REGISTER_MATCHER 950#define GET_MATCHER_IMPLEMENTATION 951#include "MipsGenAsmMatcher.inc" 952