Index: include/llvm/BinaryFormat/ELF.h =================================================================== --- include/llvm/BinaryFormat/ELF.h +++ include/llvm/BinaryFormat/ELF.h @@ -726,6 +726,38 @@ #include "ELFRelocs/BPF.def" }; +// MSP430 specific e_flags +enum : unsigned { + EF_MSP430_MACH_MSP430x11 = 11, + EF_MSP430_MACH_MSP430x11x1 = 110, + EF_MSP430_MACH_MSP430x12 = 12, + EF_MSP430_MACH_MSP430x13 = 13, + EF_MSP430_MACH_MSP430x14 = 14, + EF_MSP430_MACH_MSP430x15 = 15, + EF_MSP430_MACH_MSP430x16 = 16, + EF_MSP430_MACH_MSP430x20 = 20, + EF_MSP430_MACH_MSP430x22 = 22, + EF_MSP430_MACH_MSP430x23 = 23, + EF_MSP430_MACH_MSP430x24 = 24, + EF_MSP430_MACH_MSP430x26 = 26, + EF_MSP430_MACH_MSP430x31 = 31, + EF_MSP430_MACH_MSP430x32 = 32, + EF_MSP430_MACH_MSP430x33 = 33, + EF_MSP430_MACH_MSP430x41 = 41, + EF_MSP430_MACH_MSP430x42 = 42, + EF_MSP430_MACH_MSP430x43 = 43, + EF_MSP430_MACH_MSP430x44 = 44, + EF_MSP430_MACH_MSP430X = 45, + EF_MSP430_MACH_MSP430x46 = 46, + EF_MSP430_MACH_MSP430x47 = 47, + EF_MSP430_MACH_MSP430x54 = 54, +}; + +// ELF Relocation types for MSP430 +enum { +#include "ELFRelocs/MSP430.def" +}; + #undef ELF_RELOC // Section header. @@ -830,6 +862,8 @@ SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section. SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. + SHT_MSP430_ATTRIBUTES = 0x70000003U, + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. Index: include/llvm/BinaryFormat/ELFRelocs/MSP430.def =================================================================== --- /dev/null +++ include/llvm/BinaryFormat/ELFRelocs/MSP430.def @@ -0,0 +1,16 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_MSP430_NONE, 0) +ELF_RELOC(R_MSP430_32, 1) +ELF_RELOC(R_MSP430_10_PCREL, 2) +ELF_RELOC(R_MSP430_16, 3) +ELF_RELOC(R_MSP430_16_PCREL, 4) +ELF_RELOC(R_MSP430_16_BYTE, 5) +ELF_RELOC(R_MSP430_16_PCREL_BYTE, 6) +ELF_RELOC(R_MSP430_2X_PCREL, 7) +ELF_RELOC(R_MSP430_RL_PCREL, 8) +ELF_RELOC(R_MSP430_8, 9) +ELF_RELOC(R_MSP430_SYM_DIFF, 10) Index: include/llvm/Object/ELFObjectFile.h =================================================================== --- include/llvm/Object/ELFObjectFile.h +++ include/llvm/Object/ELFObjectFile.h @@ -1021,6 +1021,8 @@ return "ELF32-lanai"; case ELF::EM_MIPS: return "ELF32-mips"; + case ELF::EM_MSP430: + return "ELF32-msp430"; case ELF::EM_PPC: return "ELF32-ppc"; case ELF::EM_RISCV: @@ -1091,6 +1093,8 @@ default: report_fatal_error("Invalid ELFCLASS!"); } + case ELF::EM_MSP430: + return Triple::msp430; case ELF::EM_PPC: return Triple::ppc; case ELF::EM_PPC64: Index: include/llvm/module.modulemap =================================================================== --- include/llvm/module.modulemap +++ include/llvm/module.modulemap @@ -52,6 +52,7 @@ textual header "BinaryFormat/ELFRelocs/i386.def" textual header "BinaryFormat/ELFRelocs/Lanai.def" textual header "BinaryFormat/ELFRelocs/Mips.def" + textual header "BinaryFormat/ELFRelocs/MSP430.def" textual header "BinaryFormat/ELFRelocs/PowerPC64.def" textual header "BinaryFormat/ELFRelocs/PowerPC.def" textual header "BinaryFormat/ELFRelocs/RISCV.def" Index: lib/Object/ELF.cpp =================================================================== --- lib/Object/ELF.cpp +++ lib/Object/ELF.cpp @@ -139,6 +139,13 @@ break; } break; + case ELF::EM_MSP430: + switch (Type) { +#include "llvm/BinaryFormat/ELFRelocs/MSP430.def" + default: + break; + } + break; default: break; } Index: lib/Target/MSP430/AsmParser/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/MSP430/AsmParser/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMMSP430AsmParser + MSP430AsmParser.cpp +) Index: lib/Target/MSP430/AsmParser/LLVMBuild.txt =================================================================== --- lib/Target/MSP430/AsmParser/LLVMBuild.txt +++ lib/Target/MSP430/AsmParser/LLVMBuild.txt @@ -1,4 +1,4 @@ -;===- ./lib/Target/MSP430/LLVMBuild.txt ------------------------*- Conf -*--===; +;===- lib/Target/MSP430/AsmParser/LLVMBuild.txt ----------------*- Conf -*--===; ; ; The LLVM Compiler Infrastructure ; @@ -15,18 +15,9 @@ ; ;===------------------------------------------------------------------------===; -[common] -subdirectories = InstPrinter MCTargetDesc TargetInfo - [component_0] -type = TargetGroup -name = MSP430 -parent = Target -has_asmprinter = 1 - -[component_1] type = Library -name = MSP430CodeGen +name = MSP430AsmParser parent = MSP430 -required_libraries = AsmPrinter CodeGen Core MC MSP430AsmPrinter MSP430Desc MSP430Info SelectionDAG Support Target +required_libraries = MC MCParser MSP430Desc MSP430Info Support add_to_library_groups = MSP430 Index: lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp =================================================================== --- /dev/null +++ lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp @@ -0,0 +1,562 @@ +//===- 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" + +namespace llvm { + +/// Parses MSP430 assembly from a stream. +class MSP430AsmParser : public MCTargetAsmParser { + const MCSubtargetInfo &STI; + MCAsmParser &Parser; + const MCRegisterInfo *MRI; + + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, MCStreamer &Out, + uint64_t &ErrorInfo, + bool MatchingInlineAsm) override; + + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + + bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands) override; + + bool ParseDirective(AsmToken DirectiveID) override; + + unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, + unsigned Kind) override; + + bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands); + + bool ParseOperand(OperandVector &Operands); + + bool ParseLiteralValues(unsigned Size, SMLoc L); + + MCAsmParser &getParser() const { return Parser; } + MCAsmLexer &getLexer() const { return Parser.getLexer(); } + + /// @name Auto-generated Matcher Functions + /// { + +#define GET_ASSEMBLER_HEADER +#include "MSP430GenAsmMatcher.inc" + + /// } + +public: + MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, + const MCInstrInfo &MII, const MCTargetOptions &Options) + : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) { + MCAsmParserExtension::Initialize(Parser); + MRI = getContext().getRegisterInfo(); + + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + } +}; + +/// A parsed MSP430 assembly operand. +class MSP430Operand : public MCParsedAsmOperand { + typedef MCParsedAsmOperand Base; + + enum KindTy { + k_Imm, + k_Reg, + k_Tok, + k_Mem, + k_IndReg, + k_PostIndReg + } Kind; + + struct Memory { + unsigned Reg; + const MCExpr *Offset; + }; + union { + const MCExpr *Imm; + unsigned Reg; + StringRef Tok; + Memory Mem; + }; + + SMLoc Start, End; + +public: + MSP430Operand(StringRef Tok, SMLoc const &S) + : Base(), Kind(k_Tok), Tok(Tok), Start(S), End(S) {} + MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E) + : Base(), Kind(Kind), Reg(Reg), Start(S), End(E) {} + MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E) + : Base(), Kind(k_Imm), Imm(Imm), Start(S), End(E) {} + MSP430Operand(unsigned Reg, MCExpr const *Expr, SMLoc const &S, SMLoc const &E) + : Base(), Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {} + + void addRegOperands(MCInst &Inst, unsigned N) const { + assert((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) && + "Unexpected operand kind"); + assert(N == 1 && "Invalid number of operands!"); + + Inst.addOperand(MCOperand::createReg(Reg)); + } + + void addExprOperand(MCInst &Inst, const MCExpr *Expr) const { + // Add as immediate when possible + if (!Expr) + Inst.addOperand(MCOperand::createImm(0)); + else if (const MCConstantExpr *CE = dyn_cast(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; + } + } +}; + +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) { + StringRef 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; + + StringRef CC = Name.drop_front().lower(); + unsigned CondCode; + if (CC == "ne" || CC == "nz") + CondCode = MSP430CC::COND_NE; + else if (CC == "eq" || CC == "z") + CondCode = MSP430CC::COND_E; + else if (CC == "lo" || CC == "nc") + CondCode = MSP430CC::COND_LO; + else if (CC == "hs" || CC == "c") + CondCode = MSP430CC::COND_HS; + else if (CC == "n") + CondCode = MSP430CC::COND_N; + else if (CC == "ge") + CondCode = MSP430CC::COND_GE; + else if (CC == "l") + CondCode = MSP430CC::COND_L; + else if (CC == "mp") + CondCode = MSP430CC::COND_NONE; + else + return Error(NameLoc, "unknown instruction"); + + if (CondCode == (unsigned)MSP430CC::COND_NONE) + Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc)); + else { + Operands.push_back(MSP430Operand::CreateToken("j", NameLoc)); + const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext()); + Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc())); + } + + // Skip optional '$' sign. + if (getLexer().getKind() == AsmToken::Dollar) + getLexer().Lex(); // Eat '$' + + const MCExpr *Val; + SMLoc ExprLoc = getLexer().getLoc(); + if (getParser().parseExpression(Val)) + return Error(ExprLoc, "expected expression operand"); + + int64_t Res; + if (Val->evaluateAsAbsolute(Res)) + if (Res < -512 || Res > 511) + return Error(ExprLoc, "invalid jump offset"); + + Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc, + getLexer().getLoc())); + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + SMLoc Loc = getLexer().getLoc(); + getParser().eatToEndOfStatement(); + return Error(Loc, "unexpected token"); + } + + getParser().Lex(); // Consume the EndOfStatement. + return false; +} + +bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info, + StringRef Name, SMLoc NameLoc, + OperandVector &Operands) { + // Drop .w suffix + if (Name.endswith_lower(".w")) + Name = Name.drop_back(2); + + if (!parseJccInstruction(Info, Name, NameLoc, Operands)) + return false; + + // First operand is instruction mnemonic + Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc)); + + // If there are no more operands, then finish + if (getLexer().is(AsmToken::EndOfStatement)) + return false; + + // Parse first operand + if (ParseOperand(Operands)) + return true; + + // Parse second operand if any + if (getLexer().is(AsmToken::Comma)) { + getLexer().Lex(); // Eat ',' + if (ParseOperand(Operands)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + SMLoc Loc = getLexer().getLoc(); + getParser().eatToEndOfStatement(); + return Error(Loc, "unexpected token"); + } + + getParser().Lex(); // Consume the EndOfStatement. + return false; +} + +bool MSP430AsmParser::ParseDirective(AsmToken DirectiveID) { + StringRef IDVal = DirectiveID.getIdentifier(); + if (IDVal.lower() == ".long") { + ParseLiteralValues(4, DirectiveID.getLoc()); + } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") { + ParseLiteralValues(2, DirectiveID.getLoc()); + } else if (IDVal.lower() == ".byte") { + ParseLiteralValues(1, DirectiveID.getLoc()); + } + return true; +} + +bool MSP430AsmParser::ParseOperand(OperandVector &Operands) { + switch (getLexer().getKind()) { + default: return true; + case AsmToken::Identifier: { + // try rN + unsigned RegNo; + SMLoc StartLoc, EndLoc; + if (!ParseRegister(RegNo, StartLoc, EndLoc)) { + Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc)); + return false; + } + LLVM_FALLTHROUGH; + } + case AsmToken::Integer: + case AsmToken::Plus: + case AsmToken::Minus: { + SMLoc StartLoc = getParser().getTok().getLoc(); + const MCExpr *Val; + // Try constexpr[(rN)] + if (!getParser().parseExpression(Val)) { + unsigned RegNo = MSP430::PC; + SMLoc EndLoc = getParser().getTok().getLoc(); + // Try (rN) + if (getLexer().getKind() == AsmToken::LParen) { + getLexer().Lex(); // Eat '(' + SMLoc RegStartLoc; + if (ParseRegister(RegNo, RegStartLoc, EndLoc)) + return true; + if (getLexer().getKind() != AsmToken::RParen) + return true; + EndLoc = getParser().getTok().getEndLoc(); + getLexer().Lex(); // Eat ')' + } + Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc, + EndLoc)); + return false; + } + return true; + } + case AsmToken::Amp: { + // Try &constexpr + SMLoc StartLoc = getParser().getTok().getLoc(); + getLexer().Lex(); // Eat '&' + const MCExpr *Val; + if (!getParser().parseExpression(Val)) { + SMLoc EndLoc = getParser().getTok().getLoc(); + Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc, + EndLoc)); + return false; + } + return true; + } + case AsmToken::At: { + // Try @rN[+] + SMLoc StartLoc = getParser().getTok().getLoc(); + getLexer().Lex(); // Eat '@' + unsigned RegNo; + SMLoc RegStartLoc, EndLoc; + if (ParseRegister(RegNo, RegStartLoc, EndLoc)) + return true; + if (getLexer().getKind() == AsmToken::Plus) { + Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc)); + getLexer().Lex(); // Eat '+' + return false; + } + Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc)); + return false; + } + case AsmToken::Hash: + // Try #constexpr + SMLoc StartLoc = getParser().getTok().getLoc(); + getLexer().Lex(); // Eat '#' + const MCExpr *Val; + if (!getParser().parseExpression(Val)) { + SMLoc EndLoc = getParser().getTok().getLoc(); + Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc)); + return false; + } + return true; + } +} + +bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) { + auto parseOne = [&]() -> bool { + const MCExpr *Value; + if (getParser().parseExpression(Value)) + return true; + getParser().getStreamer().EmitValue(Value, Size, L); + return false; + }; + return (parseMany(parseOne)); +} + +extern "C" void LLVMInitializeMSP430AsmParser() { + RegisterMCAsmParser 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; +} + +} // end of namespace llvm Index: lib/Target/MSP430/CMakeLists.txt =================================================================== --- lib/Target/MSP430/CMakeLists.txt +++ 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_subdirectory(InstPrinter) add_subdirectory(MCTargetDesc) add_subdirectory(TargetInfo) +add_subdirectory(AsmParser) +add_subdirectory(Disassembler) Index: lib/Target/MSP430/Disassembler/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/MSP430/Disassembler/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMMSP430Disassembler + MSP430Disassembler.cpp + ) Index: lib/Target/MSP430/Disassembler/LLVMBuild.txt =================================================================== --- lib/Target/MSP430/Disassembler/LLVMBuild.txt +++ lib/Target/MSP430/Disassembler/LLVMBuild.txt @@ -1,4 +1,4 @@ -;===- ./lib/Target/MSP430/LLVMBuild.txt ------------------------*- Conf -*--===; +;====- lib/Target/MSP430/Disassembler/LLVMBuild.txt ------------*- Conf -*--===; ; ; The LLVM Compiler Infrastructure ; @@ -15,18 +15,9 @@ ; ;===------------------------------------------------------------------------===; -[common] -subdirectories = InstPrinter MCTargetDesc TargetInfo - [component_0] -type = TargetGroup -name = MSP430 -parent = Target -has_asmprinter = 1 - -[component_1] type = Library -name = MSP430CodeGen +name = MSP430Disassembler parent = MSP430 -required_libraries = AsmPrinter CodeGen Core MC MSP430AsmPrinter MSP430Desc MSP430Info SelectionDAG Support Target +required_libraries = MCDisassembler MSP430Info Support add_to_library_groups = MSP430 Index: lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp =================================================================== --- /dev/null +++ lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp @@ -0,0 +1,375 @@ +//===-- MSP430Disassembler.cpp - Disassembler for MSP430 ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the MSP430Disassembler class. +// +//===----------------------------------------------------------------------===// + +#include "MSP430.h" +#include "MCTargetDesc/MSP430MCTargetDesc.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "msp430-disassembler" + +typedef MCDisassembler::DecodeStatus DecodeStatus; + +namespace { +class MSP430Disassembler : public MCDisassembler { + DecodeStatus getInstructionI(MCInst &MI, uint64_t &Size, + ArrayRef 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: + Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16; + ++Words; + break; + default: + break; + } + switch (DstAM) { + case amIndexed: + case amSymbolic: + case amAbsolute: + Insn |= (uint64_t)support::endian::read16le(Bytes.data() + Words * 2) + << (Words * 16); + ++Words; + break; + default: + break; + } + + DecodeStatus Result = decodeInstruction(getDecoderTable(SrcAM, Words), MI, + Insn, Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = Words * 2; + return Result; + } + + Size = 2; + return DecodeStatus::Fail; +} + +DecodeStatus MSP430Disassembler::getInstructionII(MCInst &MI, uint64_t &Size, + ArrayRef Bytes, + uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const { + uint64_t Insn = support::endian::read16le(Bytes.data()); + AddrMode SrcAM = DecodeSrcAddrModeII(Insn); + if (SrcAM == amInvalid) { + Size = 2; // skip one word and let disassembler to try further + return MCDisassembler::Fail; + } + + unsigned Words = 1; + switch (SrcAM) { + case amIndexed: + case amSymbolic: + case amImmediate: + case amAbsolute: + Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16; + ++Words; + break; + default: + break; + } + + const uint8_t *DecoderTable = Words == 2 ? DecoderTable32 : DecoderTable16; + DecodeStatus Result = decodeInstruction(DecoderTable, MI, Insn, Address, + this, STI); + if (Result != MCDisassembler::Fail) { + Size = Words * 2; + return Result; + } + + Size = 2; + return DecodeStatus::Fail; +} + +static MSP430CC::CondCodes getCondCode(unsigned Cond) { + switch (Cond) { + case 0: return MSP430CC::COND_NE; + case 1: return MSP430CC::COND_E; + case 2: return MSP430CC::COND_LO; + case 3: return MSP430CC::COND_HS; + case 4: return MSP430CC::COND_N; + case 5: return MSP430CC::COND_GE; + case 6: return MSP430CC::COND_L; + case 7: return MSP430CC::COND_NONE; + default: + llvm_unreachable("Cond out of range"); + } +} + +DecodeStatus MSP430Disassembler::getInstructionCJ(MCInst &MI, uint64_t &Size, + ArrayRef 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); + } +} Index: lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h =================================================================== --- lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h +++ lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h @@ -28,13 +28,20 @@ // 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); }; Index: lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp =================================================================== --- lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp +++ 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 @@ // 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 @@ } // 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 @@ case MSP430CC::COND_L: O << 'l'; break; + case MSP430CC::COND_N: + O << 'n'; + break; } } Index: lib/Target/MSP430/LLVMBuild.txt =================================================================== --- lib/Target/MSP430/LLVMBuild.txt +++ 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 Index: lib/Target/MSP430/MCTargetDesc/CMakeLists.txt =================================================================== --- lib/Target/MSP430/MCTargetDesc/CMakeLists.txt +++ 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 ) Index: lib/Target/MSP430/MCTargetDesc/MSP430AsmBackend.cpp =================================================================== --- /dev/null +++ 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); +} Index: lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp =================================================================== --- /dev/null +++ lib/Target/MSP430/MCTargetDesc/MSP430ELFObjectWriter.cpp @@ -0,0 +1,59 @@ +//===-- MSP430ELFObjectWriter.cpp - MSP430 ELF Writer ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/MSP430FixupKinds.h" +#include "MCTargetDesc/MSP430MCTargetDesc.h" + +#include "MCTargetDesc/MSP430MCTargetDesc.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +namespace { +class MSP430ELFObjectWriter : public MCELFObjectTargetWriter { +public: + MSP430ELFObjectWriter(uint8_t OSABI) + : MCELFObjectTargetWriter(false, OSABI, ELF::EM_MSP430, + /*HasRelocationAddend*/ true) {} + + ~MSP430ELFObjectWriter() override {} + +protected: + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override { + // Translate fixup kind to ELF relocation type. + switch ((unsigned)Fixup.getKind()) { + case FK_Data_1: return ELF::R_MSP430_8; + case FK_Data_2: return ELF::R_MSP430_16; + case FK_Data_4: return ELF::R_MSP430_32; + case MSP430::fixup_32: return ELF::R_MSP430_32; + case MSP430::fixup_10_pcrel: return ELF::R_MSP430_10_PCREL; + case MSP430::fixup_16: return ELF::R_MSP430_16; + case MSP430::fixup_16_pcrel: return ELF::R_MSP430_16_PCREL; + case MSP430::fixup_16_byte: return ELF::R_MSP430_16_BYTE; + case MSP430::fixup_16_pcrel_byte: return ELF::R_MSP430_16_PCREL_BYTE; + case MSP430::fixup_2x_pcrel: return ELF::R_MSP430_2X_PCREL; + case MSP430::fixup_rl_pcrel: return ELF::R_MSP430_RL_PCREL; + case MSP430::fixup_8: return ELF::R_MSP430_8; + case MSP430::fixup_sym_diff: return ELF::R_MSP430_SYM_DIFF; + default: + llvm_unreachable("Invalid fixup kind"); + } + } +}; +} // end of anonymous namespace + +std::unique_ptr +llvm::createMSP430ELFObjectWriter(uint8_t OSABI) { + return llvm::make_unique(OSABI); +} Index: lib/Target/MSP430/MCTargetDesc/MSP430ELFStreamer.cpp =================================================================== --- /dev/null +++ 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 Index: lib/Target/MSP430/MCTargetDesc/MSP430FixupKinds.h =================================================================== --- /dev/null +++ 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 Index: lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp =================================================================== --- /dev/null +++ lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp @@ -0,0 +1,212 @@ +//===-- 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); + const uint16_t *Words = reinterpret_cast(&BinaryOpCode); + size_t WordCount = Size / 2; + + for (size_t i = 0; i < WordCount; ++i) { + uint16_t Word = Words[i]; + support::endian::write(OS, Word, support::little); + } +} + +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 (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 Index: lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h =================================================================== --- lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.h +++ 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. Index: lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp =================================================================== --- lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp +++ lib/Target/MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp @@ -58,22 +58,15 @@ } 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); } Index: lib/Target/MSP430/MSP430.h =================================================================== --- lib/Target/MSP430/MSP430.h +++ lib/Target/MSP430/MSP430.h @@ -27,6 +27,8 @@ COND_LO = 3, // aka COND_NC COND_GE = 4, COND_L = 5, + COND_N = 6, // jump if negative + COND_NONE, // unconditional COND_INVALID = -1 }; Index: lib/Target/MSP430/MSP430.td =================================================================== --- lib/Target/MSP430/MSP430.td +++ lib/Target/MSP430/MSP430.td @@ -64,11 +64,29 @@ 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]; } Index: lib/Target/MSP430/MSP430ISelDAGToDAG.cpp =================================================================== --- lib/Target/MSP430/MSP430ISelDAGToDAG.cpp +++ lib/Target/MSP430/MSP430ISelDAGToDAG.cpp @@ -98,6 +98,7 @@ 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 @@ // 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 @@ 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 @@ 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; @@ -412,47 +412,47 @@ 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. Index: lib/Target/MSP430/MSP430ISelLowering.h =================================================================== --- lib/Target/MSP430/MSP430ISelLowering.h +++ lib/Target/MSP430/MSP430ISelLowering.h @@ -36,6 +36,9 @@ /// 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 @@ /// 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, }; } Index: lib/Target/MSP430/MSP430ISelLowering.cpp =================================================================== --- lib/Target/MSP430/MSP430ISelLowering.cpp +++ lib/Target/MSP430/MSP430ISelLowering.cpp @@ -940,18 +940,7 @@ // 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(); @@ -963,7 +952,7 @@ 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 +1331,14 @@ 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 +1385,49 @@ 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 +1480,16 @@ 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 +1511,10 @@ 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(); Index: lib/Target/MSP430/MSP430InstrFormats.td =================================================================== --- lib/Target/MSP430/MSP430InstrFormats.td +++ 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; } Index: lib/Target/MSP430/MSP430InstrInfo.h =================================================================== --- lib/Target/MSP430/MSP430InstrInfo.h +++ lib/Target/MSP430/MSP430InstrInfo.h @@ -24,22 +24,6 @@ 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(); Index: lib/Target/MSP430/MSP430InstrInfo.cpp =================================================================== --- lib/Target/MSP430/MSP430InstrInfo.cpp +++ lib/Target/MSP430/MSP430InstrInfo.cpp @@ -301,35 +301,20 @@ 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(); } Index: lib/Target/MSP430/MSP430InstrInfo.td =================================================================== --- lib/Target/MSP430/MSP430InstrInfo.td +++ lib/Target/MSP430/MSP430InstrInfo.td @@ -34,8 +34,9 @@ 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 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 @@ [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 @@ // 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 @@ // 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,45 @@ 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,64 +247,69 @@ // 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))]>; +} //===----------------------------------------------------------------------===// // 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", []>; } //===----------------------------------------------------------------------===// @@ -247,55 +317,73 @@ // 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 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}", []>; +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))]>; +} + +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 +401,450 @@ 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)]>; //===----------------------------------------------------------------------===// // 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)), - (implicit SR)]>; -def ADD16rr : I16rr<0x0, - (outs GR16:$dst), (ins GR16:$src, GR16:$src2), - "add.w\t{$src2, $dst}", - [(set GR16:$dst, (add GR16:$src, GR16:$src2)), - (implicit SR)]>; -} - -def ADD8rm : I8rm<0x0, - (outs GR8:$dst), (ins GR8:$src, memsrc:$src2), - "add.b\t{$src2, $dst}", - [(set GR8:$dst, (add GR8:$src, (load addr:$src2))), - (implicit SR)]>; -def ADD16rm : I16rm<0x0, - (outs GR16:$dst), (ins GR16:$src, memsrc:$src2), - "add.w\t{$src2, $dst}", - [(set GR16:$dst, (add GR16:$src, (load addr:$src2))), - (implicit SR)]>; - -let mayLoad = 1, hasExtraDefRegAllocReq = 1, -Constraints = "$base = $base_wb, $src = $dst" in { -def ADD8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, - (outs GR8:$dst, GR16:$base_wb), - (ins GR8:$src, GR16:$base), - "add.b\t{@$base+, $dst}", []>; -def ADD16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, - (outs GR16:$dst, GR16:$base_wb), - (ins GR16:$src, GR16:$base), - "add.w\t{@$base+, $dst}", []>; -} - - -def ADD8ri : I8ri<0x0, - (outs GR8:$dst), (ins GR8:$src, i8imm:$src2), - "add.b\t{$src2, $dst}", - [(set GR8:$dst, (add GR8:$src, imm:$src2)), - (implicit SR)]>; -def ADD16ri : I16ri<0x0, - (outs GR16:$dst), (ins GR16:$src, i16imm:$src2), - "add.w\t{$src2, $dst}", - [(set GR16:$dst, (add GR16:$src, imm:$src2)), - (implicit SR)]>; - -let Constraints = "" in { -def ADD8mr : I8mr<0x0, - (outs), (ins memdst:$dst, GR8:$src), - "add.b\t{$src, $dst}", - [(store (add (load addr:$dst), GR8:$src), addr:$dst), - (implicit SR)]>; -def ADD16mr : I16mr<0x0, - (outs), (ins memdst:$dst, GR16:$src), - "add.w\t{$src, $dst}", - [(store (add (load addr:$dst), GR16:$src), addr:$dst), - (implicit SR)]>; - -def ADD8mi : I8mi<0x0, - (outs), (ins memdst:$dst, i8imm:$src), - "add.b\t{$src, $dst}", - [(store (add (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SR)]>; -def ADD16mi : I16mi<0x0, - (outs), (ins memdst:$dst, i16imm:$src), - "add.w\t{$src, $dst}", - [(store (add (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SR)]>; - -def ADD8mm : I8mm<0x0, - (outs), (ins memdst:$dst, memsrc:$src), - "add.b\t{$src, $dst}", - [(store (add (load addr:$dst), - (i8 (load addr:$src))), addr:$dst), - (implicit SR)]>; -def ADD16mm : I16mm<0x0, - (outs), (ins memdst:$dst, memsrc:$src), - "add.w\t{$src, $dst}", - [(store (add (load addr:$dst), - (i16 (load addr:$src))), addr:$dst), - (implicit SR)]>; -} - -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)]>; - -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), - (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), - (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), - (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), - (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)), - (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)), +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 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)]>; - -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 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}", []>; -} - -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)]>; - -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), - (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), - (implicit SR)]>; -def AND16mm : I16mm<0x0, - (outs), (ins memdst:$dst, memsrc:$src), - "and.w\t{$src, $dst}", - [(store (and (load addr:$dst), + } + def 8rm : I8rm; + def 16rm : I16rm; + 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 8mc : I8mc; + def 16mc : I16mc; + def 8mi : I8mi; + def 16mi : I16mi; + def 8mm : I8mm; + def 16mm : I16mm; -} - -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 XOR8ri : I8ri<0x0, - (outs GR8:$dst), (ins GR8:$src, i8imm:$src2), - "xor.b\t{$src2, $dst}", - [(set GR8:$dst, (xor GR8:$src, imm:$src2)), - (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))), - (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}", []>; -} - -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)]>; - -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), - (implicit 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 SUB8ri : I8ri<0x0, - (outs GR8:$dst), (ins GR8:$src, i8imm:$src2), - "sub.b\t{$src2, $dst}", - [(set GR8:$dst, (sub GR8:$src, imm:$src2)), - (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)), - (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))), - (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))), - (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 8mn : I8mn; + def 16mn : I16mn; + def 8mp : I8mp; + def 16mp : I16mp; + } } -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)]>; +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)>; + +let Constraints = "$rs = $rd" in { -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), - (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), - (implicit SR)]>; +let Defs = [SR] in { -def SUB8mm : I8mm<0x0, - (outs), (ins memdst:$dst, memsrc:$src), - "sub.b\t{$src, $dst}", - [(store (sub (load addr:$dst), - (i8 (load addr:$src))), addr:$dst), +// FIXME: memory variant! +def RRA8r : II8r<0b010, + (outs GR8:$rd), (ins GR8:$rs), + "rra.b\t$rd", + [(set GR8:$rd, (MSP430rra GR8:$rs)), (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), +def RRA16r : II16r<0b010, + (outs GR16:$rd), (ins GR16:$rs), + "rra\t$rd", + [(set GR16:$rd, (MSP430rra GR16:$rs)), (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)), +def RRC8r : II8r<0b000, + (outs GR8:$rd), (ins GR8:$rs), + "rrc.b\t$rd", + [(set GR8:$rd, (MSP430rrc GR8:$rs)), (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))), +def RRC16r : II16r<0b000, + (outs GR16:$rd), (ins GR16:$rs), + "rrc\t$rd", + [(set GR16:$rd, (MSP430rrc GR16:$rs)), (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))), - (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 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 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), - (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), - (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)), - (implicit SR)]>; -def SAR16r1 : II16r<0x0, - (outs GR16:$dst), (ins GR16:$src), - "rra.w\t$dst", - [(set GR16:$dst, (MSP430rra GR16:$src)), - (implicit SR)]>; - -def SHL8r1 : I8rr<0x0, - (outs GR8:$dst), (ins GR8:$src), - "rla.b\t$dst", - [(set GR8:$dst, (MSP430rla GR8:$src)), - (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 SEXT16r : II16r<0b011, + (outs GR16:$rd), (ins GR16:$rs), + "sxt\t$rd", + [(set GR16:$rd, (sext_inreg GR16:$rs, i8)), (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)))]>; +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)))]>; // FIXME: Memory bitswaps? -def SWPB16r : II16r<0x0, - (outs GR16:$dst), (ins GR16:$src), - "swpb\t$dst", - [(set GR16:$dst, (bswap GR16:$src))]>; +def SWPB16r : II16r<0b001, + (outs GR16:$rd), (ins GR16:$rs), + "swpb\t$rd", + [(set GR16:$rd, (bswap GR16:$rs))]>; } // 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)), - (implicit SR)]>; -def CMP16rm : I16rm<0x0, - (outs), (ins GR16:$src, memsrc:$src2), - "cmp.w\t{$src2, $src}", - [(MSP430cmp GR16:$src, (load addr:$src2)), - (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), +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 CMP16mc : I16mc<0b1001, + (outs), (ins memsrc:$dst, cg16imm:$imm), + "cmp\t$imm, $dst", + [(MSP430cmp (load addr:$dst), (i16 cg16imm:$imm)), + (implicit SR)]>; + +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 CMP16rm : I16rm<0b1001, + (outs), (ins GR16:$rd, memsrc:$src), + "cmp\t$src, $rd", + [(MSP430cmp GR16:$rd, (load addr:$src)), + (implicit SR)]>; + +def CMP8mr : I8mr<0b1001, + (outs), (ins memsrc:$dst, GR8:$rs), + "cmp.b\t$rs, $dst", + [(MSP430cmp (load addr:$dst), GR8:$rs), + (implicit SR)]>; +def CMP16mr : I16mr<0b1001, + (outs), (ins memsrc:$dst, GR16:$rs), + "cmp\t$rs, $dst", + [(MSP430cmp (load addr:$dst), GR16:$rs), (implicit SR)]>; - // 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), +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 BIT16rr : I16rr<0x0, - (outs), (ins GR16:$src, GR16:$src2), - "bit.w\t{$src2, $src}", - [(MSP430cmp (and_su GR16:$src, GR16:$src2), 0), +def BIT16rr : I16rr<0b1011, + (outs), (ins GR16:$rd, GR16:$rs), + "bit\t$rs, $rd", + [(MSP430cmp (and_su GR16:$rd, GR16:$rs), 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), +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 BIT16rc : I16rc<0b1011, + (outs), (ins GR16:$rd, cg16imm:$imm), + "bit\t$imm, $rd", + [(MSP430cmp (and_su GR16:$rd, cg16imm:$imm), 0), + (implicit SR)]>; + +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 BIT16ri : I16ri<0x0, - (outs), (ins GR16:$src, i16imm:$src2), - "bit.w\t{$src2, $src}", - [(MSP430cmp (and_su GR16:$src, imm:$src2), 0), +def BIT16ri : I16ri<0b1011, + (outs), (ins GR16:$rd, i16imm:$imm), + "bit\t$imm, $rd", + [(MSP430cmp (and_su GR16:$rd, imm:$imm), 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 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 BIT16rm : I16rm<0x0, - (outs), (ins GR16:$src, memdst:$src2), - "bit.w\t{$src2, $src}", - [(MSP430cmp (and_su GR16:$src, (load addr:$src2)), 0), +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 BIT8mr : I8mr<0x0, - (outs), (ins memsrc:$src, GR8:$src2), - "bit.b\t{$src2, $src}", - [(MSP430cmp (and_su (load addr:$src), GR8:$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<0x0, - (outs), (ins memsrc:$src, GR16:$src2), - "bit.w\t{$src2, $src}", - [(MSP430cmp (and_su (load addr:$src), GR16:$src2), 0), +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 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 BIT16mc : I16mc<0b1011, + (outs), (ins memsrc:$dst, i16imm:$imm), + "bit\t$imm, $dst", + [(MSP430cmp (and_su (load addr:$dst), (i16 cg16imm:$imm)), 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)]>; } // 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 Index: lib/Target/MSP430/MSP430MCInstLower.cpp =================================================================== --- lib/Target/MSP430/MSP430MCInstLower.cpp +++ lib/Target/MSP430/MSP430MCInstLower.cpp @@ -110,6 +110,9 @@ return MCOperand::createExpr(Expr); } +#define GET_REGINFO_ENUM +#include "MSP430GenRegisterInfo.inc" + void MSP430MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { OutMI.setOpcode(MI->getOpcode()); Index: lib/Target/MSP430/MSP430RegisterInfo.td =================================================================== --- lib/Target/MSP430/MSP430RegisterInfo.td +++ 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 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]>; Index: test/CodeGen/MSP430/AddrMode-bis-rx.ll =================================================================== --- test/CodeGen/MSP430/AddrMode-bis-rx.ll +++ test/CodeGen/MSP430/AddrMode-bis-rx.ll @@ -8,7 +8,7 @@ ret i16 %2 } ; CHECK-LABEL: am1: -; CHECK: bis.w 0(r13), r12 +; CHECK: bis 0(r13), r12 @foo = external global i16 @@ -18,7 +18,7 @@ ret i16 %2 } ; CHECK-LABEL: am2: -; CHECK: bis.w &foo, r12 +; CHECK: bis &foo, r12 @bar = internal constant [2 x i8] [ i8 32, i8 64 ] @@ -37,7 +37,7 @@ ret i16 %2 } ; CHECK-LABEL: am4: -; CHECK: bis.w &32, r12 +; CHECK: bis &32, r12 define i16 @am5(i16 %x, i16* %a) nounwind { %1 = getelementptr i16, i16* %a, i16 2 @@ -46,7 +46,7 @@ ret i16 %3 } ; CHECK-LABEL: am5: -; CHECK: bis.w 4(r13), r12 +; CHECK: bis 4(r13), r12 %S = type { i16, i16 } @baz = common global %S zeroinitializer, align 1 @@ -57,7 +57,7 @@ ret i16 %2 } ; CHECK-LABEL: am6: -; CHECK: bis.w &baz+2, r12 +; CHECK: bis &baz+2, r12 %T = type { i16, [2 x i8] } @duh = internal constant %T { i16 16, [2 x i8][i8 32, i8 64 ] } Index: test/CodeGen/MSP430/AddrMode-bis-xr.ll =================================================================== --- test/CodeGen/MSP430/AddrMode-bis-xr.ll +++ test/CodeGen/MSP430/AddrMode-bis-xr.ll @@ -9,7 +9,7 @@ ret void } ; CHECK-LABEL: am1: -; CHECK: bis.w r13, 0(r12) +; CHECK: bis r13, 0(r12) @foo = external global i16 @@ -20,7 +20,7 @@ ret void } ; CHECK-LABEL: am2: -; CHECK: bis.w r12, &foo +; CHECK: bis r12, &foo @bar = external global [2 x i8] @@ -41,7 +41,7 @@ ret void } ; CHECK-LABEL: am4: -; CHECK: bis.w r12, &32 +; CHECK: bis r12, &32 define void @am5(i16* %a, i16 %x) readonly { %1 = getelementptr inbounds i16, i16* %a, i16 2 @@ -51,7 +51,7 @@ ret void } ; CHECK-LABEL: am5: -; CHECK: bis.w r13, 4(r12) +; CHECK: bis r13, 4(r12) %S = type { i16, i16 } @baz = common global %S zeroinitializer @@ -63,7 +63,7 @@ ret void } ; CHECK-LABEL: am6: -; CHECK: bis.w r12, &baz+2 +; CHECK: bis r12, &baz+2 %T = type { i16, [2 x i8] } @duh = external global %T Index: test/CodeGen/MSP430/AddrMode-mov-rx.ll =================================================================== --- test/CodeGen/MSP430/AddrMode-mov-rx.ll +++ test/CodeGen/MSP430/AddrMode-mov-rx.ll @@ -7,7 +7,7 @@ ret i16 %1 } ; CHECK-LABEL: am1: -; CHECK: mov.w 0(r12), r12 +; CHECK: mov 0(r12), r12 @foo = external global i16 @@ -16,7 +16,7 @@ ret i16 %1 } ; CHECK-LABEL: am2: -; CHECK: mov.w &foo, r12 +; CHECK: mov &foo, r12 @bar = internal constant [2 x i8] [ i8 32, i8 64 ] @@ -33,7 +33,7 @@ ret i16 %1 } ; CHECK-LABEL: am4: -; CHECK: mov.w &32, r12 +; CHECK: mov &32, r12 define i16 @am5(i16* %a) nounwind { %1 = getelementptr i16, i16* %a, i16 2 @@ -41,7 +41,7 @@ ret i16 %2 } ; CHECK-LABEL: am5: -; CHECK: mov.w 4(r12), r12 +; CHECK: mov 4(r12), r12 %S = type { i16, i16 } @baz = common global %S zeroinitializer, align 1 @@ -51,7 +51,7 @@ ret i16 %1 } ; CHECK-LABEL: am6: -; CHECK: mov.w &baz+2, r12 +; CHECK: mov &baz+2, r12 %T = type { i16, [2 x i8] } @duh = internal constant %T { i16 16, [2 x i8][i8 32, i8 64 ] } Index: test/CodeGen/MSP430/AddrMode-mov-xr.ll =================================================================== --- test/CodeGen/MSP430/AddrMode-mov-xr.ll +++ test/CodeGen/MSP430/AddrMode-mov-xr.ll @@ -7,7 +7,7 @@ ret void } ; CHECK-LABEL: am1: -; CHECK: mov.w r13, 0(r12) +; CHECK: mov r13, 0(r12) @foo = external global i16 @@ -16,7 +16,7 @@ ret void } ; CHECK-LABEL: am2: -; CHECK: mov.w r12, &foo +; CHECK: mov r12, &foo @bar = external global [2 x i8] @@ -33,7 +33,7 @@ ret void } ; CHECK-LABEL: am4: -; CHECK: mov.w r12, &32 +; CHECK: mov r12, &32 define void @am5(i16* nocapture %p, i16 %a) nounwind readonly { %1 = getelementptr inbounds i16, i16* %p, i16 2 @@ -41,7 +41,7 @@ ret void } ; CHECK-LABEL: am5: -; CHECK: mov.w r13, 4(r12) +; CHECK: mov r13, 4(r12) %S = type { i16, i16 } @baz = common global %S zeroinitializer, align 1 @@ -51,7 +51,7 @@ ret void } ; CHECK-LABEL: am6: -; CHECK: mov.w r12, &baz+2 +; CHECK: mov r12, &baz+2 %T = type { i16, [2 x i8] } @duh = external global %T Index: test/CodeGen/MSP430/Inst16mi.ll =================================================================== --- test/CodeGen/MSP430/Inst16mi.ll +++ test/CodeGen/MSP430/Inst16mi.ll @@ -6,14 +6,14 @@ define void @mov() nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.w #2, &foo +; CHECK: mov #2, &foo store i16 2, i16 * @foo ret void } define void @add() nounwind { ; CHECK-LABEL: add: -; CHECK: add.w #2, &foo +; CHECK: incd &foo %1 = load i16, i16* @foo %2 = add i16 %1, 2 store i16 %2, i16 * @foo @@ -22,7 +22,7 @@ define void @and() nounwind { ; CHECK-LABEL: and: -; CHECK: and.w #2, &foo +; CHECK: and #2, &foo %1 = load i16, i16* @foo %2 = and i16 %1, 2 store i16 %2, i16 * @foo @@ -31,7 +31,7 @@ define void @bis() nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w #2, &foo +; CHECK: bis #2, &foo %1 = load i16, i16* @foo %2 = or i16 %1, 2 store i16 %2, i16 * @foo @@ -40,7 +40,7 @@ define void @xor() nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w #2, &foo +; CHECK: xor #2, &foo %1 = load i16, i16* @foo %2 = xor i16 %1, 2 store i16 %2, i16 * @foo Index: test/CodeGen/MSP430/Inst16mm.ll =================================================================== --- test/CodeGen/MSP430/Inst16mm.ll +++ test/CodeGen/MSP430/Inst16mm.ll @@ -6,7 +6,7 @@ define void @mov() nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.w &bar, &foo +; CHECK: mov &bar, &foo %1 = load i16, i16* @bar store i16 %1, i16* @foo ret void @@ -14,7 +14,7 @@ define void @add() nounwind { ; CHECK-LABEL: add: -; CHECK: add.w &bar, &foo +; CHECK: add &bar, &foo %1 = load i16, i16* @bar %2 = load i16, i16* @foo %3 = add i16 %2, %1 @@ -24,7 +24,7 @@ define void @and() nounwind { ; CHECK-LABEL: and: -; CHECK: and.w &bar, &foo +; CHECK: and &bar, &foo %1 = load i16, i16* @bar %2 = load i16, i16* @foo %3 = and i16 %2, %1 @@ -34,7 +34,7 @@ define void @bis() nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w &bar, &foo +; CHECK: bis &bar, &foo %1 = load i16, i16* @bar %2 = load i16, i16* @foo %3 = or i16 %2, %1 @@ -44,7 +44,7 @@ define void @xor() nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w &bar, &foo +; CHECK: xor &bar, &foo %1 = load i16, i16* @bar %2 = load i16, i16* @foo %3 = xor i16 %2, %1 @@ -64,6 +64,6 @@ %0 = load i16, i16* %retval ; [#uses=1] ret i16 %0 ; CHECK-LABEL: mov2: -; CHECK-DAG: mov.w 2(r1), 6(r1) -; CHECK-DAG: mov.w 0(r1), 4(r1) +; CHECK-DAG: mov 2(r1), 6(r1) +; CHECK-DAG: mov 0(r1), 4(r1) } Index: test/CodeGen/MSP430/Inst16mr.ll =================================================================== --- test/CodeGen/MSP430/Inst16mr.ll +++ test/CodeGen/MSP430/Inst16mr.ll @@ -5,14 +5,14 @@ define void @mov(i16 %a) nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.w r12, &foo +; CHECK: mov r12, &foo store i16 %a, i16* @foo ret void } define void @add(i16 %a) nounwind { ; CHECK-LABEL: add: -; CHECK: add.w r12, &foo +; CHECK: add r12, &foo %1 = load i16, i16* @foo %2 = add i16 %a, %1 store i16 %2, i16* @foo @@ -21,7 +21,7 @@ define void @and(i16 %a) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w r12, &foo +; CHECK: and r12, &foo %1 = load i16, i16* @foo %2 = and i16 %a, %1 store i16 %2, i16* @foo @@ -30,7 +30,7 @@ define void @bis(i16 %a) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w r12, &foo +; CHECK: bis r12, &foo %1 = load i16, i16* @foo %2 = or i16 %a, %1 store i16 %2, i16* @foo @@ -39,7 +39,7 @@ define void @bic(i16 zeroext %m) nounwind { ; CHECK-LABEL: bic: -; CHECK: bic.w r12, &foo +; CHECK: bic r12, &foo %1 = xor i16 %m, -1 %2 = load i16, i16* @foo %3 = and i16 %2, %1 @@ -49,7 +49,7 @@ define void @xor(i16 %a) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w r12, &foo +; CHECK: xor r12, &foo %1 = load i16, i16* @foo %2 = xor i16 %a, %1 store i16 %2, i16* @foo Index: test/CodeGen/MSP430/Inst16ri.ll =================================================================== --- test/CodeGen/MSP430/Inst16ri.ll +++ test/CodeGen/MSP430/Inst16ri.ll @@ -4,34 +4,34 @@ define i16 @mov() nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.w #1, r12 +; CHECK: mov #1, r12 ret i16 1 } define i16 @add(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: add: -; CHECK: add.w #1, r12 +; CHECK: inc r12 %1 = add i16 %a, 1 ret i16 %1 } define i16 @and(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w #1, r12 +; CHECK: and #1, r12 %1 = and i16 %a, 1 ret i16 %1 } define i16 @bis(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w #1, r12 +; CHECK: bis #1, r12 %1 = or i16 %a, 1 ret i16 %1 } define i16 @xor(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w #1, r12 +; CHECK: xor #1, r12 %1 = xor i16 %a, 1 ret i16 %1 } Index: test/CodeGen/MSP430/Inst16rm.ll =================================================================== --- test/CodeGen/MSP430/Inst16rm.ll +++ test/CodeGen/MSP430/Inst16rm.ll @@ -5,7 +5,7 @@ define i16 @add(i16 %a) nounwind { ; CHECK-LABEL: add: -; CHECK: add.w &foo, r12 +; CHECK: add &foo, r12 %1 = load i16, i16* @foo %2 = add i16 %a, %1 ret i16 %2 @@ -13,7 +13,7 @@ define i16 @and(i16 %a) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w &foo, r12 +; CHECK: and &foo, r12 %1 = load i16, i16* @foo %2 = and i16 %a, %1 ret i16 %2 @@ -21,7 +21,7 @@ define i16 @bis(i16 %a) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w &foo, r12 +; CHECK: bis &foo, r12 %1 = load i16, i16* @foo %2 = or i16 %a, %1 ret i16 %2 @@ -29,7 +29,7 @@ define i16 @bic(i16 %a) nounwind { ; CHECK-LABEL: bic: -; CHECK: bic.w &foo, r12 +; CHECK: bic &foo, r12 %1 = load i16, i16* @foo %2 = xor i16 %1, -1 %3 = and i16 %a, %2 @@ -38,7 +38,7 @@ define i16 @xor(i16 %a) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w &foo, r12 +; CHECK: xor &foo, r12 %1 = load i16, i16* @foo %2 = xor i16 %a, %1 ret i16 %2 Index: test/CodeGen/MSP430/Inst16rr.ll =================================================================== --- test/CodeGen/MSP430/Inst16rr.ll +++ test/CodeGen/MSP430/Inst16rr.ll @@ -4,34 +4,34 @@ define i16 @mov(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.w r13, r12 +; CHECK: mov r13, r12 ret i16 %b } define i16 @add(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: add: -; CHECK: add.w r13, r12 +; CHECK: add r13, r12 %1 = add i16 %a, %b ret i16 %1 } define i16 @and(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w r13, r12 +; CHECK: and r13, r12 %1 = and i16 %a, %b ret i16 %1 } define i16 @bis(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w r13, r12 +; CHECK: bis r13, r12 %1 = or i16 %a, %b ret i16 %1 } define i16 @bic(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: bic: -; CHECK: bic.w r13, r12 +; CHECK: bic r13, r12 %1 = xor i16 %b, -1 %2 = and i16 %a, %1 ret i16 %2 @@ -39,7 +39,7 @@ define i16 @xor(i16 %a, i16 %b) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w r13, r12 +; CHECK: xor r13, r12 %1 = xor i16 %a, %b ret i16 %1 } Index: test/CodeGen/MSP430/Inst8mi.ll =================================================================== --- test/CodeGen/MSP430/Inst8mi.ll +++ test/CodeGen/MSP430/Inst8mi.ll @@ -12,7 +12,7 @@ define void @add() nounwind { ; CHECK-LABEL: add: -; CHECK: add.b #2, &foo +; CHECK: incd.b &foo %1 = load i8, i8* @foo %2 = add i8 %1, 2 store i8 %2, i8 * @foo Index: test/CodeGen/MSP430/Inst8ri.ll =================================================================== --- test/CodeGen/MSP430/Inst8ri.ll +++ test/CodeGen/MSP430/Inst8ri.ll @@ -10,7 +10,7 @@ define i8 @add(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: add: -; CHECK: add.b #1, r12 +; CHECK: inc.b r12 %1 = add i8 %a, 1 ret i8 %1 } Index: test/CodeGen/MSP430/Inst8rr.ll =================================================================== --- test/CodeGen/MSP430/Inst8rr.ll +++ test/CodeGen/MSP430/Inst8rr.ll @@ -4,7 +4,7 @@ define i8 @mov(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: mov: -; CHECK: mov.{{[bw]}} r13, r12 +; CHECK: mov r13, r12 ret i8 %b } @@ -17,14 +17,14 @@ define i8 @and(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: and: -; CHECK: and.w r13, r12 +; CHECK: and r13, r12 %1 = and i8 %a, %b ret i8 %1 } define i8 @bis(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: bis: -; CHECK: bis.w r13, r12 +; CHECK: bis r13, r12 %1 = or i8 %a, %b ret i8 %1 } @@ -39,7 +39,7 @@ define i8 @xor(i8 %a, i8 %b) nounwind { ; CHECK-LABEL: xor: -; CHECK: xor.w r13, r12 +; CHECK: xor r13, r12 %1 = xor i8 %a, %b ret i8 %1 } Index: test/CodeGen/MSP430/asm-clobbers.ll =================================================================== --- test/CodeGen/MSP430/asm-clobbers.ll +++ test/CodeGen/MSP430/asm-clobbers.ll @@ -6,8 +6,8 @@ define void @test() { entry: ; CHECK-LABEL: test: -; CHECK: push.w r10 +; CHECK: push r10 call void asm sideeffect "", "~{r10}"() -; CHECK: pop.w r10 +; CHECK: pop r10 ret void } Index: test/CodeGen/MSP430/bit.ll =================================================================== --- test/CodeGen/MSP430/bit.ll +++ test/CodeGen/MSP430/bit.ll @@ -93,7 +93,7 @@ ret i16 %t3 } ; CHECK-LABEL: bitwrr: -; CHECK: bit.w r13, r12 +; CHECK: bit r13, r12 define i16 @bitwri(i16 %a) nounwind { %t1 = and i16 %a, 4080 @@ -102,7 +102,7 @@ ret i16 %t3 } ; CHECK-LABEL: bitwri: -; CHECK: bit.w #4080, r12 +; CHECK: bit #4080, r12 define i16 @bitwir(i16 %a) nounwind { %t1 = and i16 4080, %a @@ -111,7 +111,7 @@ ret i16 %t3 } ; CHECK-LABEL: bitwir: -; CHECK: bit.w #4080, r12 +; CHECK: bit #4080, r12 define i16 @bitwmi() nounwind { %t1 = load i16, i16* @foo16 @@ -121,7 +121,7 @@ ret i16 %t4 } ; CHECK-LABEL: bitwmi: -; CHECK: bit.w #4080, &foo16 +; CHECK: bit #4080, &foo16 define i16 @bitwim() nounwind { %t1 = load i16, i16* @foo16 @@ -131,7 +131,7 @@ ret i16 %t4 } ; CHECK-LABEL: bitwim: -; CHECK: bit.w #4080, &foo16 +; CHECK: bit #4080, &foo16 define i16 @bitwrm(i16 %a) nounwind { %t1 = load i16, i16* @foo16 @@ -141,7 +141,7 @@ ret i16 %t4 } ; CHECK-LABEL: bitwrm: -; CHECK: bit.w &foo16, r12 +; CHECK: bit &foo16, r12 define i16 @bitwmr(i16 %a) nounwind { %t1 = load i16, i16* @foo16 @@ -151,7 +151,7 @@ ret i16 %t4 } ; CHECK-LABEL: bitwmr: -; CHECK: bit.w r12, &foo16 +; CHECK: bit r12, &foo16 define i16 @bitwmm() nounwind { %t1 = load i16, i16* @foo16 @@ -162,5 +162,5 @@ ret i16 %t5 } ; CHECK-LABEL: bitwmm: -; CHECK: bit.w &bar16, &foo16 +; CHECK: bit &bar16, &foo16 Index: test/CodeGen/MSP430/byval.ll =================================================================== --- test/CodeGen/MSP430/byval.ll +++ test/CodeGen/MSP430/byval.ll @@ -9,7 +9,7 @@ define i16 @callee(%struct.Foo* byval %f) nounwind { entry: ; CHECK-LABEL: callee: -; CHECK: mov.w 2(r1), r12 +; CHECK: mov 2(r1), r12 %0 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 0 %1 = load i16, i16* %0, align 2 ret i16 %1 @@ -18,9 +18,9 @@ define void @caller() nounwind { entry: ; CHECK-LABEL: caller: -; CHECK: mov.w &foo+4, 4(r1) -; CHECK-NEXT: mov.w &foo+2, 2(r1) -; CHECK-NEXT: mov.w &foo, 0(r1) +; CHECK: mov &foo+4, 4(r1) +; CHECK-NEXT: mov &foo+2, 2(r1) +; CHECK-NEXT: mov &foo, 0(r1) %call = call i16 @callee(%struct.Foo* byval @foo) ret void } Index: test/CodeGen/MSP430/cc_args.ll =================================================================== --- test/CodeGen/MSP430/cc_args.ll +++ test/CodeGen/MSP430/cc_args.ll @@ -7,50 +7,50 @@ entry: ; CHECK: test: -; CHECK: mov.w #1, r12 +; CHECK: mov #1, r12 ; CHECK: call #f_i16 call void @f_i16(i16 1) -; CHECK: mov.w #772, r12 -; CHECK: mov.w #258, r13 +; CHECK: mov #772, r12 +; CHECK: mov #258, r13 ; CHECK: call #f_i32 call void @f_i32(i32 16909060) -; CHECK: mov.w #1800, r12 -; CHECK: mov.w #1286, r13 -; CHECK: mov.w #772, r14 -; CHECK: mov.w #258, r15 +; CHECK: mov #1800, r12 +; CHECK: mov #1286, r13 +; CHECK: mov #772, r14 +; CHECK: mov #258, r15 ; CHECK: call #f_i64 call void @f_i64(i64 72623859790382856) -; CHECK: mov.w #772, r12 -; CHECK: mov.w #258, r13 -; CHECK: mov.w #1800, r14 -; CHECK: mov.w #1286, r15 +; CHECK: mov #772, r12 +; CHECK: mov #258, r13 +; CHECK: mov #1800, r14 +; CHECK: mov #1286, r15 ; CHECK: call #f_i32_i32 call void @f_i32_i32(i32 16909060, i32 84281096) -; CHECK: mov.w #1, r12 -; CHECK: mov.w #772, r13 -; CHECK: mov.w #258, r14 -; CHECK: mov.w #2, r15 +; CHECK: mov #1, r12 +; CHECK: mov #772, r13 +; CHECK: mov #258, r14 +; CHECK: mov #2, r15 ; CHECK: call #f_i16_i32_i16 call void @f_i16_i32_i16(i16 1, i32 16909060, i16 2) -; CHECK: mov.w #1286, 0(r1) -; CHECK: mov.w #1, r12 -; CHECK: mov.w #772, r13 -; CHECK: mov.w #258, r14 -; CHECK: mov.w #1800, r15 +; CHECK: mov #1286, 0(r1) +; CHECK: mov #1, r12 +; CHECK: mov #772, r13 +; CHECK: mov #258, r14 +; CHECK: mov #1800, r15 ; CHECK: call #f_i16_i32_i32 call void @f_i16_i32_i32(i16 1, i32 16909060, i32 84281096) -; CHECK: mov.w #258, 6(r1) -; CHECK: mov.w #772, 4(r1) -; CHECK: mov.w #1286, 2(r1) -; CHECK: mov.w #1800, 0(r1) -; CHECK: mov.w #1, r12 -; CHECK: mov.w #2, r13 +; CHECK: mov #258, 6(r1) +; CHECK: mov #772, 4(r1) +; CHECK: mov #1286, 2(r1) +; CHECK: mov #1800, 0(r1) +; CHECK: mov #1, r12 +; CHECK: mov #2, r13 ; CHECK: call #f_i16_i64_i16 call void @f_i16_i64_i16(i16 1, i64 72623859790382856, i16 2) @@ -63,75 +63,75 @@ define void @f_i16(i16 %a) #0 { ; CHECK: f_i16: -; CHECK: mov.w r12, &g_i16 +; CHECK: mov r12, &g_i16 store volatile i16 %a, i16* @g_i16, align 2 ret void } define void @f_i32(i32 %a) #0 { ; CHECK: f_i32: -; CHECK: mov.w r13, &g_i32+2 -; CHECK: mov.w r12, &g_i32 +; CHECK: mov r13, &g_i32+2 +; CHECK: mov r12, &g_i32 store volatile i32 %a, i32* @g_i32, align 2 ret void } define void @f_i64(i64 %a) #0 { ; CHECK: f_i64: -; CHECK: mov.w r15, &g_i64+6 -; CHECK: mov.w r14, &g_i64+4 -; CHECK: mov.w r13, &g_i64+2 -; CHECK: mov.w r12, &g_i64 +; CHECK: mov r15, &g_i64+6 +; CHECK: mov r14, &g_i64+4 +; CHECK: mov r13, &g_i64+2 +; CHECK: mov r12, &g_i64 store volatile i64 %a, i64* @g_i64, align 2 ret void } define void @f_i32_i32(i32 %a, i32 %b) #0 { ; CHECK: f_i32_i32: -; CHECK: mov.w r13, &g_i32+2 -; CHECK: mov.w r12, &g_i32 +; CHECK: mov r13, &g_i32+2 +; CHECK: mov r12, &g_i32 store volatile i32 %a, i32* @g_i32, align 2 -; CHECK: mov.w r15, &g_i32+2 -; CHECK: mov.w r14, &g_i32 +; CHECK: mov r15, &g_i32+2 +; CHECK: mov r14, &g_i32 store volatile i32 %b, i32* @g_i32, align 2 ret void } define void @f_i16_i32_i32(i16 %a, i32 %b, i32 %c) #0 { ; CHECK: f_i16_i32_i32: -; CHECK: mov.w r12, &g_i16 +; CHECK: mov r12, &g_i16 store volatile i16 %a, i16* @g_i16, align 2 -; CHECK: mov.w r14, &g_i32+2 -; CHECK: mov.w r13, &g_i32 +; CHECK: mov r14, &g_i32+2 +; CHECK: mov r13, &g_i32 store volatile i32 %b, i32* @g_i32, align 2 -; CHECK: mov.w r15, &g_i32 -; CHECK: mov.w 4(r4), &g_i32+2 +; CHECK: mov r15, &g_i32 +; CHECK: mov 4(r4), &g_i32+2 store volatile i32 %c, i32* @g_i32, align 2 ret void } define void @f_i16_i32_i16(i16 %a, i32 %b, i16 %c) #0 { ; CHECK: f_i16_i32_i16: -; CHECK: mov.w r12, &g_i16 +; CHECK: mov r12, &g_i16 store volatile i16 %a, i16* @g_i16, align 2 -; CHECK: mov.w r14, &g_i32+2 -; CHECK: mov.w r13, &g_i32 +; CHECK: mov r14, &g_i32+2 +; CHECK: mov r13, &g_i32 store volatile i32 %b, i32* @g_i32, align 2 -; CHECK: mov.w r15, &g_i16 +; CHECK: mov r15, &g_i16 store volatile i16 %c, i16* @g_i16, align 2 ret void } define void @f_i16_i64_i16(i16 %a, i64 %b, i16 %c) #0 { ; CHECK: f_i16_i64_i16: -; CHECK: mov.w r12, &g_i16 +; CHECK: mov r12, &g_i16 store volatile i16 %a, i16* @g_i16, align 2 -;CHECK: mov.w 10(r4), &g_i64+6 -;CHECK: mov.w 8(r4), &g_i64+4 -;CHECK: mov.w 6(r4), &g_i64+2 -;CHECK: mov.w 4(r4), &g_i64 +;CHECK: mov 10(r4), &g_i64+6 +;CHECK: mov 8(r4), &g_i64+4 +;CHECK: mov 6(r4), &g_i64+2 +;CHECK: mov 4(r4), &g_i64 store volatile i64 %b, i64* @g_i64, align 2 -;CHECK: mov.w r13, &g_i16 +;CHECK: mov r13, &g_i16 store volatile i16 %c, i16* @g_i16, align 2 ret void } Index: test/CodeGen/MSP430/cc_ret.ll =================================================================== --- test/CodeGen/MSP430/cc_ret.ll +++ test/CodeGen/MSP430/cc_ret.ll @@ -8,21 +8,21 @@ ; CHECK: test: ; CHECK: call #f_i16 -; CHECK: mov.w r12, &g_i16 +; CHECK: mov r12, &g_i16 %0 = call i16 @f_i16() store volatile i16 %0, i16* @g_i16 ; CHECK: call #f_i32 -; CHECK: mov.w r13, &g_i32+2 -; CHECK: mov.w r12, &g_i32 +; CHECK: mov r13, &g_i32+2 +; CHECK: mov r12, &g_i32 %1 = call i32 @f_i32() store volatile i32 %1, i32* @g_i32 ; CHECK: call #f_i64 -; CHECK: mov.w r15, &g_i64+6 -; CHECK: mov.w r14, &g_i64+4 -; CHECK: mov.w r13, &g_i64+2 -; CHECK: mov.w r12, &g_i64 +; CHECK: mov r15, &g_i64+6 +; CHECK: mov r14, &g_i64+4 +; CHECK: mov r13, &g_i64+2 +; CHECK: mov r12, &g_i64 %2 = call i64 @f_i64() store volatile i64 %2, i64* @g_i64 @@ -35,25 +35,25 @@ define i16 @f_i16() #0 { ; CHECK: f_i16: -; CHECK: mov.w #1, r12 +; CHECK: mov #1, r12 ; CHECK: ret ret i16 1 } define i32 @f_i32() #0 { ; CHECK: f_i32: -; CHECK: mov.w #772, r12 -; CHECK: mov.w #258, r13 +; CHECK: mov #772, r12 +; CHECK: mov #258, r13 ; CHECK: ret ret i32 16909060 } define i64 @f_i64() #0 { ; CHECK: f_i64: -; CHECK: mov.w #1800, r12 -; CHECK: mov.w #1286, r13 -; CHECK: mov.w #772, r14 -; CHECK: mov.w #258, r15 +; CHECK: mov #1800, r12 +; CHECK: mov #1286, r13 +; CHECK: mov #772, r14 +; CHECK: mov #258, r15 ; CHECK: ret ret i64 72623859790382856 } Index: test/CodeGen/MSP430/fp.ll =================================================================== --- test/CodeGen/MSP430/fp.ll +++ test/CodeGen/MSP430/fp.ll @@ -6,13 +6,13 @@ define void @fp() nounwind { entry: ; CHECK-LABEL: fp: -; CHECK: push.w r4 -; CHECK: mov.w r1, r4 -; CHECK: sub.w #2, r1 +; CHECK: push r4 +; CHECK: mov r1, r4 +; CHECK: sub #2, r1 %i = alloca i16, align 2 -; CHECK: mov.w #0, -2(r4) +; CHECK: clr -2(r4) store i16 0, i16* %i, align 2 -; CHECK: pop.w r4 +; CHECK: pop r4 ret void } Index: test/CodeGen/MSP430/jumptable.ll =================================================================== --- test/CodeGen/MSP430/jumptable.ll +++ test/CodeGen/MSP430/jumptable.ll @@ -7,15 +7,15 @@ define i16 @test(i16 %i) #0 { entry: ; CHECK-LABEL: test: -; CHECK: sub.w #4, r1 -; CHECK-NEXT: mov.w r12, 0(r1) -; CHECK-NEXT: cmp.w #4, r12 +; CHECK: sub #4, r1 +; CHECK-NEXT: mov r12, 0(r1) +; CHECK-NEXT: cmp #4, r12 ; CHECK-NEXT: jhs .LBB0_3 %retval = alloca i16, align 2 %i.addr = alloca i16, align 2 store i16 %i, i16* %i.addr, align 2 %0 = load i16, i16* %i.addr, align 2 -; CHECK: rla.w r12 +; CHECK: add r12, r12 ; CHECK-NEXT: br .LJTI0_0(r12) switch i16 %0, label %sw.default [ i16 0, label %sw.bb Index: test/CodeGen/MSP430/memset.ll =================================================================== --- test/CodeGen/MSP430/memset.ll +++ test/CodeGen/MSP430/memset.ll @@ -9,9 +9,9 @@ entry: ; CHECK-LABEL: test: %0 = load i8*, i8** @buf, align 2 -; CHECK: mov.w &buf, r12 -; CHECK-NEXT: mov.w #5, r13 -; CHECK-NEXT: mov.w #128, r14 +; CHECK: mov &buf, r12 +; CHECK-NEXT: mov #5, r13 +; CHECK-NEXT: mov #128, r14 ; CHECK-NEXT: call #memset call void @llvm.memset.p0i8.i16(i8* %0, i8 5, i16 128, i1 false) ret void Index: test/CodeGen/MSP430/misched-msp430.ll =================================================================== --- test/CodeGen/MSP430/misched-msp430.ll +++ test/CodeGen/MSP430/misched-msp430.ll @@ -10,7 +10,7 @@ ; only verifies that the code generator ran successfully. ; ; CHECK-LABEL: @f -; CHECK: mov.w &y, &x +; CHECK: mov &y, &x ; CHECK: ret define void @f() { entry: Index: test/CodeGen/MSP430/postinc.ll =================================================================== --- test/CodeGen/MSP430/postinc.ll +++ test/CodeGen/MSP430/postinc.ll @@ -12,7 +12,7 @@ %sum.09 = phi i16 [ 0, %entry ], [ %add, %for.body ] ; [#uses=1] %arrayidx = getelementptr i16, i16* %a, i16 %i.010 ; [#uses=1] ; CHECK-LABEL: add: -; CHECK: add.w @r{{[0-9]+}}+, r{{[0-9]+}} +; CHECK: add @r{{[0-9]+}}+, r{{[0-9]+}} %tmp4 = load i16, i16* %arrayidx ; [#uses=1] %add = add i16 %tmp4, %sum.09 ; [#uses=2] %inc = add i16 %i.010, 1 ; [#uses=2] @@ -34,7 +34,7 @@ %sum.09 = phi i16 [ 0, %entry ], [ %add, %for.body ] ; [#uses=1] %arrayidx = getelementptr i16, i16* %a, i16 %i.010 ; [#uses=1] ; CHECK-LABEL: sub: -; CHECK: sub.w @r{{[0-9]+}}+, r{{[0-9]+}} +; CHECK: sub @r{{[0-9]+}}+, r{{[0-9]+}} %tmp4 = load i16, i16* %arrayidx ; [#uses=1] %add = sub i16 %tmp4, %sum.09 ; [#uses=2] %inc = add i16 %i.010, 1 ; [#uses=2] @@ -56,7 +56,7 @@ %sum.09 = phi i16 [ 0, %entry ], [ %add, %for.body ] ; [#uses=1] %arrayidx = getelementptr i16, i16* %a, i16 %i.010 ; [#uses=1] ; CHECK-LABEL: or: -; CHECK: bis.w @r{{[0-9]+}}+, r{{[0-9]+}} +; CHECK: bis @r{{[0-9]+}}+, r{{[0-9]+}} %tmp4 = load i16, i16* %arrayidx ; [#uses=1] %add = or i16 %tmp4, %sum.09 ; [#uses=2] %inc = add i16 %i.010, 1 ; [#uses=2] @@ -78,7 +78,7 @@ %sum.09 = phi i16 [ 0, %entry ], [ %add, %for.body ] ; [#uses=1] %arrayidx = getelementptr i16, i16* %a, i16 %i.010 ; [#uses=1] ; CHECK-LABEL: xor: -; CHECK: xor.w @r{{[0-9]+}}+, r{{[0-9]+}} +; CHECK: xor @r{{[0-9]+}}+, r{{[0-9]+}} %tmp4 = load i16, i16* %arrayidx ; [#uses=1] %add = xor i16 %tmp4, %sum.09 ; [#uses=2] %inc = add i16 %i.010, 1 ; [#uses=2] @@ -100,7 +100,7 @@ %sum.09 = phi i16 [ 0, %entry ], [ %add, %for.body ] ; [#uses=1] %arrayidx = getelementptr i16, i16* %a, i16 %i.010 ; [#uses=1] ; CHECK-LABEL: and: -; CHECK: and.w @r{{[0-9]+}}+, r{{[0-9]+}} +; CHECK: and @r{{[0-9]+}}+, r{{[0-9]+}} %tmp4 = load i16, i16* %arrayidx ; [#uses=1] %add = and i16 %tmp4, %sum.09 ; [#uses=2] %inc = add i16 %i.010, 1 ; [#uses=2] Index: test/CodeGen/MSP430/select-use-sr.ll =================================================================== --- test/CodeGen/MSP430/select-use-sr.ll +++ test/CodeGen/MSP430/select-use-sr.ll @@ -6,8 +6,8 @@ ; Test that CMP instruction is not removed by MachineCSE. ; ; CHECK-LABEL: @f -; CHECK: cmp.w r15, r13 -; CHECK: cmp.w r15, r13 +; CHECK: cmp r15, r13 +; CHECK: cmp r15, r13 ; CHECK-NEXT: jeq .LBB0_2 define i16 @f(i16, i16, i16, i16) { entry: Index: test/CodeGen/MSP430/setcc.ll =================================================================== --- test/CodeGen/MSP430/setcc.ll +++ test/CodeGen/MSP430/setcc.ll @@ -9,10 +9,10 @@ ret i16 %t3 } ; CHECK-LABEL: sccweqand: -; CHECK: bit.w r13, r12 -; CHECK: mov.w r2, r12 -; CHECK: rra.w r12 -; CHECK: and.w #1, r12 +; CHECK: bit r13, r12 +; CHECK: mov r2, r12 +; CHECK: rra r12 +; CHECK: and #1, r12 define i16 @sccwneand(i16 %a, i16 %b) nounwind { %t1 = and i16 %a, %b @@ -21,9 +21,9 @@ ret i16 %t3 } ; CHECK-LABEL: sccwneand: -; CHECK: bit.w r13, r12 -; CHECK: mov.w r2, r12 -; CHECK: and.w #1, r12 +; CHECK: bit r13, r12 +; CHECK: mov r2, r12 +; CHECK: and #1, r12 define i16 @sccwne(i16 %a, i16 %b) nounwind { %t1 = icmp ne i16 %a, %b @@ -31,11 +31,11 @@ ret i16 %t2 } ; CHECK-LABEL:sccwne: -; CHECK: cmp.w r13, r12 -; CHECK: mov.w r2, r13 -; CHECK: rra.w r13 -; CHECK: mov.w #1, r12 -; CHECK: bic.w r13, r12 +; CHECK: cmp r13, r12 +; CHECK: mov r2, r13 +; CHECK: rra r13 +; CHECK: mov #1, r12 +; CHECK: bic r13, r12 define i16 @sccweq(i16 %a, i16 %b) nounwind { %t1 = icmp eq i16 %a, %b @@ -43,10 +43,10 @@ ret i16 %t2 } ; CHECK-LABEL:sccweq: -; CHECK: cmp.w r13, r12 -; CHECK: mov.w r2, r12 -; CHECK: rra.w r12 -; CHECK: and.w #1, r12 +; CHECK: cmp r13, r12 +; CHECK: mov r2, r12 +; CHECK: rra r12 +; CHECK: and #1, r12 define i16 @sccwugt(i16 %a, i16 %b) nounwind { %t1 = icmp ugt i16 %a, %b @@ -54,9 +54,9 @@ ret i16 %t2 } ; CHECK-LABEL:sccwugt: -; CHECK: cmp.w r12, r13 -; CHECK: mov.w #1, r12 -; CHECK: bic.w r2, r12 +; CHECK: cmp r12, r13 +; CHECK: mov #1, r12 +; CHECK: bic r2, r12 define i16 @sccwuge(i16 %a, i16 %b) nounwind { %t1 = icmp uge i16 %a, %b @@ -64,9 +64,9 @@ ret i16 %t2 } ; CHECK-LABEL:sccwuge: -; CHECK: cmp.w r13, r12 -; CHECK: mov.w r2, r12 -; CHECK: and.w #1, r12 +; CHECK: cmp r13, r12 +; CHECK: mov r2, r12 +; CHECK: and #1, r12 define i16 @sccwult(i16 %a, i16 %b) nounwind { %t1 = icmp ult i16 %a, %b @@ -74,9 +74,9 @@ ret i16 %t2 } ; CHECK-LABEL:sccwult: -; CHECK: cmp.w r13, r12 -; CHECK: mov.w #1, r12 -; CHECK: bic.w r2, r12 +; CHECK: cmp r13, r12 +; CHECK: mov #1, r12 +; CHECK: bic r2, r12 define i16 @sccwule(i16 %a, i16 %b) nounwind { %t1 = icmp ule i16 %a, %b @@ -84,9 +84,9 @@ ret i16 %t2 } ; CHECK-LABEL:sccwule: -; CHECK: cmp.w r12, r13 -; CHECK: mov.w r2, r12 -; CHECK: and.w #1, r12 +; CHECK: cmp r12, r13 +; CHECK: mov r2, r12 +; CHECK: and #1, r12 define i16 @sccwsgt(i16 %a, i16 %b) nounwind { %t1 = icmp sgt i16 %a, %b Index: test/CodeGen/MSP430/shifts.ll =================================================================== --- test/CodeGen/MSP430/shifts.ll +++ test/CodeGen/MSP430/shifts.ll @@ -21,7 +21,7 @@ define zeroext i8 @shl8(i8 zeroext %a, i8 zeroext %cnt) nounwind readnone { entry: ; CHECK: shl8 -; CHECK: rla.b +; CHECK: add.b %shl = shl i8 %a, %cnt ret i8 %shl } @@ -29,7 +29,7 @@ define zeroext i16 @lshr16(i16 zeroext %a, i16 zeroext %cnt) nounwind readnone { entry: ; CHECK-LABEL: lshr16: -; CHECK: rrc.w +; CHECK: rrc %shr = lshr i16 %a, %cnt ret i16 %shr } @@ -37,7 +37,7 @@ define signext i16 @ashr16(i16 signext %a, i16 zeroext %cnt) nounwind readnone { entry: ; CHECK-LABEL: ashr16: -; CHECK: rra.w +; CHECK: rra %shr = ashr i16 %a, %cnt ret i16 %shr } @@ -45,7 +45,7 @@ define zeroext i16 @shl16(i16 zeroext %a, i16 zeroext %cnt) nounwind readnone { entry: ; CHECK-LABEL: shl16: -; CHECK: rla.w +; CHECK: add %shl = shl i16 %a, %cnt ret i16 %shl } Index: test/CodeGen/MSP430/struct-return.ll =================================================================== --- test/CodeGen/MSP430/struct-return.ll +++ test/CodeGen/MSP430/struct-return.ll @@ -9,14 +9,14 @@ define %s @fred() #0 { ; CHECK-LABEL: fred: -; CHECK: mov.w #2314, 14(r12) -; CHECK: mov.w #2828, 12(r12) -; CHECK: mov.w #3342, 10(r12) -; CHECK: mov.w #3840, 8(r12) -; CHECK: mov.w #258, 6(r12) -; CHECK: mov.w #772, 4(r12) -; CHECK: mov.w #1286, 2(r12) -; CHECK: mov.w #1800, 0(r12) +; CHECK: mov #2314, 14(r12) +; CHECK: mov #2828, 12(r12) +; CHECK: mov #3342, 10(r12) +; CHECK: mov #3840, 8(r12) +; CHECK: mov #258, 6(r12) +; CHECK: mov #772, 4(r12) +; CHECK: mov #1286, 2(r12) +; CHECK: mov #1800, 0(r12) ret %s {i64 72623859790382856, i64 651345242494996224} } Index: test/CodeGen/MSP430/struct_layout.ll =================================================================== --- test/CodeGen/MSP430/struct_layout.ll +++ test/CodeGen/MSP430/struct_layout.ll @@ -5,7 +5,7 @@ %struct.X = type { i8 } ; CHECK-LABEL: @foo -; CHECK: sub.w #4, r1 +; CHECK: sub #4, r1 ; CHECK: mov.b #1, 3(r1) define void @foo() { %1 = alloca %struct.X @@ -21,7 +21,7 @@ } ; CHECK-LABEL: @bar -; CHECK: sub.w #4, r1 +; CHECK: sub #4, r1 ; CHECK: mov.b #1, 3(r1) define void @bar() { %1 = alloca [3 x %struct.X] @@ -40,8 +40,8 @@ %struct.Y = type { i8, i16 } ; CHECK-LABEL: @baz -; CHECK: sub.w #8, r1 -; CHECK: mov.w #2, 6(r1) +; CHECK: sub #8, r1 +; CHECK: mov #2, 6(r1) define void @baz() { %1 = alloca %struct.Y, align 2 %2 = alloca %struct.Y, align 2 Index: test/CodeGen/MSP430/transient-stack-alignment.ll =================================================================== --- test/CodeGen/MSP430/transient-stack-alignment.ll +++ test/CodeGen/MSP430/transient-stack-alignment.ll @@ -5,11 +5,11 @@ define void @test() #0 { ; CHECK-LABEL: test: -; CHECK: sub.w #2, r1 +; CHECK: sub #2, r1 %1 = alloca i8, align 1 -; CHECK-NEXT: mov.b #0, 1(r1) +; CHECK-NEXT: clr.b 1(r1) store i8 0, i8* %1, align 1 -; CHECK-NEXT: add.w #2, r1 +; CHECK-NEXT: add #2, r1 ; CHECK-NEXT: ret ret void } Index: test/CodeGen/MSP430/vararg.ll =================================================================== --- test/CodeGen/MSP430/vararg.ll +++ test/CodeGen/MSP430/vararg.ll @@ -10,12 +10,12 @@ define void @va_start(i16 %a, ...) nounwind { entry: ; CHECK-LABEL: va_start: -; CHECK: sub.w #2, r1 +; CHECK: sub #2, r1 %vl = alloca i8*, align 2 %vl1 = bitcast i8** %vl to i8* -; CHECK-NEXT: mov.w r1, [[REG:r[0-9]+]] -; CHECK-NEXT: add.w #6, [[REG]] -; CHECK-NEXT: mov.w [[REG]], 0(r1) +; CHECK-NEXT: mov r1, [[REG:r[0-9]+]] +; CHECK-NEXT: add #6, [[REG]] +; CHECK-NEXT: mov [[REG]], 0(r1) call void @llvm.va_start(i8* %vl1) call void @llvm.va_end(i8* %vl1) ret void @@ -26,11 +26,11 @@ ; CHECK-LABEL: va_arg: %vl.addr = alloca i8*, align 2 store i8* %vl, i8** %vl.addr, align 2 -; CHECK: mov.w r12, [[REG:r[0-9]+]] -; CHECK-NEXT: add.w #2, [[REG]] -; CHECK-NEXT: mov.w [[REG]], 0(r1) +; CHECK: mov r12, [[REG:r[0-9]+]] +; CHECK-NEXT: incd [[REG]] +; CHECK-NEXT: mov [[REG]], 0(r1) %0 = va_arg i8** %vl.addr, i16 -; CHECK-NEXT: mov.w 0(r12), r12 +; CHECK-NEXT: mov 0(r12), r12 ret i16 %0 } @@ -39,11 +39,11 @@ ; CHECK-LABEL: va_copy: %vl.addr = alloca i8*, align 2 %vl2 = alloca i8*, align 2 -; CHECK-DAG: mov.w r12, 2(r1) +; CHECK-DAG: mov r12, 2(r1) store i8* %vl, i8** %vl.addr, align 2 %0 = bitcast i8** %vl2 to i8* %1 = bitcast i8** %vl.addr to i8* -; CHECK-DAG: mov.w r12, 0(r1) +; CHECK-DAG: mov r12, 0(r1) call void @llvm.va_copy(i8* %0, i8* %1) ret void } Index: test/MC/Disassembler/MSP430/lit.local.cfg =================================================================== --- /dev/null +++ test/MC/Disassembler/MSP430/lit.local.cfg @@ -0,0 +1,3 @@ +if not 'MSP430' in config.root.targets: + config.unsupported = True + Index: test/MC/Disassembler/MSP430/msp430.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/MSP430/msp430.txt @@ -0,0 +1,27 @@ +# RUN: llvm-mc -disassemble %s -triple=msp430 | FileCheck %s +0x0f 0x47 # CHECK: mov r7, r15 +0x2f 0x48 # CHECK: mov @r8, r15 +0x3f 0x48 # CHECK: mov @r8+, r15 +0x0f 0x43 # CHECK: clr r15 +0x08 0x57 # CHECK: add r7, r8 +0x28 0x57 # CHECK: add @r7, r8 +0x38 0x57 # CHECK: add @r7+, r8 +0x87 0x12 # CHECK: call r7 +0x00 0x47 # CHECK: br r7 +0x39 0xb2 # CHECK: bit #8, r9 + +0xfe 0x3f # CHECK: jmp $-2 +0xfe 0x23 # CHECK: jne $-2 + +0x3f 0x40 0x2a 0x00 # CHECK: mov #42, r15 +0x1f 0x48 0x2a 0x00 # CHECK: mov 42(r8), r15 +0x1f 0x42 0x2a 0x00 # CHECK: mov &42, r15 +0x1f 0x40 0x2a 0x00 # CHECK: mov 42, r15 +0xb0 0x12 0x81 0x01 # CHECK: call #385 +0x97 0x12 0x06 0x00 # CHECK: call 6(r7) +0xa7 0xb2 0x02 0x00 # CHECK: bit #34, 2(r7) +0xa9 0x57 0x08 0x00 # CHECK: add @r7, 8(r9) +0xb7 0xe7 0xfe 0xff # CHECK: xor @r7+, -2(r7) + +0xbf 0x40 0x2a 0x00 0x0c 0x00 # CHECK: mov #42, 12(r15) +0x9a 0xb9 0x10 0x00 0x08 0x00 # CHECK: bit 16(r9), 8(r10) Index: test/MC/MSP430/addrmode.s =================================================================== --- /dev/null +++ test/MC/MSP430/addrmode.s @@ -0,0 +1,110 @@ +; RUN: llvm-mc -triple msp430 -show-encoding < %s | FileCheck %s + +foo: + mov r8, r15 + mov disp+2(r8), r15 + mov disp+2, r15 + mov &disp+2, r15 + mov @r8, r15 + mov @r8+, r15 + mov #disp+2, r15 + +; CHECK: mov r8, r15 ; encoding: [0x0f,0x48] +; CHECK: mov disp+2(r8), r15 ; encoding: [0x1f,0x48,A,A] +; CHECK: mov disp+2, r15 ; encoding: [0x1f,0x40,A,A] +; CHECK: mov &disp+2, r15 ; encoding: [0x1f,0x42,A,A] +; CHECK: mov @r8, r15 ; encoding: [0x2f,0x48] +; CHECK: mov @r8+, r15 ; encoding: [0x3f,0x48] +; CHECK: mov #disp+2, r15 ; encoding: [0x3f,0x40,A,A] + + mov #42, r15 + mov #42, 12(r15) + mov #42, &disp + mov disp, disp+2 + +; CHECK: mov #42, r15 ; encoding: [0x3f,0x40,0x2a,0x00] +; CHECK: mov #42, 12(r15) ; encoding: [0xbf,0x40,0x2a,0x00,0x0c,0x00] +; CHECK: mov #42, &disp ; encoding: [0xb2,0x40,0x2a,0x00,A,A] +; CHECK: mov disp, disp+2 ; encoding: [0x90,0x40,A,A,B,B] + + add r7, r8 + add 6(r7), r8 + add &disp, r8 + add disp, r8 + add @r9, r8 + add @r9+, r8 + add #42, r8 + +; CHECK: add r7, r8 ; encoding: [0x08,0x57] +; CHECK: add 6(r7), r8 ; encoding: [0x18,0x57,0x06,0x00] +; CHECK: add &disp, r8 ; encoding: [0x18,0x52,A,A] +; CHECK: add disp, r8 ; encoding: [0x18,0x50,A,A] +; CHECK: add @r9, r8 ; encoding: [0x28,0x59] +; CHECK: add @r9+, r8 ; encoding: [0x38,0x59] +; CHECK: add #42, r8 ; encoding: [0x38,0x50,0x2a,0x00] + + add r7, 6(r5) + add 6(r7), 6(r5) + add &disp, 6(r5) + add disp, 6(r5) + add @r9, 6(r5) + add @r9+, 6(r5) + add #42, 6(r5) + +; CHECK: add r7, 6(r5) ; encoding: [0x85,0x57,0x06,0x00] +; CHECK: add 6(r7), 6(r5) ; encoding: [0x95,0x57,0x06,0x00,0x06,0x00] +; CHECK: add &disp, 6(r5) ; encoding: [0x95,0x52,A,A,0x06,0x00] +; CHECK: add disp, 6(r5) ; encoding: [0x95,0x50,A,A,0x06,0x00] +; CHECK: add @r9, 6(r5) ; encoding: [0xa5,0x59,0x06,0x00] +; CHECK: add @r9+, 6(r5) ; encoding: [0xb5,0x59,0x06,0x00] +; CHECK: add #42, 6(r5) ; encoding: [0xb5,0x50,0x2a,0x00,0x06,0x00] + + add r7, &disp + add 6(r7), &disp + add &disp, &disp + add disp, &disp + add @r9, &disp + add @r9+, &disp + add #42, &disp + +; CHECK: add r7, &disp ; encoding: [0x82,0x57,A,A] +; CHECK: add 6(r7), &disp ; encoding: [0x92,0x57,0x06,0x00,A,A] +; CHECK: add &disp, &disp ; encoding: [0x92,0x52,A,A,B,B] +; CHECK: add disp, &disp ; encoding: [0x92,0x50,A,A,B,B] +; CHECK: add @r9, &disp ; encoding: [0xa2,0x59,A,A] +; CHECK: add @r9+, &disp ; encoding: [0xb2,0x59,A,A] +; CHECK: add #42, &disp ; encoding: [0xb2,0x50,0x2a,0x00,A,A] + + add r7, disp + add 6(r7), disp + add &disp, disp + add disp, disp + add @r9, disp + add @r9+, disp + add #42, disp + +; CHECK: add r7, disp ; encoding: [0x80,0x57,A,A] +; CHECK: add 6(r7), disp ; encoding: [0x90,0x57,0x06,0x00,A,A] +; CHECK: add &disp, disp ; encoding: [0x90,0x52,A,A,B,B] +; CHECK: add disp, disp ; encoding: [0x90,0x50,A,A,B,B] +; CHECK: add @r9, disp ; encoding: [0xa0,0x59,A,A] +; CHECK: add @r9+, disp ; encoding: [0xb0,0x59,A,A] +; CHECK: add #42, disp ; encoding: [0xb0,0x50,0x2a,0x00,A,A] + + call r7 + call 6(r7) + call disp+6(r7) + call &disp + call disp + call #disp + +; CHECK: call r7 ; encoding: [0x87,0x12] +; CHECK: call 6(r7) ; encoding: [0x97,0x12,0x06,0x00] +; CHECK: call disp+6(r7) ; encoding: [0x97,0x12,A,A] +; CHECK: call &disp ; encoding: [0x92,0x12,A,A] +; CHECK: call disp ; encoding: [0x90,0x12,A,A] +; CHECK: call #disp ; encoding: [0xb0,0x12,A,A] + +disp: + .word 0xcafe + .word 0xbabe Index: test/MC/MSP430/altreg.s =================================================================== --- /dev/null +++ test/MC/MSP430/altreg.s @@ -0,0 +1,7 @@ +; RUN: llvm-mc -triple msp430 -show-encoding < %s | FileCheck %s + mov pc, r0 ; CHECK: mov r0, r0 + mov sp, r1 ; CHECK: mov r1, r1 + mov sr, r2 ; CHECK: mov r2, r2 + mov cg, r3 ; CHECK: mov r3, r3 + mov fp, r4 ; CHECK: mov r4, r4 + bic #8, SR ; CHECK: dint Index: test/MC/MSP430/const.s =================================================================== --- /dev/null +++ test/MC/MSP430/const.s @@ -0,0 +1,10 @@ +; RUN: llvm-mc -triple msp430 -show-encoding < %s | FileCheck %s + mov #4, r15 ; CHECK: mov #4, r15 ; encoding: [0x2f,0x42] + mov #8, r15 ; CHECK: mov #8, r15 ; encoding: [0x3f,0x42] + mov #0, r15 ; CHECK: clr r15 ; encoding: [0x0f,0x43] + mov #1, r15 ; CHECK: mov #1, r15 ; encoding: [0x1f,0x43] + mov #2, r15 ; CHECK: mov #2, r15 ; encoding: [0x2f,0x43] + mov #-1, r7 ; CHECK: mov #-1, r7 ; encoding: [0x37,0x43] + + push #8 ; CHECK: push #8 ; encoding: [0x32,0x12] + push #42 ; CHECK: push #42 ; encoding: [0x30,0x12,0x2a,0x00] Index: test/MC/MSP430/invalid.s =================================================================== --- /dev/null +++ test/MC/MSP430/invalid.s @@ -0,0 +1,19 @@ +; RUN: not llvm-mc -triple msp430 < %s 2>&1 | FileCheck %s +foo: + ;; invalid operand count + mov r7 ; CHECK: :[[@LINE]]:3: error: too few operands for instruction + + ;; invalid destination addressing modes + mov r7, @r15 ; CHECK: :[[@LINE]]:14: error: invalid operand for instruction + mov r7, @r15+ ; CHECK: :[[@LINE]]:14: error: invalid operand for instruction + mov r7, #0 ; CHECK: :[[@LINE]]:14: error: invalid operand for instruction + mov r7, #123 ; CHECK: :[[@LINE]]:14: error: invalid operand for instruction + + ;; invalid byte instructions + swpb.b r7 ; CHECK: :[[@LINE]]:3: error: invalid instruction mnemonic + sxt.b r7 ; CHECK: :[[@LINE]]:3: error: invalid instruction mnemonic + call.b r7 ; CHECK: :[[@LINE]]:3: error: invalid instruction mnemonic + + ;; invalid conditional jump offsets + jmp -513 ; CHECK: :[[@LINE]]:10: error: invalid jump offset + jmp 512 ; CHECK: :[[@LINE]]:10: error: invalid jump offset Index: test/MC/MSP430/lit.local.cfg =================================================================== --- /dev/null +++ test/MC/MSP430/lit.local.cfg @@ -0,0 +1,3 @@ +if not 'MSP430' in config.root.targets: + config.unsupported = True + Index: test/MC/MSP430/opcode.s =================================================================== --- /dev/null +++ test/MC/MSP430/opcode.s @@ -0,0 +1,163 @@ +; RUN: llvm-mc -triple msp430 -show-encoding %s \ +; RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s + +; RUN: llvm-mc -triple msp430 -filetype=obj %s \ +; RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INST %s + + ;; IForm8 instructions + mov.b r7, r8 ; CHECK-INST: mov.b r7, r8 + ; CHECK: encoding: [0x48,0x47] + add.b r7, r8 ; CHECK-INST: add.b r7, r8 + ; CHECK: encoding: [0x48,0x57] + addc.b r7, r8 ; CHECK-INST: addc.b r7, r8 + ; CHECK: encoding: [0x48,0x67] + subc.b r7, r8 ; CHECK-INST: subc.b r7, r8 + ; CHECK: encoding: [0x48,0x77] + sub.b r7, r8 ; CHECK-INST: sub.b r7, r8 + ; CHECK: encoding: [0x48,0x87] + cmp.b r7, r8 ; CHECK-INST: cmp.b r7, r8 + ; CHECK: encoding: [0x48,0x97] + dadd.b r7, r8 ; CHECK-INST: dadd.b r7, r8 + ; CHECK: encoding: [0x48,0xa7] + bit.b r7, r8 ; CHECK-INST: bit.b r7, r8 + ; CHECK: encoding: [0x48,0xb7] + bic.b r7, r8 ; CHECK-INST: bic.b r7, r8 + ; CHECK: encoding: [0x48,0xc7] + bis.b r7, r8 ; CHECK-INST: bis.b r7, r8 + ; CHECK: encoding: [0x48,0xd7] + xor.b r7, r8 ; CHECK-INST: xor.b r7, r8 + ; CHECK: encoding: [0x48,0xe7] + and.b r7, r8 ; CHECK-INST: and.b r7, r8 + ; CHECK: encoding: [0x48,0xf7] + + ;; IForm16 instructions + mov r7, r8 ; CHECK-INST: mov r7, r8 + ; CHECK: encoding: [0x08,0x47] + add r7, r8 ; CHECK-INST: add r7, r8 + ; CHECK: encoding: [0x08,0x57] + addc r7, r8 ; CHECK-INST: addc r7, r8 + ; CHECK: encoding: [0x08,0x67] + subc r7, r8 ; CHECK-INST: subc r7, r8 + ; CHECK: encoding: [0x08,0x77] + sub r7, r8 ; CHECK-INST: sub r7, r8 + ; CHECK: encoding: [0x08,0x87] + cmp r7, r8 ; CHECK-INST: cmp r7, r8 + ; CHECK: encoding: [0x08,0x97] + dadd r7, r8 ; CHECK-INST: dadd r7, r8 + ; CHECK: encoding: [0x08,0xa7] + bit r7, r8 ; CHECK-INST: bit r7, r8 + ; CHECK: encoding: [0x08,0xb7] + bic r7, r8 ; CHECK-INST: bic r7, r8 + ; CHECK: encoding: [0x08,0xc7] + bis r7, r8 ; CHECK-INST: bis r7, r8 + ; CHECK: encoding: [0x08,0xd7] + xor r7, r8 ; CHECK-INST: xor r7, r8 + ; CHECK: encoding: [0x08,0xe7] + and r7, r8 ; CHECK-INST: and r7, r8 + ; CHECK: encoding: [0x08,0xf7] + + ;; IIForm8 instructions + rrc.b r7 ; CHECK-INST: rrc.b r7 + ; CHECK: encoding: [0x47,0x10] + rra.b r7 ; CHECK-INST: rra.b r7 + ; CHECK: encoding: [0x47,0x11] + push.b r7 ; CHECK-INST: push.b r7 + ; CHECK: encoding: [0x47,0x12] + + ;; IIForm16 instructions + rrc r7 ; CHECK-INST: rrc r7 + ; CHECK: encoding: [0x07,0x10] + swpb r7 ; CHECK-INST: swpb r7 + ; CHECK: encoding: [0x87,0x10] + rra r7 ; CHECK-INST: rra r7 + ; CHECK: encoding: [0x07,0x11] + sxt r7 ; CHECK-INST: sxt r7 + ; CHECK: encoding: [0x87,0x11] + push r7 ; CHECK-INST: push r7 + ; CHECK: encoding: [0x07,0x12] + call r7 ; CHECK-INST: call r7 + ; CHECK: encoding: [0x87,0x12] + reti ; CHECK-INST: reti + ; CHECK: encoding: [0x00,0x13] + + ;; CJForm instructions + jnz -2 ; CHECK-INST: jne $-2 + ; CHECK: encoding: [0xfe,0x23] + jne -2 ; CHECK-INST: jne $-2 + ; CHECK: encoding: [0xfe,0x23] + jeq -2 ; CHECK-INST: jeq $-2 + ; CHECK: encoding: [0xfe,0x27] + jz -2 ; CHECK-INST: jeq $-2 + ; CHECK: encoding: [0xfe,0x27] + jnc -2 ; CHECK-INST: jlo $-2 + ; CHECK: encoding: [0xfe,0x2b] + jlo -2 ; CHECK-INST: jlo $-2 + ; CHECK: encoding: [0xfe,0x2b] + jc -2 ; CHECK-INST: jhs $-2 + ; CHECK: encoding: [0xfe,0x2f] + jhs -2 ; CHECK-INST: jhs $-2 + ; CHECK: encoding: [0xfe,0x2f] + jn -2 ; CHECK-INST: jn $-2 + ; CHECK: encoding: [0xfe,0x33] + jge -2 ; CHECK-INST: jge $-2 + ; CHECK: encoding: [0xfe,0x37] + jl -2 ; CHECK-INST: jl $-2 + ; CHECK: encoding: [0xfe,0x3b] + jmp $-2 ; CHECK-INST: jmp $-2 + ; CHECK: encoding: [0xfe,0x3f] + + ;; Emulated arithmetic instructions + adc r7 ; CHECK-INST: adc r7 + ; CHECK: encoding: [0x07,0x63] + dadc r7 ; CHECK-INST: dadc r7 + ; CHECK: encoding: [0x07,0xa3] + dec r7 ; CHECK-INST: dec r7 + ; CHECK: encoding: [0x17,0x83] + decd r7 ; CHECK-INST: decd r7 + ; CHECK: encoding: [0x27,0x83] + inc r7 ; CHECK-INST: inc r7 + ; CHECK: encoding: [0x17,0x53] + incd r7 ; CHECK-INST: incd r7 + ; CHECK: encoding: [0x27,0x53] + sbc r7 ; CHECK-INST: sbc r7 + ; CHECK: encoding: [0x07,0x73] + + ;; Emulated logical instructions + inv r7 ; CHECK-INST: inv r7 + ; CHECK: encoding: [0x37,0xe3] + rla r7 ; CHECK-INST: add r7, r7 + ; CHECK: encoding: [0x07,0x57] + rlc r7 ; CHECK-INST: addc r7, r7 + ; CHECK: encoding: [0x07,0x67] + + ;; Emulated program flow control instructions + br r7 ; CHECK-INST: br r7 + ; CHECK: encoding: [0x00,0x47] + dint ; CHECK-INST: dint + ; CHECK: encoding: [0x32,0xc2] + eint ; CHECK-INST: eint + ; CHECK: encoding: [0x32,0xd2] + nop ; CHECK-INST: nop + ; CHECK: encoding: [0x03,0x43] + ret ; CHECK-INST: ret + ; CHECK: encoding: [0x30,0x41] + + ;; Emulated data instruction + clr r7 ; CHECK-INST: clr r7 + ; CHECK: encoding: [0x07,0x43] + clrc ; CHECK-INST: clrc + ; CHECK: encoding: [0x12,0xc3] + clrn ; CHECK-INST: clrn + ; CHECK: encoding: [0x22,0xc2] + clrz ; CHECK-INST: clrz + ; CHECK: encoding: [0x22,0xc3] + pop r7 ; CHECK-INST: pop r7 + ; CHECK: encoding: [0x37,0x41] + setc ; CHECK-INST: setc + ; CHECK: encoding: [0x12,0xd3] + setn ; CHECK-INST: setn + ; CHECK: encoding: [0x22,0xd2] + setz ; CHECK-INST: setz + ; CHECK: encoding: [0x22,0xd3] + tst r7 ; CHECK-INST: tst r7 + ; CHECK: encoding: [0x07,0x93] Index: test/MC/MSP430/reloc.s =================================================================== --- /dev/null +++ test/MC/MSP430/reloc.s @@ -0,0 +1,22 @@ +; RUN: llvm-mc -triple msp430 -show-encoding < %s | FileCheck %s + + mov disp+2(r8), r15 +; CHECK: mov disp+2(r8), r15 ; encoding: [0x1f,0x48,A,A] +; CHECK: ; fixup A - offset: 2, value: disp+2, kind: fixup_16_byte + + mov disp+2, r15 +; CHECK: mov disp+2, r15 ; encoding: [0x1f,0x40,A,A] +; CHECK: ; fixup A - offset: 2, value: disp+2, kind: fixup_16_pcrel_byte + + mov &disp+2, r15 +; CHECK: mov &disp+2, r15 ; encoding: [0x1f,0x42,A,A] +; CHECK: ; fixup A - offset: 2, value: disp+2, kind: fixup_16 + + mov disp, disp+2 +; CHECK: mov disp, disp+2 ; encoding: [0x90,0x40,A,A,B,B] +; CHECK: ; fixup A - offset: 2, value: disp, kind: fixup_16_pcrel_byte +; CHECK: ; fixup B - offset: 4, value: disp+2, kind: fixup_16_pcrel_byte + + jmp foo +; CHECK: jmp foo ; encoding: [A,0b001111AA] +; CHECK: ; fixup A - offset: 0, value: foo, kind: fixup_10_pcrel