1 //===-- MBlazeAsmParser.cpp - Parse MBlaze asm 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/MBlazeBaseInfo.h" 11 #include "llvm/MC/MCParser/MCAsmLexer.h" 12 #include "llvm/MC/MCParser/MCAsmParser.h" 13 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 14 #include "llvm/MC/MCStreamer.h" 15 #include "llvm/MC/MCExpr.h" 16 #include "llvm/MC/MCInst.h" 17 #include "llvm/MC/MCTargetAsmParser.h" 18 #include "llvm/Support/SourceMgr.h" 19 #include "llvm/Support/TargetRegistry.h" 20 #include "llvm/Support/raw_ostream.h" 21 #include "llvm/ADT/SmallVector.h" 22 #include "llvm/ADT/Twine.h" 23 using namespace llvm; 24 25 namespace { 26 struct MBlazeOperand; 27 28 class MBlazeAsmParser : public MCTargetAsmParser { 29 MCAsmParser &Parser; 30 31 MCAsmParser &getParser() const { return Parser; } 32 MCAsmLexer &getLexer() const { return Parser.getLexer(); } 33 34 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); } 35 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } 36 37 MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 38 MBlazeOperand *ParseRegister(unsigned &RegNo); 39 MBlazeOperand *ParseImmediate(); 40 MBlazeOperand *ParseFsl(); 41 MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); 42 43 virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); 44 45 bool ParseDirectiveWord(unsigned Size, SMLoc L); 46 47 bool MatchAndEmitInstruction(SMLoc IDLoc, 48 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 49 MCStreamer &Out); 50 51 /// @name Auto-generated Match Functions 52 /// { 53 54 #define GET_ASSEMBLER_HEADER 55 #include "MBlazeGenAsmMatcher.inc" 56 57 /// } 58 59 unsigned getMCInstOperandNum(unsigned Kind, MCInst &Inst, 60 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, 61 unsigned OperandNum, unsigned &NumMCOperands) { 62 return getMCInstOperandNumImpl(Kind, Inst, Operands, OperandNum, 63 NumMCOperands); 64 } 65 66 public: 67 MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser) 68 : MCTargetAsmParser(), Parser(_Parser) {} 69 70 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, 71 SmallVectorImpl<MCParsedAsmOperand*> &Operands); 72 73 virtual bool ParseDirective(AsmToken DirectiveID); 74 }; 75 76 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine 77 /// instruction. 78 struct MBlazeOperand : public MCParsedAsmOperand { 79 enum KindTy { 80 Token, 81 Immediate, 82 Register, 83 Memory, 84 Fsl 85 } Kind; 86 87 SMLoc StartLoc, EndLoc; 88 89 union { 90 struct { 91 const char *Data; 92 unsigned Length; 93 } Tok; 94 95 struct { 96 unsigned RegNum; 97 } Reg; 98 99 struct { 100 const MCExpr *Val; 101 } Imm; 102 103 struct { 104 unsigned Base; 105 unsigned OffReg; 106 const MCExpr *Off; 107 } Mem; 108 109 struct { 110 const MCExpr *Val; 111 } FslImm; 112 }; 113 114 MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 115 public: 116 MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() { 117 Kind = o.Kind; 118 StartLoc = o.StartLoc; 119 EndLoc = o.EndLoc; 120 switch (Kind) { 121 case Register: 122 Reg = o.Reg; 123 break; 124 case Immediate: 125 Imm = o.Imm; 126 break; 127 case Token: 128 Tok = o.Tok; 129 break; 130 case Memory: 131 Mem = o.Mem; 132 break; 133 case Fsl: 134 FslImm = o.FslImm; 135 break; 136 } 137 } 138 139 /// getStartLoc - Get the location of the first token of this operand. 140 SMLoc getStartLoc() const { return StartLoc; } 141 142 /// getEndLoc - Get the location of the last token of this operand. 143 SMLoc getEndLoc() const { return EndLoc; } 144 145 unsigned getReg() const { 146 assert(Kind == Register && "Invalid access!"); 147 return Reg.RegNum; 148 } 149 150 const MCExpr *getImm() const { 151 assert(Kind == Immediate && "Invalid access!"); 152 return Imm.Val; 153 } 154 155 const MCExpr *getFslImm() const { 156 assert(Kind == Fsl && "Invalid access!"); 157 return FslImm.Val; 158 } 159 160 unsigned getMemBase() const { 161 assert(Kind == Memory && "Invalid access!"); 162 return Mem.Base; 163 } 164 165 const MCExpr* getMemOff() const { 166 assert(Kind == Memory && "Invalid access!"); 167 return Mem.Off; 168 } 169 170 unsigned getMemOffReg() const { 171 assert(Kind == Memory && "Invalid access!"); 172 return Mem.OffReg; 173 } 174 175 bool isToken() const { return Kind == Token; } 176 bool isImm() const { return Kind == Immediate; } 177 bool isMem() const { return Kind == Memory; } 178 bool isFsl() const { return Kind == Fsl; } 179 bool isReg() const { return Kind == Register; } 180 181 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 182 // Add as immediates when possible. Null MCExpr = 0. 183 if (Expr == 0) 184 Inst.addOperand(MCOperand::CreateImm(0)); 185 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 186 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 187 else 188 Inst.addOperand(MCOperand::CreateExpr(Expr)); 189 } 190 191 void addRegOperands(MCInst &Inst, unsigned N) const { 192 assert(N == 1 && "Invalid number of operands!"); 193 Inst.addOperand(MCOperand::CreateReg(getReg())); 194 } 195 196 void addImmOperands(MCInst &Inst, unsigned N) const { 197 assert(N == 1 && "Invalid number of operands!"); 198 addExpr(Inst, getImm()); 199 } 200 201 void addFslOperands(MCInst &Inst, unsigned N) const { 202 assert(N == 1 && "Invalid number of operands!"); 203 addExpr(Inst, getFslImm()); 204 } 205 206 void addMemOperands(MCInst &Inst, unsigned N) const { 207 assert(N == 2 && "Invalid number of operands!"); 208 209 Inst.addOperand(MCOperand::CreateReg(getMemBase())); 210 211 unsigned RegOff = getMemOffReg(); 212 if (RegOff) 213 Inst.addOperand(MCOperand::CreateReg(RegOff)); 214 else 215 addExpr(Inst, getMemOff()); 216 } 217 218 StringRef getToken() const { 219 assert(Kind == Token && "Invalid access!"); 220 return StringRef(Tok.Data, Tok.Length); 221 } 222 223 virtual void print(raw_ostream &OS) const; 224 225 static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) { 226 MBlazeOperand *Op = new MBlazeOperand(Token); 227 Op->Tok.Data = Str.data(); 228 Op->Tok.Length = Str.size(); 229 Op->StartLoc = S; 230 Op->EndLoc = S; 231 return Op; 232 } 233 234 static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) { 235 MBlazeOperand *Op = new MBlazeOperand(Register); 236 Op->Reg.RegNum = RegNum; 237 Op->StartLoc = S; 238 Op->EndLoc = E; 239 return Op; 240 } 241 242 static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) { 243 MBlazeOperand *Op = new MBlazeOperand(Immediate); 244 Op->Imm.Val = Val; 245 Op->StartLoc = S; 246 Op->EndLoc = E; 247 return Op; 248 } 249 250 static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) { 251 MBlazeOperand *Op = new MBlazeOperand(Fsl); 252 Op->Imm.Val = Val; 253 Op->StartLoc = S; 254 Op->EndLoc = E; 255 return Op; 256 } 257 258 static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S, 259 SMLoc E) { 260 MBlazeOperand *Op = new MBlazeOperand(Memory); 261 Op->Mem.Base = Base; 262 Op->Mem.Off = Off; 263 Op->Mem.OffReg = 0; 264 Op->StartLoc = S; 265 Op->EndLoc = E; 266 return Op; 267 } 268 269 static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S, 270 SMLoc E) { 271 MBlazeOperand *Op = new MBlazeOperand(Memory); 272 Op->Mem.Base = Base; 273 Op->Mem.OffReg = Off; 274 Op->Mem.Off = 0; 275 Op->StartLoc = S; 276 Op->EndLoc = E; 277 return Op; 278 } 279 }; 280 281 } // end anonymous namespace. 282 283 void MBlazeOperand::print(raw_ostream &OS) const { 284 switch (Kind) { 285 case Immediate: 286 getImm()->print(OS); 287 break; 288 case Register: 289 OS << "<register R"; 290 OS << getMBlazeRegisterNumbering(getReg()) << ">"; 291 break; 292 case Token: 293 OS << "'" << getToken() << "'"; 294 break; 295 case Memory: { 296 OS << "<memory R"; 297 OS << getMBlazeRegisterNumbering(getMemBase()); 298 OS << ", "; 299 300 unsigned RegOff = getMemOffReg(); 301 if (RegOff) 302 OS << "R" << getMBlazeRegisterNumbering(RegOff); 303 else 304 OS << getMemOff(); 305 OS << ">"; 306 } 307 break; 308 case Fsl: 309 getFslImm()->print(OS); 310 break; 311 } 312 } 313 314 /// @name Auto-generated Match Functions 315 /// { 316 317 static unsigned MatchRegisterName(StringRef Name); 318 319 /// } 320 // 321 bool MBlazeAsmParser:: 322 MatchAndEmitInstruction(SMLoc IDLoc, 323 SmallVectorImpl<MCParsedAsmOperand*> &Operands, 324 MCStreamer &Out) { 325 MCInst Inst; 326 unsigned Kind; 327 unsigned ErrorInfo; 328 329 switch (MatchInstructionImpl(Operands, Kind, Inst, ErrorInfo)) { 330 default: break; 331 case Match_Success: 332 Out.EmitInstruction(Inst); 333 return false; 334 case Match_MissingFeature: 335 return Error(IDLoc, "instruction use requires an option to be enabled"); 336 case Match_MnemonicFail: 337 return Error(IDLoc, "unrecognized instruction mnemonic"); 338 case Match_InvalidOperand: { 339 SMLoc ErrorLoc = IDLoc; 340 if (ErrorInfo != ~0U) { 341 if (ErrorInfo >= Operands.size()) 342 return Error(IDLoc, "too few operands for instruction"); 343 344 ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc(); 345 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; 346 } 347 348 return Error(ErrorLoc, "invalid operand for instruction"); 349 } 350 } 351 352 llvm_unreachable("Implement any new match types added!"); 353 } 354 355 MBlazeOperand *MBlazeAsmParser:: 356 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 357 if (Operands.size() != 4) 358 return 0; 359 360 MBlazeOperand &Base = *(MBlazeOperand*)Operands[2]; 361 MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3]; 362 363 SMLoc S = Base.getStartLoc(); 364 SMLoc O = Offset.getStartLoc(); 365 SMLoc E = Offset.getEndLoc(); 366 367 if (!Base.isReg()) { 368 Error(S, "base address must be a register"); 369 return 0; 370 } 371 372 if (!Offset.isReg() && !Offset.isImm()) { 373 Error(O, "offset must be a register or immediate"); 374 return 0; 375 } 376 377 MBlazeOperand *Op; 378 if (Offset.isReg()) 379 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E); 380 else 381 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E); 382 383 delete Operands.pop_back_val(); 384 delete Operands.pop_back_val(); 385 Operands.push_back(Op); 386 387 return Op; 388 } 389 390 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo, 391 SMLoc &StartLoc, SMLoc &EndLoc) { 392 return (ParseRegister(RegNo) == 0); 393 } 394 395 MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) { 396 SMLoc S = Parser.getTok().getLoc(); 397 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 398 399 switch (getLexer().getKind()) { 400 default: return 0; 401 case AsmToken::Identifier: 402 RegNo = MatchRegisterName(getLexer().getTok().getIdentifier()); 403 if (RegNo == 0) 404 return 0; 405 406 getLexer().Lex(); 407 return MBlazeOperand::CreateReg(RegNo, S, E); 408 } 409 } 410 411 static unsigned MatchFslRegister(StringRef String) { 412 if (!String.startswith("rfsl")) 413 return -1; 414 415 unsigned regNum; 416 if (String.substr(4).getAsInteger(10,regNum)) 417 return -1; 418 419 return regNum; 420 } 421 422 MBlazeOperand *MBlazeAsmParser::ParseFsl() { 423 SMLoc S = Parser.getTok().getLoc(); 424 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 425 426 switch (getLexer().getKind()) { 427 default: return 0; 428 case AsmToken::Identifier: 429 unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier()); 430 if (reg >= 16) 431 return 0; 432 433 getLexer().Lex(); 434 const MCExpr *EVal = MCConstantExpr::Create(reg,getContext()); 435 return MBlazeOperand::CreateFslImm(EVal,S,E); 436 } 437 } 438 439 MBlazeOperand *MBlazeAsmParser::ParseImmediate() { 440 SMLoc S = Parser.getTok().getLoc(); 441 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); 442 443 const MCExpr *EVal; 444 switch (getLexer().getKind()) { 445 default: return 0; 446 case AsmToken::LParen: 447 case AsmToken::Plus: 448 case AsmToken::Minus: 449 case AsmToken::Integer: 450 case AsmToken::Identifier: 451 if (getParser().ParseExpression(EVal)) 452 return 0; 453 454 return MBlazeOperand::CreateImm(EVal, S, E); 455 } 456 } 457 458 MBlazeOperand *MBlazeAsmParser:: 459 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 460 MBlazeOperand *Op; 461 462 // Attempt to parse the next token as a register name 463 unsigned RegNo; 464 Op = ParseRegister(RegNo); 465 466 // Attempt to parse the next token as an FSL immediate 467 if (!Op) 468 Op = ParseFsl(); 469 470 // Attempt to parse the next token as an immediate 471 if (!Op) 472 Op = ParseImmediate(); 473 474 // If the token could not be parsed then fail 475 if (!Op) { 476 Error(Parser.getTok().getLoc(), "unknown operand"); 477 return 0; 478 } 479 480 // Push the parsed operand into the list of operands 481 Operands.push_back(Op); 482 return Op; 483 } 484 485 /// Parse an mblaze instruction mnemonic followed by its operands. 486 bool MBlazeAsmParser:: 487 ParseInstruction(StringRef Name, SMLoc NameLoc, 488 SmallVectorImpl<MCParsedAsmOperand*> &Operands) { 489 // The first operands is the token for the instruction name 490 size_t dotLoc = Name.find('.'); 491 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc)); 492 if (dotLoc < Name.size()) 493 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc)); 494 495 // If there are no more operands then finish 496 if (getLexer().is(AsmToken::EndOfStatement)) 497 return false; 498 499 // Parse the first operand 500 if (!ParseOperand(Operands)) 501 return true; 502 503 while (getLexer().isNot(AsmToken::EndOfStatement) && 504 getLexer().is(AsmToken::Comma)) { 505 // Consume the comma token 506 getLexer().Lex(); 507 508 // Parse the next operand 509 if (!ParseOperand(Operands)) 510 return true; 511 } 512 513 // If the instruction requires a memory operand then we need to 514 // replace the last two operands (base+offset) with a single 515 // memory operand. 516 if (Name.startswith("lw") || Name.startswith("sw") || 517 Name.startswith("lh") || Name.startswith("sh") || 518 Name.startswith("lb") || Name.startswith("sb")) 519 return (ParseMemory(Operands) == NULL); 520 521 return false; 522 } 523 524 /// ParseDirective parses the MBlaze specific directives 525 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) { 526 StringRef IDVal = DirectiveID.getIdentifier(); 527 if (IDVal == ".word") 528 return ParseDirectiveWord(2, DirectiveID.getLoc()); 529 return true; 530 } 531 532 /// ParseDirectiveWord 533 /// ::= .word [ expression (, expression)* ] 534 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { 535 if (getLexer().isNot(AsmToken::EndOfStatement)) { 536 for (;;) { 537 const MCExpr *Value; 538 if (getParser().ParseExpression(Value)) 539 return true; 540 541 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/); 542 543 if (getLexer().is(AsmToken::EndOfStatement)) 544 break; 545 546 // FIXME: Improve diagnostic. 547 if (getLexer().isNot(AsmToken::Comma)) 548 return Error(L, "unexpected token in directive"); 549 Parser.Lex(); 550 } 551 } 552 553 Parser.Lex(); 554 return false; 555 } 556 557 extern "C" void LLVMInitializeMBlazeAsmLexer(); 558 559 /// Force static initialization. 560 extern "C" void LLVMInitializeMBlazeAsmParser() { 561 RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget); 562 LLVMInitializeMBlazeAsmLexer(); 563 } 564 565 #define GET_REGISTER_MATCHER 566 #define GET_MATCHER_IMPLEMENTATION 567 #include "MBlazeGenAsmMatcher.inc" 568