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