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