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