MipsAsmParser.cpp revision fce9279ac0265fd5ea637dd30253bad26f4273da
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/MCParser/MCAsmLexer.h" 17#include "llvm/MC/MCParser/MCParsedAsmOperand.h" 18#include "llvm/MC/MCStreamer.h" 19#include "llvm/MC/MCSubtargetInfo.h" 20#include "llvm/MC/MCSymbol.h" 21#include "llvm/MC/MCTargetAsmParser.h" 22#include "llvm/Support/TargetRegistry.h" 23#include "llvm/ADT/APInt.h" 24 25using namespace llvm; 26 27namespace { 28class MipsAssemblerOptions { 29public: 30 MipsAssemblerOptions(): 31 aTReg(1), reorder(true), macro(true) { 32 } 33 34 unsigned getATRegNum() {return aTReg;} 35 bool setATReg(unsigned Reg); 36 37 bool isReorder() {return reorder;} 38 void setReorder() {reorder = true;} 39 void setNoreorder() {reorder = false;} 40 41 bool isMacro() {return macro;} 42 void setMacro() {macro = true;} 43 void setNomacro() {macro = false;} 44 45private: 46 unsigned aTReg; 47 bool reorder; 48 bool macro; 49}; 50} 51 52namespace { 53class MipsAsmParser : public MCTargetAsmParser { 54 55 enum FpFormatTy { 56 FP_FORMAT_NONE = -1, 57 FP_FORMAT_S, 58 FP_FORMAT_D, 59 FP_FORMAT_L, 60 FP_FORMAT_W 61 } FpFormat; 62 63 MCSubtargetInfo &STI; 64 MCAsmParser &Parser; 65 MipsAssemblerOptions Options; 66 67#define GET_ASSEMBLER_HEADER 68#include "MipsGenAsmMatcher.inc" 69 70 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 71 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 72 MCStreamer &Out, unsigned &ErrorInfo, 73 bool MatchingInlineAsm); 74 75 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); 76 77 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 78 SMLoc NameLoc, 79 SmallVectorImpl<MCParsedAsmOperand*> &Operands); 80 81 bool ParseDirective(AsmToken DirectiveID); 82 83 MipsAsmParser::OperandMatchResultTy 84 parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 85 int RegKind); 86 87 MipsAsmParser::OperandMatchResultTy 88 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 89 90 MipsAsmParser::OperandMatchResultTy 91 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 92 93 MipsAsmParser::OperandMatchResultTy 94 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 95 96 MipsAsmParser::OperandMatchResultTy 97 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 98 99 MipsAsmParser::OperandMatchResultTy 100 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 101 102 MipsAsmParser::OperandMatchResultTy 103 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 104 105 MipsAsmParser::OperandMatchResultTy 106 parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 107 108 MipsAsmParser::OperandMatchResultTy 109 parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 110 111 MipsAsmParser::OperandMatchResultTy 112 parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 113 114 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 115 unsigned RegKind); 116 117 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, 118 StringRef Mnemonic); 119 120 int tryParseRegister(bool is64BitReg); 121 122 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 123 bool is64BitReg); 124 125 bool needsExpansion(MCInst &Inst); 126 127 void expandInstruction(MCInst &Inst, SMLoc IDLoc, 128 SmallVectorImpl<MCInst> &Instructions); 129 void expandLoadImm(MCInst &Inst, SMLoc IDLoc, 130 SmallVectorImpl<MCInst> &Instructions); 131 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, 132 SmallVectorImpl<MCInst> &Instructions); 133 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, 134 SmallVectorImpl<MCInst> &Instructions); 135 void expandMemInst(MCInst &Inst, SMLoc IDLoc, 136 SmallVectorImpl<MCInst> &Instructions, 137 bool isLoad,bool isImmOpnd); 138 bool reportParseError(StringRef ErrorMsg); 139 140 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr); 141 bool parseRelocOperand(const MCExpr *&Res); 142 143 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr); 144 145 bool isEvaluated(const MCExpr *Expr); 146 bool parseDirectiveSet(); 147 148 bool parseSetAtDirective(); 149 bool parseSetNoAtDirective(); 150 bool parseSetMacroDirective(); 151 bool parseSetNoMacroDirective(); 152 bool parseSetReorderDirective(); 153 bool parseSetNoReorderDirective(); 154 155 bool parseSetAssignment(); 156 157 bool parseDirectiveWord(unsigned Size, SMLoc L); 158 159 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol); 160 161 bool isMips64() const { 162 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0; 163 } 164 165 bool isFP64() const { 166 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0; 167 } 168 169 int matchRegisterName(StringRef Symbol, bool is64BitReg); 170 171 int matchCPURegisterName(StringRef Symbol); 172 173 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass); 174 175 int matchFPURegisterName(StringRef Name, FpFormatTy Format); 176 177 void setFpFormat(FpFormatTy Format) { 178 FpFormat = Format; 179 } 180 181 void setDefaultFpFormat(); 182 183 void setFpFormat(StringRef Format); 184 185 FpFormatTy getFpFormat() {return FpFormat;} 186 187 unsigned getReg(int RC, int RegNo); 188 189 int getATReg(); 190 191 bool processInstruction(MCInst &Inst, SMLoc IDLoc, 192 SmallVectorImpl<MCInst> &Instructions); 193public: 194 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser) 195 : MCTargetAsmParser(), STI(sti), Parser(parser) { 196 // Initialize the set of available features. 197 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 198 } 199 200 MCAsmParser &getParser() const { return Parser; } 201 MCAsmLexer &getLexer() const { return Parser.getLexer(); } 202 203}; 204} 205 206namespace { 207 208/// MipsOperand - Instances of this class represent a parsed Mips machine 209/// instruction. 210class MipsOperand : public MCParsedAsmOperand { 211 212public: 213 enum RegisterKind { 214 Kind_None, 215 Kind_CPURegs, 216 Kind_CPU64Regs, 217 Kind_HWRegs, 218 Kind_HW64Regs, 219 Kind_FGR32Regs, 220 Kind_FGR64Regs, 221 Kind_AFGR64Regs, 222 Kind_CCRRegs 223 }; 224 225private: 226 enum KindTy { 227 k_CondCode, 228 k_CoprocNum, 229 k_Immediate, 230 k_Memory, 231 k_PostIndexRegister, 232 k_Register, 233 k_Token 234 } Kind; 235 236 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 237 238 struct Token { 239 const char *Data; 240 unsigned Length; 241 }; 242 243 struct RegOp { 244 unsigned RegNum; 245 RegisterKind Kind; 246 }; 247 248 struct ImmOp { 249 const MCExpr *Val; 250 }; 251 252 struct MemOp { 253 unsigned Base; 254 const MCExpr *Off; 255 }; 256 257 union { 258 struct Token Tok; 259 struct RegOp Reg; 260 struct ImmOp Imm; 261 struct MemOp Mem; 262 }; 263 264 SMLoc StartLoc, EndLoc; 265 266public: 267 void addRegOperands(MCInst &Inst, unsigned N) const { 268 assert(N == 1 && "Invalid number of operands!"); 269 Inst.addOperand(MCOperand::CreateReg(getReg())); 270 } 271 272 void addExpr(MCInst &Inst, const MCExpr *Expr) const{ 273 // Add as immediate when possible. Null MCExpr = 0. 274 if (Expr == 0) 275 Inst.addOperand(MCOperand::CreateImm(0)); 276 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 277 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 278 else 279 Inst.addOperand(MCOperand::CreateExpr(Expr)); 280 } 281 282 void addImmOperands(MCInst &Inst, unsigned N) const { 283 assert(N == 1 && "Invalid number of operands!"); 284 const MCExpr *Expr = getImm(); 285 addExpr(Inst, Expr); 286 } 287 288 void addMemOperands(MCInst &Inst, unsigned N) const { 289 assert(N == 2 && "Invalid number of operands!"); 290 291 Inst.addOperand(MCOperand::CreateReg(getMemBase())); 292 293 const MCExpr *Expr = getMemOff(); 294 addExpr(Inst, Expr); 295 } 296 297 bool isReg() const { return Kind == k_Register; } 298 bool isImm() const { return Kind == k_Immediate; } 299 bool isToken() const { return Kind == k_Token; } 300 bool isMem() const { return Kind == k_Memory; } 301 302 StringRef getToken() const { 303 assert(Kind == k_Token && "Invalid access!"); 304 return StringRef(Tok.Data, Tok.Length); 305 } 306 307 unsigned getReg() const { 308 assert((Kind == k_Register) && "Invalid access!"); 309 return Reg.RegNum; 310 } 311 312 void setRegKind(RegisterKind RegKind) { 313 assert((Kind == k_Register) && "Invalid access!"); 314 Reg.Kind = RegKind; 315 } 316 317 const MCExpr *getImm() const { 318 assert((Kind == k_Immediate) && "Invalid access!"); 319 return Imm.Val; 320 } 321 322 unsigned getMemBase() const { 323 assert((Kind == k_Memory) && "Invalid access!"); 324 return Mem.Base; 325 } 326 327 const MCExpr *getMemOff() const { 328 assert((Kind == k_Memory) && "Invalid access!"); 329 return Mem.Off; 330 } 331 332 static MipsOperand *CreateToken(StringRef Str, SMLoc S) { 333 MipsOperand *Op = new MipsOperand(k_Token); 334 Op->Tok.Data = Str.data(); 335 Op->Tok.Length = Str.size(); 336 Op->StartLoc = S; 337 Op->EndLoc = S; 338 return Op; 339 } 340 341 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { 342 MipsOperand *Op = new MipsOperand(k_Register); 343 Op->Reg.RegNum = RegNum; 344 Op->StartLoc = S; 345 Op->EndLoc = E; 346 return Op; 347 } 348 349 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { 350 MipsOperand *Op = new MipsOperand(k_Immediate); 351 Op->Imm.Val = Val; 352 Op->StartLoc = S; 353 Op->EndLoc = E; 354 return Op; 355 } 356 357 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, 358 SMLoc S, SMLoc E) { 359 MipsOperand *Op = new MipsOperand(k_Memory); 360 Op->Mem.Base = Base; 361 Op->Mem.Off = Off; 362 Op->StartLoc = S; 363 Op->EndLoc = E; 364 return Op; 365 } 366 367 bool isCPURegsAsm() const { 368 return Kind == k_Register && Reg.Kind == Kind_CPURegs; 369 } 370 void addRegAsmOperands(MCInst &Inst, unsigned N) const { 371 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum)); 372 } 373 374 bool isCPU64RegsAsm() const { 375 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs; 376 } 377 378 bool isHWRegsAsm() const { 379 assert((Kind == k_Register) && "Invalid access!"); 380 return Reg.Kind == Kind_HWRegs; 381 } 382 383 bool isHW64RegsAsm() const { 384 assert((Kind == k_Register) && "Invalid access!"); 385 return Reg.Kind == Kind_HW64Regs; 386 } 387 388 bool isCCRAsm() const { 389 assert((Kind == k_Register) && "Invalid access!"); 390 return Reg.Kind == Kind_CCRRegs; 391 } 392 393 bool isAFGR64Asm() const { 394 return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs; 395 } 396 397 bool isFGR64Asm() const { 398 return Kind == k_Register && Reg.Kind == Kind_FGR64Regs; 399 } 400 401 bool isFGR32Asm() const { 402 return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs; 403 } 404 405 /// getStartLoc - Get the location of the first token of this operand. 406 SMLoc getStartLoc() const { 407 return StartLoc; 408 } 409 /// getEndLoc - Get the location of the last token of this operand. 410 SMLoc getEndLoc() const { 411 return EndLoc; 412 } 413 414 virtual void print(raw_ostream &OS) const { 415 llvm_unreachable("unimplemented!"); 416 } 417}; // class MipsOperand 418} // namespace 419 420namespace llvm { 421extern const MCInstrDesc MipsInsts[]; 422} 423static const MCInstrDesc &getInstDesc(unsigned Opcode) { 424 return MipsInsts[Opcode]; 425} 426 427bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 428 SmallVectorImpl<MCInst> &Instructions) { 429 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); 430 Inst.setLoc(IDLoc); 431 if (MCID.hasDelaySlot() && Options.isReorder()) { 432 // If this instruction has a delay slot and .set reorder is active, 433 // emit a NOP after it. 434 Instructions.push_back(Inst); 435 MCInst NopInst; 436 NopInst.setOpcode(Mips::SLL); 437 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); 438 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); 439 NopInst.addOperand(MCOperand::CreateImm(0)); 440 Instructions.push_back(NopInst); 441 return false; 442 } 443 444 if (MCID.mayLoad() || MCID.mayStore()) { 445 // Check the offset of memory operand, if it is a symbol 446 // reference or immediate we may have to expand instructions. 447 for (unsigned i = 0; i < MCID.getNumOperands(); i++) { 448 const MCOperandInfo &OpInfo = MCID.OpInfo[i]; 449 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) 450 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { 451 MCOperand &Op = Inst.getOperand(i); 452 if (Op.isImm()) { 453 int MemOffset = Op.getImm(); 454 if (MemOffset < -32768 || MemOffset > 32767) { 455 // Offset can't exceed 16bit value. 456 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true); 457 return false; 458 } 459 } else if (Op.isExpr()) { 460 const MCExpr *Expr = Op.getExpr(); 461 if (Expr->getKind() == MCExpr::SymbolRef) { 462 const MCSymbolRefExpr *SR = 463 static_cast<const MCSymbolRefExpr*>(Expr); 464 if (SR->getKind() == MCSymbolRefExpr::VK_None) { 465 // Expand symbol. 466 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); 467 return false; 468 } 469 } else if (!isEvaluated(Expr)) { 470 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); 471 return false; 472 } 473 } 474 } 475 } // for 476 } // if load/store 477 478 if (needsExpansion(Inst)) 479 expandInstruction(Inst, IDLoc, Instructions); 480 else 481 Instructions.push_back(Inst); 482 483 return false; 484} 485 486bool MipsAsmParser::needsExpansion(MCInst &Inst) { 487 488 switch (Inst.getOpcode()) { 489 case Mips::LoadImm32Reg: 490 case Mips::LoadAddr32Imm: 491 case Mips::LoadAddr32Reg: 492 return true; 493 default: 494 return false; 495 } 496} 497 498void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, 499 SmallVectorImpl<MCInst> &Instructions) { 500 switch (Inst.getOpcode()) { 501 case Mips::LoadImm32Reg: 502 return expandLoadImm(Inst, IDLoc, Instructions); 503 case Mips::LoadAddr32Imm: 504 return expandLoadAddressImm(Inst, IDLoc, Instructions); 505 case Mips::LoadAddr32Reg: 506 return expandLoadAddressReg(Inst, IDLoc, Instructions); 507 } 508} 509 510void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, 511 SmallVectorImpl<MCInst> &Instructions) { 512 MCInst tmpInst; 513 const MCOperand &ImmOp = Inst.getOperand(1); 514 assert(ImmOp.isImm() && "expected immediate operand kind"); 515 const MCOperand &RegOp = Inst.getOperand(0); 516 assert(RegOp.isReg() && "expected register operand kind"); 517 518 int ImmValue = ImmOp.getImm(); 519 tmpInst.setLoc(IDLoc); 520 if (0 <= ImmValue && ImmValue <= 65535) { 521 // For 0 <= j <= 65535. 522 // li d,j => ori d,$zero,j 523 tmpInst.setOpcode(Mips::ORi); 524 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); 525 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); 526 tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); 527 Instructions.push_back(tmpInst); 528 } else if (ImmValue < 0 && ImmValue >= -32768) { 529 // For -32768 <= j < 0. 530 // li d,j => addiu d,$zero,j 531 tmpInst.setOpcode(Mips::ADDiu); 532 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); 533 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); 534 tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); 535 Instructions.push_back(tmpInst); 536 } else { 537 // For any other value of j that is representable as a 32-bit integer. 538 // li d,j => lui d,hi16(j) 539 // ori d,d,lo16(j) 540 tmpInst.setOpcode(Mips::LUi); 541 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); 542 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); 543 Instructions.push_back(tmpInst); 544 tmpInst.clear(); 545 tmpInst.setOpcode(Mips::ORi); 546 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); 547 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); 548 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff)); 549 tmpInst.setLoc(IDLoc); 550 Instructions.push_back(tmpInst); 551 } 552} 553 554void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, 555 SmallVectorImpl<MCInst> &Instructions) { 556 MCInst tmpInst; 557 const MCOperand &ImmOp = Inst.getOperand(2); 558 assert(ImmOp.isImm() && "expected immediate operand kind"); 559 const MCOperand &SrcRegOp = Inst.getOperand(1); 560 assert(SrcRegOp.isReg() && "expected register operand kind"); 561 const MCOperand &DstRegOp = Inst.getOperand(0); 562 assert(DstRegOp.isReg() && "expected register operand kind"); 563 int ImmValue = ImmOp.getImm(); 564 if (-32768 <= ImmValue && ImmValue <= 65535) { 565 // For -32768 <= j <= 65535. 566 // la d,j(s) => addiu d,s,j 567 tmpInst.setOpcode(Mips::ADDiu); 568 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); 569 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg())); 570 tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); 571 Instructions.push_back(tmpInst); 572 } else { 573 // For any other value of j that is representable as a 32-bit integer. 574 // la d,j(s) => lui d,hi16(j) 575 // ori d,d,lo16(j) 576 // addu d,d,s 577 tmpInst.setOpcode(Mips::LUi); 578 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); 579 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); 580 Instructions.push_back(tmpInst); 581 tmpInst.clear(); 582 tmpInst.setOpcode(Mips::ORi); 583 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); 584 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); 585 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff)); 586 Instructions.push_back(tmpInst); 587 tmpInst.clear(); 588 tmpInst.setOpcode(Mips::ADDu); 589 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); 590 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); 591 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg())); 592 Instructions.push_back(tmpInst); 593 } 594} 595 596void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, 597 SmallVectorImpl<MCInst> &Instructions) { 598 MCInst tmpInst; 599 const MCOperand &ImmOp = Inst.getOperand(1); 600 assert(ImmOp.isImm() && "expected immediate operand kind"); 601 const MCOperand &RegOp = Inst.getOperand(0); 602 assert(RegOp.isReg() && "expected register operand kind"); 603 int ImmValue = ImmOp.getImm(); 604 if (-32768 <= ImmValue && ImmValue <= 65535) { 605 // For -32768 <= j <= 65535. 606 // la d,j => addiu d,$zero,j 607 tmpInst.setOpcode(Mips::ADDiu); 608 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); 609 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); 610 tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); 611 Instructions.push_back(tmpInst); 612 } else { 613 // For any other value of j that is representable as a 32-bit integer. 614 // la d,j => lui d,hi16(j) 615 // ori d,d,lo16(j) 616 tmpInst.setOpcode(Mips::LUi); 617 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); 618 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); 619 Instructions.push_back(tmpInst); 620 tmpInst.clear(); 621 tmpInst.setOpcode(Mips::ORi); 622 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); 623 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); 624 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff)); 625 Instructions.push_back(tmpInst); 626 } 627} 628 629void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, 630 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) { 631 const MCSymbolRefExpr *SR; 632 MCInst TempInst; 633 unsigned ImmOffset, HiOffset, LoOffset; 634 const MCExpr *ExprOffset; 635 unsigned TmpRegNum; 636 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID 637 : Mips::CPURegsRegClassID, getATReg()); 638 // 1st operand is either the source or destination register. 639 assert(Inst.getOperand(0).isReg() && "expected register operand kind"); 640 unsigned RegOpNum = Inst.getOperand(0).getReg(); 641 // 2nd operand is the base register. 642 assert(Inst.getOperand(1).isReg() && "expected register operand kind"); 643 unsigned BaseRegNum = Inst.getOperand(1).getReg(); 644 // 3rd operand is either an immediate or expression. 645 if (isImmOpnd) { 646 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind"); 647 ImmOffset = Inst.getOperand(2).getImm(); 648 LoOffset = ImmOffset & 0x0000ffff; 649 HiOffset = (ImmOffset & 0xffff0000) >> 16; 650 // If msb of LoOffset is 1(negative number) we must increment HiOffset. 651 if (LoOffset & 0x8000) 652 HiOffset++; 653 } else 654 ExprOffset = Inst.getOperand(2).getExpr(); 655 // All instructions will have the same location. 656 TempInst.setLoc(IDLoc); 657 // 1st instruction in expansion is LUi. For load instruction we can use 658 // the dst register as a temporary if base and dst are different, 659 // but for stores we must use $at. 660 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum; 661 TempInst.setOpcode(Mips::LUi); 662 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); 663 if (isImmOpnd) 664 TempInst.addOperand(MCOperand::CreateImm(HiOffset)); 665 else { 666 if (ExprOffset->getKind() == MCExpr::SymbolRef) { 667 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset); 668 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create( 669 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI, 670 getContext()); 671 TempInst.addOperand(MCOperand::CreateExpr(HiExpr)); 672 } else { 673 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi"); 674 TempInst.addOperand(MCOperand::CreateExpr(HiExpr)); 675 } 676 } 677 // Add the instruction to the list. 678 Instructions.push_back(TempInst); 679 // Prepare TempInst for next instruction. 680 TempInst.clear(); 681 // Add temp register to base. 682 TempInst.setOpcode(Mips::ADDu); 683 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); 684 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); 685 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum)); 686 Instructions.push_back(TempInst); 687 TempInst.clear(); 688 // And finaly, create original instruction with low part 689 // of offset and new base. 690 TempInst.setOpcode(Inst.getOpcode()); 691 TempInst.addOperand(MCOperand::CreateReg(RegOpNum)); 692 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); 693 if (isImmOpnd) 694 TempInst.addOperand(MCOperand::CreateImm(LoOffset)); 695 else { 696 if (ExprOffset->getKind() == MCExpr::SymbolRef) { 697 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create( 698 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO, 699 getContext()); 700 TempInst.addOperand(MCOperand::CreateExpr(LoExpr)); 701 } else { 702 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo"); 703 TempInst.addOperand(MCOperand::CreateExpr(LoExpr)); 704 } 705 } 706 Instructions.push_back(TempInst); 707 TempInst.clear(); 708} 709 710bool MipsAsmParser:: 711MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 712 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 713 MCStreamer &Out, unsigned &ErrorInfo, 714 bool MatchingInlineAsm) { 715 MCInst Inst; 716 SmallVector<MCInst, 8> Instructions; 717 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, 718 MatchingInlineAsm); 719 720 switch (MatchResult) { 721 default: 722 break; 723 case Match_Success: { 724 if (processInstruction(Inst, IDLoc, Instructions)) 725 return true; 726 for (unsigned i = 0; i < Instructions.size(); i++) 727 Out.EmitInstruction(Instructions[i]); 728 return false; 729 } 730 case Match_MissingFeature: 731 Error(IDLoc, "instruction requires a CPU feature not currently enabled"); 732 return true; 733 case Match_InvalidOperand: { 734 SMLoc ErrorLoc = IDLoc; 735 if (ErrorInfo != ~0U) { 736 if (ErrorInfo >= Operands.size()) 737 return Error(IDLoc, "too few operands for instruction"); 738 739 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc(); 740 if (ErrorLoc == SMLoc()) 741 ErrorLoc = IDLoc; 742 } 743 744 return Error(ErrorLoc, "invalid operand for instruction"); 745 } 746 case Match_MnemonicFail: 747 return Error(IDLoc, "invalid instruction"); 748 } 749 return true; 750} 751 752int MipsAsmParser::matchCPURegisterName(StringRef Name) { 753 int CC; 754 755 if (Name == "at") 756 return getATReg(); 757 758 CC = StringSwitch<unsigned>(Name) 759 .Case("zero", 0) 760 .Case("a0", 4) 761 .Case("a1", 5) 762 .Case("a2", 6) 763 .Case("a3", 7) 764 .Case("v0", 2) 765 .Case("v1", 3) 766 .Case("s0", 16) 767 .Case("s1", 17) 768 .Case("s2", 18) 769 .Case("s3", 19) 770 .Case("s4", 20) 771 .Case("s5", 21) 772 .Case("s6", 22) 773 .Case("s7", 23) 774 .Case("k0", 26) 775 .Case("k1", 27) 776 .Case("sp", 29) 777 .Case("fp", 30) 778 .Case("gp", 28) 779 .Case("ra", 31) 780 .Case("t0", 8) 781 .Case("t1", 9) 782 .Case("t2", 10) 783 .Case("t3", 11) 784 .Case("t4", 12) 785 .Case("t5", 13) 786 .Case("t6", 14) 787 .Case("t7", 15) 788 .Case("t8", 24) 789 .Case("t9", 25) 790 .Default(-1); 791 792 // Although SGI documentation just cuts out t0-t3 for n32/n64, 793 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7 794 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7. 795 if (isMips64() && 8 <= CC && CC <= 11) 796 CC += 4; 797 798 if (CC == -1 && isMips64()) 799 CC = StringSwitch<unsigned>(Name) 800 .Case("a4", 8) 801 .Case("a5", 9) 802 .Case("a6", 10) 803 .Case("a7", 11) 804 .Case("kt0", 26) 805 .Case("kt1", 27) 806 .Case("s8", 30) 807 .Default(-1); 808 809 return CC; 810} 811 812int MipsAsmParser::matchFPURegisterName(StringRef Name, FpFormatTy Format) { 813 814 if (Name[0] == 'f') { 815 StringRef NumString = Name.substr(1); 816 unsigned IntVal; 817 if (NumString.getAsInteger(10, IntVal)) 818 return -1; // This is not an integer. 819 if (IntVal > 31) 820 return -1; 821 822 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W) 823 return getReg(Mips::FGR32RegClassID, IntVal); 824 if (Format == FP_FORMAT_D) { 825 if (isFP64()) { 826 return getReg(Mips::FGR64RegClassID, IntVal); 827 } 828 // Only even numbers available as register pairs. 829 if ((IntVal > 31) || (IntVal % 2 != 0)) 830 return -1; 831 return getReg(Mips::AFGR64RegClassID, IntVal / 2); 832 } 833 } 834 return -1; 835} 836 837int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) { 838 839 if (Name.equals("fcc0")) 840 return Mips::FCC0; 841 842 int CC; 843 CC = matchCPURegisterName(Name); 844 if (CC != -1) 845 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID 846 : Mips::CPURegsRegClassID); 847 return matchFPURegisterName(Name, getFpFormat()); 848} 849 850void MipsAsmParser::setDefaultFpFormat() { 851 852 if (isMips64() || isFP64()) 853 FpFormat = FP_FORMAT_D; 854 else 855 FpFormat = FP_FORMAT_S; 856} 857 858void MipsAsmParser::setFpFormat(StringRef Format) { 859 860 FpFormat = StringSwitch<FpFormatTy>(Format.lower()) 861 .Case(".s", FP_FORMAT_S) 862 .Case(".d", FP_FORMAT_D) 863 .Case(".l", FP_FORMAT_L) 864 .Case(".w", FP_FORMAT_W) 865 .Default(FP_FORMAT_NONE); 866} 867 868bool MipsAssemblerOptions::setATReg(unsigned Reg) { 869 if (Reg > 31) 870 return false; 871 872 aTReg = Reg; 873 return true; 874} 875 876int MipsAsmParser::getATReg() { 877 return Options.getATRegNum(); 878} 879 880unsigned MipsAsmParser::getReg(int RC, int RegNo) { 881 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo); 882} 883 884int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) { 885 886 if (RegNum > 31) 887 return -1; 888 889 return getReg(RegClass, RegNum); 890} 891 892int MipsAsmParser::tryParseRegister(bool is64BitReg) { 893 const AsmToken &Tok = Parser.getTok(); 894 int RegNum = -1; 895 896 if (Tok.is(AsmToken::Identifier)) { 897 std::string lowerCase = Tok.getString().lower(); 898 RegNum = matchRegisterName(lowerCase, is64BitReg); 899 } else if (Tok.is(AsmToken::Integer)) 900 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()), 901 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID); 902 return RegNum; 903} 904 905bool MipsAsmParser::tryParseRegisterOperand( 906 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) { 907 908 SMLoc S = Parser.getTok().getLoc(); 909 int RegNo = -1; 910 911 RegNo = tryParseRegister(is64BitReg); 912 if (RegNo == -1) 913 return true; 914 915 Operands.push_back(MipsOperand::CreateReg(RegNo, S, 916 Parser.getTok().getLoc())); 917 Parser.Lex(); // Eat register token. 918 return false; 919} 920 921bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands, 922 StringRef Mnemonic) { 923 // Check if the current operand has a custom associated parser, if so, try to 924 // custom parse the operand, or fallback to the general approach. 925 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 926 if (ResTy == MatchOperand_Success) 927 return false; 928 // If there wasn't a custom match, try the generic matcher below. Otherwise, 929 // there was a match, but an error occurred, in which case, just return that 930 // the operand parsing failed. 931 if (ResTy == MatchOperand_ParseFail) 932 return true; 933 934 switch (getLexer().getKind()) { 935 default: 936 Error(Parser.getTok().getLoc(), "unexpected token in operand"); 937 return true; 938 case AsmToken::Dollar: { 939 // Parse the register. 940 SMLoc S = Parser.getTok().getLoc(); 941 Parser.Lex(); // Eat dollar token. 942 // Parse the register operand. 943 if (!tryParseRegisterOperand(Operands, isMips64())) { 944 if (getLexer().is(AsmToken::LParen)) { 945 // Check if it is indexed addressing operand. 946 Operands.push_back(MipsOperand::CreateToken("(", S)); 947 Parser.Lex(); // Eat the parenthesis. 948 if (getLexer().isNot(AsmToken::Dollar)) 949 return true; 950 951 Parser.Lex(); // Eat the dollar 952 if (tryParseRegisterOperand(Operands, isMips64())) 953 return true; 954 955 if (!getLexer().is(AsmToken::RParen)) 956 return true; 957 958 S = Parser.getTok().getLoc(); 959 Operands.push_back(MipsOperand::CreateToken(")", S)); 960 Parser.Lex(); 961 } 962 return false; 963 } 964 // Maybe it is a symbol reference. 965 StringRef Identifier; 966 if (Parser.parseIdentifier(Identifier)) 967 return true; 968 969 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 970 971 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier); 972 973 // Otherwise create a symbol reference. 974 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, 975 getContext()); 976 977 Operands.push_back(MipsOperand::CreateImm(Res, S, E)); 978 return false; 979 } 980 case AsmToken::Identifier: 981 // Look for the existing symbol, we should check if 982 // we need to assigne the propper RegisterKind. 983 if (searchSymbolAlias(Operands, MipsOperand::Kind_None)) 984 return false; 985 // Else drop to expression parsing. 986 case AsmToken::LParen: 987 case AsmToken::Minus: 988 case AsmToken::Plus: 989 case AsmToken::Integer: 990 case AsmToken::String: { 991 // Quoted label names. 992 const MCExpr *IdVal; 993 SMLoc S = Parser.getTok().getLoc(); 994 if (getParser().parseExpression(IdVal)) 995 return true; 996 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 997 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); 998 return false; 999 } 1000 case AsmToken::Percent: { 1001 // It is a symbol reference or constant expression. 1002 const MCExpr *IdVal; 1003 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. 1004 if (parseRelocOperand(IdVal)) 1005 return true; 1006 1007 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 1008 1009 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); 1010 return false; 1011 } // case AsmToken::Percent 1012 } // switch(getLexer().getKind()) 1013 return true; 1014} 1015 1016const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, 1017 StringRef RelocStr) { 1018 const MCExpr *Res; 1019 // Check the type of the expression. 1020 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) { 1021 // It's a constant, evaluate lo or hi value. 1022 if (RelocStr == "lo") { 1023 short Val = MCE->getValue(); 1024 Res = MCConstantExpr::Create(Val, getContext()); 1025 } else if (RelocStr == "hi") { 1026 int Val = MCE->getValue(); 1027 int LoSign = Val & 0x8000; 1028 Val = (Val & 0xffff0000) >> 16; 1029 // Lower part is treated as a signed int, so if it is negative 1030 // we must add 1 to the hi part to compensate. 1031 if (LoSign) 1032 Val++; 1033 Res = MCConstantExpr::Create(Val, getContext()); 1034 } else { 1035 llvm_unreachable("Invalid RelocStr value"); 1036 } 1037 return Res; 1038 } 1039 1040 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) { 1041 // It's a symbol, create a symbolic expression from the symbol. 1042 StringRef Symbol = MSRE->getSymbol().getName(); 1043 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr); 1044 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext()); 1045 return Res; 1046 } 1047 1048 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { 1049 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr); 1050 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr); 1051 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext()); 1052 return Res; 1053 } 1054 1055 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) { 1056 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr); 1057 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext()); 1058 return Res; 1059 } 1060 // Just return the original expression. 1061 return Expr; 1062} 1063 1064bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { 1065 1066 switch (Expr->getKind()) { 1067 case MCExpr::Constant: 1068 return true; 1069 case MCExpr::SymbolRef: 1070 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None); 1071 case MCExpr::Binary: 1072 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { 1073 if (!isEvaluated(BE->getLHS())) 1074 return false; 1075 return isEvaluated(BE->getRHS()); 1076 } 1077 case MCExpr::Unary: 1078 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr()); 1079 default: 1080 return false; 1081 } 1082 return false; 1083} 1084 1085bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { 1086 Parser.Lex(); // Eat the % token. 1087 const AsmToken &Tok = Parser.getTok(); // Get next token, operation. 1088 if (Tok.isNot(AsmToken::Identifier)) 1089 return true; 1090 1091 std::string Str = Tok.getIdentifier().str(); 1092 1093 Parser.Lex(); // Eat the identifier. 1094 // Now make an expression from the rest of the operand. 1095 const MCExpr *IdVal; 1096 SMLoc EndLoc; 1097 1098 if (getLexer().getKind() == AsmToken::LParen) { 1099 while (1) { 1100 Parser.Lex(); // Eat the '(' token. 1101 if (getLexer().getKind() == AsmToken::Percent) { 1102 Parser.Lex(); // Eat the % token. 1103 const AsmToken &nextTok = Parser.getTok(); 1104 if (nextTok.isNot(AsmToken::Identifier)) 1105 return true; 1106 Str += "(%"; 1107 Str += nextTok.getIdentifier(); 1108 Parser.Lex(); // Eat the identifier. 1109 if (getLexer().getKind() != AsmToken::LParen) 1110 return true; 1111 } else 1112 break; 1113 } 1114 if (getParser().parseParenExpression(IdVal, EndLoc)) 1115 return true; 1116 1117 while (getLexer().getKind() == AsmToken::RParen) 1118 Parser.Lex(); // Eat the ')' token. 1119 1120 } else 1121 return true; // Parenthesis must follow the relocation operand. 1122 1123 Res = evaluateRelocExpr(IdVal, Str); 1124 return false; 1125} 1126 1127bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 1128 SMLoc &EndLoc) { 1129 StartLoc = Parser.getTok().getLoc(); 1130 RegNo = tryParseRegister(isMips64()); 1131 EndLoc = Parser.getTok().getLoc(); 1132 return (RegNo == (unsigned) -1); 1133} 1134 1135bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { 1136 SMLoc S; 1137 bool Result = true; 1138 1139 while (getLexer().getKind() == AsmToken::LParen) 1140 Parser.Lex(); 1141 1142 switch (getLexer().getKind()) { 1143 default: 1144 return true; 1145 case AsmToken::Identifier: 1146 case AsmToken::LParen: 1147 case AsmToken::Integer: 1148 case AsmToken::Minus: 1149 case AsmToken::Plus: 1150 if (isParenExpr) 1151 Result = getParser().parseParenExpression(Res, S); 1152 else 1153 Result = (getParser().parseExpression(Res)); 1154 while (getLexer().getKind() == AsmToken::RParen) 1155 Parser.Lex(); 1156 break; 1157 case AsmToken::Percent: 1158 Result = parseRelocOperand(Res); 1159 } 1160 return Result; 1161} 1162 1163MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand( 1164 SmallVectorImpl<MCParsedAsmOperand*>&Operands) { 1165 1166 const MCExpr *IdVal = 0; 1167 SMLoc S; 1168 bool isParenExpr = false; 1169 // First operand is the offset. 1170 S = Parser.getTok().getLoc(); 1171 1172 if (getLexer().getKind() == AsmToken::LParen) { 1173 Parser.Lex(); 1174 isParenExpr = true; 1175 } 1176 1177 if (getLexer().getKind() != AsmToken::Dollar) { 1178 if (parseMemOffset(IdVal, isParenExpr)) 1179 return MatchOperand_ParseFail; 1180 1181 const AsmToken &Tok = Parser.getTok(); // Get the next token. 1182 if (Tok.isNot(AsmToken::LParen)) { 1183 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]); 1184 if (Mnemonic->getToken() == "la") { 1185 SMLoc E = SMLoc::getFromPointer( 1186 Parser.getTok().getLoc().getPointer() - 1); 1187 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E)); 1188 return MatchOperand_Success; 1189 } 1190 if (Tok.is(AsmToken::EndOfStatement)) { 1191 SMLoc E = SMLoc::getFromPointer( 1192 Parser.getTok().getLoc().getPointer() - 1); 1193 1194 // Zero register assumed, add a memory operand with ZERO as its base. 1195 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64 1196 : Mips::ZERO, 1197 IdVal, S, E)); 1198 return MatchOperand_Success; 1199 } 1200 Error(Parser.getTok().getLoc(), "'(' expected"); 1201 return MatchOperand_ParseFail; 1202 } 1203 1204 Parser.Lex(); // Eat the '(' token. 1205 } 1206 1207 const AsmToken &Tok1 = Parser.getTok(); // Get next token 1208 if (Tok1.is(AsmToken::Dollar)) { 1209 Parser.Lex(); // Eat the '$' token. 1210 if (tryParseRegisterOperand(Operands, isMips64())) { 1211 Error(Parser.getTok().getLoc(), "unexpected token in operand"); 1212 return MatchOperand_ParseFail; 1213 } 1214 1215 } else { 1216 Error(Parser.getTok().getLoc(), "unexpected token in operand"); 1217 return MatchOperand_ParseFail; 1218 } 1219 1220 const AsmToken &Tok2 = Parser.getTok(); // Get next token. 1221 if (Tok2.isNot(AsmToken::RParen)) { 1222 Error(Parser.getTok().getLoc(), "')' expected"); 1223 return MatchOperand_ParseFail; 1224 } 1225 1226 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 1227 1228 Parser.Lex(); // Eat the ')' token. 1229 1230 if (IdVal == 0) 1231 IdVal = MCConstantExpr::Create(0, getContext()); 1232 1233 // Replace the register operand with the memory operand. 1234 MipsOperand* op = static_cast<MipsOperand*>(Operands.back()); 1235 int RegNo = op->getReg(); 1236 // Remove the register from the operands. 1237 Operands.pop_back(); 1238 // Add the memory operand. 1239 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) { 1240 int64_t Imm; 1241 if (IdVal->EvaluateAsAbsolute(Imm)) 1242 IdVal = MCConstantExpr::Create(Imm, getContext()); 1243 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef) 1244 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(), 1245 getContext()); 1246 } 1247 1248 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E)); 1249 delete op; 1250 return MatchOperand_Success; 1251} 1252 1253MipsAsmParser::OperandMatchResultTy 1254MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands, 1255 int RegKind) { 1256 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind; 1257 if (getLexer().getKind() == AsmToken::Identifier) { 1258 if (searchSymbolAlias(Operands, Kind)) 1259 return MatchOperand_Success; 1260 return MatchOperand_NoMatch; 1261 } 1262 // If the first token is not '$', we have an error. 1263 if (Parser.getTok().isNot(AsmToken::Dollar)) 1264 return MatchOperand_NoMatch; 1265 1266 Parser.Lex(); // Eat $ 1267 if (!tryParseRegisterOperand(Operands, isMips64())) { 1268 // Set the proper register kind. 1269 MipsOperand* op = static_cast<MipsOperand*>(Operands.back()); 1270 op->setRegKind(Kind); 1271 return MatchOperand_Success; 1272 } 1273 return MatchOperand_NoMatch; 1274} 1275 1276MipsAsmParser::OperandMatchResultTy 1277MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1278 1279 if (!isMips64()) 1280 return MatchOperand_NoMatch; 1281 return parseRegs(Operands, (int) MipsOperand::Kind_CPU64Regs); 1282} 1283 1284MipsAsmParser::OperandMatchResultTy 1285MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1286 return parseRegs(Operands, (int) MipsOperand::Kind_CPURegs); 1287} 1288 1289MipsAsmParser::OperandMatchResultTy 1290MipsAsmParser::parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1291 1292 if (isFP64()) 1293 return MatchOperand_NoMatch; 1294 // Double operand is expected, set appropriate format 1295 setFpFormat(FP_FORMAT_D); 1296 1297 return parseRegs(Operands, (int) MipsOperand::Kind_AFGR64Regs); 1298} 1299 1300MipsAsmParser::OperandMatchResultTy 1301MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1302 if (!isFP64()) 1303 return MatchOperand_NoMatch; 1304 // Double operand is expected, set appropriate format 1305 setFpFormat(FP_FORMAT_D); 1306 1307 return parseRegs(Operands, (int) MipsOperand::Kind_FGR64Regs); 1308} 1309 1310MipsAsmParser::OperandMatchResultTy 1311MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1312 // Single operand is expected, set appropriate format 1313 setFpFormat(FP_FORMAT_S); 1314 return parseRegs(Operands, (int) MipsOperand::Kind_FGR32Regs); 1315} 1316 1317bool MipsAsmParser::searchSymbolAlias( 1318 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind) { 1319 1320 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier()); 1321 if (Sym) { 1322 SMLoc S = Parser.getTok().getLoc(); 1323 const MCExpr *Expr; 1324 if (Sym->isVariable()) 1325 Expr = Sym->getVariableValue(); 1326 else 1327 return false; 1328 if (Expr->getKind() == MCExpr::SymbolRef) { 1329 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind) RegKind; 1330 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr); 1331 const StringRef DefSymbol = Ref->getSymbol().getName(); 1332 if (DefSymbol.startswith("$")) { 1333 int RegNum = -1; 1334 APInt IntVal(32, -1); 1335 if (!DefSymbol.substr(1).getAsInteger(10, IntVal)) 1336 RegNum = matchRegisterByNumber(IntVal.getZExtValue(), 1337 isMips64() 1338 ? Mips::CPU64RegsRegClassID 1339 : Mips::CPURegsRegClassID); 1340 else { 1341 // Lookup for the register with the corresponding name. 1342 switch (Kind) { 1343 case MipsOperand::Kind_AFGR64Regs: 1344 case MipsOperand::Kind_FGR64Regs: 1345 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_D); 1346 break; 1347 case MipsOperand::Kind_FGR32Regs: 1348 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_S); 1349 break; 1350 case MipsOperand::Kind_CPU64Regs: 1351 case MipsOperand::Kind_CPURegs: 1352 default: 1353 RegNum = matchRegisterName(DefSymbol.substr(1), isMips64()); 1354 break; 1355 } 1356 } 1357 if (RegNum > -1) { 1358 Parser.Lex(); 1359 MipsOperand *op = MipsOperand::CreateReg(RegNum, S, 1360 Parser.getTok().getLoc()); 1361 op->setRegKind(Kind); 1362 Operands.push_back(op); 1363 return true; 1364 } 1365 } 1366 } else if (Expr->getKind() == MCExpr::Constant) { 1367 Parser.Lex(); 1368 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr); 1369 MipsOperand *op = MipsOperand::CreateImm(Const, S, 1370 Parser.getTok().getLoc()); 1371 Operands.push_back(op); 1372 return true; 1373 } 1374 } 1375 return false; 1376} 1377 1378MipsAsmParser::OperandMatchResultTy 1379MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1380 1381 if (isMips64()) 1382 return MatchOperand_NoMatch; 1383 1384 // If the first token is not '$' we have error. 1385 if (Parser.getTok().isNot(AsmToken::Dollar)) 1386 return MatchOperand_NoMatch; 1387 SMLoc S = Parser.getTok().getLoc(); 1388 Parser.Lex(); // Eat the '$'. 1389 1390 const AsmToken &Tok = Parser.getTok(); // Get the next token. 1391 if (Tok.isNot(AsmToken::Integer)) 1392 return MatchOperand_NoMatch; 1393 1394 unsigned RegNum = Tok.getIntVal(); 1395 // At the moment only hwreg29 is supported. 1396 if (RegNum != 29) 1397 return MatchOperand_ParseFail; 1398 1399 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S, 1400 Parser.getTok().getLoc()); 1401 op->setRegKind(MipsOperand::Kind_HWRegs); 1402 Operands.push_back(op); 1403 1404 Parser.Lex(); // Eat the register number. 1405 return MatchOperand_Success; 1406} 1407 1408MipsAsmParser::OperandMatchResultTy 1409MipsAsmParser::parseHW64Regs( 1410 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1411 1412 if (!isMips64()) 1413 return MatchOperand_NoMatch; 1414 // If the first token is not '$' we have an error. 1415 if (Parser.getTok().isNot(AsmToken::Dollar)) 1416 return MatchOperand_NoMatch; 1417 SMLoc S = Parser.getTok().getLoc(); 1418 Parser.Lex(); // Eat $ 1419 1420 const AsmToken &Tok = Parser.getTok(); // Get the next token. 1421 if (Tok.isNot(AsmToken::Integer)) 1422 return MatchOperand_NoMatch; 1423 1424 unsigned RegNum = Tok.getIntVal(); 1425 // At the moment only hwreg29 is supported. 1426 if (RegNum != 29) 1427 return MatchOperand_ParseFail; 1428 1429 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S, 1430 Parser.getTok().getLoc()); 1431 op->setRegKind(MipsOperand::Kind_HW64Regs); 1432 Operands.push_back(op); 1433 1434 Parser.Lex(); // Eat the register number. 1435 return MatchOperand_Success; 1436} 1437 1438MipsAsmParser::OperandMatchResultTy 1439MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1440 unsigned RegNum; 1441 // If the first token is not '$' we have an error. 1442 if (Parser.getTok().isNot(AsmToken::Dollar)) 1443 return MatchOperand_NoMatch; 1444 SMLoc S = Parser.getTok().getLoc(); 1445 Parser.Lex(); // Eat the '$' 1446 1447 const AsmToken &Tok = Parser.getTok(); // Get next token. 1448 if (Tok.is(AsmToken::Integer)) { 1449 RegNum = Tok.getIntVal(); 1450 // At the moment only fcc0 is supported. 1451 if (RegNum != 0) 1452 return MatchOperand_ParseFail; 1453 } else if (Tok.is(AsmToken::Identifier)) { 1454 // At the moment only fcc0 is supported. 1455 if (Tok.getIdentifier() != "fcc0") 1456 return MatchOperand_ParseFail; 1457 } else 1458 return MatchOperand_NoMatch; 1459 1460 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S, 1461 Parser.getTok().getLoc()); 1462 op->setRegKind(MipsOperand::Kind_CCRRegs); 1463 Operands.push_back(op); 1464 1465 Parser.Lex(); // Eat the register number. 1466 return MatchOperand_Success; 1467} 1468 1469MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { 1470 1471 MCSymbolRefExpr::VariantKind VK 1472 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol) 1473 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI) 1474 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO) 1475 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL) 1476 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL) 1477 .Case("got", MCSymbolRefExpr::VK_Mips_GOT) 1478 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD) 1479 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM) 1480 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI) 1481 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO) 1482 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL) 1483 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI) 1484 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO) 1485 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP) 1486 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE) 1487 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST) 1488 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI) 1489 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO) 1490 .Default(MCSymbolRefExpr::VK_None); 1491 1492 return VK; 1493} 1494 1495bool MipsAsmParser:: 1496ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, 1497 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 1498 // Check if we have valid mnemonic 1499 if (!mnemonicIsValid(Name)) { 1500 Parser.eatToEndOfStatement(); 1501 return Error(NameLoc, "Unknown instruction"); 1502 } 1503 // First operand in MCInst is instruction mnemonic. 1504 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc)); 1505 1506 // Read the remaining operands. 1507 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1508 // Read the first operand. 1509 if (ParseOperand(Operands, Name)) { 1510 SMLoc Loc = getLexer().getLoc(); 1511 Parser.eatToEndOfStatement(); 1512 return Error(Loc, "unexpected token in argument list"); 1513 } 1514 1515 while (getLexer().is(AsmToken::Comma)) { 1516 Parser.Lex(); // Eat the comma. 1517 // Parse and remember the operand. 1518 if (ParseOperand(Operands, Name)) { 1519 SMLoc Loc = getLexer().getLoc(); 1520 Parser.eatToEndOfStatement(); 1521 return Error(Loc, "unexpected token in argument list"); 1522 } 1523 } 1524 } 1525 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1526 SMLoc Loc = getLexer().getLoc(); 1527 Parser.eatToEndOfStatement(); 1528 return Error(Loc, "unexpected token in argument list"); 1529 } 1530 Parser.Lex(); // Consume the EndOfStatement. 1531 return false; 1532} 1533 1534bool MipsAsmParser::reportParseError(StringRef ErrorMsg) { 1535 SMLoc Loc = getLexer().getLoc(); 1536 Parser.eatToEndOfStatement(); 1537 return Error(Loc, ErrorMsg); 1538} 1539 1540bool MipsAsmParser::parseSetNoAtDirective() { 1541 // Line should look like: ".set noat". 1542 // set at reg to 0. 1543 Options.setATReg(0); 1544 // eat noat 1545 Parser.Lex(); 1546 // If this is not the end of the statement, report an error. 1547 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1548 reportParseError("unexpected token in statement"); 1549 return false; 1550 } 1551 Parser.Lex(); // Consume the EndOfStatement. 1552 return false; 1553} 1554 1555bool MipsAsmParser::parseSetAtDirective() { 1556 // Line can be .set at - defaults to $1 1557 // or .set at=$reg 1558 int AtRegNo; 1559 getParser().Lex(); 1560 if (getLexer().is(AsmToken::EndOfStatement)) { 1561 Options.setATReg(1); 1562 Parser.Lex(); // Consume the EndOfStatement. 1563 return false; 1564 } else if (getLexer().is(AsmToken::Equal)) { 1565 getParser().Lex(); // Eat the '='. 1566 if (getLexer().isNot(AsmToken::Dollar)) { 1567 reportParseError("unexpected token in statement"); 1568 return false; 1569 } 1570 Parser.Lex(); // Eat the '$'. 1571 const AsmToken &Reg = Parser.getTok(); 1572 if (Reg.is(AsmToken::Identifier)) { 1573 AtRegNo = matchCPURegisterName(Reg.getIdentifier()); 1574 } else if (Reg.is(AsmToken::Integer)) { 1575 AtRegNo = Reg.getIntVal(); 1576 } else { 1577 reportParseError("unexpected token in statement"); 1578 return false; 1579 } 1580 1581 if (AtRegNo < 1 || AtRegNo > 31) { 1582 reportParseError("unexpected token in statement"); 1583 return false; 1584 } 1585 1586 if (!Options.setATReg(AtRegNo)) { 1587 reportParseError("unexpected token in statement"); 1588 return false; 1589 } 1590 getParser().Lex(); // Eat the register. 1591 1592 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1593 reportParseError("unexpected token in statement"); 1594 return false; 1595 } 1596 Parser.Lex(); // Consume the EndOfStatement. 1597 return false; 1598 } else { 1599 reportParseError("unexpected token in statement"); 1600 return false; 1601 } 1602} 1603 1604bool MipsAsmParser::parseSetReorderDirective() { 1605 Parser.Lex(); 1606 // If this is not the end of the statement, report an error. 1607 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1608 reportParseError("unexpected token in statement"); 1609 return false; 1610 } 1611 Options.setReorder(); 1612 Parser.Lex(); // Consume the EndOfStatement. 1613 return false; 1614} 1615 1616bool MipsAsmParser::parseSetNoReorderDirective() { 1617 Parser.Lex(); 1618 // If this is not the end of the statement, report an error. 1619 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1620 reportParseError("unexpected token in statement"); 1621 return false; 1622 } 1623 Options.setNoreorder(); 1624 Parser.Lex(); // Consume the EndOfStatement. 1625 return false; 1626} 1627 1628bool MipsAsmParser::parseSetMacroDirective() { 1629 Parser.Lex(); 1630 // If this is not the end of the statement, report an error. 1631 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1632 reportParseError("unexpected token in statement"); 1633 return false; 1634 } 1635 Options.setMacro(); 1636 Parser.Lex(); // Consume the EndOfStatement. 1637 return false; 1638} 1639 1640bool MipsAsmParser::parseSetNoMacroDirective() { 1641 Parser.Lex(); 1642 // If this is not the end of the statement, report an error. 1643 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1644 reportParseError("`noreorder' must be set before `nomacro'"); 1645 return false; 1646 } 1647 if (Options.isReorder()) { 1648 reportParseError("`noreorder' must be set before `nomacro'"); 1649 return false; 1650 } 1651 Options.setNomacro(); 1652 Parser.Lex(); // Consume the EndOfStatement. 1653 return false; 1654} 1655 1656bool MipsAsmParser::parseSetAssignment() { 1657 StringRef Name; 1658 const MCExpr *Value; 1659 1660 if (Parser.parseIdentifier(Name)) 1661 reportParseError("expected identifier after .set"); 1662 1663 if (getLexer().isNot(AsmToken::Comma)) 1664 return reportParseError("unexpected token in .set directive"); 1665 Lex(); // Eat comma 1666 1667 if (getLexer().is(AsmToken::Dollar)) { 1668 MCSymbol *Symbol; 1669 SMLoc DollarLoc = getLexer().getLoc(); 1670 // Consume the dollar sign, and check for a following identifier. 1671 Parser.Lex(); 1672 // We have a '$' followed by something, make sure they are adjacent. 1673 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer()) 1674 return true; 1675 StringRef Res = StringRef(DollarLoc.getPointer(), 1676 getTok().getEndLoc().getPointer() - DollarLoc.getPointer()); 1677 Symbol = getContext().GetOrCreateSymbol(Res); 1678 Parser.Lex(); 1679 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, 1680 getContext()); 1681 } else if (Parser.parseExpression(Value)) 1682 return reportParseError("expected valid expression after comma"); 1683 1684 // Check if the Name already exists as a symbol. 1685 MCSymbol *Sym = getContext().LookupSymbol(Name); 1686 if (Sym) 1687 return reportParseError("symbol already defined"); 1688 Sym = getContext().GetOrCreateSymbol(Name); 1689 Sym->setVariableValue(Value); 1690 1691 return false; 1692} 1693 1694bool MipsAsmParser::parseDirectiveSet() { 1695 1696 // Get the next token. 1697 const AsmToken &Tok = Parser.getTok(); 1698 1699 if (Tok.getString() == "noat") { 1700 return parseSetNoAtDirective(); 1701 } else if (Tok.getString() == "at") { 1702 return parseSetAtDirective(); 1703 } else if (Tok.getString() == "reorder") { 1704 return parseSetReorderDirective(); 1705 } else if (Tok.getString() == "noreorder") { 1706 return parseSetNoReorderDirective(); 1707 } else if (Tok.getString() == "macro") { 1708 return parseSetMacroDirective(); 1709 } else if (Tok.getString() == "nomacro") { 1710 return parseSetNoMacroDirective(); 1711 } else if (Tok.getString() == "nomips16") { 1712 // Ignore this directive for now. 1713 Parser.eatToEndOfStatement(); 1714 return false; 1715 } else if (Tok.getString() == "nomicromips") { 1716 // Ignore this directive for now. 1717 Parser.eatToEndOfStatement(); 1718 return false; 1719 } else { 1720 // It is just an identifier, look for an assignment. 1721 parseSetAssignment(); 1722 return false; 1723 } 1724 1725 return true; 1726} 1727 1728/// parseDirectiveWord 1729/// ::= .word [ expression (, expression)* ] 1730bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) { 1731 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1732 for (;;) { 1733 const MCExpr *Value; 1734 if (getParser().parseExpression(Value)) 1735 return true; 1736 1737 getParser().getStreamer().EmitValue(Value, Size); 1738 1739 if (getLexer().is(AsmToken::EndOfStatement)) 1740 break; 1741 1742 // FIXME: Improve diagnostic. 1743 if (getLexer().isNot(AsmToken::Comma)) 1744 return Error(L, "unexpected token in directive"); 1745 Parser.Lex(); 1746 } 1747 } 1748 1749 Parser.Lex(); 1750 return false; 1751} 1752 1753bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { 1754 1755 StringRef IDVal = DirectiveID.getString(); 1756 1757 if (IDVal == ".ent") { 1758 // Ignore this directive for now. 1759 Parser.Lex(); 1760 return false; 1761 } 1762 1763 if (IDVal == ".end") { 1764 // Ignore this directive for now. 1765 Parser.Lex(); 1766 return false; 1767 } 1768 1769 if (IDVal == ".frame") { 1770 // Ignore this directive for now. 1771 Parser.eatToEndOfStatement(); 1772 return false; 1773 } 1774 1775 if (IDVal == ".set") { 1776 return parseDirectiveSet(); 1777 } 1778 1779 if (IDVal == ".fmask") { 1780 // Ignore this directive for now. 1781 Parser.eatToEndOfStatement(); 1782 return false; 1783 } 1784 1785 if (IDVal == ".mask") { 1786 // Ignore this directive for now. 1787 Parser.eatToEndOfStatement(); 1788 return false; 1789 } 1790 1791 if (IDVal == ".gpword") { 1792 // Ignore this directive for now. 1793 Parser.eatToEndOfStatement(); 1794 return false; 1795 } 1796 1797 if (IDVal == ".word") { 1798 parseDirectiveWord(4, DirectiveID.getLoc()); 1799 return false; 1800 } 1801 1802 return true; 1803} 1804 1805extern "C" void LLVMInitializeMipsAsmParser() { 1806 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget); 1807 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget); 1808 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target); 1809 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget); 1810} 1811 1812#define GET_REGISTER_MATCHER 1813#define GET_MATCHER_IMPLEMENTATION 1814#include "MipsGenAsmMatcher.inc" 1815