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