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