llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-msp430 Author: Robin Mueller (robamu) <details> <summary>Changes</summary> - Add RRCM, RRAM, RRUM, RLAM, RRCX, RRAX, RRUX and RLAX for -mcpu=msp430x - Encode extended instructions with the extension word in the low bits, matching their order in memory - Disassemble MSP430X address instructions and extension words - Report an error for instructions that need a disabled CPU feature. They were silently dropped before Based on https://reviews.llvm.org/D110723, reworked for current TableGen. Co-authored-by: Jozef Lawrynowicz <jozefl.opensrc@<!-- -->gmail.com> Assisted-by: Claude Opus 5.5 <noreply@<!-- -->anthropic.com> --- Patch is 34.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/231910.diff 21 Files Affected: - (modified) clang/lib/Basic/Targets/MSP430.cpp (+2) - (modified) clang/lib/Basic/Targets/MSP430.h (+17-1) - (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+3) - (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+11-12) - (modified) clang/lib/Driver/ToolChains/MSP430.cpp (+18) - (modified) clang/lib/Driver/ToolChains/MSP430.h (+2) - (added) clang/test/Driver/msp430-cpu.c (+25) - (modified) clang/test/Driver/msp430-toolchain.c (+28) - (added) clang/test/Preprocessor/msp430-defs.c (+9) - (modified) llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp (+17-4) - (modified) llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp (+54-2) - (modified) llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp (+18) - (modified) llvm/lib/Target/MSP430/MSP430InstrFormats.td (+95) - (modified) llvm/lib/Target/MSP430/MSP430InstrInfo.td (+9) - (added) llvm/lib/Target/MSP430/MSP430InstrInfoExtended.td (+84) - (modified) llvm/lib/Target/MSP430/MSP430Subtarget.h (+2) - (added) llvm/test/MC/Disassembler/MSP430/msp430x-invalid.txt (+13) - (added) llvm/test/MC/Disassembler/MSP430/msp430x.txt (+18) - (added) llvm/test/MC/MSP430/msp430x-feature.s (+9) - (added) llvm/test/MC/MSP430/shifts-430x-invalid.s (+23) - (added) llvm/test/MC/MSP430/shifts-430x.s (+101) ``````````diff diff --git a/clang/lib/Basic/Targets/MSP430.cpp b/clang/lib/Basic/Targets/MSP430.cpp index 844f5d3af70379..989927a8c5ab69 100644 --- a/clang/lib/Basic/Targets/MSP430.cpp +++ b/clang/lib/Basic/Targets/MSP430.cpp @@ -29,5 +29,7 @@ void MSP430TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("MSP430"); Builder.defineMacro("__MSP430__"); + if (CPU == "msp430x") + Builder.defineMacro("__MSP430X__"); // FIXME: defines for different 'flavours' of MCU } diff --git a/clang/lib/Basic/Targets/MSP430.h b/clang/lib/Basic/Targets/MSP430.h index 96a243ef70fae5..fceb7c6e68e201 100644 --- a/clang/lib/Basic/Targets/MSP430.h +++ b/clang/lib/Basic/Targets/MSP430.h @@ -23,6 +23,7 @@ namespace targets { class LLVM_LIBRARY_VISIBILITY MSP430TargetInfo : public TargetInfo { static const char *const GCCRegNames[]; + std::string CPU; public: MSP430TargetInfo(const llvm::Triple &Triple, const TargetOptions &) @@ -55,10 +56,25 @@ class LLVM_LIBRARY_VISIBILITY MSP430TargetInfo : public TargetInfo { return {}; } + bool isValidCPUName(StringRef Name) const override { + return Name == "msp430" || Name == "msp430x"; + } + + void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override { + Values.append({"msp430", "msp430x"}); + } + + bool setCPU(StringRef Name) override { + if (!isValidCPUName(Name)) + return false; + CPU = Name; + return true; + } + bool allowsLargerPreferedTypeAlignment() const override { return false; } bool hasFeature(StringRef Feature) const override { - return Feature == "msp430"; + return Feature == "msp430" || (Feature == "msp430x" && CPU == "msp430x"); } ArrayRef<const char *> getGCCRegNames() const override; diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 39dcec2f823bdd..08ae8329433452 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -810,6 +810,9 @@ std::string tools::getCPUName(const Driver &D, const ArgList &Args, return std::string(CPUName); } + case llvm::Triple::msp430: + return msp430::getMSP430TargetCPU(Args); + case llvm::Triple::nvptx: case llvm::Triple::nvptx64: if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 90fc71c147364d..0a58b251d0e693 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -1529,20 +1529,19 @@ static bool findMSP430Multilibs(const Driver &D, StringRef Path, const ArgList &Args, DetectedMultilibs &Result) { FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); - MultilibBuilder WithoutExceptions = - MultilibBuilder("/430").flag("-exceptions", /*Disallow=*/true); - MultilibBuilder WithExceptions = - MultilibBuilder("/430/exceptions").flag("-exceptions"); - - // FIXME: when clang starts to support msp430x ISA additional logic - // to select between multilib must be implemented - // MultilibBuilder MSP430xMultilib = MultilibBuilder("/large"); - - Result.Multilibs.push_back(WithoutExceptions.makeMultilib()); - Result.Multilibs.push_back(WithExceptions.makeMultilib()); - Result.Multilibs.FilterOut(NonExistent); + // The MSP430X libraries are in the root, the plain MSP430 ones in /430. + // FIXME: Add the /large multilibs once LLVM supports the large memory model. + Result.Multilibs = + MultilibSetBuilder() + .Either(MultilibBuilder().flag("-msp430x"), + MultilibBuilder("/430").flag("-msp430x", /*Disallow=*/true)) + .Maybe(MultilibBuilder("/exceptions").flag("-exceptions")) + .makeMultilibSet() + .FilterOut(NonExistent); Multilib::flags_list Flags; + std::string CPU = tools::getCPUName(D, Args, TargetTriple); + addMultilibFlag(CPU == "msp430x", "-msp430x", Flags); addMultilibFlag(Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, false), "-exceptions", Flags); diff --git a/clang/lib/Driver/ToolChains/MSP430.cpp b/clang/lib/Driver/ToolChains/MSP430.cpp index 4bd12d1e130e53..5259e0721bdb26 100644 --- a/clang/lib/Driver/ToolChains/MSP430.cpp +++ b/clang/lib/Driver/ToolChains/MSP430.cpp @@ -13,6 +13,7 @@ #include "clang/Driver/InputInfo.h" #include "clang/Driver/Multilib.h" #include "clang/Options/Options.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/Path.h" @@ -52,6 +53,23 @@ static StringRef getHWMultLib(const ArgList &Args) { .Default("-lmul_none"); } +static bool isMSP430X(StringRef CPU) { + return CPU == "msp430x" || CPU == "msp430xv2"; +} + +std::string msp430::getMSP430TargetCPU(const ArgList &Args) { + if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) + return isMSP430X(A->getValue()) ? "msp430x" : A->getValue(); + if (const Arg *A = Args.getLastArg(options::OPT_mmcu_EQ)) { + StringRef CPU = llvm::StringSwitch<StringRef>(A->getValue()) +#define MSP430_MCU(NAME, CPU, HWMULT) .Case(NAME, CPU) +#include "clang/Basic/MSP430Target.def" + .Default(""); + return isMSP430X(CPU) ? "msp430x" : CPU.str(); + } + return ""; +} + void msp430::getMSP430TargetFeatures(const Driver &D, const ArgList &Args, std::vector<StringRef> &Features) { const Arg *MCU = Args.getLastArg(options::OPT_mmcu_EQ); diff --git a/clang/lib/Driver/ToolChains/MSP430.h b/clang/lib/Driver/ToolChains/MSP430.h index 865bcfb7cd3da6..3539c62430f675 100644 --- a/clang/lib/Driver/ToolChains/MSP430.h +++ b/clang/lib/Driver/ToolChains/MSP430.h @@ -80,6 +80,8 @@ class LLVM_LIBRARY_VISIBILITY Linker final : public Tool { void getMSP430TargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, std::vector<llvm::StringRef> &Features); +std::string getMSP430TargetCPU(const llvm::opt::ArgList &Args); + } // end namespace msp430 } // end namespace tools } // end namespace driver diff --git a/clang/test/Driver/msp430-cpu.c b/clang/test/Driver/msp430-cpu.c new file mode 100644 index 00000000000000..d09272436f5700 --- /dev/null +++ b/clang/test/Driver/msp430-cpu.c @@ -0,0 +1,25 @@ +// RUN: %clang -### -c %s --target=msp430 2>&1 \ +// RUN: | FileCheck -check-prefix=NO-CPU %s +// NO-CPU-NOT: "-target-cpu" + +// RUN: %clang -### -c %s --target=msp430 -mcpu=msp430 2>&1 \ +// RUN: | FileCheck -check-prefix=MSP430 %s +// RUN: %clang -### -c %s --target=msp430 -mmcu=msp430c111 2>&1 \ +// RUN: | FileCheck -check-prefix=MSP430 %s +// MSP430: "-cc1"{{.*}} "-target-cpu" "msp430" + +// msp430xv2 is accepted for GCC compatibility and treated as msp430x. +// RUN: %clang -### -c %s --target=msp430 -mcpu=msp430x 2>&1 \ +// RUN: | FileCheck -check-prefix=MSP430X %s +// RUN: %clang -### -c %s --target=msp430 -mcpu=msp430xv2 2>&1 \ +// RUN: | FileCheck -check-prefix=MSP430X %s +// RUN: %clang -### -c %s --target=msp430 -mmcu=msp430f2617 2>&1 \ +// RUN: | FileCheck -check-prefix=MSP430X %s +// RUN: %clang -### -c %s --target=msp430 -mmcu=msp430f5529 2>&1 \ +// RUN: | FileCheck -check-prefix=MSP430X %s +// MSP430X: "-cc1"{{.*}} "-target-cpu" "msp430x" + +// RUN: not %clang -c %s --target=msp430 -mcpu=not-a-cpu -o /dev/null 2>&1 \ +// RUN: | FileCheck -check-prefix=INVALID %s +// INVALID: error: unknown target CPU 'not-a-cpu' +// INVALID-NEXT: note: valid target CPU values are: msp430, msp430x diff --git a/clang/test/Driver/msp430-toolchain.c b/clang/test/Driver/msp430-toolchain.c index 45010deb40a54d..45de069b0aafe9 100644 --- a/clang/test/Driver/msp430-toolchain.c +++ b/clang/test/Driver/msp430-toolchain.c @@ -126,6 +126,34 @@ // LIBS-EXC-NEG-NOT: "{{.*}}/430" // LIBS-EXC-NEG-NOT: "{{.*}}430/crt{{.*}}" +// The MSP430X multilibs are in the root, not in /430. +// RUN: %clang -### %s --target=msp430 -mcpu=msp430x -rtlib=libgcc \ +// RUN: --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 +// RUN: FileCheck -check-prefix=LIBS-430X-POS %s < %t +// RUN: FileCheck -check-prefix=LIBS-430X-NEG %s < %t +// RUN: %clang -### %s --target=msp430 -mmcu=msp430f5529 -rtlib=libgcc \ +// RUN: --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 +// RUN: FileCheck -check-prefix=LIBS-430X-POS %s < %t +// RUN: FileCheck -check-prefix=LIBS-430X-NEG %s < %t +// LIBS-430X-POS: "{{.*}}/Inputs/basic_msp430_tree{{/|\\\\}}msp430-elf{{/|\\\\}}lib{{/|\\\\}}crt0.o" +// LIBS-430X-POS: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1{{/|\\\\}}crtbegin_no_eh.o" +// LIBS-430X-POS: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1{{/|\\\\}}" +// LIBS-430X-POS: "-L{{.*}}/Inputs/basic_msp430_tree{{/|\\\\}}msp430-elf{{/|\\\\}}lib{{/|\\\\}}" +// LIBS-430X-POS: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1{{/|\\\\}}crtend_no_eh.o" +// LIBS-430X-NEG-NOT: /430 +// LIBS-430X-NEG-NOT: /exceptions + +// RUN: %clang -### %s --target=msp430 -mcpu=msp430x -rtlib=libgcc -fexceptions \ +// RUN: --sysroot="%S/Inputs/basic_msp430_tree" > %t 2>&1 +// RUN: FileCheck -check-prefix=LIBS-430X-EXC-POS %s < %t +// RUN: FileCheck -check-prefix=LIBS-430X-EXC-NEG %s < %t +// LIBS-430X-EXC-POS: "{{.*}}/Inputs/basic_msp430_tree{{/|\\\\}}msp430-elf{{/|\\\\}}lib/exceptions{{/|\\\\}}crt0.o" +// LIBS-430X-EXC-POS: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1/exceptions{{/|\\\\}}crtbegin.o" +// LIBS-430X-EXC-POS: "-L{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1/exceptions" +// LIBS-430X-EXC-POS: "-L{{.*}}/Inputs/basic_msp430_tree{{/|\\\\}}msp430-elf{{/|\\\\}}lib/exceptions" +// LIBS-430X-EXC-POS: "{{.*}}/Inputs/basic_msp430_tree/lib/gcc/msp430-elf/8.3.1/exceptions{{/|\\\\}}crtend.o" +// LIBS-430X-EXC-NEG-NOT: /430 + // RUN: %clang -### %s --target=msp430 -rtlib=libgcc \ // RUN: -fstack-protector --sysroot="%S/Inputs/basic_msp430_tree" 2>&1 \ // RUN: | FileCheck -check-prefix=LIBS-SSP %s diff --git a/clang/test/Preprocessor/msp430-defs.c b/clang/test/Preprocessor/msp430-defs.c new file mode 100644 index 00000000000000..6eea5c6e7521cc --- /dev/null +++ b/clang/test/Preprocessor/msp430-defs.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple msp430 -E -dM %s -o - \ +// RUN: | FileCheck -check-prefix=MSP430 %s +// RUN: %clang_cc1 -triple msp430 -target-cpu msp430 -E -dM %s -o - \ +// RUN: | FileCheck -check-prefix=MSP430 %s +// MSP430-NOT: #define __MSP430X__ + +// RUN: %clang_cc1 -triple msp430 -target-cpu msp430x -E -dM %s -o - \ +// RUN: | FileCheck -check-prefix=MSP430X %s +// MSP430X: #define __MSP430X__ 1 diff --git a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp index 847ca9b6297042..d21e1cb024d907 100644 --- a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp +++ b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp @@ -162,11 +162,8 @@ class MSP430Operand : public MCParsedAsmOperand { bool isPostIndReg() const { return Kind == k_PostIndReg; } bool isCGImm() const { - if (Kind != k_Imm) - return false; - int64_t Val; - if (!Imm->evaluateAsAbsolute(Val)) + if (!isImm() || !Imm->evaluateAsAbsolute(Val)) return false; if (Val == 0 || Val == 1 || Val == 2 || Val == 4 || Val == 8 || Val == -1) @@ -175,6 +172,19 @@ class MSP430Operand : public MCParsedAsmOperand { return false; } + /// Shift count of the MSP430X multi-bit shifts (RRAM, RRUM, RLAM). It is + /// encoded as count - 1 in a 2-bit field, so only 1 to 4 is valid. + bool isRpt2Imm() const { + int64_t Val; + if (!isImm() || !Imm->evaluateAsAbsolute(Val)) + return false; + + if (Val >= 1 && Val <= 4) + return true; + + return false; + } + StringRef getToken() const { assert(Kind == k_Tok && "Invalid access!"); return Tok; @@ -265,6 +275,9 @@ bool MSP430AsmParser::matchAndEmitInstruction(SMLoc Loc, unsigned &Opcode, return false; case Match_MnemonicFail: return Error(Loc, "invalid instruction mnemonic"); + case Match_MissingFeature: + return Error(Loc, + "instruction requires a CPU feature not currently enabled"); case Match_InvalidOperand: { SMLoc ErrorLoc = Loc; if (ErrorInfo != ~0U) { diff --git a/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp b/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp index e6666e8cafdf9d..3f473bc1504801 100644 --- a/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp +++ b/llvm/lib/Target/MSP430/Disassembler/MSP430Disassembler.cpp @@ -44,6 +44,10 @@ class MSP430Disassembler : public MCDisassembler { ArrayRef<uint8_t> Bytes, uint64_t Address, raw_ostream &CStream) const; + DecodeStatus getInstructionX(MCInst &MI, uint64_t &Size, + ArrayRef<uint8_t> Bytes, uint64_t Address, + raw_ostream &CStream) const; + public: MSP430Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx) : MCDisassembler(STI, Ctx) {} @@ -119,6 +123,15 @@ static DecodeStatus DecodeCGImm(MCInst &MI, uint64_t Bits, uint64_t Address, return MCDisassembler::Success; } +/// Decode the 2-bit shift count of RRCM, RRAM, RRUM and RLAM. It is stored as +/// count - 1. +static DecodeStatus decodeRpt2Imm(MCInst &MI, uint64_t Bits, uint64_t Address, + const MCDisassembler *Decoder) { + int64_t Imm = Bits + 1; + MI.addOperand(MCOperand::createImm(Imm)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeMemOperand(MCInst &MI, uint64_t Bits, uint64_t Address, const MCDisassembler *Decoder) { @@ -353,6 +366,37 @@ DecodeStatus MSP430Disassembler::getInstructionCJ(MCInst &MI, uint64_t &Size, return DecodeStatus::Success; } +static bool isExtensionWord(uint64_t Word) { return (Word & 0xf800) == 0x1800; } + +DecodeStatus MSP430Disassembler::getInstructionX(MCInst &MI, uint64_t &Size, + ArrayRef<uint8_t> Bytes, + uint64_t Address, + raw_ostream &CStream) const { + uint64_t Insn = support::endian::read16le(Bytes.data()); + unsigned Words = 1; + if (isExtensionWord(Insn)) { + if (Bytes.size() < 4) { + Size = 2; + return DecodeStatus::Fail; + } + Insn |= (uint64_t)support::endian::read16le(Bytes.data() + 2) << 16; + Words = 2; + } + + // MSP430X32 decodes the extension word together with the following Format I + // or II word. Each combination is its own instruction, like RRCX_16 or + // ADDX16rr, so the plain Format I and II tables are not used here. + const uint8_t *DecoderTable = + Words == 2 ? DecoderTableMSP430X32 : DecoderTableMSP430X16; + DecodeStatus Result = + decodeInstruction(DecoderTable, MI, Insn, Address, this, STI); + // The word after an extension word is a valid Format I or II instruction on + // its own. Skip it on failure too, so it is not shown without the extension + // word. + Size = Words * 2; + return Result; +} + DecodeStatus MSP430Disassembler::getInstruction(MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, @@ -362,10 +406,18 @@ DecodeStatus MSP430Disassembler::getInstruction(MCInst &MI, uint64_t &Size, return MCDisassembler::Fail; } + // The first word selects the instruction format: + // 0x0000-0x0fff MSP430X address instructions + // 0x1000-0x17ff Format II + // 0x1800-0x1fff MSP430X extension word, followed by a Format I or II word + // 0x2000-0x3fff Jumps + // 0x4000-0xffff Format I uint64_t Insn = support::endian::read16le(Bytes.data()); - unsigned Opc = fieldFromInstruction(Insn, 13, 3); - switch (Opc) { + unsigned FormatBits = fieldFromInstruction(Insn, 13, 3); + switch (FormatBits) { case 0: + if (!(Insn & 0x1000) || isExtensionWord(Insn)) + return getInstructionX(MI, Size, Bytes, Address, CStream); return getInstructionII(MI, Size, Bytes, Address, CStream); case 1: return getInstructionCJ(MI, Size, Bytes, Address, CStream); diff --git a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp index f018bdbeb0bfbc..0436434658049e 100644 --- a/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp +++ b/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp @@ -64,6 +64,12 @@ class MSP430MCCodeEmitter : public MCCodeEmitter { SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + /// Encode the repetition count for a 430X extended format exception + /// instruction. + unsigned getRpt2ImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getCCOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; @@ -192,6 +198,18 @@ unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op, } } +unsigned +MSP430MCCodeEmitter::getRpt2ImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(Op); + assert(MO.isImm() && "expr operand expected"); + + int64_t Imm = MO.getImm(); + assert((Imm >= 1 && Imm <= 4) && "invalid repetition count"); + return Imm - 1; +} + unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { diff --git a/llvm/lib/Target/MSP430/MSP430InstrFormats.td b/llvm/lib/Target/MSP430/MSP430InstrFormats.td index 0e784aa4ff9144..f850100cd2eddc 100644 --- a/llvm/lib/Target/MSP430/MSP430InstrFormats.td +++ b/llvm/lib/Target/MSP430/MSP430InstrFormats.td @@ -28,6 +28,13 @@ class DestMode<bit val> { def DstReg : DestMode<0>; // r def DstMem : DestMode<1>; // m +class ALKind<bit val> { + bit Value = val; +} + +def ALAddr : ALKind<0>; +def ALWord : ALKind<1>; + // Generic MSP430 Format class MSP430Inst<dag outs, dag ins, int size, string asmstr> : Instruction { field bits<48> Inst; @@ -432,6 +439,94 @@ class CJForm<dag outs, dag ins, string asmstr, list<dag> pattern> let Inst{9-0} = dst; } +// RRCM, RRAM, RRUM and RLAM. Single-word MSP430X instructions with their own +// layout in the Format II opcode space, without an extension word. TI calls +// them Format II exceptions. +class IIExtExcRotForm<bits<2> opcode, ALKind al, + dag outs, dag ins, string asmstr, list<dag> pattern> + : MSP430Inst<outs, ins, 2, asmstr> { + let Pattern = pattern; + let DecoderNamespace = "MSP430X"; + + bits<4> rd; + bits<2> cnt; + + let Inst{15-12} = 0b0000; + let Inst{11-10} = cnt; + let Inst{9-8} = opcode; + let Inst{7-5} = 0b010; + let Inst{4} = al.Value; + let Inst{3-0} = rd; +} + +class IIExtExcRotForm16<bits<2> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIExtExcRotForm<opcode, ALWord, outs, ins, asmstr, pattern>; + +// MSP430X extended instructions in register mode. +// +// The extension word precedes the instruction word in memory, so it occupies +// Inst{15-0} and the instruction word is in Inst{31-16}. +// +// FIXME: Add the non-register mode, which is needed for 20-bit memory +// operands. +class ExtRegForm<bit zc, bit rpt, ALKind al, + dag outs, dag ins, string asmstr, list<dag> pattern> + : MSP430Inst<outs, ins, 4, asmstr> { + let Pattern = pattern; + let DecoderNamespace = "MSP430X"; + + bits<4> cnt = 0; + + let Inst{15-9} = 0b0001100; + let Inst{8} = zc; + let Inst{7} = rpt; + let Inst{6} = al.Value; + let Inst{5-4} = 0b00; ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/231910 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
