1 //===- MSP430AsmParser.cpp - Parse MSP430 assembly to MCInst instructions -===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "MSP430.h" 10 #include "MSP430RegisterInfo.h" 11 #include "MCTargetDesc/MSP430MCTargetDesc.h" 12 #include "TargetInfo/MSP430TargetInfo.h" 13 14 #include "llvm/ADT/APInt.h" 15 #include "llvm/MC/MCContext.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCInst.h" 18 #include "llvm/MC/MCInstBuilder.h" 19 #include "llvm/MC/MCInstrInfo.h" 20 #include "llvm/MC/MCParser/MCAsmLexer.h" 21 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 22 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 23 #include "llvm/MC/MCStreamer.h" 24 #include "llvm/MC/MCSubtargetInfo.h" 25 #include "llvm/MC/MCSymbol.h" 26 #include "llvm/MC/MCValue.h" 27 #include "llvm/MC/TargetRegistry.h" 28 #include "llvm/Support/Debug.h" 29 #include "llvm/Support/MathExtras.h" 30 31 #define DEBUG_TYPE "msp430-asm-parser" 32 33 using namespace llvm; 34 35 namespace { 36 37 /// Parses MSP430 assembly from a stream. 38 class MSP430AsmParser : public MCTargetAsmParser { 39 const MCSubtargetInfo &STI; 40 MCAsmParser &Parser; 41 const MCRegisterInfo *MRI; 42 43 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 44 OperandVector &Operands, MCStreamer &Out, 45 uint64_t &ErrorInfo, 46 bool MatchingInlineAsm) override; 47 48 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 49 OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, 50 SMLoc &EndLoc) override; 51 52 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 53 SMLoc NameLoc, OperandVector &Operands) override; 54 55 bool ParseDirective(AsmToken DirectiveID) override; 56 bool ParseDirectiveRefSym(AsmToken DirectiveID); 57 58 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 59 unsigned Kind) override; 60 61 bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name, 62 SMLoc NameLoc, OperandVector &Operands); 63 64 bool ParseOperand(OperandVector &Operands); 65 66 bool ParseLiteralValues(unsigned Size, SMLoc L); 67 68 MCAsmParser &getParser() const { return Parser; } 69 MCAsmLexer &getLexer() const { return Parser.getLexer(); } 70 71 /// @name Auto-generated Matcher Functions 72 /// { 73 74 #define GET_ASSEMBLER_HEADER 75 #include "MSP430GenAsmMatcher.inc" 76 77 /// } 78 79 public: 80 MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 81 const MCInstrInfo &MII, const MCTargetOptions &Options) 82 : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) { 83 MCAsmParserExtension::Initialize(Parser); 84 MRI = getContext().getRegisterInfo(); 85 86 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 87 } 88 }; 89 90 /// A parsed MSP430 assembly operand. 91 class MSP430Operand : public MCParsedAsmOperand { 92 typedef MCParsedAsmOperand Base; 93 94 enum KindTy { 95 k_Imm, 96 k_Reg, 97 k_Tok, 98 k_Mem, 99 k_IndReg, 100 k_PostIndReg 101 } Kind; 102 103 struct Memory { 104 unsigned Reg; 105 const MCExpr *Offset; 106 }; 107 union { 108 const MCExpr *Imm; 109 unsigned Reg; 110 StringRef Tok; 111 Memory Mem; 112 }; 113 114 SMLoc Start, End; 115 116 public: 117 MSP430Operand(StringRef Tok, SMLoc const &S) 118 : Kind(k_Tok), Tok(Tok), Start(S), End(S) {} 119 MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E) 120 : Kind(Kind), Reg(Reg), Start(S), End(E) {} 121 MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E) 122 : Kind(k_Imm), Imm(Imm), Start(S), End(E) {} 123 MSP430Operand(unsigned Reg, MCExpr const *Expr, SMLoc const &S, 124 SMLoc const &E) 125 : Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {} 126 127 void addRegOperands(MCInst &Inst, unsigned N) const { 128 assert((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) && 129 "Unexpected operand kind"); 130 assert(N == 1 && "Invalid number of operands!"); 131 132 Inst.addOperand(MCOperand::createReg(Reg)); 133 } 134 135 void addExprOperand(MCInst &Inst, const MCExpr *Expr) const { 136 // Add as immediate when possible 137 if (!Expr) 138 Inst.addOperand(MCOperand::createImm(0)); 139 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 140 Inst.addOperand(MCOperand::createImm(CE->getValue())); 141 else 142 Inst.addOperand(MCOperand::createExpr(Expr)); 143 } 144 145 void addImmOperands(MCInst &Inst, unsigned N) const { 146 assert(Kind == k_Imm && "Unexpected operand kind"); 147 assert(N == 1 && "Invalid number of operands!"); 148 149 addExprOperand(Inst, Imm); 150 } 151 152 void addMemOperands(MCInst &Inst, unsigned N) const { 153 assert(Kind == k_Mem && "Unexpected operand kind"); 154 assert(N == 2 && "Invalid number of operands"); 155 156 Inst.addOperand(MCOperand::createReg(Mem.Reg)); 157 addExprOperand(Inst, Mem.Offset); 158 } 159 160 bool isReg() const override { return Kind == k_Reg; } 161 bool isImm() const override { return Kind == k_Imm; } 162 bool isToken() const override { return Kind == k_Tok; } 163 bool isMem() const override { return Kind == k_Mem; } 164 bool isIndReg() const { return Kind == k_IndReg; } 165 bool isPostIndReg() const { return Kind == k_PostIndReg; } 166 167 bool isCGImm() const { 168 if (Kind != k_Imm) 169 return false; 170 171 int64_t Val; 172 if (!Imm->evaluateAsAbsolute(Val)) 173 return false; 174 175 if (Val == 0 || Val == 1 || Val == 2 || Val == 4 || Val == 8 || Val == -1) 176 return true; 177 178 return false; 179 } 180 181 StringRef getToken() const { 182 assert(Kind == k_Tok && "Invalid access!"); 183 return Tok; 184 } 185 186 unsigned getReg() const override { 187 assert(Kind == k_Reg && "Invalid access!"); 188 return Reg; 189 } 190 191 void setReg(unsigned RegNo) { 192 assert(Kind == k_Reg && "Invalid access!"); 193 Reg = RegNo; 194 } 195 196 static std::unique_ptr<MSP430Operand> CreateToken(StringRef Str, SMLoc S) { 197 return std::make_unique<MSP430Operand>(Str, S); 198 } 199 200 static std::unique_ptr<MSP430Operand> CreateReg(unsigned RegNum, SMLoc S, 201 SMLoc E) { 202 return std::make_unique<MSP430Operand>(k_Reg, RegNum, S, E); 203 } 204 205 static std::unique_ptr<MSP430Operand> CreateImm(const MCExpr *Val, SMLoc S, 206 SMLoc E) { 207 return std::make_unique<MSP430Operand>(Val, S, E); 208 } 209 210 static std::unique_ptr<MSP430Operand> CreateMem(unsigned RegNum, 211 const MCExpr *Val, 212 SMLoc S, SMLoc E) { 213 return std::make_unique<MSP430Operand>(RegNum, Val, S, E); 214 } 215 216 static std::unique_ptr<MSP430Operand> CreateIndReg(unsigned RegNum, SMLoc S, 217 SMLoc E) { 218 return std::make_unique<MSP430Operand>(k_IndReg, RegNum, S, E); 219 } 220 221 static std::unique_ptr<MSP430Operand> CreatePostIndReg(unsigned RegNum, SMLoc S, 222 SMLoc E) { 223 return std::make_unique<MSP430Operand>(k_PostIndReg, RegNum, S, E); 224 } 225 226 SMLoc getStartLoc() const override { return Start; } 227 SMLoc getEndLoc() const override { return End; } 228 229 void print(raw_ostream &O) const override { 230 switch (Kind) { 231 case k_Tok: 232 O << "Token " << Tok; 233 break; 234 case k_Reg: 235 O << "Register " << Reg; 236 break; 237 case k_Imm: 238 O << "Immediate " << *Imm; 239 break; 240 case k_Mem: 241 O << "Memory "; 242 O << *Mem.Offset << "(" << Reg << ")"; 243 break; 244 case k_IndReg: 245 O << "RegInd " << Reg; 246 break; 247 case k_PostIndReg: 248 O << "PostInc " << Reg; 249 break; 250 } 251 } 252 }; 253 } // end anonymous namespace 254 255 bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode, 256 OperandVector &Operands, 257 MCStreamer &Out, 258 uint64_t &ErrorInfo, 259 bool MatchingInlineAsm) { 260 MCInst Inst; 261 unsigned MatchResult = 262 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); 263 264 switch (MatchResult) { 265 case Match_Success: 266 Inst.setLoc(Loc); 267 Out.emitInstruction(Inst, STI); 268 return false; 269 case Match_MnemonicFail: 270 return Error(Loc, "invalid instruction mnemonic"); 271 case Match_InvalidOperand: { 272 SMLoc ErrorLoc = Loc; 273 if (ErrorInfo != ~0U) { 274 if (ErrorInfo >= Operands.size()) 275 return Error(ErrorLoc, "too few operands for instruction"); 276 277 ErrorLoc = ((MSP430Operand &)*Operands[ErrorInfo]).getStartLoc(); 278 if (ErrorLoc == SMLoc()) 279 ErrorLoc = Loc; 280 } 281 return Error(ErrorLoc, "invalid operand for instruction"); 282 } 283 default: 284 return true; 285 } 286 } 287 288 // Auto-generated by TableGen 289 static unsigned MatchRegisterName(StringRef Name); 290 static unsigned MatchRegisterAltName(StringRef Name); 291 292 bool MSP430AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 293 SMLoc &EndLoc) { 294 switch (tryParseRegister(RegNo, StartLoc, EndLoc)) { 295 case MatchOperand_ParseFail: 296 return Error(StartLoc, "invalid register name"); 297 case MatchOperand_Success: 298 return false; 299 case MatchOperand_NoMatch: 300 return true; 301 } 302 303 llvm_unreachable("unknown match result type"); 304 } 305 306 OperandMatchResultTy MSP430AsmParser::tryParseRegister(unsigned &RegNo, 307 SMLoc &StartLoc, 308 SMLoc &EndLoc) { 309 if (getLexer().getKind() == AsmToken::Identifier) { 310 auto Name = getLexer().getTok().getIdentifier().lower(); 311 RegNo = MatchRegisterName(Name); 312 if (RegNo == MSP430::NoRegister) { 313 RegNo = MatchRegisterAltName(Name); 314 if (RegNo == MSP430::NoRegister) 315 return MatchOperand_NoMatch; 316 } 317 318 AsmToken const &T = getParser().getTok(); 319 StartLoc = T.getLoc(); 320 EndLoc = T.getEndLoc(); 321 getLexer().Lex(); // eat register token 322 323 return MatchOperand_Success; 324 } 325 326 return MatchOperand_ParseFail; 327 } 328 329 bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info, 330 StringRef Name, SMLoc NameLoc, 331 OperandVector &Operands) { 332 if (!Name.startswith_insensitive("j")) 333 return true; 334 335 auto CC = Name.drop_front().lower(); 336 unsigned CondCode; 337 if (CC == "ne" || CC == "nz") 338 CondCode = MSP430CC::COND_NE; 339 else if (CC == "eq" || CC == "z") 340 CondCode = MSP430CC::COND_E; 341 else if (CC == "lo" || CC == "nc") 342 CondCode = MSP430CC::COND_LO; 343 else if (CC == "hs" || CC == "c") 344 CondCode = MSP430CC::COND_HS; 345 else if (CC == "n") 346 CondCode = MSP430CC::COND_N; 347 else if (CC == "ge") 348 CondCode = MSP430CC::COND_GE; 349 else if (CC == "l") 350 CondCode = MSP430CC::COND_L; 351 else if (CC == "mp") 352 CondCode = MSP430CC::COND_NONE; 353 else 354 return Error(NameLoc, "unknown instruction"); 355 356 if (CondCode == (unsigned)MSP430CC::COND_NONE) 357 Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc)); 358 else { 359 Operands.push_back(MSP430Operand::CreateToken("j", NameLoc)); 360 const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext()); 361 Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc())); 362 } 363 364 // Skip optional '$' sign. 365 if (getLexer().getKind() == AsmToken::Dollar) 366 getLexer().Lex(); // Eat '$' 367 368 const MCExpr *Val; 369 SMLoc ExprLoc = getLexer().getLoc(); 370 if (getParser().parseExpression(Val)) 371 return Error(ExprLoc, "expected expression operand"); 372 373 int64_t Res; 374 if (Val->evaluateAsAbsolute(Res)) 375 if (Res < -512 || Res > 511) 376 return Error(ExprLoc, "invalid jump offset"); 377 378 Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc, 379 getLexer().getLoc())); 380 381 if (getLexer().isNot(AsmToken::EndOfStatement)) { 382 SMLoc Loc = getLexer().getLoc(); 383 getParser().eatToEndOfStatement(); 384 return Error(Loc, "unexpected token"); 385 } 386 387 getParser().Lex(); // Consume the EndOfStatement. 388 return false; 389 } 390 391 bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info, 392 StringRef Name, SMLoc NameLoc, 393 OperandVector &Operands) { 394 // Drop .w suffix 395 if (Name.endswith_insensitive(".w")) 396 Name = Name.drop_back(2); 397 398 if (!parseJccInstruction(Info, Name, NameLoc, Operands)) 399 return false; 400 401 // First operand is instruction mnemonic 402 Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc)); 403 404 // If there are no more operands, then finish 405 if (getLexer().is(AsmToken::EndOfStatement)) 406 return false; 407 408 // Parse first operand 409 if (ParseOperand(Operands)) 410 return true; 411 412 // Parse second operand if any 413 if (getLexer().is(AsmToken::Comma)) { 414 getLexer().Lex(); // Eat ',' 415 if (ParseOperand(Operands)) 416 return true; 417 } 418 419 if (getLexer().isNot(AsmToken::EndOfStatement)) { 420 SMLoc Loc = getLexer().getLoc(); 421 getParser().eatToEndOfStatement(); 422 return Error(Loc, "unexpected token"); 423 } 424 425 getParser().Lex(); // Consume the EndOfStatement. 426 return false; 427 } 428 429 bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) { 430 StringRef Name; 431 if (getParser().parseIdentifier(Name)) 432 return TokError("expected identifier in directive"); 433 434 MCSymbol *Sym = getContext().getOrCreateSymbol(Name); 435 getStreamer().emitSymbolAttribute(Sym, MCSA_Global); 436 return false; 437 } 438 439 bool MSP430AsmParser::ParseDirective(AsmToken DirectiveID) { 440 StringRef IDVal = DirectiveID.getIdentifier(); 441 if (IDVal.lower() == ".long") { 442 ParseLiteralValues(4, DirectiveID.getLoc()); 443 } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") { 444 ParseLiteralValues(2, DirectiveID.getLoc()); 445 } else if (IDVal.lower() == ".byte") { 446 ParseLiteralValues(1, DirectiveID.getLoc()); 447 } else if (IDVal.lower() == ".refsym") { 448 return ParseDirectiveRefSym(DirectiveID); 449 } 450 return true; 451 } 452 453 bool MSP430AsmParser::ParseOperand(OperandVector &Operands) { 454 switch (getLexer().getKind()) { 455 default: return true; 456 case AsmToken::Identifier: { 457 // try rN 458 unsigned RegNo; 459 SMLoc StartLoc, EndLoc; 460 if (!ParseRegister(RegNo, StartLoc, EndLoc)) { 461 Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc)); 462 return false; 463 } 464 LLVM_FALLTHROUGH; 465 } 466 case AsmToken::Integer: 467 case AsmToken::Plus: 468 case AsmToken::Minus: { 469 SMLoc StartLoc = getParser().getTok().getLoc(); 470 const MCExpr *Val; 471 // Try constexpr[(rN)] 472 if (!getParser().parseExpression(Val)) { 473 unsigned RegNo = MSP430::PC; 474 SMLoc EndLoc = getParser().getTok().getLoc(); 475 // Try (rN) 476 if (getLexer().getKind() == AsmToken::LParen) { 477 getLexer().Lex(); // Eat '(' 478 SMLoc RegStartLoc; 479 if (ParseRegister(RegNo, RegStartLoc, EndLoc)) 480 return true; 481 if (getLexer().getKind() != AsmToken::RParen) 482 return true; 483 EndLoc = getParser().getTok().getEndLoc(); 484 getLexer().Lex(); // Eat ')' 485 } 486 Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc, 487 EndLoc)); 488 return false; 489 } 490 return true; 491 } 492 case AsmToken::Amp: { 493 // Try &constexpr 494 SMLoc StartLoc = getParser().getTok().getLoc(); 495 getLexer().Lex(); // Eat '&' 496 const MCExpr *Val; 497 if (!getParser().parseExpression(Val)) { 498 SMLoc EndLoc = getParser().getTok().getLoc(); 499 Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc, 500 EndLoc)); 501 return false; 502 } 503 return true; 504 } 505 case AsmToken::At: { 506 // Try @rN[+] 507 SMLoc StartLoc = getParser().getTok().getLoc(); 508 getLexer().Lex(); // Eat '@' 509 unsigned RegNo; 510 SMLoc RegStartLoc, EndLoc; 511 if (ParseRegister(RegNo, RegStartLoc, EndLoc)) 512 return true; 513 if (getLexer().getKind() == AsmToken::Plus) { 514 Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc)); 515 getLexer().Lex(); // Eat '+' 516 return false; 517 } 518 if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd) 519 Operands.push_back(MSP430Operand::CreateMem(RegNo, 520 MCConstantExpr::create(0, getContext()), StartLoc, EndLoc)); 521 else 522 Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc)); 523 return false; 524 } 525 case AsmToken::Hash: 526 // Try #constexpr 527 SMLoc StartLoc = getParser().getTok().getLoc(); 528 getLexer().Lex(); // Eat '#' 529 const MCExpr *Val; 530 if (!getParser().parseExpression(Val)) { 531 SMLoc EndLoc = getParser().getTok().getLoc(); 532 Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc)); 533 return false; 534 } 535 return true; 536 } 537 } 538 539 bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) { 540 auto parseOne = [&]() -> bool { 541 const MCExpr *Value; 542 if (getParser().parseExpression(Value)) 543 return true; 544 getParser().getStreamer().emitValue(Value, Size, L); 545 return false; 546 }; 547 return (parseMany(parseOne)); 548 } 549 550 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430AsmParser() { 551 RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target()); 552 } 553 554 #define GET_REGISTER_MATCHER 555 #define GET_MATCHER_IMPLEMENTATION 556 #include "MSP430GenAsmMatcher.inc" 557 558 static unsigned convertGR16ToGR8(unsigned Reg) { 559 switch (Reg) { 560 default: 561 llvm_unreachable("Unknown GR16 register"); 562 case MSP430::PC: return MSP430::PCB; 563 case MSP430::SP: return MSP430::SPB; 564 case MSP430::SR: return MSP430::SRB; 565 case MSP430::CG: return MSP430::CGB; 566 case MSP430::R4: return MSP430::R4B; 567 case MSP430::R5: return MSP430::R5B; 568 case MSP430::R6: return MSP430::R6B; 569 case MSP430::R7: return MSP430::R7B; 570 case MSP430::R8: return MSP430::R8B; 571 case MSP430::R9: return MSP430::R9B; 572 case MSP430::R10: return MSP430::R10B; 573 case MSP430::R11: return MSP430::R11B; 574 case MSP430::R12: return MSP430::R12B; 575 case MSP430::R13: return MSP430::R13B; 576 case MSP430::R14: return MSP430::R14B; 577 case MSP430::R15: return MSP430::R15B; 578 } 579 } 580 581 unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 582 unsigned Kind) { 583 MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp); 584 585 if (!Op.isReg()) 586 return Match_InvalidOperand; 587 588 unsigned Reg = Op.getReg(); 589 bool isGR16 = 590 MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg); 591 592 if (isGR16 && (Kind == MCK_GR8)) { 593 Op.setReg(convertGR16ToGR8(Reg)); 594 return Match_Success; 595 } 596 597 return Match_InvalidOperand; 598 } 599