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