summaryrefslogtreecommitdiff
path: root/lib/Target/MSP430
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Target/MSP430
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
downloadsrc-test2-d8e91e46262bc44006913e6796843909f1ac7bcd.tar.gz
src-test2-d8e91e46262bc44006913e6796843909f1ac7bcd.zip
Notes
Diffstat (limited to 'lib/Target/MSP430')
-rw-r--r--lib/Target/MSP430/AsmParser/CMakeLists.txt3
-rw-r--r--lib/Target/MSP430/AsmParser/LLVMBuild.txt23
-rw-r--r--lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp580
-rw-r--r--lib/Target/MSP430/CMakeLists.txt5
-rw-r--r--lib/Target/MSP430/Disassembler/CMakeLists.txt3
-rw-r--r--lib/Target/MSP430/Disassembler/LLVMBuild.txt23
-rw-r--r--lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp387
-rw-r--r--lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp36
-rw-r--r--lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h7
-rw-r--r--lib/Target/MSP430/LLVMBuild.txt4
-rw-r--r--lib/Target/MSP430/MCTargetDesc/CMakeLists.txt6
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp178
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp59
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp81
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h53
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp1
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp211
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp27
-rw-r--r--lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h27
-rw-r--r--lib/Target/MSP430/MSP430.h2
-rw-r--r--lib/Target/MSP430/MSP430.td18
-rw-r--r--lib/Target/MSP430/MSP430ISelDAGToDAG.cpp37
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.cpp127
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.h8
-rw-r--r--lib/Target/MSP430/MSP430InstrFormats.td422
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.cpp45
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.h16
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.td1483
-rw-r--r--lib/Target/MSP430/MSP430MCInstLower.cpp3
-rw-r--r--lib/Target/MSP430/MSP430RegisterInfo.td29
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.cpp8
31 files changed, 2831 insertions, 1081 deletions
diff --git a/lib/Target/MSP430/AsmParser/CMakeLists.txt b/lib/Target/MSP430/AsmParser/CMakeLists.txt
new file mode 100644
index 000000000000..bb484898afa0
--- /dev/null
+++ b/lib/Target/MSP430/AsmParser/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMMSP430AsmParser
+ MSP430AsmParser.cpp
+)
diff --git a/lib/Target/MSP430/AsmParser/LLVMBuild.txt b/lib/Target/MSP430/AsmParser/LLVMBuild.txt
new file mode 100644
index 000000000000..58f67c07db18
--- /dev/null
+++ b/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/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp b/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
new file mode 100644
index 000000000000..1ad70ac72c73
--- /dev/null
+++ b/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
@@ -0,0 +1,580 @@
+//===- 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;
+ bool ParseDirectiveRefSym(AsmToken DirectiveID);
+
+ 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::ParseDirectiveRefSym(AsmToken DirectiveID) {
+ StringRef Name;
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+ getStreamer().EmitSymbolAttribute(Sym, MCSA_Global);
+ 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());
+ } else if (IDVal.lower() == ".refsym") {
+ return ParseDirectiveRefSym(DirectiveID);
+ }
+ 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;
+ }
+ if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd)
+ Operands.push_back(MSP430Operand::CreateMem(RegNo,
+ MCConstantExpr::create(0, getContext()), StartLoc, EndLoc));
+ else
+ 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/lib/Target/MSP430/CMakeLists.txt b/lib/Target/MSP430/CMakeLists.txt
index 3facfd526a53..2a0848fb3082 100644
--- a/lib/Target/MSP430/CMakeLists.txt
+++ b/lib/Target/MSP430/CMakeLists.txt
@@ -1,9 +1,12 @@
set(LLVM_TARGET_DEFINITIONS MSP430.td)
+tablegen(LLVM MSP430GenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM MSP430GenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM MSP430GenCallingConv.inc -gen-callingconv)
tablegen(LLVM MSP430GenDAGISel.inc -gen-dag-isel)
+tablegen(LLVM MSP430GenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM MSP430GenInstrInfo.inc -gen-instr-info)
+tablegen(LLVM MSP430GenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM MSP430GenRegisterInfo.inc -gen-register-info)
tablegen(LLVM MSP430GenSubtargetInfo.inc -gen-subtarget)
@@ -26,3 +29,5 @@ add_llvm_target(MSP430CodeGen
add_subdirectory(InstPrinter)
add_subdirectory(MCTargetDesc)
add_subdirectory(TargetInfo)
+add_subdirectory(AsmParser)
+add_subdirectory(Disassembler)
diff --git a/lib/Target/MSP430/Disassembler/CMakeLists.txt b/lib/Target/MSP430/Disassembler/CMakeLists.txt
new file mode 100644
index 000000000000..bc33b9067726
--- /dev/null
+++ b/lib/Target/MSP430/Disassembler/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMMSP430Disassembler
+ MSP430Disassembler.cpp
+ )
diff --git a/lib/Target/MSP430/Disassembler/LLVMBuild.txt b/lib/Target/MSP430/Disassembler/LLVMBuild.txt
new file mode 100644
index 000000000000..8af9cd9c2224
--- /dev/null
+++ b/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/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp b/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp
new file mode 100644
index 000000000000..e5da130f9bbb
--- /dev/null
+++ b/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp
@@ -0,0 +1,387 @@
+//===-- 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:
+ if (Bytes.size() < (Words + 1) * 2) {
+ Size = 2;
+ return DecodeStatus::Fail;
+ }
+ Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16;
+ ++Words;
+ break;
+ default:
+ break;
+ }
+ switch (DstAM) {
+ case amIndexed:
+ case amSymbolic:
+ case amAbsolute:
+ if (Bytes.size() < (Words + 1) * 2) {
+ Size = 2;
+ return DecodeStatus::Fail;
+ }
+ 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:
+ if (Bytes.size() < (Words + 1) * 2) {
+ Size = 2;
+ return DecodeStatus::Fail;
+ }
+ 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/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp
index be6d1a84a377..4d62547bc65b 100644
--- a/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp
+++ b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp
@@ -16,28 +16,34 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
using namespace llvm;
#define DEBUG_TYPE "asm-printer"
-
// Include the auto-generated portion of the assembly writer.
+#define PRINT_ALIAS_INSTR
#include "MSP430GenAsmWriter.inc"
void MSP430InstPrinter::printInst(const MCInst *MI, raw_ostream &O,
StringRef Annot, const MCSubtargetInfo &STI) {
- printInstruction(MI, O);
+ if (!printAliasInstr(MI, O))
+ printInstruction(MI, O);
printAnnotation(O, Annot);
}
void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
- if (Op.isImm())
- O << Op.getImm();
- else {
+ if (Op.isImm()) {
+ int64_t Imm = Op.getImm() * 2 + 2;
+ O << "$";
+ if (Imm >= 0)
+ O << '+';
+ O << Imm;
+ } else {
assert(Op.isExpr() && "unknown pcrel immediate operand");
Op.getExpr()->print(O, &MAI);
}
@@ -72,7 +78,7 @@ void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo,
// vs
// mov.w glb(r1), r2
// Otherwise (!) msp430-as will silently miscompile the output :(
- if (!Base.getReg())
+ if (Base.getReg() == MSP430::SR)
O << '&';
if (Disp.isExpr())
@@ -83,10 +89,23 @@ void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo,
}
// Print register base field
- if (Base.getReg())
+ if ((Base.getReg() != MSP430::SR) &&
+ (Base.getReg() != MSP430::PC))
O << '(' << getRegisterName(Base.getReg()) << ')';
}
+void MSP430InstPrinter::printIndRegOperand(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ const MCOperand &Base = MI->getOperand(OpNo);
+ O << "@" << getRegisterName(Base.getReg());
+}
+
+void MSP430InstPrinter::printPostIndRegOperand(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ const MCOperand &Base = MI->getOperand(OpNo);
+ O << "@" << getRegisterName(Base.getReg()) << "+";
+}
+
void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
unsigned CC = MI->getOperand(OpNo).getImm();
@@ -112,5 +131,8 @@ void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo,
case MSP430CC::COND_L:
O << 'l';
break;
+ case MSP430CC::COND_N:
+ O << 'n';
+ break;
}
}
diff --git a/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h
index 72afec18becb..cd02c4fa645a 100644
--- a/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h
+++ b/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h
@@ -28,13 +28,20 @@ namespace llvm {
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
+ bool printAliasInstr(const MCInst *MI, raw_ostream &O);
+ void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
+ unsigned PrintMethodIdx, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo);
+private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
const char *Modifier = nullptr);
void printPCRelImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
void printSrcMemOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
const char *Modifier = nullptr);
+ void printIndRegOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printPostIndRegOperand(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O);
void printCCOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
};
diff --git a/lib/Target/MSP430/LLVMBuild.txt b/lib/Target/MSP430/LLVMBuild.txt
index 51d9702ac560..0cbd1851777b 100644
--- a/lib/Target/MSP430/LLVMBuild.txt
+++ b/lib/Target/MSP430/LLVMBuild.txt
@@ -16,13 +16,15 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = InstPrinter MCTargetDesc TargetInfo
+subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo
[component_0]
type = TargetGroup
name = MSP430
parent = Target
+has_asmparser = 1
has_asmprinter = 1
+has_disassembler = 1
[component_1]
type = Library
diff --git a/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt b/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt
index 0f3ebd303924..a2f468779f50 100644
--- a/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt
+++ b/lib/Target/MSP430/MCTargetDesc/CMakeLists.txt
@@ -1,4 +1,8 @@
add_llvm_library(LLVMMSP430Desc
- MSP430MCTargetDesc.cpp
+ MSP430AsmBackend.cpp
+ MSP430ELFObjectWriter.cpp
+ MSP430ELFStreamer.cpp
MSP430MCAsmInfo.cpp
+ MSP430MCCodeEmitter.cpp
+ MSP430MCTargetDesc.cpp
)
diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp
new file mode 100644
index 000000000000..bd69a9d8d795
--- /dev/null
+++ b/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/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp
new file mode 100644
index 000000000000..e47db2400a05
--- /dev/null
+++ b/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_BYTE;
+ 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/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp
new file mode 100644
index 000000000000..9449cb278024
--- /dev/null
+++ b/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/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h b/lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h
new file mode 100644
index 000000000000..1eb6a2759423
--- /dev/null
+++ b/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/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
index 82e6731ecd78..36e9a9c31075 100644
--- a/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
+++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp
@@ -20,6 +20,7 @@ MSP430MCAsmInfo::MSP430MCAsmInfo(const Triple &TT) {
CodePointerSize = CalleeSaveStackSlotSize = 2;
CommentString = ";";
+ SeparatorString = "{";
AlignmentIsInBytes = false;
UsesELFSectionDirectiveForBSS = true;
diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp
new file mode 100644
index 000000000000..06f9f307cb1a
--- /dev/null
+++ b/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 ((unsigned)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
diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
index 8c715500f38b..b21145d3904a 100644
--- a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
+++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp
@@ -58,22 +58,15 @@ static MCInstPrinter *createMSP430MCInstPrinter(const Triple &T,
}
extern "C" void LLVMInitializeMSP430TargetMC() {
- // Register the MC asm info.
- RegisterMCAsmInfo<MSP430MCAsmInfo> X(getTheMSP430Target());
+ Target &T = getTheMSP430Target();
- // Register the MC instruction info.
- TargetRegistry::RegisterMCInstrInfo(getTheMSP430Target(),
- createMSP430MCInstrInfo);
-
- // Register the MC register info.
- TargetRegistry::RegisterMCRegInfo(getTheMSP430Target(),
- createMSP430MCRegisterInfo);
-
- // Register the MC subtarget info.
- TargetRegistry::RegisterMCSubtargetInfo(getTheMSP430Target(),
- createMSP430MCSubtargetInfo);
-
- // Register the MCInstPrinter.
- TargetRegistry::RegisterMCInstPrinter(getTheMSP430Target(),
- createMSP430MCInstPrinter);
+ RegisterMCAsmInfo<MSP430MCAsmInfo> X(T);
+ TargetRegistry::RegisterMCInstrInfo(T, createMSP430MCInstrInfo);
+ TargetRegistry::RegisterMCRegInfo(T, createMSP430MCRegisterInfo);
+ TargetRegistry::RegisterMCSubtargetInfo(T, createMSP430MCSubtargetInfo);
+ TargetRegistry::RegisterMCInstPrinter(T, createMSP430MCInstPrinter);
+ TargetRegistry::RegisterMCCodeEmitter(T, createMSP430MCCodeEmitter);
+ TargetRegistry::RegisterMCAsmBackend(T, createMSP430MCAsmBackend);
+ TargetRegistry::RegisterObjectTargetStreamer(
+ T, createMSP430ObjectTargetStreamer);
}
diff --git a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h
index b901c5f09794..e484c79c9ee9 100644
--- a/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h
+++ b/lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h
@@ -15,12 +15,39 @@
#define LLVM_LIB_TARGET_MSP430_MCTARGETDESC_MSP430MCTARGETDESC_H
#include "llvm/Support/DataTypes.h"
+#include <memory>
namespace llvm {
class Target;
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCInstrInfo;
+class MCSubtargetInfo;
+class MCRegisterInfo;
+class MCContext;
+class MCTargetOptions;
+class MCObjectTargetWriter;
+class MCStreamer;
+class MCTargetStreamer;
Target &getTheMSP430Target();
+/// Creates a machine code emitter for MSP430.
+MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII,
+ const MCRegisterInfo &MRI,
+ MCContext &Ctx);
+
+MCAsmBackend *createMSP430MCAsmBackend(const Target &T,
+ const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options);
+
+MCTargetStreamer *
+createMSP430ObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
+
+std::unique_ptr<MCObjectTargetWriter>
+createMSP430ELFObjectWriter(uint8_t OSABI);
+
} // End llvm namespace
// Defines symbolic names for MSP430 registers.
diff --git a/lib/Target/MSP430/MSP430.h b/lib/Target/MSP430/MSP430.h
index 796f25233123..7a5314a10844 100644
--- a/lib/Target/MSP430/MSP430.h
+++ b/lib/Target/MSP430/MSP430.h
@@ -27,6 +27,8 @@ namespace MSP430CC {
COND_LO = 3, // aka COND_NC
COND_GE = 4,
COND_L = 5,
+ COND_N = 6, // jump if negative
+ COND_NONE, // unconditional
COND_INVALID = -1
};
diff --git a/lib/Target/MSP430/MSP430.td b/lib/Target/MSP430/MSP430.td
index 203864dd4065..8fa99dc13dd5 100644
--- a/lib/Target/MSP430/MSP430.td
+++ b/lib/Target/MSP430/MSP430.td
@@ -64,11 +64,29 @@ include "MSP430InstrInfo.td"
def MSP430InstrInfo : InstrInfo;
+//===---------------------------------------------------------------------===//
+// Assembly Printers
+//===---------------------------------------------------------------------===//
+
+def MSP430AsmWriter : AsmWriter {
+ string AsmWriterClassName = "InstPrinter";
+}
+
+//===---------------------------------------------------------------------===//
+// Assembly Parsers
+//===---------------------------------------------------------------------===//
+
+def MSP430AsmParser : AsmParser {
+ let AllowDuplicateRegisterNames = 1;
+ let ShouldEmitMatchRegisterAltName = 1;
+}
+
//===----------------------------------------------------------------------===//
// Target Declaration
//===----------------------------------------------------------------------===//
def MSP430 : Target {
let InstructionSet = MSP430InstrInfo;
+ let AssemblyParsers = [MSP430AsmParser];
}
diff --git a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
index 005f5f44a635..7a1998ad355d 100644
--- a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
+++ b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp
@@ -98,6 +98,7 @@ namespace {
MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
: SelectionDAGISel(TM, OptLevel) {}
+ private:
StringRef getPassName() const override {
return "MSP430 DAG->DAG Pattern Instruction Selection";
}
@@ -112,8 +113,9 @@ namespace {
// Include the pieces autogenerated from the target description.
#include "MSP430GenDAGISel.inc"
- private:
+ // Main method to transform nodes into machine nodes.
void Select(SDNode *N) override;
+
bool tryIndexedLoad(SDNode *Op);
bool tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2, unsigned Opc8,
unsigned Opc16);
@@ -250,11 +252,9 @@ bool MSP430DAGToDAGISel::SelectAddr(SDValue N,
if (MatchAddress(N, AM))
return false;
- EVT VT = N.getValueType();
- if (AM.BaseType == MSP430ISelAddressMode::RegBase) {
+ if (AM.BaseType == MSP430ISelAddressMode::RegBase)
if (!AM.Base.Reg.getNode())
- AM.Base.Reg = CurDAG->getRegister(0, VT);
- }
+ AM.Base.Reg = CurDAG->getRegister(MSP430::SR, MVT::i16);
Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase)
? CurDAG->getTargetFrameIndex(
@@ -336,10 +336,10 @@ bool MSP430DAGToDAGISel::tryIndexedLoad(SDNode *N) {
unsigned Opcode = 0;
switch (VT.SimpleTy) {
case MVT::i8:
- Opcode = MSP430::MOV8rm_POST;
+ Opcode = MSP430::MOV8rp;
break;
case MVT::i16:
- Opcode = MSP430::MOV16rm_POST;
+ Opcode = MSP430::MOV16rp;
break;
default:
return false;
@@ -362,12 +362,11 @@ bool MSP430DAGToDAGISel::tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
MVT VT = LD->getMemoryVT().getSimpleVT();
unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
- MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
- MemRefs0[0] = cast<MemSDNode>(N1)->getMemOperand();
+ MachineMemOperand *MemRef = cast<MemSDNode>(N1)->getMemOperand();
SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
SDNode *ResNode =
CurDAG->SelectNodeTo(Op, Opc, VT, MVT::i16, MVT::Other, Ops0);
- cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1);
+ CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {MemRef});
// Transfer chain.
ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2));
// Transfer writeback.
@@ -413,47 +412,47 @@ void MSP430DAGToDAGISel::Select(SDNode *Node) {
break;
case ISD::ADD:
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
- MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
+ MSP430::ADD8rp, MSP430::ADD16rp))
return;
else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
- MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
+ MSP430::ADD8rp, MSP430::ADD16rp))
return;
// Other cases are autogenerated.
break;
case ISD::SUB:
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
- MSP430::SUB8rm_POST, MSP430::SUB16rm_POST))
+ MSP430::SUB8rp, MSP430::SUB16rp))
return;
// Other cases are autogenerated.
break;
case ISD::AND:
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
- MSP430::AND8rm_POST, MSP430::AND16rm_POST))
+ MSP430::AND8rp, MSP430::AND16rp))
return;
else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
- MSP430::AND8rm_POST, MSP430::AND16rm_POST))
+ MSP430::AND8rp, MSP430::AND16rp))
return;
// Other cases are autogenerated.
break;
case ISD::OR:
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
- MSP430::OR8rm_POST, MSP430::OR16rm_POST))
+ MSP430::BIS8rp, MSP430::BIS16rp))
return;
else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
- MSP430::OR8rm_POST, MSP430::OR16rm_POST))
+ MSP430::BIS8rp, MSP430::BIS16rp))
return;
// Other cases are autogenerated.
break;
case ISD::XOR:
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
- MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
+ MSP430::XOR8rp, MSP430::XOR16rp))
return;
else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
- MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
+ MSP430::XOR8rp, MSP430::XOR16rp))
return;
// Other cases are autogenerated.
diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp
index f5b2bda5d1e4..3e706134afc5 100644
--- a/lib/Target/MSP430/MSP430ISelLowering.cpp
+++ b/lib/Target/MSP430/MSP430ISelLowering.cpp
@@ -95,6 +95,8 @@ MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SIGN_EXTEND, MVT::i16, Custom);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i8, Expand);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i16, Expand);
+ setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
+ setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
setOperationAction(ISD::CTTZ, MVT::i8, Expand);
setOperationAction(ISD::CTTZ, MVT::i16, Expand);
@@ -217,8 +219,6 @@ MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM,
// { RTLIB::NEG_F64, "__mspabi_negd", ISD::SETCC_INVALID },
// { RTLIB::NEG_F32, "__mspabi_negf", ISD::SETCC_INVALID },
- // TODO: SLL/SRA/SRL are in libgcc, RLL isn't
-
// Universal Integer Operations - EABI Table 9
{ RTLIB::SDIV_I16, "__mspabi_divi", ISD::SETCC_INVALID },
{ RTLIB::SDIV_I32, "__mspabi_divli", ISD::SETCC_INVALID },
@@ -233,6 +233,13 @@ MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM,
{ RTLIB::UREM_I32, "__mspabi_remul", ISD::SETCC_INVALID },
{ RTLIB::UREM_I64, "__mspabi_remull", ISD::SETCC_INVALID },
+ // Bitwise Operations - EABI Table 10
+ // TODO: __mspabi_[srli/srai/slli] ARE implemented in libgcc
+ { RTLIB::SRL_I32, "__mspabi_srll", ISD::SETCC_INVALID },
+ { RTLIB::SRA_I32, "__mspabi_sral", ISD::SETCC_INVALID },
+ { RTLIB::SHL_I32, "__mspabi_slll", ISD::SETCC_INVALID },
+ // __mspabi_[srlll/srall/sllll/rlli/rlll] are NOT implemented in libgcc
+
};
for (const auto &LC : LibraryCalls) {
@@ -940,30 +947,40 @@ SDValue MSP430TargetLowering::LowerShifts(SDValue Op,
// Expand non-constant shifts to loops:
if (!isa<ConstantSDNode>(N->getOperand(1)))
- switch (Opc) {
- default: llvm_unreachable("Invalid shift opcode!");
- case ISD::SHL:
- return DAG.getNode(MSP430ISD::SHL, dl,
- VT, N->getOperand(0), N->getOperand(1));
- case ISD::SRA:
- return DAG.getNode(MSP430ISD::SRA, dl,
- VT, N->getOperand(0), N->getOperand(1));
- case ISD::SRL:
- return DAG.getNode(MSP430ISD::SRL, dl,
- VT, N->getOperand(0), N->getOperand(1));
- }
+ return Op;
uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
// Expand the stuff into sequence of shifts.
- // FIXME: for some shift amounts this might be done better!
- // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N
SDValue Victim = N->getOperand(0);
+ if (ShiftAmount >= 8) {
+ assert(VT == MVT::i16 && "Can not shift i8 by 8 and more");
+ switch(Opc) {
+ default:
+ llvm_unreachable("Unknown shift");
+ case ISD::SHL:
+ // foo << (8 + N) => swpb(zext(foo)) << N
+ Victim = DAG.getZeroExtendInReg(Victim, dl, MVT::i8);
+ Victim = DAG.getNode(ISD::BSWAP, dl, VT, Victim);
+ break;
+ case ISD::SRA:
+ case ISD::SRL:
+ // foo >> (8 + N) => sxt(swpb(foo)) >> N
+ Victim = DAG.getNode(ISD::BSWAP, dl, VT, Victim);
+ Victim = (Opc == ISD::SRA)
+ ? DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, VT, Victim,
+ DAG.getValueType(MVT::i8))
+ : DAG.getZeroExtendInReg(Victim, dl, MVT::i8);
+ break;
+ }
+ ShiftAmount -= 8;
+ }
+
if (Opc == ISD::SRL && ShiftAmount) {
// Emit a special goodness here:
// srl A, 1 => clrc; rrc A
- Victim = DAG.getNode(MSP430ISD::RRC, dl, VT, Victim);
+ Victim = DAG.getNode(MSP430ISD::RRCL, dl, VT, Victim);
ShiftAmount -= 1;
}
@@ -1342,15 +1359,14 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
case MSP430ISD::RRA: return "MSP430ISD::RRA";
case MSP430ISD::RLA: return "MSP430ISD::RLA";
case MSP430ISD::RRC: return "MSP430ISD::RRC";
+ case MSP430ISD::RRCL: return "MSP430ISD::RRCL";
case MSP430ISD::CALL: return "MSP430ISD::CALL";
case MSP430ISD::Wrapper: return "MSP430ISD::Wrapper";
case MSP430ISD::BR_CC: return "MSP430ISD::BR_CC";
case MSP430ISD::CMP: return "MSP430ISD::CMP";
case MSP430ISD::SETCC: return "MSP430ISD::SETCC";
case MSP430ISD::SELECT_CC: return "MSP430ISD::SELECT_CC";
- case MSP430ISD::SHL: return "MSP430ISD::SHL";
- case MSP430ISD::SRA: return "MSP430ISD::SRA";
- case MSP430ISD::SRL: return "MSP430ISD::SRL";
+ case MSP430ISD::DADD: return "MSP430ISD::DADD";
}
return nullptr;
}
@@ -1397,33 +1413,49 @@ MSP430TargetLowering::EmitShiftInstr(MachineInstr &MI,
const TargetInstrInfo &TII = *F->getSubtarget().getInstrInfo();
unsigned Opc;
+ bool ClearCarry = false;
const TargetRegisterClass * RC;
switch (MI.getOpcode()) {
default: llvm_unreachable("Invalid shift opcode!");
case MSP430::Shl8:
- Opc = MSP430::SHL8r1;
- RC = &MSP430::GR8RegClass;
- break;
+ Opc = MSP430::ADD8rr;
+ RC = &MSP430::GR8RegClass;
+ break;
case MSP430::Shl16:
- Opc = MSP430::SHL16r1;
- RC = &MSP430::GR16RegClass;
- break;
+ Opc = MSP430::ADD16rr;
+ RC = &MSP430::GR16RegClass;
+ break;
case MSP430::Sra8:
- Opc = MSP430::SAR8r1;
- RC = &MSP430::GR8RegClass;
- break;
+ Opc = MSP430::RRA8r;
+ RC = &MSP430::GR8RegClass;
+ break;
case MSP430::Sra16:
- Opc = MSP430::SAR16r1;
- RC = &MSP430::GR16RegClass;
- break;
+ Opc = MSP430::RRA16r;
+ RC = &MSP430::GR16RegClass;
+ break;
case MSP430::Srl8:
- Opc = MSP430::SAR8r1c;
- RC = &MSP430::GR8RegClass;
- break;
+ ClearCarry = true;
+ Opc = MSP430::RRC8r;
+ RC = &MSP430::GR8RegClass;
+ break;
case MSP430::Srl16:
- Opc = MSP430::SAR16r1c;
- RC = &MSP430::GR16RegClass;
- break;
+ ClearCarry = true;
+ Opc = MSP430::RRC16r;
+ RC = &MSP430::GR16RegClass;
+ break;
+ case MSP430::Rrcl8:
+ case MSP430::Rrcl16: {
+ BuildMI(*BB, MI, dl, TII.get(MSP430::BIC16rc), MSP430::SR)
+ .addReg(MSP430::SR).addImm(1);
+ unsigned SrcReg = MI.getOperand(1).getReg();
+ unsigned DstReg = MI.getOperand(0).getReg();
+ unsigned RrcOpc = MI.getOpcode() == MSP430::Rrcl16
+ ? MSP430::RRC16r : MSP430::RRC8r;
+ BuildMI(*BB, MI, dl, TII.get(RrcOpc), DstReg)
+ .addReg(SrcReg);
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
+ return BB;
+ }
}
const BasicBlock *LLVM_BB = BB->getBasicBlock();
@@ -1476,8 +1508,16 @@ MSP430TargetLowering::EmitShiftInstr(MachineInstr &MI,
BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftAmtReg)
.addReg(ShiftAmtSrcReg).addMBB(BB)
.addReg(ShiftAmtReg2).addMBB(LoopBB);
- BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2)
- .addReg(ShiftReg);
+ if (ClearCarry)
+ BuildMI(LoopBB, dl, TII.get(MSP430::BIC16rc), MSP430::SR)
+ .addReg(MSP430::SR).addImm(1);
+ if (Opc == MSP430::ADD8rr || Opc == MSP430::ADD16rr)
+ BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2)
+ .addReg(ShiftReg)
+ .addReg(ShiftReg);
+ else
+ BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2)
+ .addReg(ShiftReg);
BuildMI(LoopBB, dl, TII.get(MSP430::SUB8ri), ShiftAmtReg2)
.addReg(ShiftAmtReg).addImm(1);
BuildMI(LoopBB, dl, TII.get(MSP430::JCC))
@@ -1499,9 +1539,10 @@ MSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *BB) const {
unsigned Opc = MI.getOpcode();
- if (Opc == MSP430::Shl8 || Opc == MSP430::Shl16 ||
- Opc == MSP430::Sra8 || Opc == MSP430::Sra16 ||
- Opc == MSP430::Srl8 || Opc == MSP430::Srl16)
+ if (Opc == MSP430::Shl8 || Opc == MSP430::Shl16 ||
+ Opc == MSP430::Sra8 || Opc == MSP430::Sra16 ||
+ Opc == MSP430::Srl8 || Opc == MSP430::Srl16 ||
+ Opc == MSP430::Rrcl8 || Opc == MSP430::Rrcl16)
return EmitShiftInstr(MI, BB);
const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();
diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h
index 842d03df32fc..731bc1406711 100644
--- a/lib/Target/MSP430/MSP430ISelLowering.h
+++ b/lib/Target/MSP430/MSP430ISelLowering.h
@@ -36,6 +36,9 @@ namespace llvm {
/// Y = RRC X, rotate right via carry
RRC,
+ /// Rotate right via carry, carry gets cleared beforehand by clrc
+ RRCL,
+
/// CALL - These operations represent an abstract call
/// instruction, which includes a bunch of information.
CALL,
@@ -61,8 +64,9 @@ namespace llvm {
/// is condition code and operand 4 is flag operand.
SELECT_CC,
- /// SHL, SRA, SRL - Non-constant shifts.
- SHL, SRA, SRL
+ /// DADD - Decimal addition with carry
+ /// TODO Nothing generates a node of this type yet.
+ DADD,
};
}
diff --git a/lib/Target/MSP430/MSP430InstrFormats.td b/lib/Target/MSP430/MSP430InstrFormats.td
index a9e87dad0cd8..e2e4503db20c 100644
--- a/lib/Target/MSP430/MSP430InstrFormats.td
+++ b/lib/Target/MSP430/MSP430InstrFormats.td
@@ -11,201 +11,431 @@
// Describe MSP430 instructions format here
//
-// Format specifies the encoding used by the instruction. This is part of the
-// ad-hoc solution used to emit machine instruction encodings by our machine
-// code emitter.
-class Format<bits<2> val> {
- bits<2> Value = val;
-}
-
-def PseudoFrm : Format<0>;
-def SingleOpFrm : Format<1>;
-def DoubleOpFrm : Format<2>;
-def CondJumpFrm : Format<3>;
-
class SourceMode<bits<2> val> {
bits<2> Value = val;
}
-def SrcReg : SourceMode<0>;
-def SrcMem : SourceMode<1>;
-def SrcIndReg : SourceMode<2>;
-def SrcPostInc : SourceMode<3>;
-def SrcImm : SourceMode<3>;
+def SrcReg : SourceMode<0>; // r
+def SrcMem : SourceMode<1>; // m
+def SrcIndReg : SourceMode<2>; // n
+def SrcPostInc : SourceMode<3>; // p
+def SrcImm : SourceMode<3>; // i
+// SrcCGImm : SourceMode< >; // c
class DestMode<bit val> {
bit Value = val;
}
-def DstReg : DestMode<0>;
-def DstMem : DestMode<1>;
-
-class SizeVal<bits<3> val> {
- bits<3> Value = val;
-}
-
-def SizeUnknown : SizeVal<0>; // Unknown / unset size
-def SizeSpecial : SizeVal<1>; // Special instruction, e.g. pseudo
-def Size2Bytes : SizeVal<2>;
-def Size4Bytes : SizeVal<3>;
-def Size6Bytes : SizeVal<4>;
+def DstReg : DestMode<0>; // r
+def DstMem : DestMode<1>; // m
// Generic MSP430 Format
-class MSP430Inst<dag outs, dag ins, SizeVal sz, Format f,
- string asmstr> : Instruction {
- field bits<16> Inst;
+class MSP430Inst<dag outs, dag ins, int size, string asmstr> : Instruction {
+ field bits<48> Inst;
+ field bits<48> SoftFail = 0;
let Namespace = "MSP430";
dag OutOperandList = outs;
dag InOperandList = ins;
- Format Form = f;
- SizeVal Sz = sz;
-
- // Define how we want to layout our TargetSpecific information field... This
- // should be kept up-to-date with the fields in the MSP430InstrInfo.h file.
- let TSFlags{1-0} = Form.Value;
- let TSFlags{4-2} = Sz.Value;
-
- let AsmString = asmstr;
+ let AsmString = asmstr;
+ let Size = size;
}
-// FIXME: Create different classes for different addressing modes.
-
// MSP430 Double Operand (Format I) Instructions
-class IForm<bits<4> opcode, DestMode dest, bit bw, SourceMode src, SizeVal sz,
+class IForm<bits<4> opcode, DestMode ad, bit bw, SourceMode as, int size,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : MSP430Inst<outs, ins, sz, DoubleOpFrm, asmstr> {
+ : MSP430Inst<outs, ins, size, asmstr> {
let Pattern = pattern;
- DestMode ad = dest;
- SourceMode as = src;
-
- let Inst{12-15} = opcode;
+ bits<4> rs;
+ bits<4> rd;
+
+ let Inst{15-12} = opcode;
+ let Inst{11-8} = rs;
let Inst{7} = ad.Value;
let Inst{6} = bw;
- let Inst{4-5} = as.Value;
+ let Inst{5-4} = as.Value;
+ let Inst{3-0} = rd;
}
// 8 bit IForm instructions
-class IForm8<bits<4> opcode, DestMode dest, SourceMode src, SizeVal sz,
+class IForm8<bits<4> opcode, DestMode dest, SourceMode src, int size,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm<opcode, dest, 1, src, sz, outs, ins, asmstr, pattern>;
+ : IForm<opcode, dest, 1, src, size, outs, ins, asmstr, pattern>;
class I8rr<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm8<opcode, DstReg, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>;
+ : IForm8<opcode, DstReg, SrcReg, 2, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Alpha";
+}
class I8ri<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm8<opcode, DstReg, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>;
+ : IForm8<opcode, DstReg, SrcImm, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Gamma";
+ bits<16> imm;
+ let Inst{31-16} = imm;
+ let rs = 0b0000;
+}
+
+class I8rc<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : MSP430Inst<outs, ins, 2, asmstr> {
+ let DecoderNamespace = "Beta";
+ let Pattern = pattern;
+
+ bits<6> imm;
+ bits<4> rd;
+
+ let Inst{15-12} = opcode;
+ let Inst{11-8} = imm{3-0};
+ let Inst{7} = DstReg.Value;
+ let Inst{6} = 1;
+ let Inst{5-4} = imm{5-4};
+ let Inst{3-0} = rd;
+}
class I8rm<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm8<opcode, DstReg, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>;
+ : IForm8<opcode, DstReg, SrcMem, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Gamma";
+ bits<20> src;
+ let rs = src{3-0};
+ let Inst{31-16} = src{19-4};
+}
+
+class I8rn<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstReg, SrcIndReg, 2, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Delta";
+}
+
+class I8rp<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstReg, SrcPostInc, 2, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Delta";
+}
class I8mr<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm8<opcode, DstMem, SrcReg, Size4Bytes, outs, ins, asmstr, pattern>;
+ : IForm8<opcode, DstMem, SrcReg, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Alpha";
+ bits<20> dst;
+ let rd = dst{3-0};
+ let Inst{31-16} = dst{19-4};
+}
class I8mi<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm8<opcode, DstMem, SrcImm, Size6Bytes, outs, ins, asmstr, pattern>;
+ : IForm8<opcode, DstMem, SrcImm, 6, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Gamma";
+ bits<16> imm;
+ bits<20> dst;
+ let rs = 0b0000;
+ let Inst{31-16} = imm;
+ let rd = dst{3-0};
+ let Inst{47-32} = dst{19-4};
+}
+
+class I8mc<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : MSP430Inst<outs, ins, 4, asmstr> {
+ let DecoderNamespace = "Beta";
+ let Pattern = pattern;
+
+ bits<6> imm;
+ bits<20> dst;
+
+ let Inst{31-16} = dst{19-4};
+ let Inst{15-12} = opcode;
+ let Inst{11-8} = imm{3-0};
+ let Inst{7} = DstMem.Value;
+ let Inst{6} = 1;
+ let Inst{5-4} = imm{5-4};
+ let Inst{3-0} = dst{3-0};
+}
class I8mm<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm8<opcode, DstMem, SrcMem, Size6Bytes, outs, ins, asmstr, pattern>;
+ : IForm8<opcode, DstMem, SrcMem, 6, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Gamma";
+ bits<20> src;
+ bits<20> dst;
+ let rs = src{3-0};
+ let Inst{31-16} = src{19-4};
+ let rd = dst{3-0};
+ let Inst{47-32} = dst{19-4};
+}
+
+class I8mn<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstMem, SrcIndReg, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Delta";
+ bits<20> dst;
+ let rd = dst{3-0};
+ let Inst{31-16} = dst{19-4};
+}
+
+class I8mp<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm8<opcode, DstMem, SrcPostInc, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Delta";
+ bits<20> dst;
+ let rd = dst{3-0};
+ let Inst{31-16} = dst{19-4};
+}
// 16 bit IForm instructions
-class IForm16<bits<4> opcode, DestMode dest, SourceMode src, SizeVal sz,
+class IForm16<bits<4> opcode, DestMode dest, SourceMode src, int size,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm<opcode, dest, 0, src, sz, outs, ins, asmstr, pattern>;
+ : IForm<opcode, dest, 0, src, size, outs, ins, asmstr, pattern>;
class I16rr<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm16<opcode, DstReg, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>;
+ : IForm16<opcode, DstReg, SrcReg, 2, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Alpha";
+}
class I16ri<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm16<opcode, DstReg, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>;
+ : IForm16<opcode, DstReg, SrcImm, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Gamma";
+ bits<16> imm;
+ let Inst{31-16} = imm;
+ let rs = 0b0000;
+}
+
+class I16rc<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : MSP430Inst<outs, ins, 2, asmstr> {
+ let DecoderNamespace = "Beta";
+ let Pattern = pattern;
+
+ bits<6> imm;
+ bits<4> rd;
+
+ let Inst{15-12} = opcode;
+ let Inst{11-8} = imm{3-0};
+ let Inst{7} = DstReg.Value;
+ let Inst{6} = 0;
+ let Inst{5-4} = imm{5-4};
+ let Inst{3-0} = rd;
+}
class I16rm<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm16<opcode, DstReg, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>;
+ : IForm16<opcode, DstReg, SrcMem, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Gamma";
+ bits<20> src;
+ let rs = src{3-0};
+ let Inst{31-16} = src{19-4};
+}
+
+class I16rn<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstReg, SrcIndReg, 2, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Delta";
+}
+
+class I16rp<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstReg, SrcPostInc, 2, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Delta";
+}
class I16mr<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm16<opcode, DstMem, SrcReg, Size4Bytes, outs, ins, asmstr, pattern>;
+ : IForm16<opcode, DstMem, SrcReg, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Alpha";
+ bits<20> dst;
+ let rd = dst{3-0};
+ let Inst{31-16} = dst{19-4};
+}
class I16mi<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm16<opcode, DstMem, SrcImm, Size6Bytes, outs, ins, asmstr, pattern>;
+ : IForm16<opcode, DstMem, SrcImm, 6, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Gamma";
+ bits<16> imm;
+ bits<20> dst;
+ let Inst{31-16} = imm;
+ let rs = 0b0000;
+ let rd = dst{3-0};
+ let Inst{47-32} = dst{19-4};
+}
+
+class I16mc<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : MSP430Inst<outs, ins, 4, asmstr> {
+ let DecoderNamespace = "Beta";
+ let Pattern = pattern;
+
+ bits<6> imm;
+ bits<20> dst;
+
+ let Inst{31-16} = dst{19-4};
+ let Inst{15-12} = opcode;
+ let Inst{11-8} = imm{3-0};
+ let Inst{7} = DstMem.Value;
+ let Inst{6} = 0;
+ let Inst{5-4} = imm{5-4};
+ let Inst{3-0} = dst{3-0};
+}
class I16mm<bits<4> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IForm16<opcode, DstMem, SrcMem, Size6Bytes, outs, ins, asmstr, pattern>;
+ : IForm16<opcode, DstMem, SrcMem, 6, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Gamma";
+ bits<20> src;
+ bits<20> dst;
+ let rs = src{3-0};
+ let Inst{31-16} = src{19-4};
+ let rd = dst{3-0};
+ let Inst{47-32} = dst{19-4};
+}
+
+class I16mn<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstMem, SrcIndReg, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Delta";
+ bits<20> dst;
+ let rd = dst{3-0};
+ let Inst{31-16} = dst{19-4};
+}
+
+class I16mp<bits<4> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IForm16<opcode, DstMem, SrcPostInc, 4, outs, ins, asmstr, pattern> {
+ let DecoderNamespace = "Delta";
+ bits<20> dst;
+ let rd = dst{3-0};
+ let Inst{31-16} = dst{19-4};
+}
// MSP430 Single Operand (Format II) Instructions
-class IIForm<bits<9> opcode, bit bw, SourceMode src, SizeVal sz,
+class IIForm<bits<3> opcode, bit bw, SourceMode as, int size,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : MSP430Inst<outs, ins, sz, SingleOpFrm, asmstr> {
+ : MSP430Inst<outs, ins, size, asmstr> {
let Pattern = pattern;
-
- SourceMode as = src;
- let Inst{7-15} = opcode;
- let Inst{6} = bw;
- let Inst{4-5} = as.Value;
+ bits<4> rs;
+
+ let Inst{15-10} = 0b000100;
+ let Inst{9-7} = opcode;
+ let Inst{6} = bw;
+ let Inst{5-4} = as.Value;
+ let Inst{3-0} = rs;
}
// 8 bit IIForm instructions
-class IIForm8<bits<9> opcode, SourceMode src, SizeVal sz,
+class IIForm8<bits<3> opcode, SourceMode src, int size,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IIForm<opcode, 1, src, sz, outs, ins, asmstr, pattern>;
+ : IIForm<opcode, 1, src, size, outs, ins, asmstr, pattern>;
+
+class II8r<bits<3> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm8<opcode, SrcReg, 2, outs, ins, asmstr, pattern>;
-class II8r<bits<9> opcode,
+class II8m<bits<3> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IIForm8<opcode, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>;
+ : IIForm8<opcode, SrcMem, 4, outs, ins, asmstr, pattern> {
+ bits<20> src;
+ let rs = src{3-0};
+ let Inst{31-16} = src{19-4};
+}
-class II8m<bits<9> opcode,
+class II8i<bits<3> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IIForm8<opcode, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>;
+ : IIForm8<opcode, SrcImm, 4, outs, ins, asmstr, pattern> {
+ bits<16> imm;
+ let rs = 0b0000;
+ let Inst{31-16} = imm;
+}
-class II8i<bits<9> opcode,
+class II8c<bits<3> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IIForm8<opcode, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>;
+ : MSP430Inst<outs, ins, 2, asmstr> {
+ let Pattern = pattern;
+
+ bits<6> imm;
+
+ let Inst{15-10} = 0b000100;
+ let Inst{9-7} = opcode;
+ let Inst{6} = 1;
+ let Inst{5-0} = imm;
+}
+
+class II8n<bits<3> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm8<opcode, SrcIndReg, 2, outs, ins, asmstr, pattern>;
+
+class II8p<bits<3> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm8<opcode, SrcPostInc, 2, outs, ins, asmstr, pattern>;
// 16 bit IIForm instructions
-class IIForm16<bits<9> opcode, SourceMode src, SizeVal sz,
+class IIForm16<bits<3> opcode, SourceMode src, int size,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IIForm<opcode, 0, src, sz, outs, ins, asmstr, pattern>;
+ : IIForm<opcode, 0, src, size, outs, ins, asmstr, pattern>;
-class II16r<bits<9> opcode,
+class II16r<bits<3> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IIForm16<opcode, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>;
+ : IIForm16<opcode, SrcReg, 2, outs, ins, asmstr, pattern>;
-class II16m<bits<9> opcode,
+class II16m<bits<3> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IIForm16<opcode, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>;
+ : IIForm16<opcode, SrcMem, 4, outs, ins, asmstr, pattern> {
+ bits<20> src;
+ let rs = src{3-0};
+ let Inst{31-16} = src{19-4};
+}
-class II16i<bits<9> opcode,
+class II16i<bits<3> opcode,
dag outs, dag ins, string asmstr, list<dag> pattern>
- : IIForm16<opcode, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>;
+ : IIForm16<opcode, SrcImm, 4, outs, ins, asmstr, pattern> {
+ bits<16> imm;
+ let rs = 0b0000;
+ let Inst{31-16} = imm;
+}
+
+class II16c<bits<3> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : MSP430Inst<outs, ins, 2, asmstr> {
+ let Pattern = pattern;
+
+ bits<6> imm;
+
+ let Inst{15-10} = 0b000100;
+ let Inst{9-7} = opcode;
+ let Inst{6} = 0;
+ let Inst{5-0} = imm;
+}
+
+class II16n<bits<3> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm16<opcode, SrcIndReg, 2, outs, ins, asmstr, pattern>;
+
+class II16p<bits<3> opcode,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : IIForm16<opcode, SrcPostInc, 2, outs, ins, asmstr, pattern>;
// MSP430 Conditional Jumps Instructions
-class CJForm<bits<3> opcode, bits<3> cond,
- dag outs, dag ins, string asmstr, list<dag> pattern>
- : MSP430Inst<outs, ins, Size2Bytes, CondJumpFrm, asmstr> {
+class CJForm<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : MSP430Inst<outs, ins, 2, asmstr> {
let Pattern = pattern;
- let Inst{13-15} = opcode;
- let Inst{10-12} = cond;
+ bits<3> cond;
+ bits<10> dst;
+
+ let Inst{15-13} = 0b001;
+ let Inst{12-10} = cond;
+ let Inst{9-0} = dst;
}
// Pseudo instructions
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
- : MSP430Inst<outs, ins, SizeSpecial, PseudoFrm, asmstr> {
+ : MSP430Inst<outs, ins, 0, asmstr> {
let Pattern = pattern;
- let Inst{15-0} = 0;
}
diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp
index dd1b30a3e470..c136933a51bc 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.cpp
+++ b/lib/Target/MSP430/MSP430InstrInfo.cpp
@@ -301,35 +301,20 @@ unsigned MSP430InstrInfo::insertBranch(MachineBasicBlock &MBB,
unsigned MSP430InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
const MCInstrDesc &Desc = MI.getDesc();
- switch (Desc.TSFlags & MSP430II::SizeMask) {
- default:
- switch (Desc.getOpcode()) {
- default: llvm_unreachable("Unknown instruction size!");
- case TargetOpcode::CFI_INSTRUCTION:
- case TargetOpcode::EH_LABEL:
- case TargetOpcode::IMPLICIT_DEF:
- case TargetOpcode::KILL:
- case TargetOpcode::DBG_VALUE:
- return 0;
- case TargetOpcode::INLINEASM: {
- const MachineFunction *MF = MI.getParent()->getParent();
- const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
- return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),
- *MF->getTarget().getMCAsmInfo());
- }
- }
- case MSP430II::SizeSpecial:
- switch (MI.getOpcode()) {
- default: llvm_unreachable("Unknown instruction size!");
- case MSP430::SAR8r1c:
- case MSP430::SAR16r1c:
- return 4;
- }
- case MSP430II::Size2Bytes:
- return 2;
- case MSP430II::Size4Bytes:
- return 4;
- case MSP430II::Size6Bytes:
- return 6;
+ switch (Desc.getOpcode()) {
+ case TargetOpcode::CFI_INSTRUCTION:
+ case TargetOpcode::EH_LABEL:
+ case TargetOpcode::IMPLICIT_DEF:
+ case TargetOpcode::KILL:
+ case TargetOpcode::DBG_VALUE:
+ return 0;
+ case TargetOpcode::INLINEASM: {
+ const MachineFunction *MF = MI.getParent()->getParent();
+ const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
+ return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),
+ *MF->getTarget().getMCAsmInfo());
}
+ }
+
+ return Desc.getSize();
}
diff --git a/lib/Target/MSP430/MSP430InstrInfo.h b/lib/Target/MSP430/MSP430InstrInfo.h
index 45357f54c9c6..fee3bea9b8d6 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.h
+++ b/lib/Target/MSP430/MSP430InstrInfo.h
@@ -24,22 +24,6 @@ namespace llvm {
class MSP430Subtarget;
-/// MSP430II - This namespace holds all of the target specific flags that
-/// instruction info tracks.
-///
-namespace MSP430II {
- enum {
- SizeShift = 2,
- SizeMask = 7 << SizeShift,
-
- SizeUnknown = 0 << SizeShift,
- SizeSpecial = 1 << SizeShift,
- Size2Bytes = 2 << SizeShift,
- Size4Bytes = 3 << SizeShift,
- Size6Bytes = 4 << SizeShift
- };
-}
-
class MSP430InstrInfo : public MSP430GenInstrInfo {
const MSP430RegisterInfo RI;
virtual void anchor();
diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td
index cec43040f60d..25c81d94f75b 100644
--- a/lib/Target/MSP430/MSP430InstrInfo.td
+++ b/lib/Target/MSP430/MSP430InstrInfo.td
@@ -34,8 +34,9 @@ def SDT_MSP430BrCC : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>,
def SDT_MSP430SelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
SDTCisSameAs<1, 2>,
SDTCisVT<3, i8>]>;
-def SDT_MSP430Shift : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
- SDTCisI8<2>]>;
+def SDT_MSP430DAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
+ SDTCisSameAs<0, 2>,
+ SDTCisInt<0>]>;
//===----------------------------------------------------------------------===//
// MSP430 Specific Node Definitions.
@@ -48,6 +49,7 @@ def MSP430retiflag : SDNode<"MSP430ISD::RETI_FLAG", SDTNone,
def MSP430rra : SDNode<"MSP430ISD::RRA", SDTIntUnaryOp, []>;
def MSP430rla : SDNode<"MSP430ISD::RLA", SDTIntUnaryOp, []>;
def MSP430rrc : SDNode<"MSP430ISD::RRC", SDTIntUnaryOp, []>;
+def MSP430rrcl : SDNode<"MSP430ISD::RRCL", SDTIntUnaryOp, []>;
def MSP430call : SDNode<"MSP430ISD::CALL", SDT_MSP430Call,
[SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>;
@@ -63,33 +65,88 @@ def MSP430brcc : SDNode<"MSP430ISD::BR_CC", SDT_MSP430BrCC,
[SDNPHasChain, SDNPInGlue]>;
def MSP430selectcc: SDNode<"MSP430ISD::SELECT_CC", SDT_MSP430SelectCC,
[SDNPInGlue]>;
-def MSP430shl : SDNode<"MSP430ISD::SHL", SDT_MSP430Shift, []>;
-def MSP430sra : SDNode<"MSP430ISD::SRA", SDT_MSP430Shift, []>;
-def MSP430srl : SDNode<"MSP430ISD::SRL", SDT_MSP430Shift, []>;
+def MSP430dadd : SDNode<"MSP430ISD::DADD", SDT_MSP430DAdd, []>;
//===----------------------------------------------------------------------===//
// MSP430 Operand Definitions.
//===----------------------------------------------------------------------===//
+def MemAsmOperand : AsmOperandClass {
+ let Name = "Mem";
+}
+
// Address operands
def memsrc : Operand<i16> {
let PrintMethod = "printSrcMemOperand";
let MIOperandInfo = (ops GR16, i16imm);
+ let ParserMatchClass = MemAsmOperand;
+ let EncoderMethod = "getMemOpValue";
+ let DecoderMethod = "DecodeMemOperand";
}
def memdst : Operand<i16> {
let PrintMethod = "printSrcMemOperand";
let MIOperandInfo = (ops GR16, i16imm);
+ let ParserMatchClass = MemAsmOperand;
+ let EncoderMethod = "getMemOpValue";
+ let DecoderMethod = "DecodeMemOperand";
+}
+
+def IndRegAsmOperand : AsmOperandClass {
+ let Name = "IndReg";
+ let RenderMethod = "addRegOperands";
+}
+
+def indreg : Operand<i16> {
+ let PrintMethod = "printIndRegOperand";
+ let MIOperandInfo = (ops GR16);
+ let ParserMatchClass = IndRegAsmOperand;
+ let DecoderMethod = "DecodeGR16RegisterClass";
+}
+
+def PostIndRegAsmOperand : AsmOperandClass {
+ let Name = "PostIndReg";
+ let RenderMethod = "addRegOperands";
+}
+
+def postreg : Operand<i16> {
+ let PrintMethod = "printPostIndRegOperand";
+ let MIOperandInfo = (ops GR16);
+ let ParserMatchClass = PostIndRegAsmOperand;
+ let DecoderMethod = "DecodeGR16RegisterClass";
}
// Short jump targets have OtherVT type and are printed as pcrel imm values.
def jmptarget : Operand<OtherVT> {
let PrintMethod = "printPCRelImmOperand";
+ let EncoderMethod = "getPCRelImmOpValue";
}
// Operand for printing out a condition code.
def cc : Operand<i8> {
let PrintMethod = "printCCOperand";
+ let EncoderMethod = "getCCOpValue";
+}
+
+def CGImmAsmOperand : AsmOperandClass {
+ let Name = "CGImm";
+ let RenderMethod = "addImmOperands";
+}
+
+def cg8imm : Operand<i8>,
+ ImmLeaf<i8, [{return Imm == 0 || Imm == 1 || Imm == 2 ||
+ Imm == 4 || Imm == 8 || Imm == -1;}]> {
+ let ParserMatchClass = CGImmAsmOperand;
+ let EncoderMethod = "getCGImmOpValue";
+ let DecoderMethod = "DecodeCGImm";
+}
+
+def cg16imm : Operand<i16>,
+ ImmLeaf<i16, [{return Imm == 0 || Imm == 1 || Imm == 2 ||
+ Imm == 4 || Imm == 8 || Imm == -1;}]> {
+ let ParserMatchClass = CGImmAsmOperand;
+ let EncoderMethod = "getCGImmOpValue";
+ let DecoderMethod = "DecodeCGImm";
}
//===----------------------------------------------------------------------===//
@@ -102,6 +159,7 @@ def addr : ComplexPattern<iPTR, 2, "SelectAddr", [], []>;
// Pattern Fragments
def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>;
def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 ( extloadi8 node:$ptr))>;
+def bic : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, (not node:$rhs))>;
def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{
return N->hasOneUse();
}]>;
@@ -113,21 +171,21 @@ def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{
// pointer before prolog-epilog rewriting occurs.
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
// sub / add which can clobber SR.
-let Defs = [SP, SR], Uses = [SP] in {
+let isCodeGenOnly = 1, Defs = [SP, SR], Uses = [SP] in {
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i16imm:$amt1, i16imm:$amt2),
- "#ADJCALLSTACKDOWN",
+ "#ADJCALLSTACKDOWN $amt1 $amt2",
[(MSP430callseq_start timm:$amt1, timm:$amt2)]>;
def ADJCALLSTACKUP : Pseudo<(outs), (ins i16imm:$amt1, i16imm:$amt2),
- "#ADJCALLSTACKUP",
+ "#ADJCALLSTACKUP $amt1 $amt2",
[(MSP430callseq_end timm:$amt1, timm:$amt2)]>;
}
-let Defs = [SR], Uses = [SP] in {
+let isCodeGenOnly = 1, Defs = [SR], Uses = [SP] in {
def ADDframe : Pseudo<(outs GR16:$dst), (ins i16imm:$base, i16imm:$offset),
"# ADDframe PSEUDO", []>;
}
-let usesCustomInserter = 1 in {
+let isCodeGenOnly = 1, usesCustomInserter = 1 in {
let Uses = [SR] in {
def Select8 : Pseudo<(outs GR8:$dst), (ins GR8:$src, GR8:$src2, i8imm:$cc),
"# Select8 PSEUDO",
@@ -141,38 +199,44 @@ let usesCustomInserter = 1 in {
let Defs = [SR] in {
def Shl8 : Pseudo<(outs GR8:$dst), (ins GR8:$src, GR8:$cnt),
"# Shl8 PSEUDO",
- [(set GR8:$dst, (MSP430shl GR8:$src, GR8:$cnt))]>;
+ [(set GR8:$dst, (shl GR8:$src, GR8:$cnt))]>;
def Shl16 : Pseudo<(outs GR16:$dst), (ins GR16:$src, GR8:$cnt),
"# Shl16 PSEUDO",
- [(set GR16:$dst, (MSP430shl GR16:$src, GR8:$cnt))]>;
+ [(set GR16:$dst, (shl GR16:$src, GR8:$cnt))]>;
def Sra8 : Pseudo<(outs GR8:$dst), (ins GR8:$src, GR8:$cnt),
"# Sra8 PSEUDO",
- [(set GR8:$dst, (MSP430sra GR8:$src, GR8:$cnt))]>;
+ [(set GR8:$dst, (sra GR8:$src, GR8:$cnt))]>;
def Sra16 : Pseudo<(outs GR16:$dst), (ins GR16:$src, GR8:$cnt),
"# Sra16 PSEUDO",
- [(set GR16:$dst, (MSP430sra GR16:$src, GR8:$cnt))]>;
+ [(set GR16:$dst, (sra GR16:$src, GR8:$cnt))]>;
def Srl8 : Pseudo<(outs GR8:$dst), (ins GR8:$src, GR8:$cnt),
"# Srl8 PSEUDO",
- [(set GR8:$dst, (MSP430srl GR8:$src, GR8:$cnt))]>;
+ [(set GR8:$dst, (srl GR8:$src, GR8:$cnt))]>;
def Srl16 : Pseudo<(outs GR16:$dst), (ins GR16:$src, GR8:$cnt),
"# Srl16 PSEUDO",
- [(set GR16:$dst, (MSP430srl GR16:$src, GR8:$cnt))]>;
-
+ [(set GR16:$dst, (srl GR16:$src, GR8:$cnt))]>;
+ def Rrcl8 : Pseudo<(outs GR8:$dst), (ins GR8:$src), "",
+ [(set GR8:$dst, (MSP430rrcl GR8:$src))]>;
+ def Rrcl16 : Pseudo<(outs GR16:$dst), (ins GR16:$src), "",
+ [(set GR16:$dst, (MSP430rrcl GR16:$src))]>;
}
}
-let hasSideEffects = 0 in
-def NOP : Pseudo<(outs), (ins), "nop", []>;
-
//===----------------------------------------------------------------------===//
// Control Flow Instructions...
//
-// FIXME: Provide proper encoding!
let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
- def RET : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs), (ins), "ret", [(MSP430retflag)]>;
- def RETI : II16r<0x0, (outs), (ins), "reti", [(MSP430retiflag)]>;
+ def RET : IForm16<0b0100, DstReg, SrcPostInc, 2,
+ (outs), (ins), "ret", [(MSP430retflag)]> {
+ let DecoderNamespace = "Delta";
+ let rs = 1;
+ let rd = 0;
+ }
+ def RETI : IIForm16<0b110, SrcReg, 2,
+ (outs), (ins), "reti", [(MSP430retiflag)]> {
+ let rs = 0;
+ }
}
let isBranch = 1, isTerminator = 1 in {
@@ -182,120 +246,143 @@ let isBranch = 1, isTerminator = 1 in {
// Direct branch
let isBarrier = 1 in {
// Short branch
- def JMP : CJForm<0, 0, (outs), (ins jmptarget:$dst),
+ def JMP : CJForm<(outs), (ins jmptarget:$dst),
"jmp\t$dst",
- [(br bb:$dst)]>;
- let isIndirectBranch = 1 in {
+ [(br bb:$dst)]> {
+ let cond = 0b111;
+ }
+ let isIndirectBranch = 1, rd = 0 in {
// Long branches
- def Bi : I16ri<0, (outs), (ins i16imm:$brdst),
- "br\t$brdst",
- [(brind tblockaddress:$brdst)]>;
- def Br : I16rr<0, (outs), (ins GR16:$brdst),
- "br\t$brdst",
- [(brind GR16:$brdst)]>;
- def Bm : I16rm<0, (outs), (ins memsrc:$brdst),
- "br\t$brdst",
- [(brind (load addr:$brdst))]>;
+ def Bi : I16ri<0b0100, (outs), (ins i16imm:$imm),
+ "br\t$imm",
+ [(brind tblockaddress:$imm)]>;
+ def Br : I16rr<0b0100, (outs), (ins GR16:$rs),
+ "br\t$rs",
+ [(brind GR16:$rs)]>;
+ def Bm : I16rm<0b0100, (outs), (ins memsrc:$src),
+ "br\t$src",
+ [(brind (load addr:$src))]>;
}
}
// Conditional branches
let Uses = [SR] in
- def JCC : CJForm<0, 0,
- (outs), (ins jmptarget:$dst, cc:$cc),
- "j$cc\t$dst",
- [(MSP430brcc bb:$dst, imm:$cc)]>;
+ def JCC : CJForm<(outs), (ins jmptarget:$dst, cc:$cond),
+ "j$cond\t$dst",
+ [(MSP430brcc bb:$dst, imm:$cond)]>;
} // isBranch, isTerminator
//===----------------------------------------------------------------------===//
// Call Instructions...
//
-let isCall = 1 in
- // All calls clobber the non-callee saved registers. SPW is marked as
- // a use to prevent stack-pointer assignments that appear immediately
- // before calls from potentially appearing dead. Uses for argument
- // registers are added manually.
- let Defs = [R11, R12, R13, R14, R15, SR],
- Uses = [SP] in {
- def CALLi : II16i<0x0,
- (outs), (ins i16imm:$dst),
- "call\t$dst", [(MSP430call imm:$dst)]>;
- def CALLr : II16r<0x0,
- (outs), (ins GR16:$dst),
- "call\t$dst", [(MSP430call GR16:$dst)]>;
- def CALLm : II16m<0x0,
- (outs), (ins memsrc:$dst),
- "call\t${dst:mem}", [(MSP430call (load addr:$dst))]>;
- }
-
+// All calls clobber the non-callee saved registers. SPW is marked as
+// a use to prevent stack-pointer assignments that appear immediately
+// before calls from potentially appearing dead. Uses for argument
+// registers are added manually.
+let isCall = 1,
+ Defs = [R11, R12, R13, R14, R15, SR],
+ Uses = [SP] in {
+ def CALLi : II16i<0b101,
+ (outs), (ins i16imm:$imm),
+ "call\t$imm", [(MSP430call imm:$imm)]>;
+ def CALLr : II16r<0b101,
+ (outs), (ins GR16:$rs),
+ "call\t$rs", [(MSP430call GR16:$rs)]>;
+ def CALLm : II16m<0b101,
+ (outs), (ins memsrc:$src),
+ "call\t$src", [(MSP430call (load addr:$src))]>;
+ def CALLn : II16n<0b101, (outs), (ins indreg:$rs), "call\t$rs", []>;
+ def CALLp : II16p<0b101, (outs), (ins postreg:$rs), "call\t$rs", []>;
+}
//===----------------------------------------------------------------------===//
// Miscellaneous Instructions...
//
-let Defs = [SP], Uses = [SP], hasSideEffects=0 in {
+let Defs = [SP], Uses = [SP], hasSideEffects = 0 in {
let mayLoad = 1 in
-def POP16r : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR16:$reg), (ins), "pop.w\t$reg", []>;
+def POP16r : IForm16<0b0100, DstReg, SrcPostInc, 2,
+ (outs GR16:$rd), (ins), "pop\t$rd", []> {
+ let DecoderNamespace = "Delta";
+ let rs = 1;
+}
let mayStore = 1 in
-def PUSH16r : II16r<0x0,
- (outs), (ins GR16:$reg), "push.w\t$reg",[]>;
+def PUSH8r : II8r<0b100, (outs), (ins GR8:$rs), "push.b\t$rs", []>;
+def PUSH16r : II16r<0b100, (outs), (ins GR16:$rs), "push\t$rs", []>;
+def PUSH16c : II16c<0b100, (outs), (ins cg16imm:$imm), "push\t$imm", []>;
+def PUSH16i : II16i<0b100, (outs), (ins i16imm:$imm), "push\t$imm", []>;
}
//===----------------------------------------------------------------------===//
// Move Instructions
-// FIXME: Provide proper encoding!
let hasSideEffects = 0 in {
-def MOV8rr : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src),
- "mov.b\t{$src, $dst}",
+def MOV8rr : I8rr<0b0100,
+ (outs GR8:$rd), (ins GR8:$rs),
+ "mov.b\t{$rs, $rd}",
[]>;
-def MOV16rr : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src),
- "mov.w\t{$src, $dst}",
+def MOV16rr : I16rr<0b0100,
+ (outs GR16:$rd), (ins GR16:$rs),
+ "mov\t{$rs, $rd}",
[]>;
}
-// FIXME: Provide proper encoding!
let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
-def MOV8ri : I8ri<0x0,
- (outs GR8:$dst), (ins i8imm:$src),
- "mov.b\t{$src, $dst}",
- [(set GR8:$dst, imm:$src)]>;
-def MOV16ri : I16ri<0x0,
- (outs GR16:$dst), (ins i16imm:$src),
- "mov.w\t{$src, $dst}",
- [(set GR16:$dst, imm:$src)]>;
+def MOV8rc : I8rc<0b0100,
+ (outs GR8:$rd), (ins cg8imm:$imm),
+ "mov.b\t$imm, $rd",
+ [(set GR8:$rd, cg8imm:$imm)]>;
+def MOV16rc : I16rc<0b0100,
+ (outs GR16:$rd), (ins cg16imm:$imm),
+ "mov\t$imm, $rd",
+ [(set GR16:$rd, cg16imm:$imm)]>;
+def MOV8ri : I8ri<0b0100,
+ (outs GR8:$rd), (ins i8imm:$imm),
+ "mov.b\t{$imm, $rd}",
+ [(set GR8:$rd, imm:$imm)]>;
+def MOV16ri : I16ri<0b0100,
+ (outs GR16:$rd), (ins i16imm:$imm),
+ "mov\t{$imm, $rd}",
+ [(set GR16:$rd, imm:$imm)]>;
}
let canFoldAsLoad = 1, isReMaterializable = 1 in {
-def MOV8rm : I8rm<0x0,
- (outs GR8:$dst), (ins memsrc:$src),
- "mov.b\t{$src, $dst}",
- [(set GR8:$dst, (load addr:$src))]>;
-def MOV16rm : I16rm<0x0,
- (outs GR16:$dst), (ins memsrc:$src),
- "mov.w\t{$src, $dst}",
- [(set GR16:$dst, (load addr:$src))]>;
+def MOV8rm : I8rm<0b0100,
+ (outs GR8:$rd), (ins memsrc:$src),
+ "mov.b\t{$src, $rd}",
+ [(set GR8:$rd, (load addr:$src))]>;
+def MOV16rm : I16rm<0b0100,
+ (outs GR16:$rd), (ins memsrc:$src),
+ "mov\t{$src, $rd}",
+ [(set GR16:$rd, (load addr:$src))]>;
+def MOV8rn : I8rn<0b0100,
+ (outs GR8:$rd), (ins indreg:$rs),
+ "mov.b\t{$rs, $rd}",
+ [(set GR8:$rd, (load addr:$rs))]>;
+def MOV16rn : I16rn<0b0100,
+ (outs GR16:$rd), (ins indreg:$rs),
+ "mov\t{$rs, $rd}",
+ [(set GR16:$rd, (load addr:$rs))]>;
+}
+
+let isCodeGenOnly = 1 in {
+def MOVZX16rr8 : I8rr<0b0100,
+ (outs GR16:$rd), (ins GR8:$rs),
+ "mov.b\t{$rs, $rd}",
+ [(set GR16:$rd, (zext GR8:$rs))]>;
+def MOVZX16rm8 : I8rm<0b0100,
+ (outs GR16:$rd), (ins memsrc:$src),
+ "mov.b\t{$src, $rd}",
+ [(set GR16:$rd, (zextloadi16i8 addr:$src))]>;
}
-def MOVZX16rr8 : I8rr<0x0,
- (outs GR16:$dst), (ins GR8:$src),
- "mov.b\t{$src, $dst}",
- [(set GR16:$dst, (zext GR8:$src))]>;
-def MOVZX16rm8 : I8rm<0x0,
- (outs GR16:$dst), (ins memsrc:$src),
- "mov.b\t{$src, $dst}",
- [(set GR16:$dst, (zextloadi16i8 addr:$src))]>;
-
-let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb" in {
-def MOV8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR8:$dst, GR16:$base_wb), (ins GR16:$base),
- "mov.b\t{@$base+, $dst}", []>;
-def MOV16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR16:$dst, GR16:$base_wb), (ins GR16:$base),
- "mov.w\t{@$base+, $dst}", []>;
+let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$rs = $wb" in {
+def MOV8rp : I8rp<0b0100,
+ (outs GR8:$rd, GR16:$wb), (ins postreg:$rs),
+ "mov.b\t{$rs, $rd}", []>;
+def MOV16rp : I16rp<0b0100,
+ (outs GR16:$rd, GR16:$wb), (ins postreg:$rs),
+ "mov\t{$rs, $rd}", []>;
}
// Any instruction that defines a 8-bit result leaves the high half of the
@@ -313,821 +400,557 @@ def def8 : PatLeaf<(i8 GR8:$src), [{
def : Pat<(i16 (zext def8:$src)),
(SUBREG_TO_REG (i16 0), GR8:$src, subreg_8bit)>;
-def MOV8mi : I8mi<0x0,
- (outs), (ins memdst:$dst, i8imm:$src),
- "mov.b\t{$src, $dst}",
- [(store (i8 imm:$src), addr:$dst)]>;
-def MOV16mi : I16mi<0x0,
- (outs), (ins memdst:$dst, i16imm:$src),
- "mov.w\t{$src, $dst}",
- [(store (i16 imm:$src), addr:$dst)]>;
-
-def MOV8mr : I8mr<0x0,
- (outs), (ins memdst:$dst, GR8:$src),
- "mov.b\t{$src, $dst}",
- [(store GR8:$src, addr:$dst)]>;
-def MOV16mr : I16mr<0x0,
- (outs), (ins memdst:$dst, GR16:$src),
- "mov.w\t{$src, $dst}",
- [(store GR16:$src, addr:$dst)]>;
-
-def MOV8mm : I8mm<0x0,
+def MOV8mc : I8mc<0b0100,
+ (outs), (ins memdst:$dst, cg8imm:$imm),
+ "mov.b\t{$imm, $dst}",
+ [(store (i8 cg8imm:$imm), addr:$dst)]>;
+def MOV16mc : I16mc<0b0100,
+ (outs), (ins memdst:$dst, cg16imm:$imm),
+ "mov\t{$imm, $dst}",
+ [(store (i16 cg16imm:$imm), addr:$dst)]>;
+
+def MOV8mi : I8mi<0b0100,
+ (outs), (ins memdst:$dst, i8imm:$imm),
+ "mov.b\t{$imm, $dst}",
+ [(store (i8 imm:$imm), addr:$dst)]>;
+def MOV16mi : I16mi<0b0100,
+ (outs), (ins memdst:$dst, i16imm:$imm),
+ "mov\t{$imm, $dst}",
+ [(store (i16 imm:$imm), addr:$dst)]>;
+
+def MOV8mr : I8mr<0b0100,
+ (outs), (ins memdst:$dst, GR8:$rs),
+ "mov.b\t{$rs, $dst}",
+ [(store GR8:$rs, addr:$dst)]>;
+def MOV16mr : I16mr<0b0100,
+ (outs), (ins memdst:$dst, GR16:$rs),
+ "mov\t{$rs, $dst}",
+ [(store GR16:$rs, addr:$dst)]>;
+
+def MOV8mm : I8mm<0b0100,
(outs), (ins memdst:$dst, memsrc:$src),
"mov.b\t{$src, $dst}",
[(store (i8 (load addr:$src)), addr:$dst)]>;
-def MOV16mm : I16mm<0x0,
+def MOV16mm : I16mm<0b0100,
(outs), (ins memdst:$dst, memsrc:$src),
- "mov.w\t{$src, $dst}",
+ "mov\t{$src, $dst}",
[(store (i16 (load addr:$src)), addr:$dst)]>;
+def MOV8mn : I8mn<0b0100, (outs), (ins memdst:$dst, indreg:$rs),
+ "mov.b\t{$rs, $dst}", []>;
+def MOV16mn : I16mn<0b0100, (outs), (ins memdst:$dst, indreg:$rs),
+ "mov\t{$rs, $dst}", []>;
+
//===----------------------------------------------------------------------===//
// Arithmetic Instructions
-let Constraints = "$src = $dst" in {
-
-let Defs = [SR] in {
-
-let isCommutable = 1 in { // X = ADD Y, Z == X = ADD Z, Y
-
-def ADD8rr : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src, GR8:$src2),
- "add.b\t{$src2, $dst}",
- [(set GR8:$dst, (add GR8:$src, GR8:$src2)),
+multiclass Arith<bits<4> opcode, string asmstring, SDNode node,
+ bit commutes, list<Register> uses> {
+ let Defs = [SR], Uses = uses in {
+ let Constraints = "$src2 = $rd" in {
+ let isCommutable = commutes in {
+ def 8rr : I8rr<opcode, (outs GR8:$rd), (ins GR8:$src2, GR8:$rs),
+ !strconcat(asmstring, ".b\t$rs, $rd"),
+ [(set GR8:$rd, (node GR8:$src2, GR8:$rs)),
+ (implicit SR)]>;
+ def 16rr : I16rr<opcode, (outs GR16:$rd), (ins GR16:$src2, GR16:$rs),
+ !strconcat(asmstring, "\t$rs, $rd"),
+ [(set GR16:$rd, (node GR16:$src2, GR16:$rs)),
(implicit SR)]>;
-def ADD16rr : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src, GR16:$src2),
- "add.w\t{$src2, $dst}",
- [(set GR16:$dst, (add GR16:$src, GR16:$src2)),
- (implicit SR)]>;
-}
-
-def ADD8rm : I8rm<0x0,
- (outs GR8:$dst), (ins GR8:$src, memsrc:$src2),
- "add.b\t{$src2, $dst}",
- [(set GR8:$dst, (add GR8:$src, (load addr:$src2))),
+ }
+ def 8rm : I8rm<opcode, (outs GR8:$rd), (ins GR8:$src2, memsrc:$src),
+ !strconcat(asmstring, ".b\t$src, $rd"),
+ [(set GR8:$rd, (node GR8:$src2, (load addr:$src))),
+ (implicit SR)]>;
+ def 16rm : I16rm<opcode, (outs GR16:$rd), (ins GR16:$src2, memsrc:$src),
+ !strconcat(asmstring, "\t$src, $rd"),
+ [(set GR16:$rd, (node GR16:$src2, (load addr:$src))),
(implicit SR)]>;
-def ADD16rm : I16rm<0x0,
- (outs GR16:$dst), (ins GR16:$src, memsrc:$src2),
- "add.w\t{$src2, $dst}",
- [(set GR16:$dst, (add GR16:$src, (load addr:$src2))),
- (implicit SR)]>;
-
-let mayLoad = 1, hasExtraDefRegAllocReq = 1,
-Constraints = "$base = $base_wb, $src = $dst" in {
-def ADD8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR8:$dst, GR16:$base_wb),
- (ins GR8:$src, GR16:$base),
- "add.b\t{@$base+, $dst}", []>;
-def ADD16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR16:$dst, GR16:$base_wb),
- (ins GR16:$src, GR16:$base),
- "add.w\t{@$base+, $dst}", []>;
-}
-
-
-def ADD8ri : I8ri<0x0,
- (outs GR8:$dst), (ins GR8:$src, i8imm:$src2),
- "add.b\t{$src2, $dst}",
- [(set GR8:$dst, (add GR8:$src, imm:$src2)),
+ def 8rn : I8rn<opcode, (outs GR8:$rd), (ins GR8:$src2, indreg:$rs),
+ !strconcat(asmstring, ".b\t$rs, $rd"), []>;
+ def 16rn : I16rn<opcode, (outs GR16:$rd), (ins GR16:$src2, indreg:$rs),
+ !strconcat(asmstring, "\t$rs, $rd"), []>;
+ let mayLoad = 1,
+ hasExtraDefRegAllocReq = 1,
+ Constraints = "$rs = $wb, $src2 = $rd" in {
+ def 8rp : I8rp<opcode, (outs GR8:$rd, GR16:$wb), (ins GR8:$src2, postreg:$rs),
+ !strconcat(asmstring, ".b\t$rs, $rd"), []>;
+ def 16rp : I16rp<opcode, (outs GR16:$rd, GR16:$wb), (ins GR16:$src2, postreg:$rs),
+ !strconcat(asmstring, "\t$rs, $rd"), []>;
+ }
+ def 8rc : I8rc<opcode, (outs GR8:$rd), (ins GR8:$src2, cg8imm:$imm),
+ !strconcat(asmstring, ".b\t$imm, $rd"),
+ [(set GR8:$rd, (node GR8:$src2, cg8imm:$imm)),
+ (implicit SR)]>;
+ def 16rc : I16rc<opcode, (outs GR16:$rd), (ins GR16:$src2, cg16imm:$imm),
+ !strconcat(asmstring, "\t$imm, $rd"),
+ [(set GR16:$rd, (node GR16:$src2, cg16imm:$imm)),
+ (implicit SR)]>;
+ def 8ri : I8ri<opcode, (outs GR8:$rd), (ins GR8:$src2, i8imm:$imm),
+ !strconcat(asmstring, ".b\t$imm, $rd"),
+ [(set GR8:$rd, (node GR8:$src2, imm:$imm)),
+ (implicit SR)]>;
+ def 16ri : I16ri<opcode, (outs GR16:$rd), (ins GR16:$src2, i16imm:$imm),
+ !strconcat(asmstring, "\t$imm, $rd"),
+ [(set GR16:$rd, (node GR16:$src2, imm:$imm)),
+ (implicit SR)]>;
+ }
+ def 8mr : I8mr<opcode, (outs), (ins memdst:$dst, GR8:$rs),
+ !strconcat(asmstring, ".b\t$rs, $dst"),
+ [(store (node (load addr:$dst), GR8:$rs), addr:$dst),
+ (implicit SR)]>;
+ def 16mr : I16mr<opcode, (outs), (ins memdst:$dst, GR16:$rs),
+ !strconcat(asmstring, "\t$rs, $dst"),
+ [(store (node (load addr:$dst), GR16:$rs), addr:$dst),
(implicit SR)]>;
-def ADD16ri : I16ri<0x0,
- (outs GR16:$dst), (ins GR16:$src, i16imm:$src2),
- "add.w\t{$src2, $dst}",
- [(set GR16:$dst, (add GR16:$src, imm:$src2)),
- (implicit SR)]>;
-
-let Constraints = "" in {
-def ADD8mr : I8mr<0x0,
- (outs), (ins memdst:$dst, GR8:$src),
- "add.b\t{$src, $dst}",
- [(store (add (load addr:$dst), GR8:$src), addr:$dst),
+ def 8mc : I8mc<opcode, (outs), (ins memdst:$dst, cg8imm:$imm),
+ !strconcat(asmstring, ".b\t$imm, $dst"),
+ [(store (node (load addr:$dst), (i8 cg8imm:$imm)), addr:$dst),
+ (implicit SR)]>;
+ def 16mc : I16mc<opcode, (outs), (ins memdst:$dst, cg16imm:$imm),
+ !strconcat(asmstring, "\t$imm, $dst"),
+ [(store (node (load addr:$dst), (i16 cg16imm:$imm)), addr:$dst),
(implicit SR)]>;
-def ADD16mr : I16mr<0x0,
- (outs), (ins memdst:$dst, GR16:$src),
- "add.w\t{$src, $dst}",
- [(store (add (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SR)]>;
-
-def ADD8mi : I8mi<0x0,
- (outs), (ins memdst:$dst, i8imm:$src),
- "add.b\t{$src, $dst}",
- [(store (add (load addr:$dst), (i8 imm:$src)), addr:$dst),
+ def 8mi : I8mi<opcode, (outs), (ins memdst:$dst, i8imm:$imm),
+ !strconcat(asmstring, ".b\t$imm, $dst"),
+ [(store (node (load addr:$dst), (i8 imm:$imm)), addr:$dst),
+ (implicit SR)]>;
+ def 16mi : I16mi<opcode, (outs), (ins memdst:$dst, i16imm:$imm),
+ !strconcat(asmstring, "\t$imm, $dst"),
+ [(store (node (load addr:$dst), (i16 imm:$imm)), addr:$dst),
(implicit SR)]>;
-def ADD16mi : I16mi<0x0,
- (outs), (ins memdst:$dst, i16imm:$src),
- "add.w\t{$src, $dst}",
- [(store (add (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SR)]>;
-
-def ADD8mm : I8mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "add.b\t{$src, $dst}",
- [(store (add (load addr:$dst),
- (i8 (load addr:$src))), addr:$dst),
+ def 8mm : I8mm<opcode, (outs), (ins memdst:$dst, memsrc:$src),
+ !strconcat(asmstring, ".b\t$src, $dst"),
+ [(store (node (load addr:$dst),
+ (i8 (load addr:$src))), addr:$dst),
+ (implicit SR)]>;
+ def 16mm : I16mm<opcode, (outs), (ins memdst:$dst, memsrc:$src),
+ !strconcat(asmstring, "\t$src, $dst"),
+ [(store (node (load addr:$dst),
+ (i16 (load addr:$src))), addr:$dst),
(implicit SR)]>;
-def ADD16mm : I16mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "add.w\t{$src, $dst}",
- [(store (add (load addr:$dst),
- (i16 (load addr:$src))), addr:$dst),
- (implicit SR)]>;
+ def 8mn : I8mn<opcode, (outs), (ins memdst:$dst, indreg:$rs),
+ !strconcat(asmstring, ".b\t$rs, $dst"), []>;
+ def 16mn : I16mn<opcode, (outs), (ins memdst:$dst, indreg:$rs),
+ !strconcat(asmstring, "\t$rs, $dst"), []>;
+ def 8mp : I8mp<opcode, (outs), (ins memdst:$dst, postreg:$rs),
+ !strconcat(asmstring, ".b\t$rs, $dst"), []>;
+ def 16mp : I16mp<opcode, (outs), (ins memdst:$dst, postreg:$rs),
+ !strconcat(asmstring, "\t$rs, $dst"), []>;
+ }
}
-let Uses = [SR] in {
-
-let isCommutable = 1 in { // X = ADDC Y, Z == X = ADDC Z, Y
-def ADC8rr : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src, GR8:$src2),
- "addc.b\t{$src2, $dst}",
- [(set GR8:$dst, (adde GR8:$src, GR8:$src2)),
- (implicit SR)]>;
-def ADC16rr : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src, GR16:$src2),
- "addc.w\t{$src2, $dst}",
- [(set GR16:$dst, (adde GR16:$src, GR16:$src2)),
- (implicit SR)]>;
-} // isCommutable
-
-def ADC8ri : I8ri<0x0,
- (outs GR8:$dst), (ins GR8:$src, i8imm:$src2),
- "addc.b\t{$src2, $dst}",
- [(set GR8:$dst, (adde GR8:$src, imm:$src2)),
- (implicit SR)]>;
-def ADC16ri : I16ri<0x0,
- (outs GR16:$dst), (ins GR16:$src, i16imm:$src2),
- "addc.w\t{$src2, $dst}",
- [(set GR16:$dst, (adde GR16:$src, imm:$src2)),
- (implicit SR)]>;
-
-def ADC8rm : I8rm<0x0,
- (outs GR8:$dst), (ins GR8:$src, memsrc:$src2),
- "addc.b\t{$src2, $dst}",
- [(set GR8:$dst, (adde GR8:$src, (load addr:$src2))),
- (implicit SR)]>;
-def ADC16rm : I16rm<0x0,
- (outs GR16:$dst), (ins GR16:$src, memsrc:$src2),
- "addc.w\t{$src2, $dst}",
- [(set GR16:$dst, (adde GR16:$src, (load addr:$src2))),
- (implicit SR)]>;
+defm ADD : Arith<0b0101, "add", add, 1, []>;
+defm ADDC : Arith<0b0110, "addc", adde, 1, [SR]>;
+defm AND : Arith<0b1111, "and", and, 1, []>;
+defm BIS : Arith<0b1101, "bis", or, 1, []>;
+defm BIC : Arith<0b1100, "bic", bic, 0, []>;
+defm XOR : Arith<0b1110, "xor", xor, 1, []>;
+defm SUB : Arith<0b1000, "sub", sub, 0, []>;
+defm SUBC : Arith<0b0111, "subc", sube, 0, [SR]>;
+defm DADD : Arith<0b1010, "dadd", MSP430dadd, 1, [SR]>;
+
+def ADC8r : InstAlias<"adc.b\t$dst", (ADDC8rc GR8:$dst, 0)>;
+def ADC16r : InstAlias<"adc\t$dst", (ADDC16rc GR16:$dst, 0)>;
+def ADC8m : InstAlias<"adc.b\t$dst", (ADDC8mc memdst:$dst, 0)>;
+def ADC16m : InstAlias<"adc\t$dst", (ADDC16mc memdst:$dst, 0)>;
+
+def DADC8r : InstAlias<"dadc.b\t$dst", (DADD8rc GR8:$dst, 0)>;
+def DADC16r : InstAlias<"dadc\t$dst", (DADD16rc GR16:$dst, 0)>;
+def DADC8m : InstAlias<"dadc.b\t$dst", (DADD8mc memdst:$dst, 0)>;
+def DADC16m : InstAlias<"dadc\t$dst", (DADD16mc memdst:$dst, 0)>;
+
+def DEC8r : InstAlias<"dec.b\t$dst", (SUB8rc GR8:$dst, 1)>;
+def DEC16r : InstAlias<"dec\t$dst", (SUB16rc GR16:$dst, 1)>;
+def DEC8m : InstAlias<"dec.b\t$dst", (SUB8mc memdst:$dst, 1)>;
+def DEC16m : InstAlias<"dec\t$dst", (SUB16mc memdst:$dst, 1)>;
+
+def DECD8r : InstAlias<"decd.b\t$dst", (SUB8rc GR8:$dst, 2)>;
+def DECD16r : InstAlias<"decd\t$dst", (SUB16rc GR16:$dst, 2)>;
+def DECD8m : InstAlias<"decd.b\t$dst", (SUB8mc memdst:$dst, 2)>;
+def DECD16m : InstAlias<"decd\t$dst", (SUB16mc memdst:$dst, 2)>;
+
+def INC8r : InstAlias<"inc.b\t$dst", (ADD8rc GR8:$dst, 1)>;
+def INC16r : InstAlias<"inc\t$dst", (ADD16rc GR16:$dst, 1)>;
+def INC8m : InstAlias<"inc.b\t$dst", (ADD8mc memdst:$dst, 1)>;
+def INC16m : InstAlias<"inc\t$dst", (ADD16mc memdst:$dst, 1)>;
+
+def INCD8r : InstAlias<"incd.b\t$dst", (ADD8rc GR8:$dst, 2)>;
+def INCD16r : InstAlias<"incd\t$dst", (ADD16rc GR16:$dst, 2)>;
+def INCD8m : InstAlias<"incd.b\t$dst", (ADD8mc memdst:$dst, 2)>;
+def INCD16m : InstAlias<"incd\t$dst", (ADD16mc memdst:$dst, 2)>;
+
+def SBC8r : InstAlias<"sbc.b\t$dst", (SUBC8rc GR8:$dst, 0)>;
+def SBC16r : InstAlias<"sbc\t$dst", (SUBC16rc GR16:$dst, 0)>;
+def SBC8m : InstAlias<"sbc.b\t$dst", (SUBC8mc memdst:$dst, 0)>;
+def SBC16m : InstAlias<"sbc\t$dst", (SUBC16mc memdst:$dst, 0)>;
+
+def INV8r : InstAlias<"inv.b\t$dst", (XOR8rc GR8:$dst, -1)>;
+def INV16r : InstAlias<"inv\t$dst", (XOR16rc GR16:$dst, -1)>;
+def INV8m : InstAlias<"inv.b\t$dst", (XOR8mc memdst:$dst, -1)>;
+def INV16m : InstAlias<"inv\t$dst", (XOR16mc memdst:$dst, -1)>;
+
+// printAliasInstr() doesn't check $dst operands are actually equal
+// for RLA and RLC aliases below, so disable printing aliases.
+
+def RLA8r : InstAlias<"rla.b\t$dst", (ADD8rr GR8:$dst, GR8:$dst), 0>;
+def RLA16r : InstAlias<"rla\t$dst", (ADD16rr GR16:$dst, GR16:$dst), 0>;
+def RLA8m : InstAlias<"rla.b\t$dst", (ADD8mm memdst:$dst, memdst:$dst), 0>;
+def RLA16m : InstAlias<"rla\t$dst", (ADD16mm memdst:$dst, memdst:$dst), 0>;
+
+def RLC8r : InstAlias<"rlc.b\t$dst", (ADDC8rr GR8:$dst, GR8:$dst), 0>;
+def RLC16r : InstAlias<"rlc\t$dst", (ADDC16rr GR16:$dst, GR16:$dst), 0>;
+def RLC8m : InstAlias<"rlc.b\t$dst", (ADDC8mm memdst:$dst, memdst:$dst), 0>;
+def RLC16m : InstAlias<"rlc\t$dst", (ADDC16mm memdst:$dst, memdst:$dst), 0>;
+
+def DINT : InstAlias<"dint", (BIC16rc SR, 8)>;
+def EINT : InstAlias<"eint", (BIS16rc SR, 8)>;
+
+def NOP : InstAlias<"nop", (MOV16rc CG, 0)>;
+
+def CLR8r : InstAlias<"clr.b\t$dst", (MOV8rc GR8:$dst, 0)>;
+def CLR16r : InstAlias<"clr\t$dst", (MOV16rc GR16:$dst, 0)>;
+def CLR8m : InstAlias<"clr.b\t$dst", (MOV8mc memdst:$dst, 0)>;
+def CLR16m : InstAlias<"clr\t$dst", (MOV16mc memdst:$dst, 0)>;
+
+def CLRC : InstAlias<"clrc", (BIC16rc SR, 1)>;
+def CLRN : InstAlias<"clrn", (BIC16rc SR, 4)>;
+def CLRZ : InstAlias<"clrz", (BIC16rc SR, 2)>;
+def SETC : InstAlias<"setc", (BIS16rc SR, 1)>;
+def SETN : InstAlias<"setn", (BIS16rc SR, 4)>;
+def SETZ : InstAlias<"setz", (BIS16rc SR, 2)>;
+
+def : Pat<(MSP430rla GR8:$dst), (ADD8rr $dst, $dst)>;
+def : Pat<(MSP430rla GR16:$dst), (ADD16rr $dst, $dst)>;
+
+// Format-II (Single Operand) Instruction
+// Register mode
+let Constraints = "$rs = $rd" in {
-let Constraints = "" in {
-def ADC8mr : I8mr<0x0,
- (outs), (ins memdst:$dst, GR8:$src),
- "addc.b\t{$src, $dst}",
- [(store (adde (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SR)]>;
-def ADC16mr : I16mr<0x0,
- (outs), (ins memdst:$dst, GR16:$src),
- "addc.w\t{$src, $dst}",
- [(store (adde (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SR)]>;
-
-def ADC8mi : I8mi<0x0,
- (outs), (ins memdst:$dst, i8imm:$src),
- "addc.b\t{$src, $dst}",
- [(store (adde (load addr:$dst), (i8 imm:$src)), addr:$dst),
+let Defs = [SR] in {
+def RRA8r : II8r<0b010,
+ (outs GR8:$rd), (ins GR8:$rs),
+ "rra.b\t$rd",
+ [(set GR8:$rd, (MSP430rra GR8:$rs)),
(implicit SR)]>;
-def ADC16mi : I16mi<0x0,
- (outs), (ins memdst:$dst, i16imm:$src),
- "addc.w\t{$src, $dst}",
- [(store (adde (load addr:$dst), (i16 imm:$src)), addr:$dst),
+def RRA16r : II16r<0b010,
+ (outs GR16:$rd), (ins GR16:$rs),
+ "rra\t$rd",
+ [(set GR16:$rd, (MSP430rra GR16:$rs)),
(implicit SR)]>;
-def ADC8mm : I8mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "addc.b\t{$src, $dst}",
- [(store (adde (load addr:$dst),
- (i8 (load addr:$src))), addr:$dst),
+let Uses = [SR] in {
+def RRC8r : II8r<0b000,
+ (outs GR8:$rd), (ins GR8:$rs),
+ "rrc.b\t$rd",
+ [(set GR8:$rd, (MSP430rrc GR8:$rs)),
(implicit SR)]>;
-def ADC16mm : I8mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "addc.w\t{$src, $dst}",
- [(store (adde (load addr:$dst),
- (i16 (load addr:$src))), addr:$dst),
+def RRC16r : II16r<0b000,
+ (outs GR16:$rd), (ins GR16:$rs),
+ "rrc\t$rd",
+ [(set GR16:$rd, (MSP430rrc GR16:$rs)),
(implicit SR)]>;
-}
-
} // Uses = [SR]
-let isCommutable = 1 in { // X = AND Y, Z == X = AND Z, Y
-def AND8rr : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src, GR8:$src2),
- "and.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src, GR8:$src2)),
- (implicit SR)]>;
-def AND16rr : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src, GR16:$src2),
- "and.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src, GR16:$src2)),
+def SEXT16r : II16r<0b011,
+ (outs GR16:$rd), (ins GR16:$rs),
+ "sxt\t$rd",
+ [(set GR16:$rd, (sext_inreg GR16:$rs, i8)),
(implicit SR)]>;
-}
-def AND8ri : I8ri<0x0,
- (outs GR8:$dst), (ins GR8:$src, i8imm:$src2),
- "and.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src, imm:$src2)),
- (implicit SR)]>;
-def AND16ri : I16ri<0x0,
- (outs GR16:$dst), (ins GR16:$src, i16imm:$src2),
- "and.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src, imm:$src2)),
- (implicit SR)]>;
+} // Defs = [SR]
-def AND8rm : I8rm<0x0,
- (outs GR8:$dst), (ins GR8:$src, memsrc:$src2),
- "and.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src, (load addr:$src2))),
- (implicit SR)]>;
-def AND16rm : I16rm<0x0,
- (outs GR16:$dst), (ins GR16:$src, memsrc:$src2),
- "and.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src, (load addr:$src2))),
- (implicit SR)]>;
+let isCodeGenOnly = 1 in
+def ZEXT16r : I8rr<0b0100,
+ (outs GR16:$rd), (ins GR16:$rs),
+ "mov.b\t{$rs, $rd}",
+ [(set GR16:$rd, (zext (trunc GR16:$rs)))]>;
-let mayLoad = 1, hasExtraDefRegAllocReq = 1,
-Constraints = "$base = $base_wb, $src = $dst" in {
-def AND8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR8:$dst, GR16:$base_wb),
- (ins GR8:$src, GR16:$base),
- "and.b\t{@$base+, $dst}", []>;
-def AND16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR16:$dst, GR16:$base_wb),
- (ins GR16:$src, GR16:$base),
- "and.w\t{@$base+, $dst}", []>;
-}
+def SWPB16r : II16r<0b001,
+ (outs GR16:$rd), (ins GR16:$rs),
+ "swpb\t$rd",
+ [(set GR16:$rd, (bswap GR16:$rs))]>;
-let Constraints = "" in {
-def AND8mr : I8mr<0x0,
- (outs), (ins memdst:$dst, GR8:$src),
- "and.b\t{$src, $dst}",
- [(store (and (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SR)]>;
-def AND16mr : I16mr<0x0,
- (outs), (ins memdst:$dst, GR16:$src),
- "and.w\t{$src, $dst}",
- [(store (and (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SR)]>;
+} // Constraints = "$src = $dst"
-def AND8mi : I8mi<0x0,
- (outs), (ins memdst:$dst, i8imm:$src),
- "and.b\t{$src, $dst}",
- [(store (and (load addr:$dst), (i8 imm:$src)), addr:$dst),
+// Indexed, indirect register and indirect autoincrement modes
+let Defs = [SR] in {
+def RRA8m : II8m<0b010,
+ (outs), (ins memsrc:$src),
+ "rra.b\t$src",
+ [(store (MSP430rra (i8 (load addr:$src))), addr:$src),
(implicit SR)]>;
-def AND16mi : I16mi<0x0,
- (outs), (ins memdst:$dst, i16imm:$src),
- "and.w\t{$src, $dst}",
- [(store (and (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SR)]>;
-
-def AND8mm : I8mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "and.b\t{$src, $dst}",
- [(store (and (load addr:$dst),
- (i8 (load addr:$src))), addr:$dst),
+def RRA16m : II16m<0b010,
+ (outs), (ins memsrc:$src),
+ "rra\t$src",
+ [(store (MSP430rra (i16 (load addr:$src))), addr:$src),
(implicit SR)]>;
-def AND16mm : I16mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "and.w\t{$src, $dst}",
- [(store (and (load addr:$dst),
- (i16 (load addr:$src))), addr:$dst),
- (implicit SR)]>;
-}
-
-let isCommutable = 1 in { // X = OR Y, Z == X = OR Z, Y
-def OR8rr : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src, GR8:$src2),
- "bis.b\t{$src2, $dst}",
- [(set GR8:$dst, (or GR8:$src, GR8:$src2))]>;
-def OR16rr : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src, GR16:$src2),
- "bis.w\t{$src2, $dst}",
- [(set GR16:$dst, (or GR16:$src, GR16:$src2))]>;
-}
-
-def OR8ri : I8ri<0x0,
- (outs GR8:$dst), (ins GR8:$src, i8imm:$src2),
- "bis.b\t{$src2, $dst}",
- [(set GR8:$dst, (or GR8:$src, imm:$src2))]>;
-def OR16ri : I16ri<0x0,
- (outs GR16:$dst), (ins GR16:$src, i16imm:$src2),
- "bis.w\t{$src2, $dst}",
- [(set GR16:$dst, (or GR16:$src, imm:$src2))]>;
-
-def OR8rm : I8rm<0x0,
- (outs GR8:$dst), (ins GR8:$src, memsrc:$src2),
- "bis.b\t{$src2, $dst}",
- [(set GR8:$dst, (or GR8:$src, (load addr:$src2)))]>;
-def OR16rm : I16rm<0x0,
- (outs GR16:$dst), (ins GR16:$src, memsrc:$src2),
- "bis.w\t{$src2, $dst}",
- [(set GR16:$dst, (or GR16:$src, (load addr:$src2)))]>;
-
-let mayLoad = 1, hasExtraDefRegAllocReq = 1,
-Constraints = "$base = $base_wb, $src = $dst" in {
-def OR8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR8:$dst, GR16:$base_wb),
- (ins GR8:$src, GR16:$base),
- "bis.b\t{@$base+, $dst}", []>;
-def OR16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR16:$dst, GR16:$base_wb),
- (ins GR16:$src, GR16:$base),
- "bis.w\t{@$base+, $dst}", []>;
-}
-
-let Constraints = "" in {
-def OR8mr : I8mr<0x0,
- (outs), (ins memdst:$dst, GR8:$src),
- "bis.b\t{$src, $dst}",
- [(store (or (load addr:$dst), GR8:$src), addr:$dst)]>;
-def OR16mr : I16mr<0x0,
- (outs), (ins memdst:$dst, GR16:$src),
- "bis.w\t{$src, $dst}",
- [(store (or (load addr:$dst), GR16:$src), addr:$dst)]>;
-
-def OR8mi : I8mi<0x0,
- (outs), (ins memdst:$dst, i8imm:$src),
- "bis.b\t{$src, $dst}",
- [(store (or (load addr:$dst), (i8 imm:$src)), addr:$dst)]>;
-def OR16mi : I16mi<0x0,
- (outs), (ins memdst:$dst, i16imm:$src),
- "bis.w\t{$src, $dst}",
- [(store (or (load addr:$dst), (i16 imm:$src)), addr:$dst)]>;
-
-def OR8mm : I8mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "bis.b\t{$src, $dst}",
- [(store (or (i8 (load addr:$dst)),
- (i8 (load addr:$src))), addr:$dst)]>;
-def OR16mm : I16mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "bis.w\t{$src, $dst}",
- [(store (or (i16 (load addr:$dst)),
- (i16 (load addr:$src))), addr:$dst)]>;
-}
-
-// bic does not modify condition codes
-def BIC8rr : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src, GR8:$src2),
- "bic.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src, (not GR8:$src2)))]>;
-def BIC16rr : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src, GR16:$src2),
- "bic.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src, (not GR16:$src2)))]>;
-
-def BIC8rm : I8rm<0x0,
- (outs GR8:$dst), (ins GR8:$src, memsrc:$src2),
- "bic.b\t{$src2, $dst}",
- [(set GR8:$dst, (and GR8:$src, (not (i8 (load addr:$src2)))))]>;
-def BIC16rm : I16rm<0x0,
- (outs GR16:$dst), (ins GR16:$src, memsrc:$src2),
- "bic.w\t{$src2, $dst}",
- [(set GR16:$dst, (and GR16:$src, (not (i16 (load addr:$src2)))))]>;
-
-let Constraints = "" in {
-def BIC8mr : I8mr<0x0,
- (outs), (ins memdst:$dst, GR8:$src),
- "bic.b\t{$src, $dst}",
- [(store (and (load addr:$dst), (not GR8:$src)), addr:$dst)]>;
-def BIC16mr : I16mr<0x0,
- (outs), (ins memdst:$dst, GR16:$src),
- "bic.w\t{$src, $dst}",
- [(store (and (load addr:$dst), (not GR16:$src)), addr:$dst)]>;
-
-def BIC8mm : I8mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "bic.b\t{$src, $dst}",
- [(store (and (load addr:$dst),
- (not (i8 (load addr:$src)))), addr:$dst)]>;
-def BIC16mm : I16mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "bic.w\t{$src, $dst}",
- [(store (and (load addr:$dst),
- (not (i16 (load addr:$src)))), addr:$dst)]>;
-}
-let isCommutable = 1 in { // X = XOR Y, Z == X = XOR Z, Y
-def XOR8rr : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src, GR8:$src2),
- "xor.b\t{$src2, $dst}",
- [(set GR8:$dst, (xor GR8:$src, GR8:$src2)),
- (implicit SR)]>;
-def XOR16rr : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src, GR16:$src2),
- "xor.w\t{$src2, $dst}",
- [(set GR16:$dst, (xor GR16:$src, GR16:$src2)),
- (implicit SR)]>;
-}
+def RRA8n : II8n<0b010, (outs), (ins indreg:$rs), "rra.b\t$rs", []>;
+def RRA16n : II16n<0b010, (outs), (ins indreg:$rs), "rra\t$rs", []>;
+def RRA8p : II8p<0b010, (outs), (ins postreg:$rs), "rra.b\t$rs", []>;
+def RRA16p : II16p<0b010, (outs), (ins postreg:$rs), "rra\t$rs", []>;
-def XOR8ri : I8ri<0x0,
- (outs GR8:$dst), (ins GR8:$src, i8imm:$src2),
- "xor.b\t{$src2, $dst}",
- [(set GR8:$dst, (xor GR8:$src, imm:$src2)),
+let Uses = [SR] in {
+def RRC8m : II8m<0b000,
+ (outs), (ins memsrc:$src),
+ "rrc.b\t$src",
+ [(store (MSP430rrc (i8 (load addr:$src))), addr:$src),
(implicit SR)]>;
-def XOR16ri : I16ri<0x0,
- (outs GR16:$dst), (ins GR16:$src, i16imm:$src2),
- "xor.w\t{$src2, $dst}",
- [(set GR16:$dst, (xor GR16:$src, imm:$src2)),
- (implicit SR)]>;
-
-def XOR8rm : I8rm<0x0,
- (outs GR8:$dst), (ins GR8:$src, memsrc:$src2),
- "xor.b\t{$src2, $dst}",
- [(set GR8:$dst, (xor GR8:$src, (load addr:$src2))),
+def RRC16m : II16m<0b000,
+ (outs), (ins memsrc:$src),
+ "rrc\t$src",
+ [(store (MSP430rrc (i16 (load addr:$src))), addr:$src),
(implicit SR)]>;
-def XOR16rm : I16rm<0x0,
- (outs GR16:$dst), (ins GR16:$src, memsrc:$src2),
- "xor.w\t{$src2, $dst}",
- [(set GR16:$dst, (xor GR16:$src, (load addr:$src2))),
- (implicit SR)]>;
-let mayLoad = 1, hasExtraDefRegAllocReq = 1,
-Constraints = "$base = $base_wb, $src = $dst" in {
-def XOR8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR8:$dst, GR16:$base_wb),
- (ins GR8:$src, GR16:$base),
- "xor.b\t{@$base+, $dst}", []>;
-def XOR16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR16:$dst, GR16:$base_wb),
- (ins GR16:$src, GR16:$base),
- "xor.w\t{@$base+, $dst}", []>;
-}
+def RRC8n : II8n<0b000, (outs), (ins indreg:$rs), "rrc.b\t$rs", []>;
+def RRC16n : II16n<0b000, (outs), (ins indreg:$rs), "rrc\t$rs", []>;
+def RRC8p : II8p<0b000, (outs), (ins postreg:$rs), "rrc.b\t$rs", []>;
+def RRC16p : II16p<0b000, (outs), (ins postreg:$rs), "rrc\t$rs", []>;
-let Constraints = "" in {
-def XOR8mr : I8mr<0x0,
- (outs), (ins memdst:$dst, GR8:$src),
- "xor.b\t{$src, $dst}",
- [(store (xor (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SR)]>;
-def XOR16mr : I16mr<0x0,
- (outs), (ins memdst:$dst, GR16:$src),
- "xor.w\t{$src, $dst}",
- [(store (xor (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SR)]>;
-
-def XOR8mi : I8mi<0x0,
- (outs), (ins memdst:$dst, i8imm:$src),
- "xor.b\t{$src, $dst}",
- [(store (xor (load addr:$dst), (i8 imm:$src)), addr:$dst),
- (implicit SR)]>;
-def XOR16mi : I16mi<0x0,
- (outs), (ins memdst:$dst, i16imm:$src),
- "xor.w\t{$src, $dst}",
- [(store (xor (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SR)]>;
+} // Uses = [SR]
-def XOR8mm : I8mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "xor.b\t{$src, $dst}",
- [(store (xor (load addr:$dst), (i8 (load addr:$src))), addr:$dst),
- (implicit SR)]>;
-def XOR16mm : I16mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "xor.w\t{$src, $dst}",
- [(store (xor (load addr:$dst), (i16 (load addr:$src))), addr:$dst),
+def SEXT16m : II16m<0b011,
+ (outs), (ins memsrc:$src),
+ "sxt\t$src",
+ [(store (sext_inreg (extloadi16i8 addr:$src), i8),
+ addr:$src),
(implicit SR)]>;
-}
+def SEXT16n : II16n<0b011, (outs), (ins indreg:$rs), "sxt\t$rs", []>;
+def SEXT16p : II16p<0b011, (outs), (ins postreg:$rs), "sxt\t$rs", []>;
+} // Defs = [SR]
-def SUB8rr : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src, GR8:$src2),
- "sub.b\t{$src2, $dst}",
- [(set GR8:$dst, (sub GR8:$src, GR8:$src2)),
- (implicit SR)]>;
-def SUB16rr : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src, GR16:$src2),
- "sub.w\t{$src2, $dst}",
- [(set GR16:$dst, (sub GR16:$src, GR16:$src2)),
- (implicit SR)]>;
+def SWPB16m : II16m<0b001,
+ (outs), (ins memsrc:$src),
+ "swpb\t$src",
+ [(store (bswap (i16 (load addr:$src))), addr:$src)]>;
+def SWPB16n : II16n<0b001, (outs), (ins indreg:$rs), "swpb\t$rs", []>;
+def SWPB16p : II16p<0b001, (outs), (ins postreg:$rs), "swpb\t$rs", []>;
-def SUB8ri : I8ri<0x0,
- (outs GR8:$dst), (ins GR8:$src, i8imm:$src2),
- "sub.b\t{$src2, $dst}",
- [(set GR8:$dst, (sub GR8:$src, imm:$src2)),
+// Integer comparisons
+let Defs = [SR] in {
+def CMP8rr : I8rr<0b1001,
+ (outs), (ins GR8:$rd, GR8:$rs),
+ "cmp.b\t$rs, $rd",
+ [(MSP430cmp GR8:$rd, GR8:$rs), (implicit SR)]>;
+def CMP16rr : I16rr<0b1001,
+ (outs), (ins GR16:$rd, GR16:$rs),
+ "cmp\t$rs, $rd",
+ [(MSP430cmp GR16:$rd, GR16:$rs), (implicit SR)]>;
+
+def CMP8rc : I8rc<0b1001,
+ (outs), (ins GR8:$rd, cg8imm:$imm),
+ "cmp.b\t$imm, $rd",
+ [(MSP430cmp GR8:$rd, cg8imm:$imm), (implicit SR)]>;
+def CMP16rc : I16rc<0b1001,
+ (outs), (ins GR16:$rd, cg16imm:$imm),
+ "cmp\t$imm, $rd",
+ [(MSP430cmp GR16:$rd, cg16imm:$imm), (implicit SR)]>;
+
+def CMP8ri : I8ri<0b1001,
+ (outs), (ins GR8:$rd, i8imm:$imm),
+ "cmp.b\t$imm, $rd",
+ [(MSP430cmp GR8:$rd, imm:$imm), (implicit SR)]>;
+def CMP16ri : I16ri<0b1001,
+ (outs), (ins GR16:$rd, i16imm:$imm),
+ "cmp\t$imm, $rd",
+ [(MSP430cmp GR16:$rd, imm:$imm), (implicit SR)]>;
+
+def CMP8mc : I8mc<0b1001,
+ (outs), (ins memsrc:$dst, cg8imm:$imm),
+ "cmp.b\t$imm, $dst",
+ [(MSP430cmp (load addr:$dst), (i8 cg8imm:$imm)),
(implicit SR)]>;
-def SUB16ri : I16ri<0x0,
- (outs GR16:$dst), (ins GR16:$src, i16imm:$src2),
- "sub.w\t{$src2, $dst}",
- [(set GR16:$dst, (sub GR16:$src, imm:$src2)),
+def CMP16mc : I16mc<0b1001,
+ (outs), (ins memsrc:$dst, cg16imm:$imm),
+ "cmp\t$imm, $dst",
+ [(MSP430cmp (load addr:$dst), (i16 cg16imm:$imm)),
(implicit SR)]>;
-def SUB8rm : I8rm<0x0,
- (outs GR8:$dst), (ins GR8:$src, memsrc:$src2),
- "sub.b\t{$src2, $dst}",
- [(set GR8:$dst, (sub GR8:$src, (load addr:$src2))),
+def CMP8mi : I8mi<0b1001,
+ (outs), (ins memsrc:$dst, i8imm:$imm),
+ "cmp.b\t$imm, $dst",
+ [(MSP430cmp (load addr:$dst),
+ (i8 imm:$imm)), (implicit SR)]>;
+def CMP16mi : I16mi<0b1001,
+ (outs), (ins memsrc:$dst, i16imm:$imm),
+ "cmp\t$imm, $dst",
+ [(MSP430cmp (load addr:$dst),
+ (i16 imm:$imm)), (implicit SR)]>;
+
+def CMP8rm : I8rm<0b1001,
+ (outs), (ins GR8:$rd, memsrc:$src),
+ "cmp.b\t$src, $rd",
+ [(MSP430cmp GR8:$rd, (load addr:$src)),
(implicit SR)]>;
-def SUB16rm : I16rm<0x0,
- (outs GR16:$dst), (ins GR16:$src, memsrc:$src2),
- "sub.w\t{$src2, $dst}",
- [(set GR16:$dst, (sub GR16:$src, (load addr:$src2))),
+def CMP16rm : I16rm<0b1001,
+ (outs), (ins GR16:$rd, memsrc:$src),
+ "cmp\t$src, $rd",
+ [(MSP430cmp GR16:$rd, (load addr:$src)),
(implicit SR)]>;
-let mayLoad = 1, hasExtraDefRegAllocReq = 1,
-Constraints = "$base = $base_wb, $src = $dst" in {
-def SUB8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR8:$dst, GR16:$base_wb),
- (ins GR8:$src, GR16:$base),
- "sub.b\t{@$base+, $dst}", []>;
-def SUB16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes,
- (outs GR16:$dst, GR16:$base_wb),
- (ins GR16:$src, GR16:$base),
- "sub.w\t{@$base+, $dst}", []>;
-}
+def CMP8rn : I8rn<0b1001,
+ (outs), (ins GR8:$rd, indreg:$rs), "cmp.b\t$rs, $rd", []>;
+def CMP16rn : I16rn<0b1001,
+ (outs), (ins GR16:$rd, indreg:$rs), "cmp\t$rs, $rd", []>;
-let Constraints = "" in {
-def SUB8mr : I8mr<0x0,
- (outs), (ins memdst:$dst, GR8:$src),
- "sub.b\t{$src, $dst}",
- [(store (sub (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SR)]>;
-def SUB16mr : I16mr<0x0,
- (outs), (ins memdst:$dst, GR16:$src),
- "sub.w\t{$src, $dst}",
- [(store (sub (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SR)]>;
+def CMP8rp : I8rp<0b1001,
+ (outs), (ins GR8:$rd, postreg:$rs), "cmp.b\t$rs, $rd", []>;
+def CMP16rp : I16rp<0b1001,
+ (outs), (ins GR16:$rd, postreg:$rs), "cmp\t$rs, $rd", []>;
-def SUB8mi : I8mi<0x0,
- (outs), (ins memdst:$dst, i8imm:$src),
- "sub.b\t{$src, $dst}",
- [(store (sub (load addr:$dst), (i8 imm:$src)), addr:$dst),
+def CMP8mr : I8mr<0b1001,
+ (outs), (ins memsrc:$dst, GR8:$rs),
+ "cmp.b\t$rs, $dst",
+ [(MSP430cmp (load addr:$dst), GR8:$rs),
(implicit SR)]>;
-def SUB16mi : I16mi<0x0,
- (outs), (ins memdst:$dst, i16imm:$src),
- "sub.w\t{$src, $dst}",
- [(store (sub (load addr:$dst), (i16 imm:$src)), addr:$dst),
+def CMP16mr : I16mr<0b1001,
+ (outs), (ins memsrc:$dst, GR16:$rs),
+ "cmp\t$rs, $dst",
+ [(MSP430cmp (load addr:$dst), GR16:$rs),
(implicit SR)]>;
-
-def SUB8mm : I8mm<0x0,
+def CMP8mm : I8mm<0b1001,
(outs), (ins memdst:$dst, memsrc:$src),
- "sub.b\t{$src, $dst}",
- [(store (sub (load addr:$dst),
- (i8 (load addr:$src))), addr:$dst),
- (implicit SR)]>;
-def SUB16mm : I16mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "sub.w\t{$src, $dst}",
- [(store (sub (load addr:$dst),
- (i16 (load addr:$src))), addr:$dst),
- (implicit SR)]>;
-}
-
-let Uses = [SR] in {
-def SBC8rr : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src, GR8:$src2),
- "subc.b\t{$src2, $dst}",
- [(set GR8:$dst, (sube GR8:$src, GR8:$src2)),
- (implicit SR)]>;
-def SBC16rr : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src, GR16:$src2),
- "subc.w\t{$src2, $dst}",
- [(set GR16:$dst, (sube GR16:$src, GR16:$src2)),
- (implicit SR)]>;
-
-def SBC8ri : I8ri<0x0,
- (outs GR8:$dst), (ins GR8:$src, i8imm:$src2),
- "subc.b\t{$src2, $dst}",
- [(set GR8:$dst, (sube GR8:$src, imm:$src2)),
- (implicit SR)]>;
-def SBC16ri : I16ri<0x0,
- (outs GR16:$dst), (ins GR16:$src, i16imm:$src2),
- "subc.w\t{$src2, $dst}",
- [(set GR16:$dst, (sube GR16:$src, imm:$src2)),
- (implicit SR)]>;
-
-def SBC8rm : I8rm<0x0,
- (outs GR8:$dst), (ins GR8:$src, memsrc:$src2),
- "subc.b\t{$src2, $dst}",
- [(set GR8:$dst, (sube GR8:$src, (load addr:$src2))),
+ "cmp.b\t$src, $dst",
+ [(MSP430cmp (load addr:$dst), (i8 (load addr:$src))),
(implicit SR)]>;
-def SBC16rm : I16rm<0x0,
- (outs GR16:$dst), (ins GR16:$src, memsrc:$src2),
- "subc.w\t{$src2, $dst}",
- [(set GR16:$dst, (sube GR16:$src, (load addr:$src2))),
+def CMP16mm : I16mm<0b1001, (outs), (ins memdst:$dst, memsrc:$src),
+ "cmp\t$src, $dst",
+ [(MSP430cmp (load addr:$dst), (i16 (load addr:$src))),
(implicit SR)]>;
-let Constraints = "" in {
-def SBC8mr : I8mr<0x0,
- (outs), (ins memdst:$dst, GR8:$src),
- "subc.b\t{$src, $dst}",
- [(store (sube (load addr:$dst), GR8:$src), addr:$dst),
- (implicit SR)]>;
-def SBC16mr : I16mr<0x0,
- (outs), (ins memdst:$dst, GR16:$src),
- "subc.w\t{$src, $dst}",
- [(store (sube (load addr:$dst), GR16:$src), addr:$dst),
- (implicit SR)]>;
+def CMP8mn : I8mn<0b1001, (outs), (ins memsrc:$dst, indreg:$rs),
+ "cmp.b\t$rs, $dst", []>;
+def CMP16mn : I16mn<0b1001, (outs), (ins memsrc:$dst, indreg:$rs),
+ "cmp\t$rs, $dst", []>;
-def SBC8mi : I8mi<0x0,
- (outs), (ins memdst:$dst, i8imm:$src),
- "subc.b\t{$src, $dst}",
- [(store (sube (load addr:$dst), (i8 imm:$src)), addr:$dst),
- (implicit SR)]>;
-def SBC16mi : I16mi<0x0,
- (outs), (ins memdst:$dst, i16imm:$src),
- "subc.w\t{$src, $dst}",
- [(store (sube (load addr:$dst), (i16 imm:$src)), addr:$dst),
- (implicit SR)]>;
+def CMP8mp : I8mp<0b1001, (outs), (ins memsrc:$dst, postreg:$rs),
+ "cmp.b\t$rs, $dst", []>;
+def CMP16mp : I16mp<0b1001, (outs), (ins memsrc:$dst, postreg:$rs),
+ "cmp\t$rs, $dst", []>;
-def SBC8mm : I8mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "subc.b\t{$src, $dst}",
- [(store (sube (load addr:$dst),
- (i8 (load addr:$src))), addr:$dst),
+// BIT TESTS, just sets condition codes
+// Note that the C condition is set differently than when using CMP.
+let isCommutable = 1 in {
+def BIT8rr : I8rr<0b1011,
+ (outs), (ins GR8:$rd, GR8:$rs),
+ "bit.b\t$rs, $rd",
+ [(MSP430cmp (and_su GR8:$rd, GR8:$rs), 0),
(implicit SR)]>;
-def SBC16mm : I16mm<0x0,
- (outs), (ins memdst:$dst, memsrc:$src),
- "subc.w\t{$src, $dst}",
- [(store (sube (load addr:$dst),
- (i16 (load addr:$src))), addr:$dst),
+def BIT16rr : I16rr<0b1011,
+ (outs), (ins GR16:$rd, GR16:$rs),
+ "bit\t$rs, $rd",
+ [(MSP430cmp (and_su GR16:$rd, GR16:$rs), 0),
(implicit SR)]>;
}
-
-} // Uses = [SR]
-
-// FIXME: memory variant!
-def SAR8r1 : II8r<0x0,
- (outs GR8:$dst), (ins GR8:$src),
- "rra.b\t$dst",
- [(set GR8:$dst, (MSP430rra GR8:$src)),
+def BIT8rc : I8rc<0b1011,
+ (outs), (ins GR8:$rd, cg8imm:$imm),
+ "bit.b\t$imm, $rd",
+ [(MSP430cmp (and_su GR8:$rd, cg8imm:$imm), 0),
(implicit SR)]>;
-def SAR16r1 : II16r<0x0,
- (outs GR16:$dst), (ins GR16:$src),
- "rra.w\t$dst",
- [(set GR16:$dst, (MSP430rra GR16:$src)),
+def BIT16rc : I16rc<0b1011,
+ (outs), (ins GR16:$rd, cg16imm:$imm),
+ "bit\t$imm, $rd",
+ [(MSP430cmp (and_su GR16:$rd, cg16imm:$imm), 0),
(implicit SR)]>;
-def SHL8r1 : I8rr<0x0,
- (outs GR8:$dst), (ins GR8:$src),
- "rla.b\t$dst",
- [(set GR8:$dst, (MSP430rla GR8:$src)),
+def BIT8ri : I8ri<0b1011,
+ (outs), (ins GR8:$rd, i8imm:$imm),
+ "bit.b\t$imm, $rd",
+ [(MSP430cmp (and_su GR8:$rd, imm:$imm), 0),
(implicit SR)]>;
-def SHL16r1 : I16rr<0x0,
- (outs GR16:$dst), (ins GR16:$src),
- "rla.w\t$dst",
- [(set GR16:$dst, (MSP430rla GR16:$src)),
- (implicit SR)]>;
-
-def SAR8r1c : Pseudo<(outs GR8:$dst), (ins GR8:$src),
- "clrc\n\t"
- "rrc.b\t$dst",
- [(set GR8:$dst, (MSP430rrc GR8:$src)),
- (implicit SR)]>;
-def SAR16r1c : Pseudo<(outs GR16:$dst), (ins GR16:$src),
- "clrc\n\t"
- "rrc.w\t$dst",
- [(set GR16:$dst, (MSP430rrc GR16:$src)),
- (implicit SR)]>;
-
-// FIXME: Memory sext's ?
-def SEXT16r : II16r<0x0,
- (outs GR16:$dst), (ins GR16:$src),
- "sxt\t$dst",
- [(set GR16:$dst, (sext_inreg GR16:$src, i8)),
+def BIT16ri : I16ri<0b1011,
+ (outs), (ins GR16:$rd, i16imm:$imm),
+ "bit\t$imm, $rd",
+ [(MSP430cmp (and_su GR16:$rd, imm:$imm), 0),
(implicit SR)]>;
-} // Defs = [SR]
-
-def ZEXT16r : I8rr<0x0,
- (outs GR16:$dst), (ins GR16:$src),
- "mov.b\t{$src, $dst}",
- [(set GR16:$dst, (zext (trunc GR16:$src)))]>;
-
-// FIXME: Memory bitswaps?
-def SWPB16r : II16r<0x0,
- (outs GR16:$dst), (ins GR16:$src),
- "swpb\t$dst",
- [(set GR16:$dst, (bswap GR16:$src))]>;
-
-} // Constraints = "$src = $dst"
-
-// Integer comparisons
-let Defs = [SR] in {
-def CMP8rr : I8rr<0x0,
- (outs), (ins GR8:$src, GR8:$src2),
- "cmp.b\t{$src2, $src}",
- [(MSP430cmp GR8:$src, GR8:$src2), (implicit SR)]>;
-def CMP16rr : I16rr<0x0,
- (outs), (ins GR16:$src, GR16:$src2),
- "cmp.w\t{$src2, $src}",
- [(MSP430cmp GR16:$src, GR16:$src2), (implicit SR)]>;
-
-def CMP8ri : I8ri<0x0,
- (outs), (ins GR8:$src, i8imm:$src2),
- "cmp.b\t{$src2, $src}",
- [(MSP430cmp GR8:$src, imm:$src2), (implicit SR)]>;
-def CMP16ri : I16ri<0x0,
- (outs), (ins GR16:$src, i16imm:$src2),
- "cmp.w\t{$src2, $src}",
- [(MSP430cmp GR16:$src, imm:$src2), (implicit SR)]>;
-
-def CMP8mi : I8mi<0x0,
- (outs), (ins memsrc:$src, i8imm:$src2),
- "cmp.b\t{$src2, $src}",
- [(MSP430cmp (load addr:$src),
- (i8 imm:$src2)), (implicit SR)]>;
-def CMP16mi : I16mi<0x0,
- (outs), (ins memsrc:$src, i16imm:$src2),
- "cmp.w\t{$src2, $src}",
- [(MSP430cmp (load addr:$src),
- (i16 imm:$src2)), (implicit SR)]>;
-
-def CMP8rm : I8rm<0x0,
- (outs), (ins GR8:$src, memsrc:$src2),
- "cmp.b\t{$src2, $src}",
- [(MSP430cmp GR8:$src, (load addr:$src2)),
+def BIT8rm : I8rm<0b1011,
+ (outs), (ins GR8:$rd, memdst:$src),
+ "bit.b\t$src, $rd",
+ [(MSP430cmp (and_su GR8:$rd, (load addr:$src)), 0),
(implicit SR)]>;
-def CMP16rm : I16rm<0x0,
- (outs), (ins GR16:$src, memsrc:$src2),
- "cmp.w\t{$src2, $src}",
- [(MSP430cmp GR16:$src, (load addr:$src2)),
+def BIT16rm : I16rm<0b1011,
+ (outs), (ins GR16:$rd, memdst:$src),
+ "bit\t$src, $rd",
+ [(MSP430cmp (and_su GR16:$rd, (load addr:$src)), 0),
(implicit SR)]>;
-def CMP8mr : I8mr<0x0,
- (outs), (ins memsrc:$src, GR8:$src2),
- "cmp.b\t{$src2, $src}",
- [(MSP430cmp (load addr:$src), GR8:$src2),
- (implicit SR)]>;
-def CMP16mr : I16mr<0x0,
- (outs), (ins memsrc:$src, GR16:$src2),
- "cmp.w\t{$src2, $src}",
- [(MSP430cmp (load addr:$src), GR16:$src2),
- (implicit SR)]>;
+def BIT8rn : I8rn<0b1011, (outs), (ins GR8:$rd, indreg:$rs),
+ "bit.b\t$rs, $rd", []>;
+def BIT16rn : I16rn<0b1011, (outs), (ins GR16:$rd, indreg:$rs),
+ "bit\t$rs, $rd", []>;
+def BIT8rp : I8rp<0b1011, (outs), (ins GR8:$rd, postreg:$rs),
+ "bit.b\t$rs, $rd", []>;
+def BIT16rp : I16rp<0b1011, (outs), (ins GR16:$rd, postreg:$rs),
+ "bit\t$rs, $rd", []>;
-// BIT TESTS, just sets condition codes
-// Note that the C condition is set differently than when using CMP.
-let isCommutable = 1 in {
-def BIT8rr : I8rr<0x0,
- (outs), (ins GR8:$src, GR8:$src2),
- "bit.b\t{$src2, $src}",
- [(MSP430cmp (and_su GR8:$src, GR8:$src2), 0),
- (implicit SR)]>;
-def BIT16rr : I16rr<0x0,
- (outs), (ins GR16:$src, GR16:$src2),
- "bit.w\t{$src2, $src}",
- [(MSP430cmp (and_su GR16:$src, GR16:$src2), 0),
- (implicit SR)]>;
-}
-def BIT8ri : I8ri<0x0,
- (outs), (ins GR8:$src, i8imm:$src2),
- "bit.b\t{$src2, $src}",
- [(MSP430cmp (and_su GR8:$src, imm:$src2), 0),
- (implicit SR)]>;
-def BIT16ri : I16ri<0x0,
- (outs), (ins GR16:$src, i16imm:$src2),
- "bit.w\t{$src2, $src}",
- [(MSP430cmp (and_su GR16:$src, imm:$src2), 0),
+def BIT8mr : I8mr<0b1011,
+ (outs), (ins memsrc:$dst, GR8:$rs),
+ "bit.b\t$rs, $dst",
+ [(MSP430cmp (and_su (load addr:$dst), GR8:$rs), 0),
+ (implicit SR)]>;
+def BIT16mr : I16mr<0b1011,
+ (outs), (ins memsrc:$dst, GR16:$rs),
+ "bit\t$rs, $dst",
+ [(MSP430cmp (and_su (load addr:$dst), GR16:$rs), 0),
(implicit SR)]>;
-def BIT8rm : I8rm<0x0,
- (outs), (ins GR8:$src, memdst:$src2),
- "bit.b\t{$src2, $src}",
- [(MSP430cmp (and_su GR8:$src, (load addr:$src2)), 0),
+def BIT8mc : I8mc<0b1011,
+ (outs), (ins memsrc:$dst, cg8imm:$imm),
+ "bit.b\t$imm, $dst",
+ [(MSP430cmp (and_su (load addr:$dst), (i8 cg8imm:$imm)), 0),
(implicit SR)]>;
-def BIT16rm : I16rm<0x0,
- (outs), (ins GR16:$src, memdst:$src2),
- "bit.w\t{$src2, $src}",
- [(MSP430cmp (and_su GR16:$src, (load addr:$src2)), 0),
+def BIT16mc : I16mc<0b1011,
+ (outs), (ins memdst:$dst, cg16imm:$imm),
+ "bit\t$imm, $dst",
+ [(MSP430cmp (and_su (load addr:$dst), (i16 cg16imm:$imm)), 0),
(implicit SR)]>;
-def BIT8mr : I8mr<0x0,
- (outs), (ins memsrc:$src, GR8:$src2),
- "bit.b\t{$src2, $src}",
- [(MSP430cmp (and_su (load addr:$src), GR8:$src2), 0),
- (implicit SR)]>;
-def BIT16mr : I16mr<0x0,
- (outs), (ins memsrc:$src, GR16:$src2),
- "bit.w\t{$src2, $src}",
- [(MSP430cmp (and_su (load addr:$src), GR16:$src2), 0),
- (implicit SR)]>;
-
-def BIT8mi : I8mi<0x0,
- (outs), (ins memsrc:$src, i8imm:$src2),
- "bit.b\t{$src2, $src}",
- [(MSP430cmp (and_su (load addr:$src), (i8 imm:$src2)), 0),
+def BIT8mi : I8mi<0b1011,
+ (outs), (ins memsrc:$dst, i8imm:$imm),
+ "bit.b\t$imm, $dst",
+ [(MSP430cmp (and_su (load addr:$dst), (i8 imm:$imm)), 0),
(implicit SR)]>;
-def BIT16mi : I16mi<0x0,
- (outs), (ins memsrc:$src, i16imm:$src2),
- "bit.w\t{$src2, $src}",
- [(MSP430cmp (and_su (load addr:$src), (i16 imm:$src2)), 0),
+def BIT16mi : I16mi<0b1011,
+ (outs), (ins memsrc:$dst, i16imm:$imm),
+ "bit\t$imm, $dst",
+ [(MSP430cmp (and_su (load addr:$dst), (i16 imm:$imm)), 0),
(implicit SR)]>;
-def BIT8mm : I8mm<0x0,
- (outs), (ins memsrc:$src, memsrc:$src2),
- "bit.b\t{$src2, $src}",
- [(MSP430cmp (and_su (i8 (load addr:$src)),
- (load addr:$src2)),
+def BIT8mm : I8mm<0b1011,
+ (outs), (ins memsrc:$dst, memsrc:$src),
+ "bit.b\t$src, $dst",
+ [(MSP430cmp (and_su (i8 (load addr:$dst)),
+ (load addr:$src)),
0),
(implicit SR)]>;
-def BIT16mm : I16mm<0x0,
- (outs), (ins memsrc:$src, memsrc:$src2),
- "bit.w\t{$src2, $src}",
- [(MSP430cmp (and_su (i16 (load addr:$src)),
- (load addr:$src2)),
+def BIT16mm : I16mm<0b1011,
+ (outs), (ins memsrc:$dst, memsrc:$src),
+ "bit\t$src, $dst",
+ [(MSP430cmp (and_su (i16 (load addr:$dst)),
+ (load addr:$src)),
0),
(implicit SR)]>;
+def BIT8mn : I8mn<0b1011, (outs), (ins memsrc:$dst, indreg:$rs),
+ "bit.b\t$rs, $dst", []>;
+def BIT16mn : I16mn<0b1011, (outs), (ins memsrc:$dst, indreg:$rs),
+ "bit\t$rs, $dst", []>;
+
+def BIT8mp : I8mp<0b1011, (outs), (ins memsrc:$dst, postreg:$rs),
+ "bit.b\t$rs, $dst", []>;
+def BIT16mp : I16mp<0b1011, (outs), (ins memsrc:$dst, postreg:$rs),
+ "bit\t$rs, $dst", []>;
+
} // Defs = [SR]
+def TST8r : InstAlias<"tst.b\t$dst", (CMP8rc GR8:$dst, 0)>;
+def TST16r : InstAlias<"tst\t$dst", (CMP16rc GR16:$dst, 0)>;
+def TST8m : InstAlias<"tst.b\t$dst", (CMP8mc memdst:$dst, 0)>;
+def TST16m : InstAlias<"tst\t$dst", (CMP16mc memdst:$dst, 0)>;
+
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
diff --git a/lib/Target/MSP430/MSP430MCInstLower.cpp b/lib/Target/MSP430/MSP430MCInstLower.cpp
index e7716382b222..860c0006f782 100644
--- a/lib/Target/MSP430/MSP430MCInstLower.cpp
+++ b/lib/Target/MSP430/MSP430MCInstLower.cpp
@@ -110,6 +110,9 @@ LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const {
return MCOperand::createExpr(Expr);
}
+#define GET_REGINFO_ENUM
+#include "MSP430GenRegisterInfo.inc"
+
void MSP430MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
OutMI.setOpcode(MI->getOpcode());
diff --git a/lib/Target/MSP430/MSP430RegisterInfo.td b/lib/Target/MSP430/MSP430RegisterInfo.td
index b5a6ed0f0a56..1e86bdf34a0b 100644
--- a/lib/Target/MSP430/MSP430RegisterInfo.td
+++ b/lib/Target/MSP430/MSP430RegisterInfo.td
@@ -11,26 +11,31 @@
// Declarations that describe the MSP430 register file
//===----------------------------------------------------------------------===//
-class MSP430Reg<bits<4> num, string n> : Register<n> {
+class MSP430Reg<bits<4> num, string n, list<string> alt = []> : Register<n> {
field bits<4> Num = num;
let Namespace = "MSP430";
+ let HWEncoding{3-0} = num;
+ let AltNames = alt;
}
-class MSP430RegWithSubregs<bits<4> num, string n, list<Register> subregs>
+class MSP430RegWithSubregs<bits<4> num, string n, list<Register> subregs,
+ list<string> alt = []>
: RegisterWithSubRegs<n, subregs> {
field bits<4> Num = num;
let Namespace = "MSP430";
+ let HWEncoding{3-0} = num;
+ let AltNames = alt;
}
//===----------------------------------------------------------------------===//
// Registers
//===----------------------------------------------------------------------===//
-def PCB : MSP430Reg<0, "r0">;
-def SPB : MSP430Reg<1, "r1">;
-def SRB : MSP430Reg<2, "r2">;
-def CGB : MSP430Reg<3, "r3">;
-def FPB : MSP430Reg<4, "r4">;
+def PCB : MSP430Reg<0, "r0", ["pc"]>;
+def SPB : MSP430Reg<1, "r1", ["sp"]>;
+def SRB : MSP430Reg<2, "r2", ["sr"]>;
+def CGB : MSP430Reg<3, "r3", ["cg"]>;
+def FPB : MSP430Reg<4, "r4", ["fp"]>;
def R5B : MSP430Reg<5, "r5">;
def R6B : MSP430Reg<6, "r6">;
def R7B : MSP430Reg<7, "r7">;
@@ -46,11 +51,11 @@ def R15B : MSP430Reg<15, "r15">;
def subreg_8bit : SubRegIndex<8> { let Namespace = "MSP430"; }
let SubRegIndices = [subreg_8bit] in {
-def PC : MSP430RegWithSubregs<0, "r0", [PCB]>;
-def SP : MSP430RegWithSubregs<1, "r1", [SPB]>;
-def SR : MSP430RegWithSubregs<2, "r2", [SRB]>;
-def CG : MSP430RegWithSubregs<3, "r3", [CGB]>;
-def FP : MSP430RegWithSubregs<4, "r4", [FPB]>;
+def PC : MSP430RegWithSubregs<0, "r0", [PCB], ["pc"]>;
+def SP : MSP430RegWithSubregs<1, "r1", [SPB], ["sp"]>;
+def SR : MSP430RegWithSubregs<2, "r2", [SRB], ["sr"]>;
+def CG : MSP430RegWithSubregs<3, "r3", [CGB], ["cg"]>;
+def FP : MSP430RegWithSubregs<4, "r4", [FPB], ["fp"]>;
def R5 : MSP430RegWithSubregs<5, "r5", [R5B]>;
def R6 : MSP430RegWithSubregs<6, "r6", [R6B]>;
def R7 : MSP430RegWithSubregs<7, "r7", [R7B]>;
diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp
index 01f44e266d7b..9f6ebba75ec6 100644
--- a/lib/Target/MSP430/MSP430TargetMachine.cpp
+++ b/lib/Target/MSP430/MSP430TargetMachine.cpp
@@ -32,12 +32,6 @@ static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
return *RM;
}
-static CodeModel::Model getEffectiveCodeModel(Optional<CodeModel::Model> CM) {
- if (CM)
- return *CM;
- return CodeModel::Small;
-}
-
static std::string computeDataLayout(const Triple &TT, StringRef CPU,
const TargetOptions &Options) {
return "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16";
@@ -51,7 +45,7 @@ MSP430TargetMachine::MSP430TargetMachine(const Target &T, const Triple &TT,
CodeGenOpt::Level OL, bool JIT)
: LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options), TT, CPU, FS,
Options, getEffectiveRelocModel(RM),
- getEffectiveCodeModel(CM), OL),
+ getEffectiveCodeModel(CM, CodeModel::Small), OL),
TLOF(make_unique<TargetLoweringObjectFileELF>()),
Subtarget(TT, CPU, FS, *this) {
initAsmInfo();