brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.1 KiB · a8891d6 Raw
589 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "MCTargetDesc/MSP430MCAsmInfo.h"10#include "MCTargetDesc/MSP430MCTargetDesc.h"11#include "MSP430.h"12#include "MSP430RegisterInfo.h"13#include "TargetInfo/MSP430TargetInfo.h"14 15#include "llvm/ADT/APInt.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCExpr.h"18#include "llvm/MC/MCInst.h"19#include "llvm/MC/MCInstrInfo.h"20#include "llvm/MC/MCParser/AsmLexer.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/MC/TargetRegistry.h"28#include "llvm/Support/Compiler.h"29#include "llvm/Support/Debug.h"30 31#define DEBUG_TYPE "msp430-asm-parser"32 33using namespace llvm;34 35namespace {36 37/// Parses MSP430 assembly from a stream.38class MSP430AsmParser : public MCTargetAsmParser {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(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;48  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,49                               SMLoc &EndLoc) override;50 51  bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,52                        SMLoc NameLoc, OperandVector &Operands) override;53 54  ParseStatus 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  AsmLexer &getLexer() const { return Parser.getLexer(); }69 70  /// @name Auto-generated Matcher Functions71  /// {72 73#define GET_ASSEMBLER_HEADER74#include "MSP430GenAsmMatcher.inc"75 76  /// }77 78public:79  MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,80                  const MCInstrInfo &MII, const MCTargetOptions &Options)81      : MCTargetAsmParser(Options, STI, MII), 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.90class 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_PostIndReg100  } Kind;101 102  struct Memory {103    MCRegister Reg;104    const MCExpr *Offset;105  };106  union {107    const MCExpr *Imm;108    MCRegister    Reg;109    StringRef     Tok;110    Memory        Mem;111  };112 113  SMLoc Start, End;114 115public:116  MSP430Operand(StringRef Tok, SMLoc const &S)117      : Kind(k_Tok), Tok(Tok), Start(S), End(S) {}118  MSP430Operand(KindTy Kind, MCRegister Reg, SMLoc const &S, SMLoc const &E)119      : Kind(Kind), Reg(Reg), Start(S), End(E) {}120  MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)121      : Kind(k_Imm), Imm(Imm), Start(S), End(E) {}122  MSP430Operand(MCRegister Reg, MCExpr const *Expr, SMLoc const &S,123                SMLoc const &E)124      : 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 possible136    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    else141      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  MCRegister getReg() const override {186    assert(Kind == k_Reg && "Invalid access!");187    return Reg;188  }189 190  void setReg(MCRegister 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(MCRegister Reg, SMLoc S,200                                                  SMLoc E) {201    return std::make_unique<MSP430Operand>(k_Reg, Reg, 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>210  CreateMem(MCRegister Reg, const MCExpr *Val, SMLoc S, SMLoc E) {211    return std::make_unique<MSP430Operand>(Reg, Val, S, E);212  }213 214  static std::unique_ptr<MSP430Operand> CreateIndReg(MCRegister Reg, SMLoc S,215                                                     SMLoc E) {216    return std::make_unique<MSP430Operand>(k_IndReg, Reg, S, E);217  }218 219  static std::unique_ptr<MSP430Operand> CreatePostIndReg(MCRegister Reg,220                                                         SMLoc S, SMLoc E) {221    return std::make_unique<MSP430Operand>(k_PostIndReg, Reg, 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 MCAsmInfo &MAI) const override {228    switch (Kind) {229    case k_Tok:230      O << "Token " << Tok;231      break;232    case k_Reg:233      O << "Register " << Reg.id();234      break;235    case k_Imm:236      O << "Immediate ";237      MAI.printExpr(O, *Imm);238      break;239    case k_Mem:240      O << "Memory ";241      MAI.printExpr(O, *Mem.Offset);242      break;243    case k_IndReg:244      O << "RegInd " << Reg.id();245      break;246    case k_PostIndReg:247      O << "PostInc " << Reg.id();248      break;249    }250  }251};252} // end anonymous namespace253 254bool 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 TableGen288static MCRegister MatchRegisterName(StringRef Name);289static MCRegister MatchRegisterAltName(StringRef Name);290 291bool MSP430AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,292                                    SMLoc &EndLoc) {293  ParseStatus Res = tryParseRegister(Reg, StartLoc, EndLoc);294  if (Res.isFailure())295    return Error(StartLoc, "invalid register name");296  if (Res.isSuccess())297    return false;298  if (Res.isNoMatch())299    return true;300 301  llvm_unreachable("unknown parse status");302}303 304ParseStatus MSP430AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,305                                              SMLoc &EndLoc) {306  if (getLexer().getKind() == AsmToken::Identifier) {307    auto Name = getLexer().getTok().getIdentifier().lower();308    Reg = MatchRegisterName(Name);309    if (Reg == MSP430::NoRegister) {310      Reg = MatchRegisterAltName(Name);311      if (Reg == MSP430::NoRegister)312        return ParseStatus::NoMatch;313    }314 315    AsmToken const &T = getParser().getTok();316    StartLoc = T.getLoc();317    EndLoc = T.getEndLoc();318    getLexer().Lex(); // eat register token319 320    return ParseStatus::Success;321  }322 323  return ParseStatus::Failure;324}325 326bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info,327                                          StringRef Name, SMLoc NameLoc,328                                          OperandVector &Operands) {329  if (!Name.starts_with_insensitive("j"))330    return true;331 332  auto CC = Name.drop_front().lower();333  unsigned CondCode;334  if (CC == "ne" || CC == "nz")335    CondCode = MSP430CC::COND_NE;336  else if (CC == "eq" || CC == "z")337    CondCode = MSP430CC::COND_E;338  else if (CC == "lo" || CC == "nc")339    CondCode = MSP430CC::COND_LO;340  else if (CC == "hs" || CC == "c")341    CondCode = MSP430CC::COND_HS;342  else if (CC == "n")343    CondCode = MSP430CC::COND_N;344  else if (CC == "ge")345    CondCode = MSP430CC::COND_GE;346  else if (CC == "l")347    CondCode = MSP430CC::COND_L;348  else if (CC == "mp")349    CondCode = MSP430CC::COND_NONE;350  else351    return Error(NameLoc, "unknown instruction");352 353  if (CondCode == (unsigned)MSP430CC::COND_NONE)354    Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc));355  else {356    Operands.push_back(MSP430Operand::CreateToken("j", NameLoc));357    const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext());358    Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc()));359  }360 361  // Skip optional '$' sign.362  (void)parseOptionalToken(AsmToken::Dollar);363 364  const MCExpr *Val;365  SMLoc ExprLoc = getLexer().getLoc();366  if (getParser().parseExpression(Val))367    return Error(ExprLoc, "expected expression operand");368 369  int64_t Res;370  if (Val->evaluateAsAbsolute(Res))371    if (Res < -512 || Res > 511)372      return Error(ExprLoc, "invalid jump offset");373 374  Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc,375    getLexer().getLoc()));376 377  if (getLexer().isNot(AsmToken::EndOfStatement)) {378    SMLoc Loc = getLexer().getLoc();379    getParser().eatToEndOfStatement();380    return Error(Loc, "unexpected token");381  }382 383  getParser().Lex(); // Consume the EndOfStatement.384  return false;385}386 387bool MSP430AsmParser::parseInstruction(ParseInstructionInfo &Info,388                                       StringRef Name, SMLoc NameLoc,389                                       OperandVector &Operands) {390  // Drop .w suffix391  if (Name.ends_with_insensitive(".w"))392    Name = Name.drop_back(2);393 394  if (!parseJccInstruction(Info, Name, NameLoc, Operands))395    return false;396 397  // First operand is instruction mnemonic398  Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc));399 400  // If there are no more operands, then finish401  if (getLexer().is(AsmToken::EndOfStatement))402    return false;403 404  // Parse first operand405  if (ParseOperand(Operands))406    return true;407 408  // Parse second operand if any409  if (parseOptionalToken(AsmToken::Comma) && ParseOperand(Operands))410    return true;411 412  if (getLexer().isNot(AsmToken::EndOfStatement)) {413    SMLoc Loc = getLexer().getLoc();414    getParser().eatToEndOfStatement();415    return Error(Loc, "unexpected token");416  }417 418  getParser().Lex(); // Consume the EndOfStatement.419  return false;420}421 422bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) {423  StringRef Name;424  if (getParser().parseIdentifier(Name))425    return TokError("expected identifier in directive");426 427  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);428  getStreamer().emitSymbolAttribute(Sym, MCSA_Global);429  return parseEOL();430}431 432ParseStatus MSP430AsmParser::parseDirective(AsmToken DirectiveID) {433  StringRef IDVal = DirectiveID.getIdentifier();434  if (IDVal.lower() == ".long")435    return ParseLiteralValues(4, DirectiveID.getLoc());436  if (IDVal.lower() == ".word" || IDVal.lower() == ".short")437    return ParseLiteralValues(2, DirectiveID.getLoc());438  if (IDVal.lower() == ".byte")439    return ParseLiteralValues(1, DirectiveID.getLoc());440  if (IDVal.lower() == ".refsym")441    return ParseDirectiveRefSym(DirectiveID);442  return ParseStatus::NoMatch;443}444 445bool MSP430AsmParser::ParseOperand(OperandVector &Operands) {446  switch (getLexer().getKind()) {447    default: return true;448    case AsmToken::Identifier: {449      // try rN450      MCRegister RegNo;451      SMLoc StartLoc, EndLoc;452      if (!parseRegister(RegNo, StartLoc, EndLoc)) {453        Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc));454        return false;455      }456      [[fallthrough]];457    }458    case AsmToken::Integer:459    case AsmToken::Plus:460    case AsmToken::Minus: {461      SMLoc StartLoc = getParser().getTok().getLoc();462      const MCExpr *Val;463      // Try constexpr[(rN)]464      if (!getParser().parseExpression(Val)) {465        MCRegister RegNo = MSP430::PC;466        SMLoc EndLoc = getParser().getTok().getLoc();467        // Try (rN)468        if (parseOptionalToken(AsmToken::LParen)) {469          SMLoc RegStartLoc;470          if (parseRegister(RegNo, RegStartLoc, EndLoc))471            return true;472          EndLoc = getParser().getTok().getEndLoc();473          if (!parseOptionalToken(AsmToken::RParen))474            return true;475        }476        Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc,477          EndLoc));478        return false;479      }480      return true;481    }482    case AsmToken::Amp: {483      // Try &constexpr484      SMLoc StartLoc = getParser().getTok().getLoc();485      getLexer().Lex(); // Eat '&'486      const MCExpr *Val;487      if (!getParser().parseExpression(Val)) {488        SMLoc EndLoc = getParser().getTok().getLoc();489        Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc,490          EndLoc));491        return false;492      }493      return true;494    }495    case AsmToken::At: {496      // Try @rN[+]497      SMLoc StartLoc = getParser().getTok().getLoc();498      getLexer().Lex(); // Eat '@'499      MCRegister RegNo;500      SMLoc RegStartLoc, EndLoc;501      if (parseRegister(RegNo, RegStartLoc, EndLoc))502        return true;503      if (parseOptionalToken(AsmToken::Plus)) {504        Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc));505        return false;506      }507      if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd)508        Operands.push_back(MSP430Operand::CreateMem(RegNo,509            MCConstantExpr::create(0, getContext()), StartLoc, EndLoc));510      else511        Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc));512      return false;513    }514    case AsmToken::Hash:515      // Try #constexpr516      SMLoc StartLoc = getParser().getTok().getLoc();517      getLexer().Lex(); // Eat '#'518      const MCExpr *Val;519      if (!getParser().parseExpression(Val)) {520        SMLoc EndLoc = getParser().getTok().getLoc();521        Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc));522        return false;523      }524      return true;525  }526}527 528bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) {529  auto parseOne = [&]() -> bool {530    const MCExpr *Value;531    if (getParser().parseExpression(Value))532      return true;533    getParser().getStreamer().emitValue(Value, Size, L);534    return false;535  };536  return (parseMany(parseOne));537}538 539extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void540LLVMInitializeMSP430AsmParser() {541  RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target());542}543 544#define GET_REGISTER_MATCHER545#define GET_MATCHER_IMPLEMENTATION546#include "MSP430GenAsmMatcher.inc"547 548static MCRegister convertGR16ToGR8(MCRegister Reg) {549  switch (Reg.id()) {550  default:551    llvm_unreachable("Unknown GR16 register");552  case MSP430::PC:  return MSP430::PCB;553  case MSP430::SP:  return MSP430::SPB;554  case MSP430::SR:  return MSP430::SRB;555  case MSP430::CG:  return MSP430::CGB;556  case MSP430::R4:  return MSP430::R4B;557  case MSP430::R5:  return MSP430::R5B;558  case MSP430::R6:  return MSP430::R6B;559  case MSP430::R7:  return MSP430::R7B;560  case MSP430::R8:  return MSP430::R8B;561  case MSP430::R9:  return MSP430::R9B;562  case MSP430::R10: return MSP430::R10B;563  case MSP430::R11: return MSP430::R11B;564  case MSP430::R12: return MSP430::R12B;565  case MSP430::R13: return MSP430::R13B;566  case MSP430::R14: return MSP430::R14B;567  case MSP430::R15: return MSP430::R15B;568  }569}570 571unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,572                                                     unsigned Kind) {573  MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp);574 575  if (!Op.isReg())576    return Match_InvalidOperand;577 578  MCRegister Reg = Op.getReg();579  bool isGR16 =580      MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg);581 582  if (isGR16 && (Kind == MCK_GR8)) {583    Op.setReg(convertGR16ToGR8(Reg));584    return Match_Success;585  }586 587  return Match_InvalidOperand;588}589