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