diff options
| author | Anton Korobeynikov <anton@korobeynikov.info> | 2018-11-15 12:35:04 +0000 | 
|---|---|---|
| committer | Anton Korobeynikov <anton@korobeynikov.info> | 2018-11-15 12:35:04 +0000 | 
| commit | f0001f41860d3656481acbf89366368fab9f6f67 (patch) | |
| tree | 6a832b41dace15dfce4bb198812953c95c334ebe /llvm/lib | |
| parent | 49045c6a0d2cfd7fe844067105aef21da2286f8c (diff) | |
| download | bcm5719-llvm-f0001f41860d3656481acbf89366368fab9f6f67.tar.gz bcm5719-llvm-f0001f41860d3656481acbf89366368fab9f6f67.zip | |
Add missed files from prev. commit
llvm-svn: 346949
Diffstat (limited to 'llvm/lib')
11 files changed, 1572 insertions, 0 deletions
| diff --git a/llvm/lib/Target/MSP430/AsmParser/CMakeLists.txt b/llvm/lib/Target/MSP430/AsmParser/CMakeLists.txt new file mode 100644 index 00000000000..bb484898afa --- /dev/null +++ b/llvm/lib/Target/MSP430/AsmParser/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMMSP430AsmParser +  MSP430AsmParser.cpp +) diff --git a/llvm/lib/Target/MSP430/AsmParser/LLVMBuild.txt b/llvm/lib/Target/MSP430/AsmParser/LLVMBuild.txt new file mode 100644 index 00000000000..58f67c07db1 --- /dev/null +++ b/llvm/lib/Target/MSP430/AsmParser/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- lib/Target/MSP430/AsmParser/LLVMBuild.txt ----------------*- Conf -*--===; +; +;                     The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +;   http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = MSP430AsmParser +parent = MSP430 +required_libraries = MC MCParser MSP430Desc MSP430Info Support +add_to_library_groups = MSP430 diff --git a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp new file mode 100644 index 00000000000..51b6918105e --- /dev/null +++ b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp @@ -0,0 +1,563 @@ +//===- MSP430AsmParser.cpp - Parse MSP430 assembly to MCInst instructions -===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MSP430.h" +#include "MSP430RegisterInfo.h" +#include "MCTargetDesc/MSP430MCTargetDesc.h" + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstBuilder.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/TargetRegistry.h" + +#define DEBUG_TYPE "msp430-asm-parser" + +using namespace llvm; + +namespace { + +/// Parses MSP430 assembly from a stream. +class MSP430AsmParser : public MCTargetAsmParser { +  const MCSubtargetInfo &STI; +  MCAsmParser &Parser; +  const MCRegisterInfo *MRI; + +  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, +                               OperandVector &Operands, MCStreamer &Out, +                               uint64_t &ErrorInfo, +                               bool MatchingInlineAsm) override; + +  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + +  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, +                        SMLoc NameLoc, OperandVector &Operands) override; + +  bool ParseDirective(AsmToken DirectiveID) override; + +  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, +                                      unsigned Kind) override; + +  bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name, +                           SMLoc NameLoc, OperandVector &Operands); + +  bool ParseOperand(OperandVector &Operands); + +  bool ParseLiteralValues(unsigned Size, SMLoc L); + +  MCAsmParser &getParser() const { return Parser; } +  MCAsmLexer &getLexer() const { return Parser.getLexer(); } + +  /// @name Auto-generated Matcher Functions +  /// { + +#define GET_ASSEMBLER_HEADER +#include "MSP430GenAsmMatcher.inc" + +  /// } + +public: +  MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, +                  const MCInstrInfo &MII, const MCTargetOptions &Options) +      : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) { +    MCAsmParserExtension::Initialize(Parser); +    MRI = getContext().getRegisterInfo(); + +    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); +  } +}; + +/// A parsed MSP430 assembly operand. +class MSP430Operand : public MCParsedAsmOperand { +  typedef MCParsedAsmOperand Base; + +  enum KindTy { +    k_Imm, +    k_Reg, +    k_Tok, +    k_Mem, +    k_IndReg, +    k_PostIndReg +  } Kind; + +  struct Memory { +    unsigned Reg; +    const MCExpr *Offset; +  }; +  union { +    const MCExpr *Imm; +    unsigned      Reg; +    StringRef     Tok; +    Memory        Mem; +  }; + +  SMLoc Start, End; + +public: +  MSP430Operand(StringRef Tok, SMLoc const &S) +      : Base(), Kind(k_Tok), Tok(Tok), Start(S), End(S) {} +  MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E) +      : Base(), Kind(Kind), Reg(Reg), Start(S), End(E) {} +  MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E) +      : Base(), Kind(k_Imm), Imm(Imm), Start(S), End(E) {} +  MSP430Operand(unsigned Reg, MCExpr const *Expr, SMLoc const &S, SMLoc const &E) +      : Base(), Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {} + +  void addRegOperands(MCInst &Inst, unsigned N) const { +    assert((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) && +        "Unexpected operand kind"); +    assert(N == 1 && "Invalid number of operands!"); + +    Inst.addOperand(MCOperand::createReg(Reg)); +  } + +  void addExprOperand(MCInst &Inst, const MCExpr *Expr) const { +    // Add as immediate when possible +    if (!Expr) +      Inst.addOperand(MCOperand::createImm(0)); +    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) +      Inst.addOperand(MCOperand::createImm(CE->getValue())); +    else +      Inst.addOperand(MCOperand::createExpr(Expr)); +  } + +  void addImmOperands(MCInst &Inst, unsigned N) const { +    assert(Kind == k_Imm && "Unexpected operand kind"); +    assert(N == 1 && "Invalid number of operands!"); + +    addExprOperand(Inst, Imm); +  } + +  void addMemOperands(MCInst &Inst, unsigned N) const { +    assert(Kind == k_Mem && "Unexpected operand kind"); +    assert(N == 2 && "Invalid number of operands"); + +    Inst.addOperand(MCOperand::createReg(Mem.Reg)); +    addExprOperand(Inst, Mem.Offset); +  } + +  bool isReg() const        { return Kind == k_Reg; } +  bool isImm() const        { return Kind == k_Imm; } +  bool isToken() const      { return Kind == k_Tok; } +  bool isMem() const        { return Kind == k_Mem; } +  bool isIndReg() const     { return Kind == k_IndReg; } +  bool isPostIndReg() const { return Kind == k_PostIndReg; } + +  bool isCGImm() const { +    if (Kind != k_Imm) +      return false; + +    int64_t Val; +    if (!Imm->evaluateAsAbsolute(Val)) +      return false; +     +    if (Val == 0 || Val == 1 || Val == 2 || Val == 4 || Val == 8 || Val == -1) +      return true; + +    return false; +  } + +  StringRef getToken() const { +    assert(Kind == k_Tok && "Invalid access!"); +    return Tok; +  } + +  unsigned getReg() const { +    assert(Kind == k_Reg && "Invalid access!"); +    return Reg; +  } + +  void setReg(unsigned RegNo) { +    assert(Kind == k_Reg && "Invalid access!"); +    Reg = RegNo; +  } + +  static std::unique_ptr<MSP430Operand> CreateToken(StringRef Str, SMLoc S) { +    return make_unique<MSP430Operand>(Str, S); +  } + +  static std::unique_ptr<MSP430Operand> CreateReg(unsigned RegNum, SMLoc S, +                                                  SMLoc E) { +    return make_unique<MSP430Operand>(k_Reg, RegNum, S, E); +  } + +  static std::unique_ptr<MSP430Operand> CreateImm(const MCExpr *Val, SMLoc S, +                                                  SMLoc E) { +    return make_unique<MSP430Operand>(Val, S, E); +  } + +  static std::unique_ptr<MSP430Operand> CreateMem(unsigned RegNum, +                                                  const MCExpr *Val, +                                                  SMLoc S, SMLoc E) { +    return make_unique<MSP430Operand>(RegNum, Val, S, E); +  } + +  static std::unique_ptr<MSP430Operand> CreateIndReg(unsigned RegNum, SMLoc S, +                                                  SMLoc E) { +    return make_unique<MSP430Operand>(k_IndReg, RegNum, S, E); +  } + +  static std::unique_ptr<MSP430Operand> CreatePostIndReg(unsigned RegNum, SMLoc S, +                                                  SMLoc E) { +    return make_unique<MSP430Operand>(k_PostIndReg, RegNum, S, E); +  } + +  SMLoc getStartLoc() const { return Start; } +  SMLoc getEndLoc() const { return End; } + +  virtual void print(raw_ostream &O) const { +    switch (Kind) { +    case k_Tok: +      O << "Token " << Tok; +      break; +    case k_Reg: +      O << "Register " << Reg; +      break; +    case k_Imm: +      O << "Immediate " << *Imm; +      break; +    case k_Mem: +      O << "Memory "; +      O << *Mem.Offset << "(" << Reg << ")"; +      break; +    case k_IndReg: +      O << "RegInd " << Reg; +      break; +    case k_PostIndReg: +      O << "PostInc " << Reg; +      break; +    } +  } +}; +} // end anonymous namespace + +bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode, +                                              OperandVector &Operands, +                                              MCStreamer &Out, +                                              uint64_t &ErrorInfo, +                                              bool MatchingInlineAsm) { +  MCInst Inst; +  unsigned MatchResult = +      MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); + +  switch (MatchResult) { +  case Match_Success: +    Inst.setLoc(Loc); +    Out.EmitInstruction(Inst, STI); +    return false; +  case Match_MnemonicFail: +    return Error(Loc, "invalid instruction mnemonic"); +  case Match_InvalidOperand: { +    SMLoc ErrorLoc = Loc; +    if (ErrorInfo != ~0U) { +      if (ErrorInfo >= Operands.size()) +        return Error(ErrorLoc, "too few operands for instruction"); + +      ErrorLoc = ((MSP430Operand &)*Operands[ErrorInfo]).getStartLoc(); +      if (ErrorLoc == SMLoc()) +        ErrorLoc = Loc; +    } +    return Error(ErrorLoc, "invalid operand for instruction"); +  } +  default: +    return true; +  } +} + +// Auto-generated by TableGen +static unsigned MatchRegisterName(StringRef Name); +static unsigned MatchRegisterAltName(StringRef Name); + +bool MSP430AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, +                                    SMLoc &EndLoc) { +  if (getLexer().getKind() == AsmToken::Identifier) { +    auto Name = getLexer().getTok().getIdentifier().lower(); +    RegNo = MatchRegisterName(Name); +    if (RegNo == MSP430::NoRegister) { +      RegNo = MatchRegisterAltName(Name); +      if (RegNo == MSP430::NoRegister) +        return true; +    } + +    AsmToken const &T = getParser().getTok(); +    StartLoc = T.getLoc(); +    EndLoc = T.getEndLoc(); +    getLexer().Lex(); // eat register token + +    return false; +  } + +  return Error(StartLoc, "invalid register name"); +} + +bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info, +                                          StringRef Name, SMLoc NameLoc, +                                          OperandVector &Operands) { +  if (!Name.startswith_lower("j")) +    return true; + +  auto CC = Name.drop_front().lower(); +  unsigned CondCode; +  if (CC == "ne" || CC == "nz") +    CondCode = MSP430CC::COND_NE; +  else if (CC == "eq" || CC == "z") +    CondCode = MSP430CC::COND_E; +  else if (CC == "lo" || CC == "nc") +    CondCode = MSP430CC::COND_LO; +  else if (CC == "hs" || CC == "c") +    CondCode = MSP430CC::COND_HS; +  else if (CC == "n") +    CondCode = MSP430CC::COND_N; +  else if (CC == "ge") +    CondCode = MSP430CC::COND_GE; +  else if (CC == "l") +    CondCode = MSP430CC::COND_L; +  else if (CC == "mp") +    CondCode = MSP430CC::COND_NONE; +  else +    return Error(NameLoc, "unknown instruction"); + +  if (CondCode == (unsigned)MSP430CC::COND_NONE) +    Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc)); +  else { +    Operands.push_back(MSP430Operand::CreateToken("j", NameLoc)); +    const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext()); +    Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc())); +  } + +  // Skip optional '$' sign. +  if (getLexer().getKind() == AsmToken::Dollar) +    getLexer().Lex(); // Eat '$' + +  const MCExpr *Val; +  SMLoc ExprLoc = getLexer().getLoc(); +  if (getParser().parseExpression(Val)) +    return Error(ExprLoc, "expected expression operand"); + +  int64_t Res; +  if (Val->evaluateAsAbsolute(Res)) +    if (Res < -512 || Res > 511) +      return Error(ExprLoc, "invalid jump offset"); + +  Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc, +    getLexer().getLoc())); + +  if (getLexer().isNot(AsmToken::EndOfStatement)) { +    SMLoc Loc = getLexer().getLoc(); +    getParser().eatToEndOfStatement(); +    return Error(Loc, "unexpected token"); +  } + +  getParser().Lex(); // Consume the EndOfStatement. +  return false; +} + +bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info, +                                       StringRef Name, SMLoc NameLoc, +                                       OperandVector &Operands) { +  // Drop .w suffix +  if (Name.endswith_lower(".w")) +    Name = Name.drop_back(2); + +  if (!parseJccInstruction(Info, Name, NameLoc, Operands)) +    return false; + +  // First operand is instruction mnemonic +  Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc)); + +  // If there are no more operands, then finish +  if (getLexer().is(AsmToken::EndOfStatement)) +    return false; + +  // Parse first operand +  if (ParseOperand(Operands)) +    return true; + +  // Parse second operand if any +  if (getLexer().is(AsmToken::Comma)) { +    getLexer().Lex(); // Eat ',' +    if (ParseOperand(Operands)) +      return true; +  } + +  if (getLexer().isNot(AsmToken::EndOfStatement)) { +    SMLoc Loc = getLexer().getLoc(); +    getParser().eatToEndOfStatement(); +    return Error(Loc, "unexpected token"); +  } + +  getParser().Lex(); // Consume the EndOfStatement. +  return false; +} + +bool MSP430AsmParser::ParseDirective(AsmToken DirectiveID) { +  StringRef IDVal = DirectiveID.getIdentifier(); +  if (IDVal.lower() == ".long") { +    ParseLiteralValues(4, DirectiveID.getLoc()); +  } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") { +    ParseLiteralValues(2, DirectiveID.getLoc()); +  } else if (IDVal.lower() == ".byte") { +    ParseLiteralValues(1, DirectiveID.getLoc()); +  } +  return true; +} + +bool MSP430AsmParser::ParseOperand(OperandVector &Operands) { +  switch (getLexer().getKind()) { +    default: return true; +    case AsmToken::Identifier: { +      // try rN +      unsigned RegNo; +      SMLoc StartLoc, EndLoc; +      if (!ParseRegister(RegNo, StartLoc, EndLoc)) { +        Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc)); +        return false; +      } +      LLVM_FALLTHROUGH; +    } +    case AsmToken::Integer: +    case AsmToken::Plus: +    case AsmToken::Minus: { +      SMLoc StartLoc = getParser().getTok().getLoc(); +      const MCExpr *Val; +      // Try constexpr[(rN)] +      if (!getParser().parseExpression(Val)) { +        unsigned RegNo = MSP430::PC; +        SMLoc EndLoc = getParser().getTok().getLoc(); +        // Try (rN) +        if (getLexer().getKind() == AsmToken::LParen) { +          getLexer().Lex(); // Eat '(' +          SMLoc RegStartLoc; +          if (ParseRegister(RegNo, RegStartLoc, EndLoc)) +            return true; +          if (getLexer().getKind() != AsmToken::RParen) +            return true; +          EndLoc = getParser().getTok().getEndLoc(); +          getLexer().Lex(); // Eat ')' +        } +        Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc, +          EndLoc)); +        return false; +      } +      return true; +    } +    case AsmToken::Amp: { +      // Try &constexpr +      SMLoc StartLoc = getParser().getTok().getLoc(); +      getLexer().Lex(); // Eat '&' +      const MCExpr *Val; +      if (!getParser().parseExpression(Val)) { +        SMLoc EndLoc = getParser().getTok().getLoc(); +        Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc, +          EndLoc)); +        return false; +      } +      return true; +    } +    case AsmToken::At: { +      // Try @rN[+] +      SMLoc StartLoc = getParser().getTok().getLoc(); +      getLexer().Lex(); // Eat '@' +      unsigned RegNo; +      SMLoc RegStartLoc, EndLoc; +      if (ParseRegister(RegNo, RegStartLoc, EndLoc)) +        return true; +      if (getLexer().getKind() == AsmToken::Plus) { +        Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc)); +        getLexer().Lex(); // Eat '+' +        return false; +      } +      Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc)); +      return false; +    } +    case AsmToken::Hash: +      // Try #constexpr +      SMLoc StartLoc = getParser().getTok().getLoc(); +      getLexer().Lex(); // Eat '#' +      const MCExpr *Val; +      if (!getParser().parseExpression(Val)) { +        SMLoc EndLoc = getParser().getTok().getLoc(); +        Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc)); +        return false; +      } +      return true; +  } +} + +bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) { +  auto parseOne = [&]() -> bool { +    const MCExpr *Value; +    if (getParser().parseExpression(Value)) +      return true; +    getParser().getStreamer().EmitValue(Value, Size, L); +    return false; +  }; +  return (parseMany(parseOne)); +} + +extern "C" void LLVMInitializeMSP430AsmParser() { +  RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target()); +} + +#define GET_REGISTER_MATCHER +#define GET_MATCHER_IMPLEMENTATION +#include "MSP430GenAsmMatcher.inc" + +static unsigned convertGR16ToGR8(unsigned Reg) { +  switch (Reg) { +  default: +    llvm_unreachable("Unknown GR16 register"); +  case MSP430::PC:  return MSP430::PCB; +  case MSP430::SP:  return MSP430::SPB; +  case MSP430::SR:  return MSP430::SRB; +  case MSP430::CG:  return MSP430::CGB; +  case MSP430::FP:  return MSP430::FPB; +  case MSP430::R5:  return MSP430::R5B; +  case MSP430::R6:  return MSP430::R6B; +  case MSP430::R7:  return MSP430::R7B; +  case MSP430::R8:  return MSP430::R8B; +  case MSP430::R9:  return MSP430::R9B; +  case MSP430::R10: return MSP430::R10B; +  case MSP430::R11: return MSP430::R11B; +  case MSP430::R12: return MSP430::R12B; +  case MSP430::R13: return MSP430::R13B; +  case MSP430::R14: return MSP430::R14B; +  case MSP430::R15: return MSP430::R15B; +  } +} + +unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, +                                                     unsigned Kind) { +  MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp); + +  if (!Op.isReg()) +    return Match_InvalidOperand; + +  unsigned Reg = Op.getReg(); +  bool isGR16 = +      MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg); + +  if (isGR16 && (Kind == MCK_GR8)) { +    Op.setReg(convertGR16ToGR8(Reg)); +    return Match_Success; +  } + +  return Match_InvalidOperand; +} diff --git a/llvm/lib/Target/MSP430/Disassembler/CMakeLists.txt b/llvm/lib/Target/MSP430/Disassembler/CMakeLists.txt new file mode 100644 index 00000000000..bc33b906772 --- /dev/null +++ b/llvm/lib/Target/MSP430/Disassembler/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMMSP430Disassembler +  MSP430Disassembler.cpp +  ) diff --git a/llvm/lib/Target/MSP430/Disassembler/LLVMBuild.txt b/llvm/lib/Target/MSP430/Disassembler/LLVMBuild.txt new file mode 100644 index 00000000000..8af9cd9c222 --- /dev/null +++ b/llvm/lib/Target/MSP430/Disassembler/LLVMBuild.txt @@ -0,0 +1,23 @@ +;====- lib/Target/MSP430/Disassembler/LLVMBuild.txt ------------*- Conf -*--===; +; +;                     The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +;   http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = MSP430Disassembler +parent = MSP430 +required_libraries = MCDisassembler MSP430Info Support +add_to_library_groups = MSP430 diff --git a/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp b/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp new file mode 100644 index 00000000000..2a66b4ed7f2 --- /dev/null +++ b/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp @@ -0,0 +1,375 @@ +//===-- MSP430Disassembler.cpp - Disassembler for MSP430 ------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MSP430Disassembler class. +// +//===----------------------------------------------------------------------===// + +#include "MSP430.h" +#include "MCTargetDesc/MSP430MCTargetDesc.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "msp430-disassembler" + +typedef MCDisassembler::DecodeStatus DecodeStatus; + +namespace { +class MSP430Disassembler : public MCDisassembler { +  DecodeStatus getInstructionI(MCInst &MI, uint64_t &Size, +                               ArrayRef<uint8_t> Bytes, uint64_t Address, +                               raw_ostream &VStream, +                               raw_ostream &CStream) const; + +  DecodeStatus getInstructionII(MCInst &MI, uint64_t &Size, +                                ArrayRef<uint8_t> Bytes, uint64_t Address, +                                raw_ostream &VStream, +                                raw_ostream &CStream) const; + +  DecodeStatus getInstructionCJ(MCInst &MI, uint64_t &Size, +                                ArrayRef<uint8_t> Bytes, uint64_t Address, +                                raw_ostream &VStream, +                                raw_ostream &CStream) const; + +public: +  MSP430Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx) +      : MCDisassembler(STI, Ctx) {} + +  DecodeStatus getInstruction(MCInst &MI, uint64_t &Size, +                              ArrayRef<uint8_t> Bytes, uint64_t Address, +                              raw_ostream &VStream, +                              raw_ostream &CStream) const override; +}; +} // end anonymous namespace + +static MCDisassembler *createMSP430Disassembler(const Target &T, +                                                const MCSubtargetInfo &STI, +                                                MCContext &Ctx) { +  return new MSP430Disassembler(STI, Ctx); +} + +extern "C" void LLVMInitializeMSP430Disassembler() { +  TargetRegistry::RegisterMCDisassembler(getTheMSP430Target(), +                                         createMSP430Disassembler); +} + +static const unsigned GR8DecoderTable[] = { +  MSP430::PCB,  MSP430::SPB,  MSP430::SRB,  MSP430::CGB, +  MSP430::FPB,  MSP430::R5B,  MSP430::R6B,  MSP430::R7B, +  MSP430::R8B,  MSP430::R9B,  MSP430::R10B, MSP430::R11B, +  MSP430::R12B, MSP430::R13B, MSP430::R14B, MSP430::R15B +}; + +static DecodeStatus DecodeGR8RegisterClass(MCInst &MI, uint64_t RegNo, +                                           uint64_t Address, +                                           const void *Decoder) { +  if (RegNo > 15) +    return MCDisassembler::Fail; + +  unsigned Reg = GR8DecoderTable[RegNo]; +  MI.addOperand(MCOperand::createReg(Reg)); +  return MCDisassembler::Success; +} + +static const unsigned GR16DecoderTable[] = { +  MSP430::PC,  MSP430::SP,  MSP430::SR,  MSP430::CG, +  MSP430::FP,  MSP430::R5,  MSP430::R6,  MSP430::R7, +  MSP430::R8,  MSP430::R9,  MSP430::R10, MSP430::R11, +  MSP430::R12, MSP430::R13, MSP430::R14, MSP430::R15 +}; + +static DecodeStatus DecodeGR16RegisterClass(MCInst &MI, uint64_t RegNo, +                                            uint64_t Address, +                                            const void *Decoder) { +  if (RegNo > 15) +    return MCDisassembler::Fail; + +  unsigned Reg = GR16DecoderTable[RegNo]; +  MI.addOperand(MCOperand::createReg(Reg)); +  return MCDisassembler::Success; +} + +static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address, +                                const void *Decoder); + +static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits, +                                     uint64_t Address, +                                     const void *Decoder); + +#include "MSP430GenDisassemblerTables.inc" + +static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address, +                                const void *Decoder) { +  int64_t Imm; +  switch (Bits) { +  default: +    llvm_unreachable("Invalid immediate value"); +  case 0x22: Imm =  4; break; +  case 0x32: Imm =  8; break; +  case 0x03: Imm =  0; break; +  case 0x13: Imm =  1; break; +  case 0x23: Imm =  2; break; +  case 0x33: Imm = -1; break; +  } +  MI.addOperand(MCOperand::createImm(Imm)); +  return MCDisassembler::Success; +} + +static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits, +                                     uint64_t Address, +                                     const void *Decoder) { +  unsigned Reg = Bits & 15; +  unsigned Imm = Bits >> 4; + +  if (DecodeGR16RegisterClass(MI, Reg, Address, Decoder) != +      MCDisassembler::Success) +    return MCDisassembler::Fail; +   +  MI.addOperand(MCOperand::createImm((int16_t)Imm)); +  return MCDisassembler::Success; +} + +enum AddrMode { +  amInvalid = 0, +  amRegister, +  amIndexed, +  amIndirect, +  amIndirectPost, +  amSymbolic, +  amImmediate, +  amAbsolute, +  amConstant +}; + +static AddrMode DecodeSrcAddrMode(unsigned Rs, unsigned As) { +  switch (Rs) { +  case 0: +    if (As == 1) return amSymbolic; +    if (As == 2) return amInvalid; +    if (As == 3) return amImmediate; +    break; +  case 2: +    if (As == 1) return amAbsolute; +    if (As == 2) return amConstant; +    if (As == 3) return amConstant; +    break; +  case 3: +    return amConstant; +  default: +    break; +  } +  switch (As) { +  case 0: return amRegister; +  case 1: return amIndexed; +  case 2: return amIndirect; +  case 3: return amIndirectPost; +  default: +    llvm_unreachable("As out of range"); +  } +} + +static AddrMode DecodeSrcAddrModeI(unsigned Insn) { +  unsigned Rs = fieldFromInstruction(Insn, 8, 4); +  unsigned As = fieldFromInstruction(Insn, 4, 2); +  return DecodeSrcAddrMode(Rs, As); +} + +static AddrMode DecodeSrcAddrModeII(unsigned Insn) { +  unsigned Rs = fieldFromInstruction(Insn, 0, 4); +  unsigned As = fieldFromInstruction(Insn, 4, 2); +  return DecodeSrcAddrMode(Rs, As); +} + +static AddrMode DecodeDstAddrMode(unsigned Insn) { +  unsigned Rd = fieldFromInstruction(Insn, 0, 4); +  unsigned Ad = fieldFromInstruction(Insn, 7, 1); +  switch (Rd) { +  case 0: return Ad ? amSymbolic : amRegister; +  case 2: return Ad ? amAbsolute : amRegister; +  default: +    break; +  } +  return Ad ? amIndexed : amRegister; +} + +static const uint8_t *getDecoderTable(AddrMode SrcAM, unsigned Words) { +  assert(0 < Words && Words < 4 && "Incorrect number of words"); +  switch (SrcAM) { +  default: +    llvm_unreachable("Invalid addressing mode"); +  case amRegister: +    assert(Words < 3 && "Incorrect number of words"); +    return Words == 2 ? DecoderTableAlpha32 : DecoderTableAlpha16; +  case amConstant: +    assert(Words < 3 && "Incorrect number of words"); +    return Words == 2 ? DecoderTableBeta32 : DecoderTableBeta16; +  case amIndexed: +  case amSymbolic: +  case amImmediate: +  case amAbsolute: +    assert(Words > 1 && "Incorrect number of words"); +    return Words == 2 ? DecoderTableGamma32 : DecoderTableGamma48; +  case amIndirect: +  case amIndirectPost: +    assert(Words < 3 && "Incorrect number of words"); +    return Words == 2 ? DecoderTableDelta32 : DecoderTableDelta16; +  } +} + +DecodeStatus MSP430Disassembler::getInstructionI(MCInst &MI, uint64_t &Size, +                                                 ArrayRef<uint8_t> Bytes, +                                                 uint64_t Address, +                                                 raw_ostream &VStream, +                                                 raw_ostream &CStream) const { +  uint64_t Insn = support::endian::read16le(Bytes.data()); +  AddrMode SrcAM = DecodeSrcAddrModeI(Insn); +  AddrMode DstAM = DecodeDstAddrMode(Insn); +  if (SrcAM == amInvalid || DstAM == amInvalid) { +    Size = 2; // skip one word and let disassembler to try further +    return MCDisassembler::Fail; +  } + +  unsigned Words = 1; +  switch (SrcAM) { +  case amIndexed: +  case amSymbolic: +  case amImmediate: +  case amAbsolute: +    Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16; +    ++Words; +    break; +  default: +    break; +  } +  switch (DstAM) { +  case amIndexed: +  case amSymbolic: +  case amAbsolute: +    Insn |= (uint64_t)support::endian::read16le(Bytes.data() + Words * 2) +        << (Words * 16); +    ++Words; +    break; +  default: +    break; +  } + +  DecodeStatus Result = decodeInstruction(getDecoderTable(SrcAM, Words), MI, +                                          Insn, Address, this, STI); +  if (Result != MCDisassembler::Fail) { +    Size = Words * 2; +    return Result; +  } + +  Size = 2; +  return DecodeStatus::Fail; +} + +DecodeStatus MSP430Disassembler::getInstructionII(MCInst &MI, uint64_t &Size, +                                                  ArrayRef<uint8_t> Bytes, +                                                  uint64_t Address, +                                                  raw_ostream &VStream, +                                                  raw_ostream &CStream) const { +  uint64_t Insn = support::endian::read16le(Bytes.data()); +  AddrMode SrcAM = DecodeSrcAddrModeII(Insn); +  if (SrcAM == amInvalid) { +    Size = 2; // skip one word and let disassembler to try further +    return MCDisassembler::Fail; +  } + +  unsigned Words = 1; +  switch (SrcAM) { +  case amIndexed: +  case amSymbolic: +  case amImmediate: +  case amAbsolute: +    Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16; +    ++Words; +    break; +  default: +    break; +  } + +  const uint8_t *DecoderTable = Words == 2 ? DecoderTable32 : DecoderTable16; +  DecodeStatus Result = decodeInstruction(DecoderTable, MI, Insn, Address, +                                          this, STI); +  if (Result != MCDisassembler::Fail) { +    Size = Words * 2; +    return Result; +  } + +  Size = 2; +  return DecodeStatus::Fail; +} + +static MSP430CC::CondCodes getCondCode(unsigned Cond) { +  switch (Cond) { +  case 0: return MSP430CC::COND_NE; +  case 1: return MSP430CC::COND_E; +  case 2: return MSP430CC::COND_LO; +  case 3: return MSP430CC::COND_HS; +  case 4: return MSP430CC::COND_N; +  case 5: return MSP430CC::COND_GE; +  case 6: return MSP430CC::COND_L; +  case 7: return MSP430CC::COND_NONE; +  default: +    llvm_unreachable("Cond out of range"); +  } +} + +DecodeStatus MSP430Disassembler::getInstructionCJ(MCInst &MI, uint64_t &Size, +                                                  ArrayRef<uint8_t> Bytes, +                                                  uint64_t Address, +                                                  raw_ostream &VStream, +                                                  raw_ostream &CStream) const { +  uint64_t Insn = support::endian::read16le(Bytes.data()); +  unsigned Cond = fieldFromInstruction(Insn, 10, 3); +  unsigned Offset = fieldFromInstruction(Insn, 0, 10); + +  MI.addOperand(MCOperand::createImm(SignExtend32(Offset, 10))); + +  if (Cond == 7) +    MI.setOpcode(MSP430::JMP); +  else { +    MI.setOpcode(MSP430::JCC); +    MI.addOperand(MCOperand::createImm(getCondCode(Cond))); +  } + +  Size = 2; +  return DecodeStatus::Success; +} + +DecodeStatus MSP430Disassembler::getInstruction(MCInst &MI, uint64_t &Size, +                                                ArrayRef<uint8_t> Bytes, +                                                uint64_t Address, +                                                raw_ostream &VStream, +                                                raw_ostream &CStream) const { +  if (Bytes.size() < 2) { +    Size = 0; +    return MCDisassembler::Fail; +  } + +  uint64_t Insn = support::endian::read16le(Bytes.data()); +  unsigned Opc = fieldFromInstruction(Insn, 13, 3); +  switch (Opc) { +  case 0: +    return getInstructionII(MI, Size, Bytes, Address, VStream, CStream); +  case 1: +    return getInstructionCJ(MI, Size, Bytes, Address, VStream, CStream); +  default: +    return getInstructionI(MI, Size, Bytes, Address, VStream, CStream); +  } +} diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp new file mode 100644 index 00000000000..bd69a9d8d79 --- /dev/null +++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp @@ -0,0 +1,178 @@ +//===-- MSP430AsmBackend.cpp - MSP430 Assembler Backend -------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/MSP430FixupKinds.h" +#include "MCTargetDesc/MSP430MCTargetDesc.h" +#include "llvm/ADT/APInt.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { +class MSP430AsmBackend : public MCAsmBackend { +  uint8_t OSABI; + +  uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, +                            MCContext &Ctx) const; + +public: +  MSP430AsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI) +      : MCAsmBackend(support::little), OSABI(OSABI) {} +  ~MSP430AsmBackend() override {} + +  void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, +                  const MCValue &Target, MutableArrayRef<char> Data, +                  uint64_t Value, bool IsResolved, +                  const MCSubtargetInfo *STI) const override; + +  std::unique_ptr<MCObjectTargetWriter> +  createObjectTargetWriter() const override { +    return createMSP430ELFObjectWriter(OSABI); +  } + +  bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, +                            const MCRelaxableFragment *DF, +                            const MCAsmLayout &Layout) const override { +    return false; +  } + +  bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved, +                                    uint64_t Value, +                                    const MCRelaxableFragment *DF, +                                    const MCAsmLayout &Layout, +                                    const bool WasForced) const override { +    return false; +  } + +  unsigned getNumFixupKinds() const override { +    return MSP430::NumTargetFixupKinds; +  } + +  const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { +    const static MCFixupKindInfo Infos[MSP430::NumTargetFixupKinds] = { +      // This table must be in the same order of enum in MSP430FixupKinds.h. +      // +      // name            offset bits flags +      {"fixup_32",            0, 32, 0}, +      {"fixup_10_pcrel",      0, 10, MCFixupKindInfo::FKF_IsPCRel}, +      {"fixup_16",            0, 16, 0}, +      {"fixup_16_pcrel",      0, 16, MCFixupKindInfo::FKF_IsPCRel}, +      {"fixup_16_byte",       0, 16, 0}, +      {"fixup_16_pcrel_byte", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, +      {"fixup_2x_pcrel",      0, 10, MCFixupKindInfo::FKF_IsPCRel}, +      {"fixup_rl_pcrel",      0, 16, MCFixupKindInfo::FKF_IsPCRel}, +      {"fixup_8",             0,  8, 0}, +      {"fixup_sym_diff",      0, 32, 0}, +    }; +    static_assert((array_lengthof(Infos)) == MSP430::NumTargetFixupKinds, +                  "Not all fixup kinds added to Infos array"); +   +    if (Kind < FirstTargetFixupKind) +      return MCAsmBackend::getFixupKindInfo(Kind); +   +    return Infos[Kind - FirstTargetFixupKind]; +  } + +  bool mayNeedRelaxation(const MCInst &Inst, +                         const MCSubtargetInfo &STI) const override { +    return false; +  } + +  void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, +                        MCInst &Res) const override {} + +  bool writeNopData(raw_ostream &OS, uint64_t Count) const override; +}; + +uint64_t MSP430AsmBackend::adjustFixupValue(const MCFixup &Fixup, +                                            uint64_t Value, +                                            MCContext &Ctx) const { +  unsigned Kind = Fixup.getKind(); +  switch (Kind) { +  case MSP430::fixup_10_pcrel: { +    if (Value & 0x1) +      Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned"); + +    // Offset is signed +    int16_t Offset = Value; +    // Jumps are in words +    Offset >>= 1; +    // PC points to the next instruction so decrement by one +    --Offset; + +    if (Offset < -512 || Offset > 511) +      Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); + +    // Mask 10 bits +    Offset &= 0x3ff; + +    return Offset; +  } +  default: +    return Value; +  } +} + +void MSP430AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, +                                  const MCValue &Target, +                                  MutableArrayRef<char> Data, +                                  uint64_t Value, bool IsResolved, +                                  const MCSubtargetInfo *STI) const { +  Value = adjustFixupValue(Fixup, Value, Asm.getContext()); +  MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); +  if (!Value) +    return; // Doesn't change encoding. + +  // Shift the value into position. +  Value <<= Info.TargetOffset; + +  unsigned Offset = Fixup.getOffset(); +  unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8; + +  assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); + +  // For each byte of the fragment that the fixup touches, mask in the +  // bits from the fixup value. +  for (unsigned i = 0; i != NumBytes; ++i) { +    Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); +  } +} + +bool MSP430AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { +  if ((Count % 2) != 0) +    return false; + +  // The canonical nop on MSP430 is mov #0, r3 +  uint64_t NopCount = Count / 2; +  while (NopCount--) +    OS.write("\x03\x43", 2); + +  return true; +} + +} // end anonymous namespace + +MCAsmBackend *llvm::createMSP430MCAsmBackend(const Target &T, +                                             const MCSubtargetInfo &STI, +                                             const MCRegisterInfo &MRI, +                                             const MCTargetOptions &Options) { +  return new MSP430AsmBackend(STI, ELF::ELFOSABI_STANDALONE); +} diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp new file mode 100644 index 00000000000..30d077b5b58 --- /dev/null +++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp @@ -0,0 +1,59 @@ +//===-- MSP430ELFObjectWriter.cpp - MSP430 ELF Writer ---------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/MSP430FixupKinds.h" +#include "MCTargetDesc/MSP430MCTargetDesc.h" + +#include "MCTargetDesc/MSP430MCTargetDesc.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +namespace { +class MSP430ELFObjectWriter : public MCELFObjectTargetWriter { +public: +  MSP430ELFObjectWriter(uint8_t OSABI) +    : MCELFObjectTargetWriter(false, OSABI, ELF::EM_MSP430, +                              /*HasRelocationAddend*/ true) {} + +  ~MSP430ELFObjectWriter() override {} + +protected: +  unsigned getRelocType(MCContext &Ctx, const MCValue &Target, +                        const MCFixup &Fixup, bool IsPCRel) const override { +    // Translate fixup kind to ELF relocation type. +    switch ((unsigned)Fixup.getKind()) { +    case FK_Data_1:                   return ELF::R_MSP430_8; +    case FK_Data_2:                   return ELF::R_MSP430_16; +    case FK_Data_4:                   return ELF::R_MSP430_32; +    case MSP430::fixup_32:            return ELF::R_MSP430_32; +    case MSP430::fixup_10_pcrel:      return ELF::R_MSP430_10_PCREL; +    case MSP430::fixup_16:            return ELF::R_MSP430_16; +    case MSP430::fixup_16_pcrel:      return ELF::R_MSP430_16_PCREL; +    case MSP430::fixup_16_byte:       return ELF::R_MSP430_16_BYTE; +    case MSP430::fixup_16_pcrel_byte: return ELF::R_MSP430_16_PCREL_BYTE; +    case MSP430::fixup_2x_pcrel:      return ELF::R_MSP430_2X_PCREL; +    case MSP430::fixup_rl_pcrel:      return ELF::R_MSP430_RL_PCREL; +    case MSP430::fixup_8:             return ELF::R_MSP430_8; +    case MSP430::fixup_sym_diff:      return ELF::R_MSP430_SYM_DIFF; +    default: +      llvm_unreachable("Invalid fixup kind"); +    } +  } +}; +} // end of anonymous namespace + +std::unique_ptr<MCObjectTargetWriter> +llvm::createMSP430ELFObjectWriter(uint8_t OSABI) { +  return llvm::make_unique<MSP430ELFObjectWriter>(OSABI); +} diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp new file mode 100644 index 00000000000..9449cb27802 --- /dev/null +++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp @@ -0,0 +1,81 @@ +//===-- MSP430ELFStreamer.cpp - MSP430 ELF Target Streamer Methods --------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides MSP430 specific target streamer methods. +// +//===----------------------------------------------------------------------===// + +#include "MSP430MCTargetDesc.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" + +using namespace llvm; + +namespace llvm { + +class MSP430TargetELFStreamer : public MCTargetStreamer { +public: +  MCELFStreamer &getStreamer(); +  MSP430TargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); +}; + +// This part is for ELF object output. +MSP430TargetELFStreamer::MSP430TargetELFStreamer(MCStreamer &S, +                                                 const MCSubtargetInfo &STI) +    : MCTargetStreamer(S) { +  MCAssembler &MCA = getStreamer().getAssembler(); +  unsigned EFlags = MCA.getELFHeaderEFlags(); +  MCA.setELFHeaderEFlags(EFlags); + +  // Emit build attributes section according to +  // MSP430 EABI (slaa534.pdf, part 13). +  MCSection *AttributeSection = getStreamer().getContext().getELFSection( +      ".MSP430.attributes", ELF::SHT_MSP430_ATTRIBUTES, 0); +  Streamer.SwitchSection(AttributeSection); + +  // Format version. +  Streamer.EmitIntValue(0x41, 1); +  // Subsection length. +  Streamer.EmitIntValue(22, 4); +  // Vendor name string, zero-terminated. +  Streamer.EmitBytes("mspabi"); +  Streamer.EmitIntValue(0, 1); + +  // Attribute vector scope tag. 1 stands for the entire file. +  Streamer.EmitIntValue(1, 1); +  // Attribute vector length. +  Streamer.EmitIntValue(11, 4); +  // OFBA_MSPABI_Tag_ISA(4) = 1, MSP430 +  Streamer.EmitIntValue(4, 1); +  Streamer.EmitIntValue(1, 1); +  // OFBA_MSPABI_Tag_Code_Model(6) = 1, Small +  Streamer.EmitIntValue(6, 1); +  Streamer.EmitIntValue(1, 1); +  // OFBA_MSPABI_Tag_Data_Model(8) = 1, Small +  Streamer.EmitIntValue(8, 1); +  Streamer.EmitIntValue(1, 1); +} + +MCELFStreamer &MSP430TargetELFStreamer::getStreamer() { +  return static_cast<MCELFStreamer &>(Streamer); +} + +MCTargetStreamer * +createMSP430ObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { +  const Triple &TT = STI.getTargetTriple(); +  if (TT.isOSBinFormatELF()) +    return new MSP430TargetELFStreamer(S, STI); +  return nullptr; +} + +} // namespace llvm diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h new file mode 100644 index 00000000000..1eb6a275942 --- /dev/null +++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h @@ -0,0 +1,53 @@ +//===-- MSP430FixupKinds.h - MSP430 Specific Fixup Entries ------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_MSP430_MCTARGETDESC_MSP430FIXUPKINDS_H +#define LLVM_LIB_TARGET_MSP430_MCTARGETDESC_MSP430FIXUPKINDS_H + +#include "llvm/MC/MCFixup.h" + +#undef MSP430 + +namespace llvm { +namespace MSP430 { + +// This table must be in the same order of +// MCFixupKindInfo Infos[MSP430::NumTargetFixupKinds] +// in MSP430AsmBackend.cpp. +// +enum Fixups { +  // A 32 bit absolute fixup. +  fixup_32 = FirstTargetFixupKind, +  // A 10 bit PC relative fixup. +  fixup_10_pcrel, +  // A 16 bit absolute fixup. +  fixup_16, +  // A 16 bit PC relative fixup. +  fixup_16_pcrel, +  // A 16 bit absolute fixup for byte operations. +  fixup_16_byte, +  // A 16 bit PC relative fixup for command address. +  fixup_16_pcrel_byte, +  // A 10 bit PC relative fixup for complicated polymorphs. +  fixup_2x_pcrel, +  // A 16 bit relaxable fixup. +  fixup_rl_pcrel, +  // A 8 bit absolute fixup. +  fixup_8, +  // A 32 bit symbol difference fixup. +  fixup_sym_diff, + +  // Marker +  LastTargetFixupKind, +  NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind +}; +} // end namespace MSP430 +} // end namespace llvm + +#endif diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp new file mode 100644 index 00000000000..adf2384f6e9 --- /dev/null +++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp @@ -0,0 +1,211 @@ +//===-- MSP430MCCodeEmitter.cpp - Convert MSP430 code to machine code -----===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MSP430MCCodeEmitter class. +// +//===----------------------------------------------------------------------===// + +#include "MSP430.h" +#include "MCTargetDesc/MSP430MCTargetDesc.h" +#include "MCTargetDesc/MSP430FixupKinds.h" + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "mccodeemitter" + +namespace llvm { + +class MSP430MCCodeEmitter : public MCCodeEmitter { +  MCContext &Ctx; +  MCInstrInfo const &MCII; + +  // Offset keeps track of current word number being emitted +  // inside a particular instruction. +  mutable unsigned Offset; + +  /// TableGen'erated function for getting the binary encoding for an +  /// instruction. +  uint64_t getBinaryCodeForInstr(const MCInst &MI, +                                 SmallVectorImpl<MCFixup> &Fixups, +                                 const MCSubtargetInfo &STI) const; + +  /// Returns the binary encoding of operands. +  /// +  /// If an operand requires relocation, the relocation is recorded +  /// and zero is returned. +  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, +                             SmallVectorImpl<MCFixup> &Fixups, +                             const MCSubtargetInfo &STI) const; + +  unsigned getMemOpValue(const MCInst &MI, unsigned Op, +                         SmallVectorImpl<MCFixup> &Fixups, +                         const MCSubtargetInfo &STI) const; + +  unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op, +                              SmallVectorImpl<MCFixup> &Fixups, +                              const MCSubtargetInfo &STI) const; + +  unsigned getCGImmOpValue(const MCInst &MI, unsigned Op, +                           SmallVectorImpl<MCFixup> &Fixups, +                           const MCSubtargetInfo &STI) const; + +  unsigned getCCOpValue(const MCInst &MI, unsigned Op, +                        SmallVectorImpl<MCFixup> &Fixups, +                        const MCSubtargetInfo &STI) const; + +public: +  MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII) +      : Ctx(ctx), MCII(MCII) {} + +  void encodeInstruction(const MCInst &MI, raw_ostream &OS, +                         SmallVectorImpl<MCFixup> &Fixups, +                         const MCSubtargetInfo &STI) const override; +}; + +void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, +                                            SmallVectorImpl<MCFixup> &Fixups, +                                            const MCSubtargetInfo &STI) const { +  const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); +  // Get byte count of instruction. +  unsigned Size = Desc.getSize(); + +  // Initialize fixup offset +  Offset = 2; + +  uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI); +  size_t WordCount = Size / 2; + +  while (WordCount--) { +    support::endian::write(OS, (uint16_t)BinaryOpCode, support::little); +    BinaryOpCode >>= 16; +  } +} + +unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI, +                                                const MCOperand &MO, +                                                SmallVectorImpl<MCFixup> &Fixups, +                                                const MCSubtargetInfo &STI) const { +  if (MO.isReg()) +    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); + +  if (MO.isImm()) { +    Offset += 2; +    return MO.getImm(); +  } + +  assert(MO.isExpr() && "Expected expr operand"); +  Fixups.push_back(MCFixup::create(Offset, MO.getExpr(), +      static_cast<MCFixupKind>(MSP430::fixup_16_byte), MI.getLoc())); +  Offset += 2; +  return 0; +} + +unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op, +                                            SmallVectorImpl<MCFixup> &Fixups, +                                            const MCSubtargetInfo &STI) const { +  const MCOperand &MO1 = MI.getOperand(Op); +  assert(MO1.isReg() && "Register operand expected"); +  unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg()); + +  const MCOperand &MO2 = MI.getOperand(Op + 1); +  if (MO2.isImm()) { +    Offset += 2; +    return (MO2.getImm() << 4) | Reg; +  } + +  assert(MO2.isExpr() && "Expr operand expected"); +  MSP430::Fixups FixupKind; +  switch (Reg) { +  case 0: +    FixupKind = MSP430::fixup_16_pcrel_byte; +    break; +  case 2: +    FixupKind = MSP430::fixup_16_byte; +    break; +  default: +    FixupKind = MSP430::fixup_16_byte; +    break; +  } +  Fixups.push_back(MCFixup::create(Offset, MO2.getExpr(), +    static_cast<MCFixupKind>(FixupKind), MI.getLoc())); +  Offset += 2; +  return Reg; +} + +unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op, +                                                 SmallVectorImpl<MCFixup> &Fixups, +                                                 const MCSubtargetInfo &STI) const { +  const MCOperand &MO = MI.getOperand(Op); +  if (MO.isImm()) +    return MO.getImm(); + +  assert(MO.isExpr() && "Expr operand expected"); +  Fixups.push_back(MCFixup::create(0, MO.getExpr(), +    static_cast<MCFixupKind>(MSP430::fixup_10_pcrel), MI.getLoc())); +  return 0; +} + +unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op, +                                              SmallVectorImpl<MCFixup> &Fixups, +                                              const MCSubtargetInfo &STI) const { +  const MCOperand &MO = MI.getOperand(Op); +  assert(MO.isImm() && "Expr operand expected"); +   +  int64_t Imm = MO.getImm(); +  switch (Imm) { +  default: +    llvm_unreachable("Invalid immediate value"); +  case 4:  return 0x22; +  case 8:  return 0x32; +  case 0:  return 0x03; +  case 1:  return 0x13; +  case 2:  return 0x23; +  case -1: return 0x33; +  } +} + +unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op, +                                           SmallVectorImpl<MCFixup> &Fixups, +                                           const MCSubtargetInfo &STI) const { +  const MCOperand &MO = MI.getOperand(Op); +  assert(MO.isImm() && "Immediate operand expected"); +  switch (MO.getImm()) { +  case MSP430CC::COND_NE: return 0; +  case MSP430CC::COND_E:  return 1; +  case MSP430CC::COND_LO: return 2; +  case MSP430CC::COND_HS: return 3; +  case MSP430CC::COND_N:  return 4; +  case MSP430CC::COND_GE: return 5; +  case MSP430CC::COND_L:  return 6; +  default: +    llvm_unreachable("Unknown condition code"); +  } +} + +MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII, +                                         const MCRegisterInfo &MRI, +                                         MCContext &Ctx) { +  return new MSP430MCCodeEmitter(Ctx, MCII); +} + +#include "MSP430GenMCCodeEmitter.inc" + +} // end of namespace llvm | 

