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