[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