[llvm] 8dddc15 - [M68k](4/8) MC layer and object file support
Min-Yih Hsu via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 8 12:33:48 PST 2021
Author: Min-Yih Hsu
Date: 2021-03-08T12:30:57-08:00
New Revision: 8dddc15297f1101f7e312dd0fd9cd57246dbc8bb
URL: https://github.com/llvm/llvm-project/commit/8dddc15297f1101f7e312dd0fd9cd57246dbc8bb
DIFF: https://github.com/llvm/llvm-project/commit/8dddc15297f1101f7e312dd0fd9cd57246dbc8bb.diff
LOG: [M68k](4/8) MC layer and object file support
- Add the M68k-specific MC layer implementation
- Add ELF support for M68k
- Add M68k-specifc CC and reloc
TODO: Currently AsmParser and disassembler are not implemented yet.
Please use this bug to track the status:
https://bugs.llvm.org/show_bug.cgi?id=48976
Authors: myhsu, m4yers, glaubitz
Differential Revision: https://reviews.llvm.org/D88390
Added:
llvm/include/llvm/BinaryFormat/ELFRelocs/M68k.def
llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h
llvm/lib/Target/M68k/MCTargetDesc/M68kELFObjectWriter.cpp
llvm/lib/Target/M68k/MCTargetDesc/M68kFixupKinds.h
llvm/lib/Target/M68k/MCTargetDesc/M68kInstPrinter.cpp
llvm/lib/Target/M68k/MCTargetDesc/M68kInstPrinter.h
llvm/lib/Target/M68k/MCTargetDesc/M68kMCAsmInfo.cpp
llvm/lib/Target/M68k/MCTargetDesc/M68kMCAsmInfo.h
llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp
llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.h
Modified:
llvm/include/llvm/BinaryFormat/ELF.h
llvm/include/llvm/IR/CallingConv.h
llvm/include/llvm/Object/ELFObjectFile.h
llvm/include/llvm/module.modulemap
llvm/lib/Object/ELF.cpp
llvm/lib/ObjectYAML/ELFYAML.cpp
llvm/lib/Target/M68k/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.cpp
llvm/lib/Target/M68k/TargetInfo/M68kTargetInfo.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 4a04877b9ac9..30209a59ca89 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -756,6 +756,11 @@ enum {
#include "ELFRelocs/BPF.def"
};
+// ELF Relocation types for M68k
+enum {
+#include "ELFRelocs/M68k.def"
+};
+
// MSP430 specific e_flags
enum : unsigned {
EF_MSP430_MACH_MSP430x11 = 11,
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/M68k.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/M68k.def
new file mode 100644
index 000000000000..11f148566c78
--- /dev/null
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/M68k.def
@@ -0,0 +1,49 @@
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_68K_NONE, 0) /* No reloc */
+ELF_RELOC(R_68K_32, 1) /* Direct 32 bit */
+ELF_RELOC(R_68K_16, 2) /* Direct 16 bit */
+ELF_RELOC(R_68K_8, 3) /* Direct 8 bit */
+ELF_RELOC(R_68K_PC32, 4) /* PC relative 32 bit */
+ELF_RELOC(R_68K_PC16, 5) /* PC relative 16 bit */
+ELF_RELOC(R_68K_PC8, 6) /* PC relative 8 bit */
+ELF_RELOC(R_68K_GOTPCREL32, 7) /* 32 bit PC relative GOT entry */
+ELF_RELOC(R_68K_GOTPCREL16, 8) /* 16 bit PC relative GOT entry */
+ELF_RELOC(R_68K_GOTPCREL8, 9) /* 8 bit PC relative GOT entry */
+ELF_RELOC(R_68K_GOTOFF32, 10) /* 32 bit GOT offset */
+ELF_RELOC(R_68K_GOTOFF16, 11) /* 16 bit GOT offset */
+ELF_RELOC(R_68K_GOTOFF8, 12) /* 8 bit GOT offset */
+ELF_RELOC(R_68K_PLT32, 13) /* 32 bit PC relative PLT address */
+ELF_RELOC(R_68K_PLT16, 14) /* 16 bit PC relative PLT address */
+ELF_RELOC(R_68K_PLT8, 15) /* 8 bit PC relative PLT address */
+ELF_RELOC(R_68K_PLTOFF32, 16) /* 32 bit PLT offset */
+ELF_RELOC(R_68K_PLTOFF16, 17) /* 16 bit PLT offset */
+ELF_RELOC(R_68K_PLTOFF8, 18) /* 8 bit PLT offset */
+ELF_RELOC(R_68K_COPY, 19) /* Copy symbol at runtime */
+ELF_RELOC(R_68K_GLOB_DAT, 20) /* Create GOT entry */
+ELF_RELOC(R_68K_JMP_SLOT, 21) /* Create PLT entry */
+ELF_RELOC(R_68K_RELATIVE, 22) /* Adjust by program base */
+/* These are GNU extensions to enable C++ vtable garbage collection. */
+ELF_RELOC(R_68K_GNU_VTINHERIT, 23)
+ELF_RELOC(R_68K_GNU_VTENTRY, 24)
+/* TLS static relocations. */
+ELF_RELOC(R_68K_TLS_GD32, 25)
+ELF_RELOC(R_68K_TLS_GD16, 26)
+ELF_RELOC(R_68K_TLS_GD8, 27)
+ELF_RELOC(R_68K_TLS_LDM32, 28)
+ELF_RELOC(R_68K_TLS_LDM16, 29)
+ELF_RELOC(R_68K_TLS_LDM8, 30)
+ELF_RELOC(R_68K_TLS_LDO32, 31)
+ELF_RELOC(R_68K_TLS_LDO16, 32)
+ELF_RELOC(R_68K_TLS_LDO8, 33)
+ELF_RELOC(R_68K_TLS_IE32, 34)
+ELF_RELOC(R_68K_TLS_IE16, 35)
+ELF_RELOC(R_68K_TLS_IE8, 36)
+ELF_RELOC(R_68K_TLS_LE32, 37)
+ELF_RELOC(R_68K_TLS_LE16, 38)
+ELF_RELOC(R_68K_TLS_LE8, 39)
+ELF_RELOC(R_68K_TLS_DTPMOD32, 40)
+ELF_RELOC(R_68K_TLS_DTPREL32, 41)
+ELF_RELOC(R_68K_TLS_TPREL32, 42)
diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h
index 6a4e368b2e9d..ec7d18129a10 100644
--- a/llvm/include/llvm/IR/CallingConv.h
+++ b/llvm/include/llvm/IR/CallingConv.h
@@ -244,6 +244,9 @@ namespace CallingConv {
/// Calling convention used for AMD graphics targets.
AMDGPU_Gfx = 100,
+ /// M68k_INTR - Calling convention used for M68k interrupt routines.
+ M68k_INTR = 101,
+
/// The highest possible calling convention ID. Must be some 2^k - 1.
MaxID = 1023
};
diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index 0999d4b25d2d..fd93ed42b812 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -1141,6 +1141,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
switch (EF.getHeader().e_ident[ELF::EI_CLASS]) {
case ELF::ELFCLASS32:
switch (EF.getHeader().e_machine) {
+ case ELF::EM_68K:
+ return "elf32-m68k";
case ELF::EM_386:
return "elf32-i386";
case ELF::EM_IAMCU:
@@ -1209,6 +1211,8 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const {
bool IsLittleEndian = ELFT::TargetEndianness == support::little;
switch (EF.getHeader().e_machine) {
+ case ELF::EM_68K:
+ return Triple::m68k;
case ELF::EM_386:
case ELF::EM_IAMCU:
return Triple::x86;
diff --git a/llvm/include/llvm/module.modulemap b/llvm/include/llvm/module.modulemap
index f6bbbd09728a..848fb266374e 100644
--- a/llvm/include/llvm/module.modulemap
+++ b/llvm/include/llvm/module.modulemap
@@ -70,6 +70,7 @@ module LLVM_BinaryFormat {
textual header "BinaryFormat/ELFRelocs/Hexagon.def"
textual header "BinaryFormat/ELFRelocs/i386.def"
textual header "BinaryFormat/ELFRelocs/Lanai.def"
+ textual header "BinaryFormat/ELFRelocs/M68k.def"
textual header "BinaryFormat/ELFRelocs/Mips.def"
textual header "BinaryFormat/ELFRelocs/MSP430.def"
textual header "BinaryFormat/ELFRelocs/PowerPC64.def"
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index 27a35bbd759d..ffeec3112b7e 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -22,6 +22,13 @@ using namespace object;
StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine,
uint32_t Type) {
switch (Machine) {
+ case ELF::EM_68K:
+ switch (Type) {
+#include "llvm/BinaryFormat/ELFRelocs/M68k.def"
+ default:
+ break;
+ }
+ break;
case ELF::EM_X86_64:
switch (Type) {
#include "llvm/BinaryFormat/ELFRelocs/x86_64.def"
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index f4bdba1aa272..1ae09647593c 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -787,6 +787,9 @@ void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration(
case ELF::EM_PPC64:
#include "llvm/BinaryFormat/ELFRelocs/PowerPC64.def"
break;
+ case ELF::EM_68K:
+#include "llvm/BinaryFormat/ELFRelocs/M68k.def"
+ break;
default:
// Nothing to do.
break;
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/M68k/MCTargetDesc/CMakeLists.txt
index dadb6919d928..acd8be9b25fc 100644
--- a/llvm/lib/Target/M68k/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/M68k/MCTargetDesc/CMakeLists.txt
@@ -1,4 +1,9 @@
add_llvm_component_library(LLVMM68kDesc
+ M68kAsmBackend.cpp
+ M68kELFObjectWriter.cpp
+ M68kInstPrinter.cpp
+ M68kMCAsmInfo.cpp
+ M68kMCCodeEmitter.cpp
M68kMCTargetDesc.cpp
LINK_COMPONENTS
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
new file mode 100644
index 000000000000..f15d0d18edaa
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kAsmBackend.cpp
@@ -0,0 +1,242 @@
+//===-- M68kAsmBackend.cpp - M68k Assembler Backend ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains definitions for M68k assembler backend.
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/M68kBaseInfo.h"
+#include "MCTargetDesc/M68kFixupKinds.h"
+
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionCOFF.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+
+class M68kAsmBackend : public MCAsmBackend {
+
+public:
+ M68kAsmBackend(const Target &T) : MCAsmBackend(support::big) {}
+
+ unsigned getNumFixupKinds() const override { return 0; }
+
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
+ uint64_t Value, bool IsResolved,
+ const MCSubtargetInfo *STI) const override {
+ unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
+
+ assert(Fixup.getOffset() + Size <= Data.size() && "Invalid fixup offset!");
+
+ // Check that uppper bits are either all zeros or all ones.
+ // Specifically ignore overflow/underflow as long as the leakage is
+ // limited to the lower bits. This is to remain compatible with
+ // other assemblers.
+ assert(isIntN(Size * 8 + 1, Value) &&
+ "Value does not fit in the Fixup field");
+
+ // Write in Big Endian
+ for (unsigned i = 0; i != Size; ++i)
+ Data[Fixup.getOffset() + i] = uint8_t(Value >> ((Size - i - 1) * 8));
+ }
+
+ bool mayNeedRelaxation(const MCInst &Inst,
+ const MCSubtargetInfo &STI) const override;
+
+ bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout) const override;
+
+ void relaxInstruction(MCInst &Inst,
+ const MCSubtargetInfo &STI) const override;
+
+ /// Returns the minimum size of a nop in bytes on this target. The assembler
+ /// will use this to emit excess padding in situations where the padding
+ /// required for simple alignment would be less than the minimum nop size.
+ unsigned getMinimumNopSize() const override { return 2; }
+
+ /// Write a sequence of optimal nops to the output, covering \p Count bytes.
+ /// \return - true on success, false on failure
+ bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
+};
+} // end anonymous namespace
+
+/// cc—Carry clear GE—Greater than or equal
+/// LS—Lower or same PL—Plus
+/// CS—Carry set GT—Greater than
+/// LT—Less than
+/// EQ—Equal HI—Higher
+/// MI—Minus VC—Overflow clear
+/// LE—Less than or equal
+/// NE—Not equal VS—Overflow set
+static unsigned getRelaxedOpcodeBranch(const MCInst &Inst) {
+ unsigned Op = Inst.getOpcode();
+ switch (Op) {
+ default:
+ return Op;
+ case M68k::BRA8:
+ return M68k::BRA16;
+ case M68k::Bcc8:
+ return M68k::Bcc16;
+ case M68k::Bls8:
+ return M68k::Bls16;
+ case M68k::Blt8:
+ return M68k::Blt16;
+ case M68k::Beq8:
+ return M68k::Beq16;
+ case M68k::Bmi8:
+ return M68k::Bmi16;
+ case M68k::Bne8:
+ return M68k::Bne16;
+ case M68k::Bge8:
+ return M68k::Bge16;
+ case M68k::Bcs8:
+ return M68k::Bcs16;
+ case M68k::Bpl8:
+ return M68k::Bpl16;
+ case M68k::Bgt8:
+ return M68k::Bgt16;
+ case M68k::Bhi8:
+ return M68k::Bhi16;
+ case M68k::Bvc8:
+ return M68k::Bvc16;
+ case M68k::Ble8:
+ return M68k::Ble16;
+ case M68k::Bvs8:
+ return M68k::Bvs16;
+ }
+}
+
+static unsigned getRelaxedOpcodeArith(const MCInst &Inst) {
+ unsigned Op = Inst.getOpcode();
+ switch (Op) {
+ default:
+ return Op;
+ // NOTE there will be some relaxations for PCD and ARD mem for x20
+ }
+}
+
+static unsigned getRelaxedOpcode(const MCInst &Inst) {
+ unsigned R = getRelaxedOpcodeArith(Inst);
+ if (R != Inst.getOpcode())
+ return R;
+ return getRelaxedOpcodeBranch(Inst);
+}
+
+bool M68kAsmBackend::mayNeedRelaxation(const MCInst &Inst,
+ const MCSubtargetInfo &STI) const {
+ // Branches can always be relaxed in either mode.
+ if (getRelaxedOpcodeBranch(Inst) != Inst.getOpcode())
+ return true;
+
+ // Check if this instruction is ever relaxable.
+ if (getRelaxedOpcodeArith(Inst) == Inst.getOpcode())
+ return false;
+
+ // Check if the relaxable operand has an expression. For the current set of
+ // relaxable instructions, the relaxable operand is always the last operand.
+ // NOTE will change for x20 mem
+ unsigned RelaxableOp = Inst.getNumOperands() - 1;
+ if (Inst.getOperand(RelaxableOp).isExpr())
+ return true;
+
+ return false;
+}
+
+bool M68kAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout) const {
+ // TODO Newer CPU can use 32 bit offsets, so check for this when ready
+ if (!isInt<16>(Value)) {
+ llvm_unreachable("Cannot relax the instruction, value does not fit");
+ }
+ // Relax if the value is too big for a (signed) i8. This means that byte-wide
+ // instructions have to matched by default
+ //
+ // NOTE
+ // A branch to the immediately following instruction automatically
+ // uses the 16-bit displacement format because the 8-bit
+ // displacement field contains $00 (zero offset).
+ return Value == 0 || !isInt<8>(Value);
+}
+
+// NOTE Can tblgen help at all here to verify there aren't other instructions
+// we can relax?
+void M68kAsmBackend::relaxInstruction(MCInst &Inst,
+ const MCSubtargetInfo &STI) const {
+ // The only relaxations M68k does is from a 1byte pcrel to a 2byte PCRel.
+ unsigned RelaxedOp = getRelaxedOpcode(Inst);
+
+ if (RelaxedOp == Inst.getOpcode()) {
+ SmallString<256> Tmp;
+ raw_svector_ostream OS(Tmp);
+ Inst.dump_pretty(OS);
+ OS << "\n";
+ report_fatal_error("unexpected instruction to relax: " + OS.str());
+ }
+
+ Inst.setOpcode(RelaxedOp);
+}
+
+bool M68kAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
+ // Cannot emit NOP with size being not multiple of 16 bits.
+ if (Count % 2 != 0)
+ return false;
+
+ uint64_t NumNops = Count / 2;
+ for (uint64_t i = 0; i != NumNops; ++i) {
+ OS << "\x4E\x71";
+ }
+
+ return true;
+}
+
+namespace {
+
+class M68kELFAsmBackend : public M68kAsmBackend {
+public:
+ uint8_t OSABI;
+ M68kELFAsmBackend(const Target &T, uint8_t OSABI)
+ : M68kAsmBackend(T), OSABI(OSABI) {}
+
+ std::unique_ptr<MCObjectTargetWriter>
+ createObjectTargetWriter() const override {
+ return createM68kELFObjectWriter(OSABI);
+ }
+};
+
+} // end anonymous namespace
+
+MCAsmBackend *llvm::createM68kAsmBackend(const Target &T,
+ const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options) {
+ const Triple &TheTriple = STI.getTargetTriple();
+ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
+ return new M68kELFAsmBackend(T, OSABI);
+}
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h b/llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h
new file mode 100644
index 000000000000..36592fda1a96
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kBaseInfo.h
@@ -0,0 +1,247 @@
+//===-- M68kBaseInfo.h - Top level definitions for M68k MC --*- C++ -*-----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains small standalone helper functions and enum definitions
+/// for the M68k target useful for the compiler back-end and the MC
+/// libraries. As such, it deliberately does not include references to LLVM
+/// core code gen types, passes, etc..
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KBASEINFO_H
+#define LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KBASEINFO_H
+
+#include "M68kMCTargetDesc.h"
+
+#include "llvm/MC/MCExpr.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#define GET_INSTRINFO_MI_OPS_INFO
+#define GET_INSTRINFO_OPERAND_TYPES_ENUM
+#define GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP
+#include "M68kGenInstrInfo.inc"
+
+namespace llvm {
+
+namespace M68k {
+
+/// Enums for memory operand decoding. Supports these forms:
+/// (d,An)
+/// (d,An,Xn)
+/// ([bd,An],Xn,od)
+/// ([bd,An,Xn],od)
+/// TODO Implement scaling other than 1
+enum { MemDisp = 0, MemBase = 1, MemIndex = 2, MemOuter = 3 };
+
+/// Enums for pc-relative memory operand decoding. Supports these forms:
+/// (d,PC)
+/// (d,PC,Xn)
+/// ([bd,PC],Xn,od)
+/// ([bd,PC,Xn],od)
+enum { PCRelDisp = 0, PCRelIndex = 1, PCRelOuter = 2 };
+} // namespace M68k
+
+namespace M68kBeads {
+enum {
+ Ctrl = 0x0,
+ Bits1 = 0x1,
+ Bits2 = 0x2,
+ Bits3 = 0x3,
+ Bits4 = 0x4,
+ DAReg = 0x5,
+ DA = 0x6,
+ Reg = 0x7,
+ Disp8 = 0x8,
+ Imm8 = 0x9,
+ Imm16 = 0xA,
+ Imm32 = 0xB,
+ Imm3 = 0xC,
+};
+
+// Ctrl payload
+enum {
+ Term = 0x0,
+ Ignore = 0x1,
+};
+} // namespace M68kBeads
+
+/// This namespace holds all of the target specific flags that instruction info
+/// tracks.
+namespace M68kII {
+/// Target Operand Flag enum.
+enum TOF {
+
+ MO_NO_FLAG,
+
+ /// On a symbol operand this indicates that the immediate is the absolute
+ /// address of the symbol.
+ MO_ABSOLUTE_ADDRESS,
+
+ /// On a symbol operand this indicates that the immediate is the pc-relative
+ /// address of the symbol.
+ MO_PC_RELATIVE_ADDRESS,
+
+ /// On a symbol operand this indicates that the immediate is the offset to
+ /// the GOT entry for the symbol name from the base of the GOT.
+ ///
+ /// name at GOT
+ MO_GOT,
+
+ /// On a symbol operand this indicates that the immediate is the offset to
+ /// the location of the symbol name from the base of the GOT.
+ ///
+ /// name at GOTOFF
+ MO_GOTOFF,
+
+ /// On a symbol operand this indicates that the immediate is offset to the
+ /// GOT entry for the symbol name from the current code location.
+ ///
+ /// name at GOTPCREL
+ MO_GOTPCREL,
+
+ /// On a symbol operand this indicates that the immediate is offset to the
+ /// PLT entry of symbol name from the current code location.
+ ///
+ /// name at PLT
+ MO_PLT,
+}; // enum TOF
+
+/// Return true if the specified TargetFlag operand is a reference to a stub
+/// for a global, not the global itself.
+inline static bool isGlobalStubReference(unsigned char TargetFlag) {
+ switch (TargetFlag) {
+ default:
+ return false;
+ case M68kII::MO_GOTPCREL: // pc-relative GOT reference.
+ case M68kII::MO_GOT: // normal GOT reference.
+ return true;
+ }
+}
+
+/// Return True if the specified GlobalValue is a direct reference for a
+/// symbol.
+inline static bool isDirectGlobalReference(unsigned char Flag) {
+ switch (Flag) {
+ default:
+ return false;
+ case M68kII::MO_NO_FLAG:
+ case M68kII::MO_ABSOLUTE_ADDRESS:
+ case M68kII::MO_PC_RELATIVE_ADDRESS:
+ return true;
+ }
+}
+
+/// Return true if the specified global value reference is relative to a 32-bit
+/// PIC base (M68kISD::GLOBAL_BASE_REG). If this is true, the addressing mode
+/// has the PIC base register added in.
+inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
+ switch (TargetFlag) {
+ default:
+ return false;
+ case M68kII::MO_GOTOFF: // isPICStyleGOT: local global.
+ case M68kII::MO_GOT: // isPICStyleGOT: other global.
+ return true;
+ }
+}
+
+/// Return True if the specified GlobalValue requires PC addressing mode.
+inline static bool isPCRelGlobalReference(unsigned char Flag) {
+ switch (Flag) {
+ default:
+ return false;
+ case M68kII::MO_GOTPCREL:
+ case M68kII::MO_PC_RELATIVE_ADDRESS:
+ return true;
+ }
+}
+
+/// Return True if the Block is referenced using PC
+inline static bool isPCRelBlockReference(unsigned char Flag) {
+ switch (Flag) {
+ default:
+ return false;
+ case M68kII::MO_PC_RELATIVE_ADDRESS:
+ return true;
+ }
+}
+
+static inline bool isAddressRegister(unsigned RegNo) {
+ switch (RegNo) {
+ case M68k::WA0:
+ case M68k::WA1:
+ case M68k::WA2:
+ case M68k::WA3:
+ case M68k::WA4:
+ case M68k::WA5:
+ case M68k::WA6:
+ case M68k::WA7:
+ case M68k::A0:
+ case M68k::A1:
+ case M68k::A2:
+ case M68k::A3:
+ case M68k::A4:
+ case M68k::A5:
+ case M68k::A6:
+ case M68k::A7:
+ case M68k::SP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool hasMultiMIOperands(unsigned Op, unsigned LogicalOpIdx) {
+ return M68k::getLogicalOperandSize(Op, LogicalOpIdx) > 1;
+}
+
+static inline unsigned getMaskedSpillRegister(unsigned order) {
+ switch (order) {
+ default:
+ return 0;
+ case 0:
+ return M68k::D0;
+ case 1:
+ return M68k::D1;
+ case 2:
+ return M68k::D2;
+ case 3:
+ return M68k::D3;
+ case 4:
+ return M68k::D4;
+ case 5:
+ return M68k::D5;
+ case 6:
+ return M68k::D6;
+ case 7:
+ return M68k::D7;
+ case 8:
+ return M68k::A0;
+ case 9:
+ return M68k::A1;
+ case 10:
+ return M68k::A2;
+ case 11:
+ return M68k::A3;
+ case 12:
+ return M68k::A4;
+ case 13:
+ return M68k::A5;
+ case 14:
+ return M68k::A6;
+ case 15:
+ return M68k::A7;
+ }
+}
+
+} // namespace M68kII
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kELFObjectWriter.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kELFObjectWriter.cpp
new file mode 100644
index 000000000000..4c9a3297424d
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kELFObjectWriter.cpp
@@ -0,0 +1,120 @@
+//===---------- M68kELFObjectWriter.cpp - M68k ELF Writer ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains definitions for M68k ELF Writers
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/M68kFixupKinds.h"
+#include "MCTargetDesc/M68kMCTargetDesc.h"
+
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+namespace {
+class M68kELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+ M68kELFObjectWriter(uint8_t OSABI);
+
+ ~M68kELFObjectWriter() override;
+
+protected:
+ unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup, bool IsPCRel) const override;
+};
+} // namespace
+
+M68kELFObjectWriter::M68kELFObjectWriter(uint8_t OSABI)
+ : MCELFObjectTargetWriter(false, OSABI, ELF::EM_68K, /* RELA */ true) {}
+
+M68kELFObjectWriter::~M68kELFObjectWriter() {}
+
+enum M68kRelType { RT_32, RT_16, RT_8 };
+
+static M68kRelType
+getType(unsigned Kind, MCSymbolRefExpr::VariantKind &Modifier, bool &IsPCRel) {
+ switch (Kind) {
+ case FK_Data_4:
+ case FK_PCRel_4:
+ return RT_32;
+ case FK_PCRel_2:
+ case FK_Data_2:
+ return RT_16;
+ case FK_PCRel_1:
+ case FK_Data_1:
+ return RT_8;
+ }
+ llvm_unreachable("Unimplemented");
+}
+
+unsigned M68kELFObjectWriter::getRelocType(MCContext &Ctx,
+ const MCValue &Target,
+ const MCFixup &Fixup,
+ bool IsPCRel) const {
+ MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
+ unsigned Kind = Fixup.getKind();
+ M68kRelType Type = getType(Kind, Modifier, IsPCRel);
+ switch (Modifier) {
+ default:
+ llvm_unreachable("Unimplemented");
+ case MCSymbolRefExpr::VK_None:
+ switch (Type) {
+ case RT_32:
+ return IsPCRel ? ELF::R_68K_PC32 : ELF::R_68K_32;
+ case RT_16:
+ return IsPCRel ? ELF::R_68K_PC16 : ELF::R_68K_16;
+ case RT_8:
+ return IsPCRel ? ELF::R_68K_PC8 : ELF::R_68K_8;
+ }
+ llvm_unreachable("Unrecognized size");
+ case MCSymbolRefExpr::VK_GOTPCREL:
+ switch (Type) {
+ case RT_32:
+ return ELF::R_68K_GOTPCREL32;
+ case RT_16:
+ return ELF::R_68K_GOTPCREL16;
+ case RT_8:
+ return ELF::R_68K_GOTPCREL8;
+ }
+ llvm_unreachable("Unrecognized size");
+ case MCSymbolRefExpr::VK_GOTOFF:
+ assert(!IsPCRel);
+ switch (Type) {
+ case RT_32:
+ return ELF::R_68K_GOTOFF32;
+ case RT_16:
+ return ELF::R_68K_GOTOFF16;
+ case RT_8:
+ return ELF::R_68K_GOTOFF8;
+ }
+ llvm_unreachable("Unrecognized size");
+ case MCSymbolRefExpr::VK_PLT:
+ switch (Type) {
+ case RT_32:
+ return ELF::R_68K_PLT32;
+ case RT_16:
+ return ELF::R_68K_PLT16;
+ case RT_8:
+ return ELF::R_68K_PLT8;
+ }
+ llvm_unreachable("Unrecognized size");
+ }
+}
+
+std::unique_ptr<MCObjectTargetWriter>
+llvm::createM68kELFObjectWriter(uint8_t OSABI) {
+ return std::make_unique<M68kELFObjectWriter>(OSABI);
+}
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kFixupKinds.h b/llvm/lib/Target/M68k/MCTargetDesc/M68kFixupKinds.h
new file mode 100644
index 000000000000..2b760dec9e41
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kFixupKinds.h
@@ -0,0 +1,54 @@
+//===-- M68kFixupKinds.h - M68k Specific Fixup Entries ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains M68k specific fixup entries.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_M68k_MCTARGETDESC_M68kFIXUPKINDS_H
+#define LLVM_LIB_TARGET_M68k_MCTARGETDESC_M68kFIXUPKINDS_H
+
+#include "llvm/MC/MCFixup.h"
+
+namespace llvm {
+static inline unsigned getFixupKindLog2Size(unsigned Kind) {
+ switch (Kind) {
+ case FK_PCRel_1:
+ case FK_SecRel_1:
+ case FK_Data_1:
+ return 0;
+ case FK_PCRel_2:
+ case FK_SecRel_2:
+ case FK_Data_2:
+ return 1;
+ case FK_PCRel_4:
+ case FK_SecRel_4:
+ case FK_Data_4:
+ return 2;
+ }
+ llvm_unreachable("invalid fixup kind!");
+}
+
+static inline MCFixupKind getFixupForSize(unsigned Size, bool isPCRel) {
+ switch (Size) {
+ case 8:
+ return isPCRel ? FK_PCRel_1 : FK_Data_1;
+ case 16:
+ return isPCRel ? FK_PCRel_2 : FK_Data_2;
+ case 32:
+ return isPCRel ? FK_PCRel_4 : FK_Data_4;
+ case 64:
+ return isPCRel ? FK_PCRel_8 : FK_Data_8;
+ }
+ llvm_unreachable("Invalid generic fixup size!");
+}
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kInstPrinter.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kInstPrinter.cpp
new file mode 100644
index 000000000000..6667f5678145
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kInstPrinter.cpp
@@ -0,0 +1,217 @@
+//===-- M68kInstPrinter.cpp - Convert M68k MCInst to asm ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains definitions for an M68k MCInst printer.
+///
+//===----------------------------------------------------------------------===//
+
+// TODO Conform with all supported Motorola ASM syntax
+// Motorola's assembly has several syntax variants, especially on
+// addressing modes.
+// For example, you can write pc indirect w/ displacement as
+// `x(%pc)`, where `x` is the displacement imm, or `(x,%pc)`.
+// Currently we're picking the variant that is
diff erent from
+// GCC, albeit being recognizable by GNU AS.
+// Not sure what is the impact now (e.g. some syntax might
+// not be recognized by some old consoles' toolchains, in which
+// case we can not use our integrated assembler), but either way,
+// it will be great to support all of the variants in the future.
+
+#include "M68kInstPrinter.h"
+#include "M68kBaseInfo.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-printer"
+
+#define PRINT_ALIAS_INSTR
+#include "M68kGenAsmWriter.inc"
+
+void M68kInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
+ OS << "%" << getRegisterName(RegNo);
+}
+
+void M68kInstPrinter::printInst(const MCInst *MI, uint64_t Address,
+ StringRef Annot, const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ if (!printAliasInstr(MI, Address, O))
+ printInstruction(MI, Address, O);
+
+ printAnnotation(O, Annot);
+}
+
+void M68kInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ const MCOperand &MO = MI->getOperand(OpNo);
+ if (MO.isReg()) {
+ printRegName(O, MO.getReg());
+ return;
+ }
+
+ if (MO.isImm()) {
+ printImmediate(MI, OpNo, O);
+ return;
+ }
+
+ assert(MO.isExpr() && "Unknown operand kind in printOperand");
+ MO.getExpr()->print(O, &MAI);
+}
+
+void M68kInstPrinter::printImmediate(const MCInst *MI, unsigned opNum,
+ raw_ostream &O) {
+ const MCOperand &MO = MI->getOperand(opNum);
+ if (MO.isImm())
+ O << '#' << MO.getImm();
+ else if (MO.isExpr()) {
+ O << '#';
+ MO.getExpr()->print(O, &MAI);
+ } else
+ llvm_unreachable("Unknown immediate kind");
+}
+
+void M68kInstPrinter::printMoveMask(const MCInst *MI, unsigned opNum,
+ raw_ostream &O) {
+ unsigned Mask = MI->getOperand(opNum).getImm();
+ assert((Mask & 0xFFFF) == Mask && "Mask is always 16 bits");
+
+ // A move mask is splitted into two parts:
+ // bits 0 ~ 7 correspond to D0 ~ D7 regs
+ // bits 8 ~ 15 correspond to A0 ~ A7 regs
+ //
+ // In the assembly syntax, we want to use a dash to replace
+ // a continuous range of registers. For example, if the bit
+ // mask is 0b101110, we want to print "D1-D3,D5" instead of
+ // "D1,D2,D3,D4,D5".
+ //
+ // However, we don't want a dash to cross between data registers
+ // and address registers (i.e. there shouldn't be a dash crossing
+ // bit 7 and 8) since that is not really intuitive. So we simply
+ // print the data register part (bit 0~7) and address register part
+ // separately.
+ uint8_t HalfMask;
+ unsigned Reg;
+ for (int s = 0; s < 16; s += 8) {
+ HalfMask = (Mask >> s) & 0xFF;
+ // Print separation comma only if
+ // both data & register parts have bit(s) set
+ if (s != 0 && (Mask & 0xFF) && HalfMask)
+ O << ',';
+
+ for (int i = 0; HalfMask; ++i) {
+ if ((HalfMask >> i) & 0b1) {
+ HalfMask ^= 0b1 << i;
+ Reg = M68kII::getMaskedSpillRegister(i + s);
+ printRegName(O, Reg);
+
+ int j = i;
+ while ((HalfMask >> (j + 1)) & 0b1)
+ HalfMask ^= 0b1 << ++j;
+
+ if (j != i) {
+ O << '-';
+ Reg = M68kII::getMaskedSpillRegister(j + s);
+ printRegName(O, Reg);
+ }
+
+ i = j;
+
+ if (HalfMask)
+ O << ',';
+ }
+ }
+ }
+}
+
+void M68kInstPrinter::printDisp(const MCInst *MI, unsigned opNum,
+ raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(opNum);
+ if (Op.isImm()) {
+ O << Op.getImm();
+ return;
+ }
+ assert(Op.isExpr() && "Unknown operand kind in printOperand");
+ Op.getExpr()->print(O, &MAI);
+}
+
+void M68kInstPrinter::printARIMem(const MCInst *MI, unsigned opNum,
+ raw_ostream &O) {
+ O << '(';
+ printOperand(MI, opNum, O);
+ O << ')';
+}
+
+void M68kInstPrinter::printARIPIMem(const MCInst *MI, unsigned opNum,
+ raw_ostream &O) {
+ O << "(";
+ printOperand(MI, opNum, O);
+ O << ")+";
+}
+
+void M68kInstPrinter::printARIPDMem(const MCInst *MI, unsigned opNum,
+ raw_ostream &O) {
+ O << "-(";
+ printOperand(MI, opNum, O);
+ O << ")";
+}
+
+void M68kInstPrinter::printARIDMem(const MCInst *MI, unsigned opNum,
+ raw_ostream &O) {
+ O << '(';
+ printDisp(MI, opNum + M68k::MemDisp, O);
+ O << ',';
+ printOperand(MI, opNum + M68k::MemBase, O);
+ O << ')';
+}
+
+void M68kInstPrinter::printARIIMem(const MCInst *MI, unsigned opNum,
+ raw_ostream &O) {
+ O << '(';
+ printDisp(MI, opNum + M68k::MemDisp, O);
+ O << ',';
+ printOperand(MI, opNum + M68k::MemBase, O);
+ O << ',';
+ printOperand(MI, opNum + M68k::MemIndex, O);
+ O << ')';
+}
+
+// NOTE forcing (W,L) size available since M68020 only
+void M68kInstPrinter::printAbsMem(const MCInst *MI, unsigned opNum,
+ raw_ostream &O) {
+ const MCOperand &MO = MI->getOperand(opNum);
+ if (MO.isImm()) {
+ // ??? Print it in hex?
+ O << (unsigned int)MO.getImm();
+ } else {
+ printOperand(MI, opNum, O);
+ }
+}
+
+void M68kInstPrinter::printPCDMem(const MCInst *MI, uint64_t Address,
+ unsigned opNum, raw_ostream &O) {
+ O << '(';
+ printDisp(MI, opNum + M68k::PCRelDisp, O);
+ O << ",%pc)";
+}
+
+void M68kInstPrinter::printPCIMem(const MCInst *MI, uint64_t Address,
+ unsigned opNum, raw_ostream &O) {
+ O << '(';
+ printDisp(MI, opNum + M68k::PCRelDisp, O);
+ O << ",%pc,";
+ printOperand(MI, opNum + M68k::PCRelIndex, O);
+ O << ')';
+}
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kInstPrinter.h b/llvm/lib/Target/M68k/MCTargetDesc/M68kInstPrinter.h
new file mode 100644
index 000000000000..b10449f9ef29
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kInstPrinter.h
@@ -0,0 +1,169 @@
+//===-- M68kInstPrinter.h - Convert M68k MCInst to asm ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains declarations for an M68k MCInst printer.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_M68K_INSTPRINTER_M68KINSTPRINTER_H
+#define LLVM_LIB_TARGET_M68K_INSTPRINTER_M68KINSTPRINTER_H
+
+#include "llvm/MC/MCInstPrinter.h"
+
+namespace llvm {
+
+class TargetMachine;
+
+class M68kInstPrinter : public MCInstPrinter {
+public:
+ M68kInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI)
+ : MCInstPrinter(MAI, MII, MRI) {}
+
+ // Autogenerated by tblgen.
+ void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O);
+ static const char *getRegisterName(unsigned RegNo);
+
+ void printRegName(raw_ostream &OS, unsigned RegNo) const override;
+ void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
+ const MCSubtargetInfo &STI, raw_ostream &O) override;
+
+ bool printAliasInstr(const MCInst *MI, uint64_t Address, raw_ostream &OS);
+ void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
+ unsigned PrintMethodIdx, raw_ostream &O);
+
+ std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;
+
+private:
+ void printOperand(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ void printImmediate(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ /// Print register mask for MOVEM instruction in order D0-D7,A0-A7
+ void printMoveMask(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ /// Print register mask for MOVEM instruction in order A7-A0,D7-D0
+ void printMoveMaskR(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ void printDisp(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ void printARIMem(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ void printARIPIMem(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ void printARIPDMem(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ void printARIDMem(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ void printARIIMem(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ void printAbsMem(const MCInst *MI, unsigned opNum, raw_ostream &O);
+ void printPCDMem(const MCInst *MI, uint64_t Address, unsigned opNum,
+ raw_ostream &O);
+ void printPCIMem(const MCInst *MI, uint64_t Address, unsigned opNum,
+ raw_ostream &O);
+
+ //===----------------------------------------------------------------------===//
+ // Specializations
+ //===----------------------------------------------------------------------===//
+ //
+ void printPCRelImm(const MCInst *MI, uint64_t Address, unsigned opNum,
+ raw_ostream &O) {
+ printOperand(MI, opNum, O);
+ }
+
+ void printARI8Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIMem(MI, opNum, O);
+ }
+ void printARI16Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIMem(MI, opNum, O);
+ }
+ void printARI32Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIMem(MI, opNum, O);
+ }
+
+ void printARIPI8Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIPIMem(MI, opNum, O);
+ }
+ void printARIPI16Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIPIMem(MI, opNum, O);
+ }
+ void printARIPI32Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIPIMem(MI, opNum, O);
+ }
+
+ void printARIPD8Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIPDMem(MI, opNum, O);
+ }
+ void printARIPD16Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIPDMem(MI, opNum, O);
+ }
+ void printARIPD32Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIPDMem(MI, opNum, O);
+ }
+
+ void printARID8Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIDMem(MI, opNum, O);
+ }
+ void printARID16Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIDMem(MI, opNum, O);
+ }
+ void printARID32Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIDMem(MI, opNum, O);
+ }
+
+ void printARII8Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIIMem(MI, opNum, O);
+ }
+ void printARII16Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIIMem(MI, opNum, O);
+ }
+ void printARII32Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printARIIMem(MI, opNum, O);
+ }
+
+ void printAS8Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printAbsMem(MI, opNum, O);
+ }
+ void printAS16Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printAbsMem(MI, opNum, O);
+ }
+ void printAS32Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printAbsMem(MI, opNum, O);
+ }
+
+ void printAL8Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printAbsMem(MI, opNum, O);
+ }
+ void printAL16Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printAbsMem(MI, opNum, O);
+ }
+ void printAL32Mem(const MCInst *MI, unsigned opNum, raw_ostream &O) {
+ printAbsMem(MI, opNum, O);
+ }
+
+ void printPCD8Mem(const MCInst *MI, uint64_t Address, unsigned opNum,
+ raw_ostream &O) {
+ printPCDMem(MI, Address, opNum, O);
+ }
+ void printPCD16Mem(const MCInst *MI, uint64_t Address, unsigned opNum,
+ raw_ostream &O) {
+ printPCDMem(MI, Address, opNum, O);
+ }
+ void printPCD32Mem(const MCInst *MI, uint64_t Address, unsigned opNum,
+ raw_ostream &O) {
+ printPCDMem(MI, Address, opNum, O);
+ }
+
+ void printPCI8Mem(const MCInst *MI, uint64_t Address, unsigned opNum,
+ raw_ostream &O) {
+ printPCIMem(MI, Address, opNum, O);
+ }
+ void printPCI16Mem(const MCInst *MI, uint64_t Address, unsigned opNum,
+ raw_ostream &O) {
+ printPCIMem(MI, Address, opNum, O);
+ }
+ void printPCI32Mem(const MCInst *MI, uint64_t Address, unsigned opNum,
+ raw_ostream &O) {
+ printPCIMem(MI, Address, opNum, O);
+ }
+};
+} // end namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCAsmInfo.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCAsmInfo.cpp
new file mode 100644
index 000000000000..848bd5e1c12e
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCAsmInfo.cpp
@@ -0,0 +1,35 @@
+//===-- M68kMCAsmInfo.cpp - M68k Asm Properties -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the definitions of the M68k MCAsmInfo properties.
+///
+//===----------------------------------------------------------------------===//
+
+#include "M68kMCAsmInfo.h"
+
+#include "llvm/ADT/Triple.h"
+
+using namespace llvm;
+
+void M68kELFMCAsmInfo::anchor() {}
+
+M68kELFMCAsmInfo::M68kELFMCAsmInfo(const Triple &T) {
+ CodePointerSize = 4;
+ CalleeSaveStackSlotSize = 4;
+
+ IsLittleEndian = false;
+
+ // Debug Information
+ SupportsDebugInformation = true;
+
+ // Exceptions handling
+ ExceptionsType = ExceptionHandling::DwarfCFI;
+
+ CommentString = ";";
+}
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCAsmInfo.h b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCAsmInfo.h
new file mode 100644
index 000000000000..b3a58cc61223
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCAsmInfo.h
@@ -0,0 +1,31 @@
+//===-- M68kMCAsmInfo.h - M68k Asm Info --------------------*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the declarations of the M68k MCAsmInfo properties.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KMCASMINFO_H
+#define LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KMCASMINFO_H
+
+#include "llvm/MC/MCAsmInfoELF.h"
+
+namespace llvm {
+class Triple;
+
+class M68kELFMCAsmInfo : public MCAsmInfoELF {
+ void anchor() override;
+
+public:
+ explicit M68kELFMCAsmInfo(const Triple &Triple);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp
new file mode 100644
index 000000000000..2ba4cc8a3e2f
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp
@@ -0,0 +1,396 @@
+//===-- M68kMCCodeEmitter.cpp - Convert M68k code emitter ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains defintions for M68k code emitter.
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/M68kBaseInfo.h"
+#include "MCTargetDesc/M68kFixupKinds.h"
+#include "MCTargetDesc/M68kMCTargetDesc.h"
+
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace M68k {
+// Forward declarations
+const uint8_t *getMCInstrBeads(unsigned);
+} // end namespace M68k
+} // end namespace llvm
+
+using namespace llvm;
+
+#define DEBUG_TYPE "m68k-mccodeemitter"
+
+namespace {
+class M68kMCCodeEmitter : public MCCodeEmitter {
+ M68kMCCodeEmitter(const M68kMCCodeEmitter &) = delete;
+ void operator=(const M68kMCCodeEmitter &) = delete;
+ const MCInstrInfo &MCII;
+ MCContext &Ctx;
+
+public:
+ M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
+ : MCII(mcii), Ctx(ctx) {}
+
+ ~M68kMCCodeEmitter() override {}
+
+ // TableGen'erated function
+ const uint8_t *getGenInstrBeads(const MCInst &MI) const {
+ return M68k::getMCInstrBeads(MI.getOpcode());
+ }
+
+ unsigned encodeBits(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
+ const MCInstrDesc &Desc, uint64_t &Buffer,
+ unsigned Offset, SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ unsigned encodeReg(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
+ const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ unsigned encodeImm(unsigned ThisByte, uint8_t Bead, const MCInst &MI,
+ const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ void encodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const override;
+};
+
+} // end anonymous namespace
+
+unsigned M68kMCCodeEmitter::encodeBits(unsigned ThisByte, uint8_t Bead,
+ const MCInst &MI,
+ const MCInstrDesc &Desc,
+ uint64_t &Buffer, unsigned Offset,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ unsigned Num = 0;
+ switch (Bead & 0xF) {
+ case M68kBeads::Bits1:
+ Num = 1;
+ break;
+ case M68kBeads::Bits2:
+ Num = 2;
+ break;
+ case M68kBeads::Bits3:
+ Num = 3;
+ break;
+ case M68kBeads::Bits4:
+ Num = 4;
+ break;
+ }
+ unsigned char Val = (Bead & 0xF0) >> 4;
+
+ LLVM_DEBUG(dbgs() << "\tEncodeBits"
+ << " Num: " << Num << " Val: 0x");
+ LLVM_DEBUG(dbgs().write_hex(Val) << "\n");
+
+ Buffer |= (Val << Offset);
+
+ return Num;
+}
+
+unsigned M68kMCCodeEmitter::encodeReg(unsigned ThisByte, uint8_t Bead,
+ const MCInst &MI, const MCInstrDesc &Desc,
+ uint64_t &Buffer, unsigned Offset,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ bool DA, Reg;
+ switch (Bead & 0xF) {
+ default:
+ llvm_unreachable("Unrecognized Bead code for register type");
+ case M68kBeads::DAReg:
+ Reg = true;
+ DA = true;
+ break;
+ case M68kBeads::DA:
+ Reg = false;
+ DA = true;
+ break;
+ case M68kBeads::Reg:
+ Reg = true;
+ DA = false;
+ break;
+ }
+
+ unsigned Op = (Bead & 0x70) >> 4;
+ bool Alt = (Bead & 0x80);
+ LLVM_DEBUG(dbgs() << "\tEncodeReg"
+ << " Op: " << Op << ", DA: " << DA << ", Reg: " << Reg
+ << ", Alt: " << Alt << "\n");
+
+ auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
+ bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
+
+ MCOperand MCO;
+ if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
+ if (IsPCRel) {
+ assert(Alt &&
+ "PCRel addresses use Alt bead register encoding by default");
+ MCO = MI.getOperand(MIOpIdx + M68k::PCRelIndex);
+ } else {
+ MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemIndex : M68k::MemBase));
+ }
+ } else {
+ assert(!Alt && "You cannot use Alt register with a simple operand");
+ MCO = MI.getOperand(MIOpIdx);
+ }
+
+ unsigned RegNum = MCO.getReg();
+ auto RI = Ctx.getRegisterInfo();
+
+ unsigned Written = 0;
+ if (Reg) {
+ uint32_t Val = RI->getEncodingValue(RegNum);
+ Buffer |= Val << Offset;
+ Offset += 3;
+ Written += 3;
+ }
+
+ if (DA) {
+ Buffer |= (char)M68kII::isAddressRegister(RegNum) << Offset;
+ Written++;
+ }
+
+ return Written;
+}
+
+static unsigned EmitConstant(uint64_t Val, unsigned Size, unsigned Pad,
+ uint64_t &Buffer, unsigned Offset) {
+ assert(Size + Offset <= 64 && isUIntN(Size, Val) && "Value does not fit");
+
+ // Pad the instruction with zeros if any
+ // FIXME Emit zeros in the padding, since there might be trash in the buffer.
+ Size += Pad;
+
+ // Writing Value in host's endianness
+ Buffer |= Val << Offset;
+ return Size;
+}
+
+unsigned M68kMCCodeEmitter::encodeImm(unsigned ThisByte, uint8_t Bead,
+ const MCInst &MI, const MCInstrDesc &Desc,
+ uint64_t &Buffer, unsigned Offset,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ unsigned ThisWord = ThisByte / 2;
+ unsigned Size = 0;
+ unsigned Pad = 0;
+ unsigned FixOffset = 0;
+ int64_t Addendum = 0;
+ bool NoExpr = false;
+
+ unsigned Type = Bead & 0xF;
+ unsigned Op = (Bead & 0x70) >> 4;
+ bool Alt = (Bead & 0x80);
+
+ auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op);
+ bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
+
+ // The PC value upon instruction reading of a short jump will point to the
+ // next instruction, thus we need to compensate 2 bytes, which is the
diff
+ // between the patch point and the PC.
+ if (IsPCRel && ThisWord == 0)
+ Addendum -= 2;
+
+ switch (Type) {
+ // ??? what happens if it is not byte aligned
+ // ??? is it even possible
+ case M68kBeads::Disp8:
+ Size = 8;
+ Pad = 0;
+ FixOffset = ThisByte + 1;
+ Addendum += 1;
+ break;
+ case M68kBeads::Imm8:
+ Size = 8;
+ Pad = 8;
+ FixOffset = ThisByte;
+ break;
+ case M68kBeads::Imm16:
+ Size = 16;
+ Pad = 0;
+ FixOffset = ThisByte;
+ break;
+ case M68kBeads::Imm32:
+ Size = 32;
+ Pad = 0;
+ FixOffset = ThisByte;
+ break;
+ case M68kBeads::Imm3:
+ Size = 3;
+ Pad = 0;
+ NoExpr = true;
+ break;
+ }
+
+ LLVM_DEBUG(dbgs() << "\tEncodeImm"
+ << " Op: " << Op << ", Size: " << Size << ", Alt: " << Alt
+ << "\n");
+
+ MCOperand MCO;
+ if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) {
+
+ if (IsPCRel) {
+ assert(!Alt && "You cannot use ALT operand with PCRel");
+ MCO = MI.getOperand(MIOpIdx + M68k::PCRelDisp);
+ } else {
+ MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemOuter : M68k::MemDisp));
+ }
+
+ if (MCO.isExpr()) {
+ assert(!NoExpr && "Cannot use expression here");
+ const MCExpr *Expr = MCO.getExpr();
+
+ // This only makes sense for PCRel instructions since PC points to the
+ // extension word and Disp8 for example is right justified and requires
+ // correction. E.g. R_68K_PC32 is calculated as S + A - P, P for Disp8
+ // will be EXTENSION_WORD + 1 thus we need to have A equal to 1 to
+ // compensate.
+ // TODO count extension words
+ if (IsPCRel && Addendum != 0) {
+ Expr = MCBinaryExpr::createAdd(
+ Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
+ }
+
+ Fixups.push_back(MCFixup::create(
+ FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
+ // Write zeros
+ return EmitConstant(0, Size, Pad, Buffer, Offset);
+ }
+
+ } else {
+ MCO = MI.getOperand(MIOpIdx);
+ if (MCO.isExpr()) {
+ assert(!NoExpr && "Cannot use expression here");
+ const MCExpr *Expr = MCO.getExpr();
+
+ if (Addendum != 0) {
+ Expr = MCBinaryExpr::createAdd(
+ Expr, MCConstantExpr::create(Addendum, Ctx), Ctx);
+ }
+
+ Fixups.push_back(MCFixup::create(
+ FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc()));
+ // Write zeros
+ return EmitConstant(0, Size, Pad, Buffer, Offset);
+ }
+ }
+
+ int64_t I = MCO.getImm();
+
+ // Store 8 as 0, thus making range 1-8
+ if (Type == M68kBeads::Imm3 && Alt) {
+ assert(I && "Cannot encode Alt Imm3 zero value");
+ I %= 8;
+ } else {
+ assert(isIntN(Size, I));
+ }
+
+ uint64_t Imm = I;
+
+ // 32 bit Imm requires HI16 first then LO16
+ if (Size == 32) {
+ Offset += EmitConstant((Imm >> 16) & 0xFFFF, 16, Pad, Buffer, Offset);
+ EmitConstant(Imm & 0xFFFF, 16, Pad, Buffer, Offset);
+ return Size;
+ }
+
+ return EmitConstant(Imm & (UINT64_MAX >> (64 - Size)), Size, Pad, Buffer,
+ Offset);
+}
+
+#include "M68kGenMCCodeBeads.inc"
+
+void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ unsigned Opcode = MI.getOpcode();
+ const MCInstrDesc &Desc = MCII.get(Opcode);
+
+ LLVM_DEBUG(dbgs() << "EncodeInstruction: " << MCII.getName(Opcode) << "("
+ << Opcode << ")\n");
+
+ const uint8_t *Beads = getGenInstrBeads(MI);
+ if (!Beads || !*Beads) {
+ llvm_unreachable("*** Instruction does not have Beads defined");
+ }
+
+ uint64_t Buffer = 0;
+ unsigned Offset = 0;
+ unsigned ThisByte = 0;
+
+ for (uint8_t Bead = *Beads; Bead; Bead = *++Beads) {
+ // Check for control beads
+ if (!(Bead & 0xF)) {
+ switch (Bead >> 4) {
+ case M68kBeads::Ignore:
+ continue;
+ }
+ }
+
+ switch (Bead & 0xF) {
+ default:
+ llvm_unreachable("Unknown Bead code");
+ break;
+ case M68kBeads::Bits1:
+ case M68kBeads::Bits2:
+ case M68kBeads::Bits3:
+ case M68kBeads::Bits4:
+ Offset +=
+ encodeBits(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
+ break;
+ case M68kBeads::DAReg:
+ case M68kBeads::DA:
+ case M68kBeads::Reg:
+ Offset +=
+ encodeReg(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
+ break;
+ case M68kBeads::Disp8:
+ case M68kBeads::Imm8:
+ case M68kBeads::Imm16:
+ case M68kBeads::Imm32:
+ case M68kBeads::Imm3:
+ Offset +=
+ encodeImm(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI);
+ break;
+ }
+
+ // Since M68k is Big Endian we need to rotate each instruction word
+ while (Offset / 16) {
+ support::endian::write<uint16_t>(OS, Buffer, support::big);
+ Buffer >>= 16;
+ Offset -= 16;
+ ThisByte += 2;
+ }
+ }
+
+ assert(Offset == 0 && "M68k Instructions are % 2 bytes");
+ assert((ThisByte && !(ThisByte % 2)) && "M68k Instructions are % 2 bytes");
+}
+
+MCCodeEmitter *llvm::createM68kMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCRegisterInfo &MRI,
+ MCContext &Ctx) {
+ return new M68kMCCodeEmitter(MCII, Ctx);
+}
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.cpp
index 7a1fe4580148..0f1bbaffd9da 100644
--- a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.cpp
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.cpp
@@ -11,7 +11,126 @@
///
//===----------------------------------------------------------------------===//
-/// This is just a placeholder to make current
-/// commit buildable. Body of this function will
-/// be filled in later commits
-extern "C" void LLVMInitializeM68kTargetMC() {}
+#include "M68kMCTargetDesc.h"
+
+#include "M68kMCAsmInfo.h"
+
+#include "M68kInstPrinter.h"
+
+#include "llvm/MC/MCELFStreamer.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+#define GET_INSTRINFO_MC_DESC
+#include "M68kGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_MC_DESC
+#include "M68kGenSubtargetInfo.inc"
+
+#define GET_REGINFO_MC_DESC
+#include "M68kGenRegisterInfo.inc"
+
+// TODO Implement feature set parsing logics
+static std::string ParseM68kTriple(const Triple &TT, StringRef CPU) {
+ return "";
+}
+
+static MCInstrInfo *createM68kMCInstrInfo() {
+ MCInstrInfo *X = new MCInstrInfo();
+ InitM68kMCInstrInfo(X); // defined in M68kGenInstrInfo.inc
+ return X;
+}
+
+static MCRegisterInfo *createM68kMCRegisterInfo(const Triple &TT) {
+ MCRegisterInfo *X = new MCRegisterInfo();
+ InitM68kMCRegisterInfo(X, llvm::M68k::A0, 0, 0, llvm::M68k::PC);
+ return X;
+}
+
+static MCSubtargetInfo *createM68kMCSubtargetInfo(const Triple &TT,
+ StringRef CPU, StringRef FS) {
+ std::string ArchFS = ParseM68kTriple(TT, CPU);
+ if (!FS.empty()) {
+ if (!ArchFS.empty()) {
+ ArchFS = (ArchFS + "," + FS).str();
+ } else {
+ ArchFS = FS.str();
+ }
+ }
+ return createM68kMCSubtargetInfoImpl(TT, CPU, /*TuneCPU=*/CPU, ArchFS);
+}
+
+static MCAsmInfo *createM68kMCAsmInfo(const MCRegisterInfo &MRI,
+ const Triple &TT,
+ const MCTargetOptions &TO) {
+ MCAsmInfo *MAI = new M68kELFMCAsmInfo(TT);
+
+ // Initialize initial frame state.
+ // Calculate amount of bytes used for return address storing
+ int StackGrowth = -4;
+
+ // Initial state of the frame pointer is SP+StackGrowth.
+ // TODO: Add tests for `cfi_*` directives
+ MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(
+ nullptr, MRI.getDwarfRegNum(llvm::M68k::SP, true), -StackGrowth);
+ MAI->addInitialFrameState(Inst);
+
+ // Add return address to move list
+ Inst = MCCFIInstruction::createOffset(
+ nullptr, MRI.getDwarfRegNum(M68k::PC, true), StackGrowth);
+ MAI->addInitialFrameState(Inst);
+
+ return MAI;
+}
+
+static MCRelocationInfo *createM68kMCRelocationInfo(const Triple &TheTriple,
+ MCContext &Ctx) {
+ // Default to the stock relocation info.
+ return llvm::createMCRelocationInfo(TheTriple, Ctx);
+}
+
+static MCInstPrinter *createM68kMCInstPrinter(const Triple &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI) {
+ return new M68kInstPrinter(MAI, MII, MRI);
+}
+
+extern "C" void LLVMInitializeM68kTargetMC() {
+ Target &T = TheM68kTarget;
+
+ // Register the MC asm info.
+ RegisterMCAsmInfoFn X(T, createM68kMCAsmInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(T, createM68kMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(T, createM68kMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(T, createM68kMCSubtargetInfo);
+
+ // Register the code emitter.
+ TargetRegistry::RegisterMCCodeEmitter(T, createM68kMCCodeEmitter);
+
+ // Register the MCInstPrinter.
+ TargetRegistry::RegisterMCInstPrinter(T, createM68kMCInstPrinter);
+
+ // Register the MC relocation info.
+ TargetRegistry::RegisterMCRelocationInfo(T, createM68kMCRelocationInfo);
+
+ // Register the asm backend.
+ TargetRegistry::RegisterMCAsmBackend(T, createM68kAsmBackend);
+}
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.h b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.h
new file mode 100644
index 000000000000..0c44be0c804c
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.h
@@ -0,0 +1,63 @@
+//===-- M68kMCTargetDesc.h - M68k Target Descriptions -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file provides M68k specific target descriptions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KMCTARGETDESC_H
+#define LLVM_LIB_TARGET_M68K_MCTARGETDESC_M68KMCTARGETDESC_H
+
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
+class MCRegisterInfo;
+class MCSubtargetInfo;
+class MCRelocationInfo;
+class MCTargetOptions;
+class Target;
+class Triple;
+class StringRef;
+class raw_ostream;
+class raw_pwrite_stream;
+
+extern Target TheM68kTarget;
+
+MCAsmBackend *createM68kAsmBackend(const Target &T, const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options);
+
+MCCodeEmitter *createM68kMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCRegisterInfo &MRI,
+ MCContext &Ctx);
+
+/// Construct an M68k ELF object writer.
+std::unique_ptr<MCObjectTargetWriter> createM68kELFObjectWriter(uint8_t OSABI);
+
+} // namespace llvm
+
+// Defines symbolic names for M68k registers. This defines a mapping from
+// register name to register number.
+#define GET_REGINFO_ENUM
+#include "M68kGenRegisterInfo.inc"
+
+// Defines symbolic names for the M68k instructions.
+#define GET_INSTRINFO_ENUM
+#include "M68kGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_ENUM
+#include "M68kGenSubtargetInfo.inc"
+
+#endif
diff --git a/llvm/lib/Target/M68k/TargetInfo/M68kTargetInfo.cpp b/llvm/lib/Target/M68k/TargetInfo/M68kTargetInfo.cpp
index faedeb1deadd..0a0747f58581 100644
--- a/llvm/lib/Target/M68k/TargetInfo/M68kTargetInfo.cpp
+++ b/llvm/lib/Target/M68k/TargetInfo/M68kTargetInfo.cpp
@@ -10,8 +10,14 @@
/// This file contains M68k target initializer.
///
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/M68kMCTargetDesc.h"
+#include "llvm/Support/TargetRegistry.h"
-/// This is just a placeholder to make current
-/// commit buildable. Body of this function will
-/// be filled in later commits
-extern "C" void LLVMInitializeM68kTargetInfo() {}
+using namespace llvm;
+
+Target llvm::TheM68kTarget;
+
+extern "C" void LLVMInitializeM68kTargetInfo() {
+ RegisterTarget<Triple::m68k, /*HasJIT=*/true> X(
+ TheM68kTarget, "m68k", "Motorola 68000 family", "M68k");
+}
More information about the llvm-commits
mailing list