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