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