[llvm] r346949 - Add missed files from prev. commit
Anton Korobeynikov via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 15 04:35:04 PST 2018
Author: asl
Date: Thu Nov 15 04:35:04 2018
New Revision: 346949
URL: http://llvm.org/viewvc/llvm-project?rev=346949&view=rev
Log:
Add missed files from prev. commit
Added:
llvm/trunk/include/llvm/BinaryFormat/ELFRelocs/MSP430.def
llvm/trunk/lib/Target/MSP430/AsmParser/
llvm/trunk/lib/Target/MSP430/AsmParser/CMakeLists.txt
llvm/trunk/lib/Target/MSP430/AsmParser/LLVMBuild.txt
llvm/trunk/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
llvm/trunk/lib/Target/MSP430/Disassembler/
llvm/trunk/lib/Target/MSP430/Disassembler/CMakeLists.txt
llvm/trunk/lib/Target/MSP430/Disassembler/LLVMBuild.txt
llvm/trunk/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp
llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp
llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp
llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp
llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h
llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp
Added: llvm/trunk/include/llvm/BinaryFormat/ELFRelocs/MSP430.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/ELFRelocs/MSP430.def?rev=346949&view=auto
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/ELFRelocs/MSP430.def (added)
+++ llvm/trunk/include/llvm/BinaryFormat/ELFRelocs/MSP430.def Thu Nov 15 04:35:04 2018
@@ -0,0 +1,16 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_MSP430_NONE, 0)
+ELF_RELOC(R_MSP430_32, 1)
+ELF_RELOC(R_MSP430_10_PCREL, 2)
+ELF_RELOC(R_MSP430_16, 3)
+ELF_RELOC(R_MSP430_16_PCREL, 4)
+ELF_RELOC(R_MSP430_16_BYTE, 5)
+ELF_RELOC(R_MSP430_16_PCREL_BYTE, 6)
+ELF_RELOC(R_MSP430_2X_PCREL, 7)
+ELF_RELOC(R_MSP430_RL_PCREL, 8)
+ELF_RELOC(R_MSP430_8, 9)
+ELF_RELOC(R_MSP430_SYM_DIFF, 10)
Added: llvm/trunk/lib/Target/MSP430/AsmParser/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/AsmParser/CMakeLists.txt?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/AsmParser/CMakeLists.txt (added)
+++ llvm/trunk/lib/Target/MSP430/AsmParser/CMakeLists.txt Thu Nov 15 04:35:04 2018
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMMSP430AsmParser
+ MSP430AsmParser.cpp
+)
Added: llvm/trunk/lib/Target/MSP430/AsmParser/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/AsmParser/LLVMBuild.txt?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/AsmParser/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Target/MSP430/AsmParser/LLVMBuild.txt Thu Nov 15 04:35:04 2018
@@ -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
Added: llvm/trunk/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp (added)
+++ llvm/trunk/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp Thu Nov 15 04:35:04 2018
@@ -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;
+}
Added: llvm/trunk/lib/Target/MSP430/Disassembler/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/Disassembler/CMakeLists.txt?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/Disassembler/CMakeLists.txt (added)
+++ llvm/trunk/lib/Target/MSP430/Disassembler/CMakeLists.txt Thu Nov 15 04:35:04 2018
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMMSP430Disassembler
+ MSP430Disassembler.cpp
+ )
Added: llvm/trunk/lib/Target/MSP430/Disassembler/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/Disassembler/LLVMBuild.txt?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/Disassembler/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Target/MSP430/Disassembler/LLVMBuild.txt Thu Nov 15 04:35:04 2018
@@ -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
Added: llvm/trunk/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp (added)
+++ llvm/trunk/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp Thu Nov 15 04:35:04 2018
@@ -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);
+ }
+}
Added: llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp (added)
+++ llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp Thu Nov 15 04:35:04 2018
@@ -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);
+}
Added: llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp (added)
+++ llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp Thu Nov 15 04:35:04 2018
@@ -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);
+}
Added: llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp (added)
+++ llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp Thu Nov 15 04:35:04 2018
@@ -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
Added: llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h (added)
+++ llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h Thu Nov 15 04:35:04 2018
@@ -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
Added: llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp?rev=346949&view=auto
==============================================================================
--- llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp (added)
+++ llvm/trunk/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp Thu Nov 15 04:35:04 2018
@@ -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
More information about the llvm-commits
mailing list