From d8e91e46262bc44006913e6796843909f1ac7bcd Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 19 Jan 2019 10:01:25 +0000 Subject: Vendor import of llvm trunk r351319 (just before the release_80 branch point): https://llvm.org/svn/llvm-project/llvm/trunk@351319 --- lib/Target/MSP430/AsmParser/CMakeLists.txt | 3 + lib/Target/MSP430/AsmParser/LLVMBuild.txt | 23 + lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp | 580 ++++++++ lib/Target/MSP430/CMakeLists.txt | 5 + lib/Target/MSP430/Disassembler/CMakeLists.txt | 3 + lib/Target/MSP430/Disassembler/LLVMBuild.txt | 23 + .../MSP430/Disassembler/MSP430Disassembler.cpp | 387 +++++ .../MSP430/InstPrinter/MSP430InstPrinter.cpp | 36 +- lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h | 7 + lib/Target/MSP430/LLVMBuild.txt | 4 +- lib/Target/MSP430/MCTargetDesc/CMakeLists.txt | 6 +- .../MSP430/MCTargetDesc/MSP430AsmBackend.cpp | 178 +++ .../MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp | 59 + .../MSP430/MCTargetDesc/MSP430ELFStreamer.cpp | 81 ++ lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h | 53 + lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.cpp | 1 + .../MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp | 211 +++ .../MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp | 27 +- .../MSP430/MCTargetDesc/MSP430MCTargetDesc.h | 27 + lib/Target/MSP430/MSP430.h | 2 + lib/Target/MSP430/MSP430.td | 18 + lib/Target/MSP430/MSP430ISelDAGToDAG.cpp | 37 +- lib/Target/MSP430/MSP430ISelLowering.cpp | 127 +- lib/Target/MSP430/MSP430ISelLowering.h | 8 +- lib/Target/MSP430/MSP430InstrFormats.td | 422 ++++-- lib/Target/MSP430/MSP430InstrInfo.cpp | 45 +- lib/Target/MSP430/MSP430InstrInfo.h | 16 - lib/Target/MSP430/MSP430InstrInfo.td | 1483 +++++++++----------- lib/Target/MSP430/MSP430MCInstLower.cpp | 3 + lib/Target/MSP430/MSP430RegisterInfo.td | 29 +- lib/Target/MSP430/MSP430TargetMachine.cpp | 8 +- 31 files changed, 2831 insertions(+), 1081 deletions(-) create mode 100644 lib/Target/MSP430/AsmParser/CMakeLists.txt create mode 100644 lib/Target/MSP430/AsmParser/LLVMBuild.txt create mode 100644 lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp create mode 100644 lib/Target/MSP430/Disassembler/CMakeLists.txt create mode 100644 lib/Target/MSP430/Disassembler/LLVMBuild.txt create mode 100644 lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp create mode 100644 lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp create mode 100644 lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp create mode 100644 lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp create mode 100644 lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h create mode 100644 lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp (limited to 'lib/Target/MSP430') 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(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 CreateToken(StringRef Str, SMLoc S) { + return make_unique(Str, S); + } + + static std::unique_ptr CreateReg(unsigned RegNum, SMLoc S, + SMLoc E) { + return make_unique(k_Reg, RegNum, S, E); + } + + static std::unique_ptr CreateImm(const MCExpr *Val, SMLoc S, + SMLoc E) { + return make_unique(Val, S, E); + } + + static std::unique_ptr CreateMem(unsigned RegNum, + const MCExpr *Val, + SMLoc S, SMLoc E) { + return make_unique(RegNum, Val, S, E); + } + + static std::unique_ptr CreateIndReg(unsigned RegNum, SMLoc S, + SMLoc E) { + return make_unique(k_IndReg, RegNum, S, E); + } + + static std::unique_ptr CreatePostIndReg(unsigned RegNum, SMLoc S, + SMLoc E) { + return make_unique(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 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(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 Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const; + + DecodeStatus getInstructionII(MCInst &MI, uint64_t &Size, + ArrayRef Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const; + + DecodeStatus getInstructionCJ(MCInst &MI, uint64_t &Size, + ArrayRef 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 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 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 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 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 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 Data, + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; + + std::unique_ptr + 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 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 +llvm::createMSP430ELFObjectWriter(uint8_t OSABI) { + return llvm::make_unique(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(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 &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 &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getMemOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getCGImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getCCOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &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 &Fixups, + const MCSubtargetInfo &STI) const override; +}; + +void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &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 &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(MSP430::fixup_16_byte), MI.getLoc())); + Offset += 2; + return 0; +} + +unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &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(FixupKind), MI.getLoc())); + Offset += 2; + return Reg; +} + +unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &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(MSP430::fixup_10_pcrel), MI.getLoc())); + return 0; +} + +unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &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 &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 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 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 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 +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(N1)->getMemOperand(); + MachineMemOperand *MemRef = cast(N1)->getMemOperand(); SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() }; SDNode *ResNode = CurDAG->SelectNodeTo(Op, Opc, VT, MVT::i16, MVT::Other, Ops0); - cast(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1); + CurDAG->setNodeMemRefs(cast(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(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(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 val> { - bits<2> Value = val; -} - -def PseudoFrm : Format<0>; -def SingleOpFrm : Format<1>; -def DoubleOpFrm : Format<2>; -def CondJumpFrm : Format<3>; - class SourceMode 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 Value = val; } -def DstReg : DestMode<0>; -def DstMem : DestMode<1>; - -class SizeVal 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 : Instruction { - field bits<16> Inst; +class MSP430Inst : 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 opcode, DestMode dest, bit bw, SourceMode src, SizeVal sz, +class IForm opcode, DestMode ad, bit bw, SourceMode as, int size, dag outs, dag ins, string asmstr, list pattern> - : MSP430Inst { + : MSP430Inst { 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 opcode, DestMode dest, SourceMode src, SizeVal sz, +class IForm8 opcode, DestMode dest, SourceMode src, int size, dag outs, dag ins, string asmstr, list pattern> - : IForm; + : IForm; class I8rr opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm8; + : IForm8 { + let DecoderNamespace = "Alpha"; +} class I8ri opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm8; + : IForm8 { + let DecoderNamespace = "Gamma"; + bits<16> imm; + let Inst{31-16} = imm; + let rs = 0b0000; +} + +class I8rc opcode, + dag outs, dag ins, string asmstr, list pattern> + : MSP430Inst { + 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 opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm8; + : IForm8 { + let DecoderNamespace = "Gamma"; + bits<20> src; + let rs = src{3-0}; + let Inst{31-16} = src{19-4}; +} + +class I8rn opcode, + dag outs, dag ins, string asmstr, list pattern> + : IForm8 { + let DecoderNamespace = "Delta"; +} + +class I8rp opcode, + dag outs, dag ins, string asmstr, list pattern> + : IForm8 { + let DecoderNamespace = "Delta"; +} class I8mr opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm8; + : IForm8 { + let DecoderNamespace = "Alpha"; + bits<20> dst; + let rd = dst{3-0}; + let Inst{31-16} = dst{19-4}; +} class I8mi opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm8; + : IForm8 { + 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 opcode, + dag outs, dag ins, string asmstr, list pattern> + : MSP430Inst { + 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 opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm8; + : IForm8 { + 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 opcode, + dag outs, dag ins, string asmstr, list pattern> + : IForm8 { + let DecoderNamespace = "Delta"; + bits<20> dst; + let rd = dst{3-0}; + let Inst{31-16} = dst{19-4}; +} + +class I8mp opcode, + dag outs, dag ins, string asmstr, list pattern> + : IForm8 { + let DecoderNamespace = "Delta"; + bits<20> dst; + let rd = dst{3-0}; + let Inst{31-16} = dst{19-4}; +} // 16 bit IForm instructions -class IForm16 opcode, DestMode dest, SourceMode src, SizeVal sz, +class IForm16 opcode, DestMode dest, SourceMode src, int size, dag outs, dag ins, string asmstr, list pattern> - : IForm; + : IForm; class I16rr opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm16; + : IForm16 { + let DecoderNamespace = "Alpha"; +} class I16ri opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm16; + : IForm16 { + let DecoderNamespace = "Gamma"; + bits<16> imm; + let Inst{31-16} = imm; + let rs = 0b0000; +} + +class I16rc opcode, + dag outs, dag ins, string asmstr, list pattern> + : MSP430Inst { + 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 opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm16; + : IForm16 { + let DecoderNamespace = "Gamma"; + bits<20> src; + let rs = src{3-0}; + let Inst{31-16} = src{19-4}; +} + +class I16rn opcode, + dag outs, dag ins, string asmstr, list pattern> + : IForm16 { + let DecoderNamespace = "Delta"; +} + +class I16rp opcode, + dag outs, dag ins, string asmstr, list pattern> + : IForm16 { + let DecoderNamespace = "Delta"; +} class I16mr opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm16; + : IForm16 { + let DecoderNamespace = "Alpha"; + bits<20> dst; + let rd = dst{3-0}; + let Inst{31-16} = dst{19-4}; +} class I16mi opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm16; + : IForm16 { + 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 opcode, + dag outs, dag ins, string asmstr, list pattern> + : MSP430Inst { + 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 opcode, dag outs, dag ins, string asmstr, list pattern> - : IForm16; + : IForm16 { + 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 opcode, + dag outs, dag ins, string asmstr, list pattern> + : IForm16 { + let DecoderNamespace = "Delta"; + bits<20> dst; + let rd = dst{3-0}; + let Inst{31-16} = dst{19-4}; +} + +class I16mp opcode, + dag outs, dag ins, string asmstr, list pattern> + : IForm16 { + 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 opcode, bit bw, SourceMode src, SizeVal sz, +class IIForm opcode, bit bw, SourceMode as, int size, dag outs, dag ins, string asmstr, list pattern> - : MSP430Inst { + : MSP430Inst { 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 opcode, SourceMode src, SizeVal sz, +class IIForm8 opcode, SourceMode src, int size, dag outs, dag ins, string asmstr, list pattern> - : IIForm; + : IIForm; + +class II8r opcode, + dag outs, dag ins, string asmstr, list pattern> + : IIForm8; -class II8r opcode, +class II8m opcode, dag outs, dag ins, string asmstr, list pattern> - : IIForm8; + : IIForm8 { + bits<20> src; + let rs = src{3-0}; + let Inst{31-16} = src{19-4}; +} -class II8m opcode, +class II8i opcode, dag outs, dag ins, string asmstr, list pattern> - : IIForm8; + : IIForm8 { + bits<16> imm; + let rs = 0b0000; + let Inst{31-16} = imm; +} -class II8i opcode, +class II8c opcode, dag outs, dag ins, string asmstr, list pattern> - : IIForm8; + : MSP430Inst { + 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 opcode, + dag outs, dag ins, string asmstr, list pattern> + : IIForm8; + +class II8p opcode, + dag outs, dag ins, string asmstr, list pattern> + : IIForm8; // 16 bit IIForm instructions -class IIForm16 opcode, SourceMode src, SizeVal sz, +class IIForm16 opcode, SourceMode src, int size, dag outs, dag ins, string asmstr, list pattern> - : IIForm; + : IIForm; -class II16r opcode, +class II16r opcode, dag outs, dag ins, string asmstr, list pattern> - : IIForm16; + : IIForm16; -class II16m opcode, +class II16m opcode, dag outs, dag ins, string asmstr, list pattern> - : IIForm16; + : IIForm16 { + bits<20> src; + let rs = src{3-0}; + let Inst{31-16} = src{19-4}; +} -class II16i opcode, +class II16i opcode, dag outs, dag ins, string asmstr, list pattern> - : IIForm16; + : IIForm16 { + bits<16> imm; + let rs = 0b0000; + let Inst{31-16} = imm; +} + +class II16c opcode, + dag outs, dag ins, string asmstr, list pattern> + : MSP430Inst { + 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 opcode, + dag outs, dag ins, string asmstr, list pattern> + : IIForm16; + +class II16p opcode, + dag outs, dag ins, string asmstr, list pattern> + : IIForm16; // MSP430 Conditional Jumps Instructions -class CJForm opcode, bits<3> cond, - dag outs, dag ins, string asmstr, list pattern> - : MSP430Inst { +class CJForm pattern> + : MSP430Inst { 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 pattern> - : MSP430Inst { + : MSP430Inst { 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 { let PrintMethod = "printSrcMemOperand"; let MIOperandInfo = (ops GR16, i16imm); + let ParserMatchClass = MemAsmOperand; + let EncoderMethod = "getMemOpValue"; + let DecoderMethod = "DecodeMemOperand"; } def memdst : Operand { 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 { + 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 { + 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 { let PrintMethod = "printPCRelImmOperand"; + let EncoderMethod = "getPCRelImmOpValue"; } // Operand for printing out a condition code. def cc : Operand { let PrintMethod = "printCCOperand"; + let EncoderMethod = "getCCOpValue"; +} + +def CGImmAsmOperand : AsmOperandClass { + let Name = "CGImm"; + let RenderMethod = "addImmOperands"; +} + +def cg8imm : Operand, + ImmLeaf { + let ParserMatchClass = CGImmAsmOperand; + let EncoderMethod = "getCGImmOpValue"; + let DecoderMethod = "DecodeCGImm"; +} + +def cg16imm : Operand, + ImmLeaf { + let ParserMatchClass = CGImmAsmOperand; + let EncoderMethod = "getCGImmOpValue"; + let DecoderMethod = "DecodeCGImm"; } //===----------------------------------------------------------------------===// @@ -102,6 +159,7 @@ def addr : ComplexPattern; // 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 opcode, string asmstring, SDNode node, + bit commutes, list uses> { + let Defs = [SR], Uses = uses in { + let Constraints = "$src2 = $rd" in { + let isCommutable = commutes in { + def 8rr : I8rr; + def 16rr : I16rr; -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; + def 16rm : I16rm; -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; + def 16rn : I16rn; + let mayLoad = 1, + hasExtraDefRegAllocReq = 1, + Constraints = "$rs = $wb, $src2 = $rd" in { + def 8rp : I8rp; + def 16rp : I16rp; + } + def 8rc : I8rc; + def 16rc : I16rc; + def 8ri : I8ri; + def 16ri : I16ri; + } + def 8mr : I8mr; + def 16mr : I16mr; -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; + def 16mc : I16mc; -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; + def 16mi : I16mi; -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; + def 16mm : I16mm; -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; + def 16mn : I16mn; + def 8mp : I8mp; + def 16mp : I16mp; + } } -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 num, string n> : Register { +class MSP430Reg num, string n, list alt = []> : Register { field bits<4> Num = num; let Namespace = "MSP430"; + let HWEncoding{3-0} = num; + let AltNames = alt; } -class MSP430RegWithSubregs num, string n, list subregs> +class MSP430RegWithSubregs num, string n, list subregs, + list alt = []> : RegisterWithSubRegs { 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 RM) { return *RM; } -static CodeModel::Model getEffectiveCodeModel(Optional 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()), Subtarget(TT, CPU, FS, *this) { initAsmInfo(); -- cgit v1.2.3