[llvm] bec7b16 - [M68k](3/8) Skeleton and target description files
Min-Yih Hsu via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 8 12:33:46 PST 2021
Author: Min-Yih Hsu
Date: 2021-03-08T12:30:57-08:00
New Revision: bec7b166923bbaf0882ff4665224d7a8a7320aa0
URL: https://github.com/llvm/llvm-project/commit/bec7b166923bbaf0882ff4665224d7a8a7320aa0
DIFF: https://github.com/llvm/llvm-project/commit/bec7b166923bbaf0882ff4665224d7a8a7320aa0.diff
LOG: [M68k](3/8) Skeleton and target description files
- Infrastructure for the target (i.e. build files, target triple etc.)
- All of the target description TableGen file
Authors: myhsu, m4yers, glaubitz
Differential Revision: https://reviews.llvm.org/D88389
Added:
llvm/lib/Target/M68k/CMakeLists.txt
llvm/lib/Target/M68k/M68k.td
llvm/lib/Target/M68k/M68kCallingConv.td
llvm/lib/Target/M68k/M68kInstrArithmetic.td
llvm/lib/Target/M68k/M68kInstrBits.td
llvm/lib/Target/M68k/M68kInstrCompiler.td
llvm/lib/Target/M68k/M68kInstrControl.td
llvm/lib/Target/M68k/M68kInstrData.td
llvm/lib/Target/M68k/M68kInstrFormats.td
llvm/lib/Target/M68k/M68kInstrInfo.td
llvm/lib/Target/M68k/M68kInstrShiftRotate.td
llvm/lib/Target/M68k/M68kRegisterInfo.td
llvm/lib/Target/M68k/M68kSchedule.td
llvm/lib/Target/M68k/M68kTargetMachine.cpp
llvm/lib/Target/M68k/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.cpp
llvm/lib/Target/M68k/TargetInfo/CMakeLists.txt
llvm/lib/Target/M68k/TargetInfo/M68kTargetInfo.cpp
Modified:
llvm/cmake/config-ix.cmake
llvm/include/llvm/ADT/Triple.h
llvm/lib/Support/Triple.cpp
Removed:
################################################################################
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index 7473599f7513..fa250b917f6f 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -452,6 +452,8 @@ elseif (LLVM_NATIVE_ARCH MATCHES "riscv32")
set(LLVM_NATIVE_ARCH RISCV)
elseif (LLVM_NATIVE_ARCH MATCHES "riscv64")
set(LLVM_NATIVE_ARCH RISCV)
+elseif (LLVM_NATIVE_ARCH STREQUAL "m68k")
+ set(LLVM_NATIVE_ARCH M68k)
else ()
message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}")
endif ()
diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h
index eed315c929ad..3b351b732e9a 100644
--- a/llvm/include/llvm/ADT/Triple.h
+++ b/llvm/include/llvm/ADT/Triple.h
@@ -58,6 +58,7 @@ class Triple {
bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
csky, // CSKY: csky
hexagon, // Hexagon: hexagon
+ m68k, // M68k: Motorola 680x0 family
mips, // MIPS: mips, mipsallegrex, mipsr6
mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el
mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6
diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp
index 2ec123fcca73..e5dd32fb5827 100644
--- a/llvm/lib/Support/Triple.cpp
+++ b/llvm/lib/Support/Triple.cpp
@@ -44,6 +44,7 @@ StringRef Triple::getArchTypeName(ArchType Kind) {
case lanai: return "lanai";
case le32: return "le32";
case le64: return "le64";
+ case m68k: return "m68k";
case mips64: return "mips64";
case mips64el: return "mips64el";
case mips: return "mips";
@@ -105,6 +106,8 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) {
case ppc:
case ppcle: return "ppc";
+ case m68k: return "m68k";
+
case mips:
case mipsel:
case mips64:
@@ -281,6 +284,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("armeb", armeb)
.Case("avr", avr)
.StartsWith("bpf", BPFArch)
+ .Case("m68k", m68k)
.Case("mips", mips)
.Case("mipsel", mipsel)
.Case("mips64", mips64)
@@ -419,6 +423,7 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("thumb", Triple::thumb)
.Case("thumbeb", Triple::thumbeb)
.Case("avr", Triple::avr)
+ .Case("m68k", Triple::m68k)
.Case("msp430", Triple::msp430)
.Cases("mips", "mipseb", "mipsallegrex", "mipsisa32r6",
"mipsr6", Triple::mips)
@@ -704,6 +709,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) {
case Triple::lanai:
case Triple::le32:
case Triple::le64:
+ case Triple::m68k:
case Triple::mips64:
case Triple::mips64el:
case Triple::mips:
@@ -1277,6 +1283,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::kalimba:
case llvm::Triple::lanai:
case llvm::Triple::le32:
+ case llvm::Triple::m68k:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::nvptx:
@@ -1361,6 +1368,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::kalimba:
case Triple::lanai:
case Triple::le32:
+ case Triple::m68k:
case Triple::mips:
case Triple::mipsel:
case Triple::nvptx:
@@ -1413,6 +1421,7 @@ Triple Triple::get64BitArchVariant() const {
case Triple::hexagon:
case Triple::kalimba:
case Triple::lanai:
+ case Triple::m68k:
case Triple::msp430:
case Triple::r600:
case Triple::shave:
@@ -1537,6 +1546,7 @@ Triple Triple::getLittleEndianArchVariant() const {
case Triple::lanai:
case Triple::sparcv9:
case Triple::systemz:
+ case Triple::m68k:
// ARM is intentionally unsupported here, changing the architecture would
// drop any arch suffixes.
diff --git a/llvm/lib/Target/M68k/CMakeLists.txt b/llvm/lib/Target/M68k/CMakeLists.txt
new file mode 100644
index 000000000000..1bd78445f572
--- /dev/null
+++ b/llvm/lib/Target/M68k/CMakeLists.txt
@@ -0,0 +1,36 @@
+add_llvm_component_group(M68k)
+
+set(LLVM_TARGET_DEFINITIONS M68k.td)
+
+tablegen(LLVM M68kGenRegisterInfo.inc -gen-register-info)
+tablegen(LLVM M68kGenInstrInfo.inc -gen-instr-info)
+tablegen(LLVM M68kGenSubtargetInfo.inc -gen-subtarget)
+tablegen(LLVM M68kGenMCCodeBeads.inc -gen-code-beads)
+tablegen(LLVM M68kGenMCPseudoLowering.inc -gen-pseudo-lowering)
+tablegen(LLVM M68kGenDAGISel.inc -gen-dag-isel)
+tablegen(LLVM M68kGenCallingConv.inc -gen-callingconv)
+tablegen(LLVM M68kGenAsmWriter.inc -gen-asm-writer)
+
+add_public_tablegen_target(M68kCommonTableGen)
+
+add_llvm_target(M68kCodeGen
+ M68kTargetMachine.cpp
+
+ LINK_COMPONENTS
+ Analysis
+ AsmPrinter
+ CodeGen
+ Core
+ MC
+ SelectionDAG
+ Support
+ Target
+ M68kDesc
+ M68kInfo
+
+ ADD_TO_COMPONENT
+ M68k
+)
+
+add_subdirectory(TargetInfo)
+add_subdirectory(MCTargetDesc)
diff --git a/llvm/lib/Target/M68k/M68k.td b/llvm/lib/Target/M68k/M68k.td
new file mode 100644
index 000000000000..f308a6d6387d
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68k.td
@@ -0,0 +1,93 @@
+//===-- M68k.td - Motorola 680x0 target definitions ------*- tablegen -*-===//
+//
+// 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 is a target description file for the Motorola 680x0 family, referred
+/// to here as the "M68k" architecture.
+///
+//===----------------------------------------------------------------------===//
+
+include "llvm/Target/Target.td"
+
+//===----------------------------------------------------------------------===//
+// M68k Subtarget features
+//===----------------------------------------------------------------------===//
+
+def FeatureISA00
+ : SubtargetFeature<"isa-68000", "SubtargetKind", "M00",
+ "Is M68000 ISA supported">;
+
+def FeatureISA10
+ : SubtargetFeature<"isa-68010", "SubtargetKind", "M10",
+ "Is M68010 ISA supported",
+ [ FeatureISA00 ]>;
+
+def FeatureISA20
+ : SubtargetFeature<"isa-68020", "SubtargetKind", "M20",
+ "Is M68020 ISA supported",
+ [ FeatureISA10 ]>;
+
+def FeatureISA30
+ : SubtargetFeature<"isa-68030", "SubtargetKind", "M30",
+ "Is M68030 ISA supported",
+ [ FeatureISA20 ]>;
+
+def FeatureISA40
+ : SubtargetFeature<"isa-68040", "SubtargetKind", "M40",
+ "Is M68040 ISA supported",
+ [ FeatureISA30 ]>;
+
+def FeatureISA60
+ : SubtargetFeature<"isa-68060", "SubtargetKind", "M60",
+ "Is M68060 ISA supported",
+ [ FeatureISA40 ]>;
+
+//===----------------------------------------------------------------------===//
+// M68k processors supported.
+//===----------------------------------------------------------------------===//
+
+include "M68kSchedule.td"
+
+class Proc<string Name, list<SubtargetFeature> Features>
+ : ProcessorModel<Name, GenericM68kModel, Features>;
+
+def : Proc<"generic", [ FeatureISA00 ]>;
+def : Proc<"M68000", [ FeatureISA00 ]>;
+def : Proc<"M68010", [ FeatureISA10 ]>;
+def : Proc<"M68020", [ FeatureISA20 ]>;
+def : Proc<"M68030", [ FeatureISA30 ]>;
+def : Proc<"M68040", [ FeatureISA40 ]>;
+def : Proc<"M68060", [ FeatureISA60 ]>;
+
+//===----------------------------------------------------------------------===//
+// Register File Description
+//===----------------------------------------------------------------------===//
+
+include "M68kRegisterInfo.td"
+
+//===----------------------------------------------------------------------===//
+// Instruction Descriptions
+//===----------------------------------------------------------------------===//
+
+include "M68kInstrInfo.td"
+
+def M68kInstrInfo : InstrInfo;
+
+//===----------------------------------------------------------------------===//
+// Calling Conventions
+//===----------------------------------------------------------------------===//
+
+include "M68kCallingConv.td"
+
+//===----------------------------------------------------------------------===//
+// Target
+//===----------------------------------------------------------------------===//
+
+def M68k : Target {
+ let InstructionSet = M68kInstrInfo;
+}
diff --git a/llvm/lib/Target/M68k/M68kCallingConv.td b/llvm/lib/Target/M68k/M68kCallingConv.td
new file mode 100644
index 000000000000..360f2199cf6f
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kCallingConv.td
@@ -0,0 +1,119 @@
+//===-- M68kCallingConv.td - Calling Conventions for M68k --*- tablegen -*-===//
+//
+// 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 describes the calling conventions for the M68k architectures. These
+/// conventions assume Int to be 4 bytes and 4 byte aligned.
+///
+//===----------------------------------------------------------------------===//
+
+// TODO Verify C convention follows SysV M68K ABI
+
+class CCIfSubtarget<string F, CCAction A>
+ : CCIf<!strconcat("static_cast<const M68kSubtarget &>"
+ "(State.getMachineFunction().getSubtarget()).", F), A>;
+
+//===----------------------------------------------------------------------===//
+// Return Value Calling Conventions
+//===----------------------------------------------------------------------===//
+
+/// Return-value conventions common to all M68k CC's.
+def RetCC_M68kCommon : CallingConv<[
+]>;
+
+/// M68k C return convention.
+/// TODO: Return via address register
+def RetCC_M68k_C : CallingConv<[
+ CCIfType<[i1], CCPromoteToType<i8>>,
+ CCIfType<[i8], CCAssignToReg<[BD0, BD1]>>,
+ CCIfType<[i16], CCAssignToReg<[WD0, WD1]>>,
+ CCIfType<[i32], CCAssignToReg<[D0, D1]>>,
+ CCDelegateTo<RetCC_M68kCommon>
+]>;
+
+/// M68k fastcc return convention.
+/// This convention allows to return up to 16 bytes in registers which can be
+/// split among 16 1-byte values or used for a single 16-byte value.
+/// TODO: Verify its functionality and write tests
+def RetCC_M68k_Fast : CallingConv<[
+ CCIfType<[i1], CCPromoteToType<i8>>,
+ CCIfType<[i8], CCAssignToReg<[BD0, BD1]>>,
+ CCIfType<[i16], CCAssignToReg<[WD0, WD1, WA0, WA1]>>,
+ CCIfType<[i32], CCAssignToReg<[D0, D1, A0, A1]>>,
+ CCDelegateTo<RetCC_M68kCommon>
+]>;
+
+/// This is the root return-value convention for the M68k backend.
+def RetCC_M68k : CallingConv<[
+ CCIfCC<"CallingConv::Fast", CCDelegateTo<RetCC_M68k_Fast>>,
+ CCDelegateTo<RetCC_M68k_C>
+]>;
+
+//===----------------------------------------------------------------------===//
+// M68k C Calling Convention
+//===----------------------------------------------------------------------===//
+
+/// CC_M68k_Common - In all M68k calling conventions, extra integers and FP
+/// values are spilled on the stack.
+def CC_M68k_Common : CallingConv<[
+ /// Handles byval parameters.
+ CCIfByVal<CCPassByVal<4, 4>>,
+
+ /// Integer values get stored in stack slots that are 4 bytes in
+ /// size and 4-byte aligned.
+ CCIfType<[i32], CCAssignToStack<4, 4>>
+]>;
+
+def CC_M68k_Fast : CallingConv<[
+ /// Promote i1/i8/i16 arguments to i32.
+ CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
+
+ /// The 'nest' parameter, if any, is passed in A1.
+ CCIfNest<CCAssignToReg<[A1]>>, // FIXME verify if this is correct
+
+ /// Since M68k uses %An for pointers and we want them be passed in regs
+ /// too we have to use custom function.
+ CCIfType<[i32], CCCustom<"CC_M68k_Any_AssignToReg">>,
+
+ /// Otherwise, same as everything else.
+ CCDelegateTo<CC_M68k_Common>
+]>;
+
+def CC_M68k_C : CallingConv<[
+ /// Promote i1/i8/i16 arguments to i32.
+ CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
+
+ /// The 'nest' parameter, if any, is passed in A1.
+ CCIfNest<CCAssignToReg<[A1]>>, // FIXME verify if this is correct
+
+ /// Use registers only if 'inreg' used and the call is not vararg
+ CCIfNotVarArg<CCIfInReg<CCIfType<[i32], CCAssignToReg<[D0, D1]>>>>,
+
+ // TODO: Support for 'sret'
+
+ /// Otherwise, same as everything else.
+ CCDelegateTo<CC_M68k_Common>
+]>;
+
+/// This is the root argument convention for the M68k backend.
+def CC_M68k : CallingConv<[
+ CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_M68k_Fast>>,
+ CCDelegateTo<CC_M68k_C>
+]>;
+
+//===----------------------------------------------------------------------===//
+// Callee-saved Registers.
+//===----------------------------------------------------------------------===//
+
+def CSR_NoRegs : CalleeSavedRegs<(add)>;
+
+// A5 - BP
+// A6 - FP
+def CSR_STD : CalleeSavedRegs<(add D2, D3, D4, D5, D6, D7,
+ A2, A3, A4, A5, A6)>;
+
diff --git a/llvm/lib/Target/M68k/M68kInstrArithmetic.td b/llvm/lib/Target/M68k/M68kInstrArithmetic.td
new file mode 100644
index 000000000000..f4714d2534bd
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kInstrArithmetic.td
@@ -0,0 +1,886 @@
+//===-- M68kInstrArithmetic.td - Integer Arith Instrs ------*- tablegen -*-===//
+//
+// 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 describes the integer arithmetic instructions in the M68k
+/// architecture. Here is the current status of the file:
+///
+/// Machine:
+///
+/// ADD [~] ADDA [~] ADDI [~] ADDQ [ ] ADDX [~]
+/// CLR [ ] CMP [~] CMPA [~] CMPI [~] CMPM [ ]
+/// CMP2 [ ] DIVS/DIVU [~] DIVSL/DIVUL [ ] EXT [~] EXTB [ ]
+/// MULS/MULU [~] NEG [~] NEGX [~] SUB [~] SUBA [~]
+/// SUBI [~] SUBQ [ ] SUBX [~]
+///
+/// Map:
+///
+/// [ ] - was not touched at all
+/// [!] - requires extarnal stuff implemented
+/// [~] - functional implementation
+/// [X] - complete implementation
+///
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Encoding
+//===----------------------------------------------------------------------===//
+
+/// Encoding for Normal forms
+/// ----------------------------------------------------
+/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0
+/// ----------------------------------------------------
+/// | | | EFFECTIVE ADDRESS
+/// x x x x | REG | OP MODE | MODE | REG
+/// ----------------------------------------------------
+class MxArithEncoding<MxBead4Bits CMD, MxEncOpMode OPMODE, MxBeadReg REG,
+ MxEncEA EA, MxEncExt EXT>
+ : MxEncoding<EA.Reg, EA.DA, EA.Mode, OPMODE.B0, OPMODE.B1, OPMODE.B2, REG,
+ CMD,EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
+
+/// Encoding for Extended forms
+/// ------------------------------------------------------
+/// F E D C | B A 9 | 8 | 7 6 | 5 4 | 3 | 2 1 0
+/// ------------------------------------------------------
+/// x x x x | REG Rx | 1 | SIZE | 0 0 | M | REG Ry
+/// ------------------------------------------------------
+/// Rx - destination
+/// Ry - source
+/// M - address mode switch
+class MxArithXEncoding<MxBead4Bits CMD, MxEncSize SIZE, MxBead1Bit MODE,
+ MxBeadReg SRC, MxBeadReg DST>
+ : MxEncoding<SRC, MODE, MxBead2Bits<0b00>, SIZE, MxBead1Bit<0b1>, DST, CMD>;
+
+/// Encoding for Immediate forms
+/// ---------------------------------------------------
+/// F E D C B A 9 8 | 7 6 | 5 4 3 | 2 1 0
+/// ---------------------------------------------------
+/// | | EFFECTIVE ADDRESS
+/// x x x x x x x x | SIZE | MODE | REG
+/// ---------------------------------------------------
+/// 16-BIT WORD DATA | 8-BIT BYTE DATA
+/// ---------------------------------------------------
+/// 32-BIT LONG DATA
+/// ---------------------------------------------------
+/// NOTE It is used to store an immediate to memory, imm-to-reg are handled with
+/// normal version
+class MxArithImmEncoding<MxBead4Bits CMD, MxEncSize SIZE,
+ MxEncEA DST_EA, MxEncExt DST_EXT, MxEncExt SRC_EXT>
+ : MxEncoding<DST_EA.Reg, DST_EA.DA, DST_EA.Mode, SIZE, CMD, MxBead4Bits<0>,
+ // Source
+ SRC_EXT.Imm, SRC_EXT.B8, SRC_EXT.Scale,
+ SRC_EXT.WL, SRC_EXT.DAReg,
+ // Destination
+ DST_EXT.Imm, DST_EXT.B8, DST_EXT.Scale,
+ DST_EXT.WL, DST_EXT.DAReg>;
+
+
+//===----------------------------------------------------------------------===//
+// Add/Sub
+//===----------------------------------------------------------------------===//
+
+let Defs = [CCR] in {
+let Constraints = "$src = $dst" in {
+
+// $reg, $ccr <- $reg op $reg
+class MxBiArOp_RFRR_xEA<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
+ : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
+ MN#"."#TYPE.Prefix#"\t$opd, $dst",
+ [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))],
+ MxArithEncoding<MxBead4Bits<CMD>,
+ !cast<MxEncOpMode>("MxOpMode"#TYPE.Size#TYPE.RLet#"EA"),
+ MxBeadReg<0>,
+ !cast<MxEncEA>("MxEncEA"#TYPE.RLet#"_2"),
+ MxExtEmpty>>;
+
+/// This Op is similar to the one above except it uses reversed opmode, some
+/// commands(e.g. eor) do not support dEA or rEA modes and require EAd for
+/// register only operations.
+/// NOTE when using dd commands it is irrelevant which opmode to use(as it seems)
+/// but some opcodes support address register and some do not which creates this
+/// mess.
+class MxBiArOp_RFRR_EAd<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
+ : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
+ MN#"."#TYPE.Prefix#"\t$opd, $dst",
+ [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))],
+ MxArithEncoding<MxBead4Bits<CMD>,
+ !cast<MxEncOpMode>("MxOpMode"#TYPE.Size#"EAd"),
+ MxBeadReg<2>, MxEncEAd_0, MxExtEmpty>>;
+
+// $reg <- $reg op $imm
+class MxBiArOp_RFRI_xEA<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
+ : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd),
+ MN#"."#TYPE.Prefix#"\t$opd, $dst",
+ [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))],
+ MxArithEncoding<MxBead4Bits<CMD>,
+ !cast<MxEncOpMode>("MxOpMode"#TYPE.Size#TYPE.RLet#"EA"),
+ MxBeadReg<0>, MxEncEAi,
+ !cast<MxEncExt>("MxExtI"#TYPE.Size#"_2")>>;
+
+// Again, there are two ways to write an immediate to Dn register either dEA
+// opmode or using *I encoding, and again some instrucitons also support address
+// registers some do not.
+class MxBiArOp_RFRI<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
+ : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd),
+ MN#"i."#TYPE.Prefix#"\t$opd, $dst",
+ [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))],
+ MxArithImmEncoding<MxBead4Bits<CMD>, !cast<MxEncSize>("MxEncSize"#TYPE.Size),
+ !cast<MxEncEA>("MxEncEA"#TYPE.RLet#"_0"), MxExtEmpty,
+ !cast<MxEncExt>("MxExtI"#TYPE.Size#"_2")>>;
+
+let mayLoad = 1 in
+class MxBiArOp_RFRM<string MN, SDNode NODE, MxType TYPE, MxOperand OPD, ComplexPattern PAT,
+ bits<4> CMD, MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, OPD:$opd),
+ MN#"."#TYPE.Prefix#"\t$opd, $dst",
+ [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, (TYPE.Load PAT:$opd)))],
+ MxArithEncoding<MxBead4Bits<CMD>,
+ !cast<MxEncOpMode>("MxOpMode"#TYPE.Size#TYPE.RLet#"EA"),
+ MxBeadReg<0>, EA, EXT>>;
+
+} // Constraints
+
+let mayLoad = 1, mayStore = 1 in {
+
+// FIXME MxBiArOp_FMR/FMI cannot consume CCR from MxAdd/MxSub which leads for
+// MxAdd to survive the match and subsequent mismatch.
+class MxBiArOp_FMR<string MN, SDNode NODE, MxType TYPE,
+ MxOperand MEMOpd, ComplexPattern MEMPat,
+ bits<4> CMD, MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins MEMOpd:$dst, TYPE.ROp:$opd),
+ MN#"."#TYPE.Prefix#"\t$opd, $dst",
+ [],
+ MxArithEncoding<MxBead4Bits<CMD>,
+ !cast<MxEncOpMode>("MxOpMode"#TYPE.Size#"EA"#TYPE.RLet),
+ MxBeadReg<1>, EA, EXT>>;
+
+class MxBiArOp_FMI<string MN, SDNode NODE, MxType TYPE,
+ MxOperand MEMOpd, ComplexPattern MEMPat,
+ bits<4> CMD, MxEncEA MEMEA, MxEncExt MEMExt>
+ : MxInst<(outs), (ins MEMOpd:$dst, TYPE.IOp:$opd),
+ MN#"."#TYPE.Prefix#"\t$opd, $dst",
+ [],
+ MxArithImmEncoding<MxBead4Bits<CMD>,
+ !cast<MxEncSize>("MxEncSize"#TYPE.Size),
+ MEMEA, MEMExt,
+ !cast<MxEncExt>("MxExtI"#TYPE.Size#"_1")>>;
+} // mayLoad, mayStore
+} // Defs = [CCR]
+
+multiclass MxBiArOp_DF<string MN, SDNode NODE, bit isComm,
+ bits<4> CMD, bits<4> CMDI> {
+
+ // op $mem, $reg
+ def NAME#"8dk" : MxBiArOp_RFRM<MN, NODE, MxType8d, MxType8.KOp, MxType8.KPat,
+ CMD, MxEncEAk, MxExtBrief_2>;
+ def NAME#"16dk" : MxBiArOp_RFRM<MN, NODE, MxType16d, MxType16.KOp, MxType16.KPat,
+ CMD, MxEncEAk, MxExtBrief_2>;
+ def NAME#"32dk" : MxBiArOp_RFRM<MN, NODE, MxType32d, MxType32.KOp, MxType32.KPat,
+ CMD, MxEncEAk, MxExtBrief_2>;
+
+ def NAME#"8dq" : MxBiArOp_RFRM<MN, NODE, MxType8d, MxType8.QOp, MxType8.QPat,
+ CMD, MxEncEAq, MxExtI16_2>;
+ def NAME#"16dq" : MxBiArOp_RFRM<MN, NODE, MxType16d, MxType16.QOp, MxType16.QPat,
+ CMD, MxEncEAq, MxExtI16_2>;
+ def NAME#"32dq" : MxBiArOp_RFRM<MN, NODE, MxType32d, MxType32.QOp, MxType32.QPat,
+ CMD, MxEncEAq, MxExtI16_2>;
+
+ def NAME#"8dp" : MxBiArOp_RFRM<MN, NODE, MxType8d, MxType8.POp, MxType8.PPat,
+ CMD, MxEncEAp_2, MxExtI16_2>;
+ def NAME#"16dp" : MxBiArOp_RFRM<MN, NODE, MxType16d, MxType16.POp, MxType16.PPat,
+ CMD, MxEncEAp_2, MxExtI16_2>;
+ def NAME#"32dp" : MxBiArOp_RFRM<MN, NODE, MxType32d, MxType32.POp, MxType32.PPat,
+ CMD, MxEncEAp_2, MxExtI16_2>;
+
+ def NAME#"8df" : MxBiArOp_RFRM<MN, NODE, MxType8d, MxType8.FOp, MxType8.FPat,
+ CMD, MxEncEAf_2, MxExtBrief_2>;
+ def NAME#"16df" : MxBiArOp_RFRM<MN, NODE, MxType16d, MxType16.FOp, MxType16.FPat,
+ CMD, MxEncEAf_2, MxExtBrief_2>;
+ def NAME#"32df" : MxBiArOp_RFRM<MN, NODE, MxType32d, MxType32.FOp, MxType32.FPat,
+ CMD, MxEncEAf_2, MxExtBrief_2>;
+
+ def NAME#"8dj" : MxBiArOp_RFRM<MN, NODE, MxType8d, MxType8.JOp, MxType8.JPat,
+ CMD, MxEncEAj_2, MxExtEmpty>;
+ def NAME#"16dj" : MxBiArOp_RFRM<MN, NODE, MxType16d, MxType16.JOp, MxType16.JPat,
+ CMD, MxEncEAj_2, MxExtEmpty>;
+ def NAME#"32dj" : MxBiArOp_RFRM<MN, NODE, MxType32d, MxType32.JOp, MxType32.JPat,
+ CMD, MxEncEAj_2, MxExtEmpty>;
+
+ // op $imm, $reg
+ def NAME#"8di" : MxBiArOp_RFRI_xEA<MN, NODE, MxType8d, CMD>;
+ def NAME#"16di" : MxBiArOp_RFRI_xEA<MN, NODE, MxType16d, CMD>;
+ def NAME#"32di" : MxBiArOp_RFRI_xEA<MN, NODE, MxType32d, CMD>;
+
+ // op $reg, $mem
+ def NAME#"8pd" : MxBiArOp_FMR<MN, NODE, MxType8d, MxType8.POp, MxType8.PPat,
+ CMD, MxEncEAp_0, MxExtI16_0>;
+ def NAME#"16pd" : MxBiArOp_FMR<MN, NODE, MxType16d, MxType16.POp, MxType16.PPat,
+ CMD, MxEncEAp_0, MxExtI16_0>;
+ def NAME#"32pd" : MxBiArOp_FMR<MN, NODE, MxType32d, MxType32.POp, MxType32.PPat,
+ CMD, MxEncEAp_0, MxExtI16_0>;
+
+ def NAME#"8fd" : MxBiArOp_FMR<MN, NODE, MxType8d, MxType8.FOp, MxType8.FPat,
+ CMD, MxEncEAf_0, MxExtBrief_0>;
+ def NAME#"16fd" : MxBiArOp_FMR<MN, NODE, MxType16d, MxType16.FOp, MxType16.FPat,
+ CMD, MxEncEAf_0, MxExtBrief_0>;
+ def NAME#"32fd" : MxBiArOp_FMR<MN, NODE, MxType32d, MxType32.FOp, MxType32.FPat,
+ CMD, MxEncEAf_0, MxExtBrief_0>;
+
+ def NAME#"8jd" : MxBiArOp_FMR<MN, NODE, MxType8d, MxType8.JOp, MxType8.JPat,
+ CMD, MxEncEAj_0, MxExtEmpty>;
+ def NAME#"16jd" : MxBiArOp_FMR<MN, NODE, MxType16d, MxType16.JOp, MxType16.JPat,
+ CMD, MxEncEAj_0, MxExtEmpty>;
+ def NAME#"32jd" : MxBiArOp_FMR<MN, NODE, MxType32d, MxType32.JOp, MxType32.JPat,
+ CMD, MxEncEAj_0, MxExtEmpty>;
+
+ // op $imm, $mem
+ def NAME#"8pi" : MxBiArOp_FMI<MN, NODE, MxType8, MxType8.POp, MxType8.PPat,
+ CMDI, MxEncEAp_0, MxExtI16_0>;
+ def NAME#"16pi" : MxBiArOp_FMI<MN, NODE, MxType16, MxType16.POp, MxType16.PPat,
+ CMDI, MxEncEAp_0, MxExtI16_0>;
+ def NAME#"32pi" : MxBiArOp_FMI<MN, NODE, MxType32, MxType32.POp, MxType32.PPat,
+ CMDI, MxEncEAp_0, MxExtI16_0>;
+
+ def NAME#"8fi" : MxBiArOp_FMI<MN, NODE, MxType8, MxType8.FOp, MxType8.FPat,
+ CMDI, MxEncEAf_0, MxExtBrief_0>;
+ def NAME#"16fi" : MxBiArOp_FMI<MN, NODE, MxType16, MxType16.FOp, MxType16.FPat,
+ CMDI, MxEncEAf_0, MxExtBrief_0>;
+ def NAME#"32fi" : MxBiArOp_FMI<MN, NODE, MxType32, MxType32.FOp, MxType32.FPat,
+ CMDI, MxEncEAf_0, MxExtBrief_0>;
+
+ def NAME#"8ji" : MxBiArOp_FMI<MN, NODE, MxType8, MxType8.JOp, MxType8.JPat,
+ CMDI, MxEncEAj_0, MxExtEmpty>;
+ def NAME#"16ji" : MxBiArOp_FMI<MN, NODE, MxType16, MxType16.JOp, MxType16.JPat,
+ CMDI, MxEncEAj_0, MxExtEmpty>;
+ def NAME#"32ji" : MxBiArOp_FMI<MN, NODE, MxType32, MxType32.JOp, MxType32.JPat,
+ CMDI, MxEncEAj_0, MxExtEmpty>;
+
+ let isCommutable = isComm in {
+
+ def NAME#"8dd" : MxBiArOp_RFRR_xEA<MN, NODE, MxType8d, CMD>;
+ def NAME#"16dd" : MxBiArOp_RFRR_xEA<MN, NODE, MxType16d, CMD>;
+ def NAME#"32dd" : MxBiArOp_RFRR_xEA<MN, NODE, MxType32d, CMD>;
+
+ } // isComm
+
+} // MxBiArOp_DF
+
+
+// These special snowflakes allowed to match address registers but since *A
+// operations do not produce CCR we should not match them against Mx nodes that
+// produce it.
+let Pattern = [(null_frag)] in
+multiclass MxBiArOp_AF<string MN, SDNode NODE, bit isComm,
+ bits<4> CMD, bits<4> CMDI> {
+
+ def NAME#"32rk" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.KOp, MxType32.KPat,
+ CMD, MxEncEAk, MxExtBrief_2>;
+ def NAME#"32rq" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.QOp, MxType32.QPat,
+ CMD, MxEncEAq, MxExtI16_2>;
+ def NAME#"32rf" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.FOp, MxType32.FPat,
+ CMD, MxEncEAf_2, MxExtBrief_2>;
+ def NAME#"32rp" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.POp, MxType32.PPat,
+ CMD, MxEncEAp_2, MxExtI16_2>;
+ def NAME#"32rj" : MxBiArOp_RFRM<MN, NODE, MxType32r, MxType32.JOp, MxType32.JPat,
+ CMD, MxEncEAj_2, MxExtEmpty>;
+ def NAME#"32ri" : MxBiArOp_RFRI_xEA<MN, NODE, MxType32r, CMD>;
+
+ let isCommutable = isComm in
+ def NAME#"32rr" : MxBiArOp_RFRR_xEA<MN, NODE, MxType32r, CMD>;
+
+} // MxBiArOp_AF
+
+// NOTE These naturally produce CCR
+
+defm ADD : MxBiArOp_DF<"add", MxAdd, 1, 0xD, 0x6>;
+defm ADD : MxBiArOp_AF<"add", MxAdd, 1, 0xD, 0x6>;
+defm SUB : MxBiArOp_DF<"sub", MxSub, 0, 0x9, 0x4>;
+defm SUB : MxBiArOp_AF<"sub", MxSub, 0, 0x9, 0x4>;
+
+
+let Uses = [CCR], Defs = [CCR] in {
+let Constraints = "$src = $dst" in {
+
+// $reg, ccr <- $reg op $reg op ccr
+class MxBiArOp_RFRRF<string MN, SDNode NODE, MxType TYPE, bits<4> CMD>
+ : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
+ MN#"."#TYPE.Prefix#"\t$opd, $dst",
+ [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd, CCR))],
+ MxArithXEncoding<MxBead4Bits<CMD>,
+ !cast<MxEncSize>("MxEncSize"#TYPE.Size),
+ MxBead1Bit<0>, MxBeadReg<2>, MxBeadReg<0>>>;
+
+} // Constraints
+} // Uses, Defs
+
+multiclass MxBiArOp_RFF<string MN, SDNode NODE, bit isComm, bits<4> CMD> {
+
+let isCommutable = isComm in {
+
+ def NAME#"8dd" : MxBiArOp_RFRRF<MN, NODE, MxType8d, CMD>;
+ def NAME#"16dd" : MxBiArOp_RFRRF<MN, NODE, MxType16d, CMD>;
+ def NAME#"32dd" : MxBiArOp_RFRRF<MN, NODE, MxType32d, CMD>;
+
+} // isComm
+
+} // MxBiArOp_RFF
+
+// NOTE These consume and produce CCR
+defm ADDX : MxBiArOp_RFF<"addx", MxAddX, 1, 0xD>;
+defm SUBX : MxBiArOp_RFF<"subx", MxSubX, 0, 0x9>;
+
+
+//===----------------------------------------------------------------------===//
+// And/Xor/Or
+//===----------------------------------------------------------------------===//
+
+defm AND : MxBiArOp_DF<"and", MxAnd, 1, 0xC, 0x2>;
+defm OR : MxBiArOp_DF<"or", MxOr, 1, 0x8, 0x0>;
+
+multiclass MxBiArOp_DF_EAd<string MN, SDNode NODE, bits<4> CMD, bits<4> CMDI> {
+
+ let isCommutable = 1 in {
+
+ def NAME#"8dd" : MxBiArOp_RFRR_EAd<MN, NODE, MxType8d, CMD>;
+ def NAME#"16dd" : MxBiArOp_RFRR_EAd<MN, NODE, MxType16d, CMD>;
+ def NAME#"32dd" : MxBiArOp_RFRR_EAd<MN, NODE, MxType32d, CMD>;
+
+ } // isCommutable = 1
+
+ def NAME#"8di" : MxBiArOp_RFRI<MN, NODE, MxType8d, CMDI>;
+ def NAME#"16di" : MxBiArOp_RFRI<MN, NODE, MxType16d, CMDI>;
+ def NAME#"32di" : MxBiArOp_RFRI<MN, NODE, MxType32d, CMDI>;
+
+} // MxBiArOp_DF_EAd
+
+defm XOR : MxBiArOp_DF_EAd<"eor", MxXor, 0xB, 0xA>;
+
+
+//===----------------------------------------------------------------------===//
+// CMP
+//===----------------------------------------------------------------------===//
+
+let Defs = [CCR] in {
+class MxCmp_RR<MxType TYPE>
+ : MxInst<(outs), (ins TYPE.ROp:$lhs, TYPE.ROp:$rhs),
+ "cmp."#TYPE.Prefix#"\t$lhs, $rhs",
+ [(set CCR, (MxCmp TYPE.VT:$lhs, TYPE.VT:$rhs))],
+ MxArithEncoding<MxBead4Bits<0xB>,
+ !cast<MxEncOpMode>("MxOpMode"#TYPE.Size#"dEA"),
+ MxBeadReg<1>, MxEncEAd_0, MxExtEmpty>>;
+
+class MxCmp_RI<MxType TYPE>
+ : MxInst<(outs), (ins TYPE.IOp:$imm, TYPE.ROp:$reg),
+ "cmpi."#TYPE.Prefix#"\t$imm, $reg",
+ [(set CCR, (MxCmp TYPE.IPat:$imm, TYPE.VT:$reg))],
+ MxArithImmEncoding<MxBead4Bits<0xC>,
+ !cast<MxEncSize>("MxEncSize"#TYPE.Size),
+ MxEncEAd_1, MxExtEmpty,
+ !cast<MxEncExt>("MxExtI"#TYPE.Size#"_0")>>;
+
+let mayLoad = 1 in {
+
+class MxCmp_MI<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
+ MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins TYPE.IOp:$imm, MEMOpd:$mem),
+ "cmpi."#TYPE.Prefix#"\t$imm, $mem",
+ [(set CCR, (MxCmp TYPE.IPat:$imm, (load MEMPat:$mem)))],
+ MxArithImmEncoding<MxBead4Bits<0xC>,
+ !cast<MxEncSize>("MxEncSize"#TYPE.Size),
+ EA, EXT,
+ !cast<MxEncExt>("MxExtI"#TYPE.Size#"_0")>>;
+
+class MxCmp_BI<MxType TYPE>
+ : MxInst<(outs), (ins TYPE.IOp:$imm, MxAL32:$abs),
+ "cmpi."#TYPE.Prefix#"\t$imm, $abs",
+ [(set CCR, (MxCmp TYPE.IPat:$imm,
+ (load (i32 (MxWrapper tglobaladdr:$abs)))))],
+ MxArithImmEncoding<MxBead4Bits<0xC>,
+ !cast<MxEncSize>("MxEncSize"#TYPE.Size),
+ MxEncEAb, MxExtI32_1,
+ !cast<MxEncExt>("MxExtI"#TYPE.Size#"_0")>>;
+
+class MxCmp_RM<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
+ MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins TYPE.ROp:$reg, MEMOpd:$mem),
+ "cmp."#TYPE.Prefix#"\t$mem, $reg",
+ [(set CCR, (MxCmp (load MEMPat:$mem), TYPE.ROp:$reg))],
+ MxArithEncoding<MxBead4Bits<0xB>,
+ !cast<MxEncOpMode>("MxOpMode"#TYPE.Size#"dEA"),
+ MxBeadReg<0>, EA, EXT>>;
+} // let mayLoad = 1
+
+} // let Defs = [CCR]
+
+multiclass MMxCmp_RM<MxType TYPE> {
+ def NAME#TYPE.KOp.Letter : MxCmp_RM<TYPE, TYPE.KOp, TYPE.KPat, MxEncEAk,
+ MxExtBrief_1>;
+ def NAME#TYPE.QOp.Letter : MxCmp_RM<TYPE, TYPE.QOp, TYPE.QPat, MxEncEAq,
+ MxExtI16_1>;
+ def NAME#TYPE.POp.Letter : MxCmp_RM<TYPE, TYPE.POp, TYPE.PPat, MxEncEAp_1,
+ MxExtI16_1>;
+ def NAME#TYPE.FOp.Letter : MxCmp_RM<TYPE, TYPE.FOp, TYPE.FPat, MxEncEAf_1,
+ MxExtBrief_1>;
+ def NAME#TYPE.JOp.Letter : MxCmp_RM<TYPE, TYPE.JOp, TYPE.JPat, MxEncEAj_1,
+ MxExtEmpty>;
+}
+
+multiclass MMxCmp_MI<MxType TYPE> {
+ def NAME#TYPE.KOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.KOp, TYPE.KPat, MxEncEAk,
+ MxExtBrief_1>;
+ def NAME#TYPE.QOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.QOp, TYPE.QPat, MxEncEAq,
+ MxExtI16_1>;
+ def NAME#TYPE.POp.Letter#"i" : MxCmp_MI<TYPE, TYPE.POp, TYPE.PPat, MxEncEAp_1,
+ MxExtI16_1>;
+ def NAME#TYPE.FOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.FOp, TYPE.FPat, MxEncEAf_1,
+ MxExtBrief_1>;
+ def NAME#TYPE.JOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.JOp, TYPE.JPat, MxEncEAj_1,
+ MxExtEmpty>;
+}
+
+foreach S = [8, 16, 32] in {
+ def CMP#S#dd : MxCmp_RR<!cast<MxType>("MxType"#S#"d")>;
+ def CMP#S#di : MxCmp_RI<!cast<MxType>("MxType"#S#"d")>;
+ def CMP#S#bi : MxCmp_BI<!cast<MxType>("MxType"#S#"d")>;
+} // foreach
+
+// cmp mem, Dn
+defm CMP8d : MMxCmp_RM<MxType8d>;
+defm CMP16d : MMxCmp_RM<MxType16d>;
+defm CMP32d : MMxCmp_RM<MxType32d>;
+
+// cmp #imm, mem
+defm CMP8 : MMxCmp_MI<MxType8d>;
+defm CMP16 : MMxCmp_MI<MxType16d>;
+defm CMP32 : MMxCmp_MI<MxType32d>;
+
+
+//===----------------------------------------------------------------------===//
+// EXT
+//===----------------------------------------------------------------------===//
+
+def MxExtOpmode_wb : MxBead3Bits<0b010>;
+def MxExtOpmode_lw : MxBead3Bits<0b011>;
+def MxExtOpmode_lb : MxBead3Bits<0b111>;
+
+/// ---------------------------------------------------
+/// F E D C B A 9 | 8 7 6 | 5 4 3 | 2 1 0
+/// ---------------------------------------------------
+/// 0 1 0 0 1 0 0 | OPMODE | 0 0 0 | REG
+/// ---------------------------------------------------
+class MxExtEncoding<MxBead3Bits OPMODE>
+ : MxEncoding<MxBeadReg<0>, MxBead3Bits<0b000>, OPMODE,
+ MxBead3Bits<0b100>, MxBead4Bits<0b0100>>;
+
+let Defs = [CCR] in
+let Constraints = "$src = $dst" in
+class MxExt<MxType TO, MxType FROM>
+ : MxInst<(outs TO.ROp:$dst), (ins TO.ROp:$src),
+ "ext."#TO.Prefix#"\t$src", [],
+ MxExtEncoding<!cast<MxBead3Bits>("MxExtOpmode_"#TO.Prefix#FROM.Prefix)>>;
+
+def EXT16 : MxExt<MxType16d, MxType8d>;
+def EXT32 : MxExt<MxType32d, MxType16d>;
+
+def : Pat<(sext_inreg i16:$src, i8), (EXT16 $src)>;
+def : Pat<(sext_inreg i32:$src, i16), (EXT32 $src)>;
+def : Pat<(sext_inreg i32:$src, i8),
+ (EXT32 (MOVXd32d16 (EXT16 (EXTRACT_SUBREG $src, MxSubRegIndex16Lo))))>;
+
+
+//===----------------------------------------------------------------------===//
+// DIV/MUL
+//===----------------------------------------------------------------------===//
+
+def MxSDiMuOpmode : MxBead3Bits<0b111>;
+def MxUDiMuOpmode : MxBead3Bits<0b011>;
+
+/// Word operation:
+/// ----------------------------------------------------
+/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0
+/// ----------------------------------------------------
+/// | | | EFFECTIVE ADDRESS
+/// x x x x | REG | OP MODE | MODE | REG
+/// ----------------------------------------------------
+class MxDiMuEncoding<MxBead4Bits CMD, MxBead3Bits OPMODE, MxEncEA EA, MxEncExt EXT>
+ : MxEncoding<EA.Reg, EA.DA, EA.Mode, OPMODE, MxBeadReg<0>, CMD,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
+
+let Defs = [CCR] in {
+let Constraints = "$src = $dst" in {
+// $reg <- $reg op $reg
+class MxDiMuOp_DD<string MN, bits<4> CMD, MxBead3Bits OPMODE,
+ MxOperand DST, MxOperand OPD>
+ : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", [],
+ MxDiMuEncoding<MxBead4Bits<CMD>, OPMODE, MxEncEAd_2, MxExtEmpty>>;
+
+// $reg <- $reg op $imm
+class MxDiMuOp_DI<string MN, bits<4> CMD, MxBead3Bits OPMODE,
+ MxOperand DST, MxOperand OPD>
+ : MxInst<(outs DST:$dst), (ins DST:$src, unknown:$opd), MN#"\t$opd, $dst", [],
+ MxDiMuEncoding<MxBead4Bits<CMD>, OPMODE, MxEncEAi, MxExtI16_2>>;
+} // let Constraints
+} // Defs = [CCR]
+
+multiclass MxDiMuOp<string MN, bits<4> CMD, bit isComm = 0> {
+
+ let isCommutable = isComm in {
+ def "S"#NAME#"d32d16" : MxDiMuOp_DD<MN#"s", CMD, MxSDiMuOpmode, MxDRD32,
+ MxDRD16>;
+ def "U"#NAME#"d32d16" : MxDiMuOp_DD<MN#"u", CMD, MxUDiMuOpmode, MxDRD32,
+ MxDRD16>;
+ }
+
+ def "S"#NAME#"d32i16" : MxDiMuOp_DI<MN#"s", CMD, MxSDiMuOpmode, MxDRD32,
+ Mxi16imm>;
+ def "U"#NAME#"d32i16" : MxDiMuOp_DI<MN#"u", CMD, MxUDiMuOpmode, MxDRD32,
+ Mxi16imm>;
+
+}
+
+defm DIV : MxDiMuOp<"div", 0x8>;
+
+// RR i8
+def : Pat<(sdiv i8:$dst, i8:$opd),
+ (EXTRACT_SUBREG
+ (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)),
+ MxSubRegIndex8Lo)>;
+
+def : Pat<(udiv i8:$dst, i8:$opd),
+ (EXTRACT_SUBREG
+ (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)),
+ MxSubRegIndex8Lo)>;
+
+def : Pat<(srem i8:$dst, i8:$opd),
+ (EXTRACT_SUBREG
+ (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)), 8), 8),
+ MxSubRegIndex8Lo)>;
+
+def : Pat<(urem i8:$dst, i8:$opd),
+ (EXTRACT_SUBREG
+ (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)), 8), 8),
+ MxSubRegIndex8Lo)>;
+
+// RR i16
+def : Pat<(sdiv i16:$dst, i16:$opd),
+ (EXTRACT_SUBREG
+ (SDIVd32d16 (MOVSXd32d16 $dst), $opd),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(udiv i16:$dst, i16:$opd),
+ (EXTRACT_SUBREG
+ (UDIVd32d16 (MOVZXd32d16 $dst), $opd),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(srem i16:$dst, i16:$opd),
+ (EXTRACT_SUBREG
+ (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d16 $dst), $opd), 8), 8),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(urem i16:$dst, i16:$opd),
+ (EXTRACT_SUBREG
+ (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d16 $dst), $opd), 8), 8),
+ MxSubRegIndex16Lo)>;
+
+
+// RI i8
+def : Pat<(sdiv i8:$dst, MximmSExt8:$opd),
+ (EXTRACT_SUBREG
+ (SDIVd32i16 (MOVSXd32d8 $dst), imm:$opd),
+ MxSubRegIndex8Lo)>;
+
+def : Pat<(udiv i8:$dst, MximmSExt8:$opd),
+ (EXTRACT_SUBREG
+ (UDIVd32i16 (MOVZXd32d8 $dst), imm:$opd),
+ MxSubRegIndex8Lo)>;
+
+def : Pat<(srem i8:$dst, MximmSExt8:$opd),
+ (EXTRACT_SUBREG
+ (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d8 $dst), imm:$opd), 8), 8),
+ MxSubRegIndex8Lo)>;
+
+def : Pat<(urem i8:$dst, MximmSExt8:$opd),
+ (EXTRACT_SUBREG
+ (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d8 $dst), imm:$opd), 8), 8),
+ MxSubRegIndex8Lo)>;
+
+// RI i16
+def : Pat<(sdiv i16:$dst, MximmSExt16:$opd),
+ (EXTRACT_SUBREG
+ (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(udiv i16:$dst, MximmSExt16:$opd),
+ (EXTRACT_SUBREG
+ (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(srem i16:$dst, MximmSExt16:$opd),
+ (EXTRACT_SUBREG
+ (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd), 8), 8),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(urem i16:$dst, MximmSExt16:$opd),
+ (EXTRACT_SUBREG
+ (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd), 8), 8),
+ MxSubRegIndex16Lo)>;
+
+
+defm MUL : MxDiMuOp<"mul", 0xC, 1>;
+
+// RR
+def : Pat<(mul i16:$dst, i16:$opd),
+ (EXTRACT_SUBREG
+ (SMULd32d16 (MOVXd32d16 $dst), $opd),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(mulhs i16:$dst, i16:$opd),
+ (EXTRACT_SUBREG
+ (ASR32di (ASR32di (SMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(mulhu i16:$dst, i16:$opd),
+ (EXTRACT_SUBREG
+ (LSR32di (LSR32di (UMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8),
+ MxSubRegIndex16Lo)>;
+
+
+// RI
+def : Pat<(mul i16:$dst, MximmSExt16:$opd),
+ (EXTRACT_SUBREG
+ (SMULd32i16 (MOVXd32d16 $dst), imm:$opd),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(mulhs i16:$dst, MximmSExt16:$opd),
+ (EXTRACT_SUBREG
+ (ASR32di (ASR32di (SMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8),
+ MxSubRegIndex16Lo)>;
+
+def : Pat<(mulhu i16:$dst, MximmSExt16:$opd),
+ (EXTRACT_SUBREG
+ (LSR32di (LSR32di (UMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8),
+ MxSubRegIndex16Lo)>;
+
+
+//===----------------------------------------------------------------------===//
+// NEG/NEGX
+//===----------------------------------------------------------------------===//
+
+/// ------------+------------+------+---------+---------
+/// F E D C | B A 9 8 | 7 6 | 5 4 3 | 2 1 0
+/// ------------+------------+------+-------------------
+/// | | | EFFECTIVE ADDRESS
+/// 0 1 0 0 | x x x x | SIZE | MODE | REG
+/// ------------+------------+------+---------+---------
+class MxNEGEncoding<MxBead4Bits CMD, MxEncSize SIZE, MxEncEA EA, MxEncExt EXT>
+ : MxEncoding<EA.Reg, EA.DA, EA.Mode, SIZE, CMD, MxBead4Bits<0b0100>,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
+
+let Defs = [CCR] in {
+let Constraints = "$src = $dst" in {
+
+class MxNeg_D<MxType TYPE>
+ : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src),
+ "neg."#TYPE.Prefix#"\t$dst",
+ [(set TYPE.VT:$dst, (ineg TYPE.VT:$src))],
+ MxNEGEncoding<MxBead4Bits<0x4>,
+ !cast<MxEncSize>("MxEncSize"#TYPE.Size),
+ MxEncEAd_0, MxExtEmpty>>;
+
+let Uses = [CCR] in {
+class MxNegX_D<MxType TYPE>
+ : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src),
+ "negx."#TYPE.Prefix#"\t$dst",
+ [(set TYPE.VT:$dst, (MxSubX 0, TYPE.VT:$src, CCR))],
+ MxNEGEncoding<MxBead4Bits<0x0>,
+ !cast<MxEncSize>("MxEncSize"#TYPE.Size),
+ MxEncEAd_0, MxExtEmpty>>;
+}
+
+} // let Constraints
+} // let Defs = [CCR]
+
+foreach S = [8, 16, 32] in {
+ def NEG#S#d : MxNeg_D<!cast<MxType>("MxType"#S#"d")>;
+ def NEGX#S#d : MxNegX_D<!cast<MxType>("MxType"#S#"d")>;
+}
+
+def : Pat<(MxSub 0, i8 :$src), (NEG8d MxDRD8 :$src)>;
+def : Pat<(MxSub 0, i16:$src), (NEG16d MxDRD16:$src)>;
+def : Pat<(MxSub 0, i32:$src), (NEG32d MxDRD32:$src)>;
+
+//===----------------------------------------------------------------------===//
+// no-CCR Patterns
+//===----------------------------------------------------------------------===//
+
+/// Basically the reason for this stuff is that add and addc share the same
+/// operand types constraints for whatever reasons and I had to define a common
+/// MxAdd and MxSub instructions that produce CCR and then pattern-map add and addc
+/// to it.
+/// NOTE On the other hand I see no reason why I cannot just drop explicit CCR
+/// result. Anyway works for now, hopefully I will better understand how this stuff
+/// is designed later
+foreach N = ["add", "addc"] in {
+
+ // add reg, reg
+ def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd),
+ (ADD8dd MxDRD8 :$src, MxDRD8 :$opd)>;
+ def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
+ (ADD16dd MxDRD16:$src, MxDRD16:$opd)>;
+ def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
+ (ADD32rr MxXRD32:$src, MxXRD32:$opd)>;
+
+ // add (An), reg
+ def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)),
+ (ADD8dj MxDRD8:$src, MxType8.JOp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
+ (ADD16dj MxDRD16:$src, MxType16.JOp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
+ (ADD32rj MxXRD32:$src, MxType32.JOp:$opd)>;
+
+ // add (i,An), reg
+ def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
+ (ADD8dp MxDRD8:$src, MxType8.POp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
+ (ADD16dp MxDRD16:$src, MxType16.POp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
+ (ADD32rp MxXRD32:$src, MxType32.POp:$opd)>;
+
+ // add (i,An,Xn), reg
+ def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
+ (ADD8df MxDRD8:$src, MxType8.FOp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
+ (ADD16df MxDRD16:$src, MxType16.FOp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
+ (ADD32rf MxXRD32:$src, MxType32.FOp:$opd)>;
+
+ // add reg, imm
+ def : Pat<(!cast<SDNode>(N) i8: $src, MximmSExt8:$opd),
+ (ADD8di MxDRD8 :$src, imm:$opd)>;
+ def : Pat<(!cast<SDNode>(N) i16:$src, MximmSExt16:$opd),
+ (ADD16di MxDRD16:$src, imm:$opd)>;
+
+ // LEAp is more complex and thus will be selected over normal ADD32ri but it cannot
+ // be used with data registers, here by adding complexity to a simple ADD32ri insts
+ // we make sure it will be selected over LEAp
+ let AddedComplexity = 15 in {
+ def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd),
+ (ADD32ri MxXRD32:$src, imm:$opd)>;
+ } // AddedComplexity = 15
+
+ // add imm, (An)
+ def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd),
+ MxType8.JPat:$dst),
+ (ADD8ji MxType8.JOp:$dst, imm:$opd)>;
+ def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd),
+ MxType16.JPat:$dst),
+ (ADD16ji MxType16.JOp:$dst, imm:$opd)>;
+ def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd),
+ MxType32.JPat:$dst),
+ (ADD32ji MxType32.JOp:$dst, imm:$opd)>;
+
+} // foreach add, addc
+
+def : Pat<(adde i8 :$src, i8 :$opd), (ADDX8dd MxDRD8 :$src, MxDRD8 :$opd)>;
+def : Pat<(adde i16:$src, i16:$opd), (ADDX16dd MxDRD16:$src, MxDRD16:$opd)>;
+def : Pat<(adde i32:$src, i32:$opd), (ADDX32dd MxDRD32:$src, MxDRD32:$opd)>;
+
+
+
+foreach N = ["sub", "subc"] in {
+
+ // sub reg, reg
+ def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd),
+ (SUB8dd MxDRD8 :$src, MxDRD8 :$opd)>;
+ def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd),
+ (SUB16dd MxDRD16:$src, MxDRD16:$opd)>;
+ def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd),
+ (SUB32rr MxXRD32:$src, MxXRD32:$opd)>;
+
+
+ // sub (An), reg
+ def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)),
+ (SUB8dj MxDRD8:$src, MxType8.JOp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)),
+ (SUB16dj MxDRD16:$src, MxType16.JOp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)),
+ (SUB32rj MxXRD32:$src, MxType32.JOp:$opd)>;
+
+ // sub (i,An), reg
+ def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)),
+ (SUB8dp MxDRD8:$src, MxType8.POp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)),
+ (SUB16dp MxDRD16:$src, MxType16.POp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)),
+ (SUB32rp MxXRD32:$src, MxType32.POp:$opd)>;
+
+ // sub (i,An,Xn), reg
+ def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)),
+ (SUB8df MxDRD8:$src, MxType8.FOp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)),
+ (SUB16df MxDRD16:$src, MxType16.FOp:$opd)>;
+ def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)),
+ (SUB32rf MxXRD32:$src, MxType32.FOp:$opd)>;
+
+ // sub reg, imm
+ def : Pat<(!cast<SDNode>(N) i8 :$src, MximmSExt8 :$opd),
+ (SUB8di MxDRD8 :$src, imm:$opd)>;
+ def : Pat<(!cast<SDNode>(N) i16:$src, MximmSExt16:$opd),
+ (SUB16di MxDRD16:$src, imm:$opd)>;
+ def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd),
+ (SUB32ri MxXRD32:$src, imm:$opd)>;
+
+ // sub imm, (An)
+ def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd),
+ MxType8.JPat:$dst),
+ (SUB8ji MxType8.JOp:$dst, imm:$opd)>;
+ def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd),
+ MxType16.JPat:$dst),
+ (SUB16ji MxType16.JOp:$dst, imm:$opd)>;
+ def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd),
+ MxType32.JPat:$dst),
+ (SUB32ji MxType32.JOp:$dst, imm:$opd)>;
+
+} // foreach sub, subx
+
+def : Pat<(sube i8 :$src, i8 :$opd), (SUBX8dd MxDRD8 :$src, MxDRD8 :$opd)>;
+def : Pat<(sube i16:$src, i16:$opd), (SUBX16dd MxDRD16:$src, MxDRD16:$opd)>;
+def : Pat<(sube i32:$src, i32:$opd), (SUBX32dd MxDRD32:$src, MxDRD32:$opd)>;
+
+
+// and reg, reg
+def : Pat<(and i8 :$src, i8 :$opd), (AND8dd MxDRD8 :$src, MxDRD8 :$opd)>;
+def : Pat<(and i16:$src, i16:$opd), (AND16dd MxDRD16:$src, MxDRD16:$opd)>;
+def : Pat<(and i32:$src, i32:$opd), (AND32dd MxDRD32:$src, MxDRD32:$opd)>;
+
+// and reg, imm
+def : Pat<(and i8: $src, MximmSExt8 :$opd), (AND8di MxDRD8 :$src, imm:$opd)>;
+def : Pat<(and i16:$src, MximmSExt16:$opd), (AND16di MxDRD16:$src, imm:$opd)>;
+def : Pat<(and i32:$src, MximmSExt32:$opd), (AND32di MxDRD32:$src, imm:$opd)>;
+
+
+// xor reg,reg
+def : Pat<(xor i8 :$src, i8 :$opd), (XOR8dd MxDRD8 :$src, MxDRD8 :$opd)>;
+def : Pat<(xor i16:$src, i16:$opd), (XOR16dd MxDRD16:$src, MxDRD16:$opd)>;
+def : Pat<(xor i32:$src, i32:$opd), (XOR32dd MxDRD32:$src, MxDRD32:$opd)>;
+
+// xor reg, imm
+def : Pat<(xor i8: $src, MximmSExt8 :$opd), (XOR8di MxDRD8 :$src, imm:$opd)>;
+def : Pat<(xor i16:$src, MximmSExt16:$opd), (XOR16di MxDRD16:$src, imm:$opd)>;
+def : Pat<(xor i32:$src, MximmSExt32:$opd), (XOR32di MxDRD32:$src, imm:$opd)>;
+
+
+// or reg, reg
+def : Pat<(or i8 :$src, i8 :$opd), (OR8dd MxDRD8 :$src, MxDRD8 :$opd)>;
+def : Pat<(or i16:$src, i16:$opd), (OR16dd MxDRD16:$src, MxDRD16:$opd)>;
+def : Pat<(or i32:$src, i32:$opd), (OR32dd MxDRD32:$src, MxDRD32:$opd)>;
+
+// or reg, imm
+def : Pat<(or i8: $src, MximmSExt8 :$opd), (OR8di MxDRD8 :$src, imm:$opd)>;
+def : Pat<(or i16:$src, MximmSExt16:$opd), (OR16di MxDRD16:$src, imm:$opd)>;
+def : Pat<(or i32:$src, MximmSExt32:$opd), (OR32di MxDRD32:$src, imm:$opd)>;
diff --git a/llvm/lib/Target/M68k/M68kInstrBits.td b/llvm/lib/Target/M68k/M68kInstrBits.td
new file mode 100644
index 000000000000..96d536520939
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kInstrBits.td
@@ -0,0 +1,100 @@
+//===------- M68kInstrBits.td - Bit Manipulation Instrs --*- tablegen -*-===//
+//
+// 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 describes the bit manipulation instructions in the M68k
+/// architecture. Here is the current status of the file:
+///
+/// Machine:
+///
+/// BCNG [ ] BCLR [ ] BSET [ ] BTST [~]
+///
+/// Map:
+///
+/// [ ] - was not touched at all
+/// [!] - requires extarnal stuff implemented
+/// [~] - in progress but usable
+/// [x] - done
+///
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// BTST
+//===----------------------------------------------------------------------===//
+
+/// ------------+---------+---------+---------+---------
+/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0
+/// ------------+---------+---------+---------+---------
+/// 0 0 0 0 | REG | 1 0 0 | MODE | REG
+/// ------------+---------+---------+---------+---------
+class MxBTSTEnc_R<MxBeadReg REG, MxEncEA EA, MxEncExt EXT>
+ : MxEncoding<EA.Reg, EA.DA, EA.Mode, MxBead3Bits<0b100>, REG, MxBead4Bits<0b0000>,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
+
+/// -------------------------------+---------+---------
+/// F E D C B A 9 8 . 7 6 | 5 4 3 | 2 1 0
+/// -------------------------------+---------+---------
+/// 0 0 0 0 1 0 0 0 . 0 0 | MODE | REG
+/// ------------------------+------+---------+---------
+/// 0 0 0 0 0 0 0 0 | BIT NUMBER
+/// ------------------------+--------------------------
+class MxBTSTEnc_I<MxBead8Imm IMM, MxEncEA EA, MxEncExt EXT>
+ : MxEncoding<EA.Reg, EA.DA, EA.Mode, MxBead2Bits<0b00>,
+ MxBead4Bits<0b1000>, MxBead4Bits<0b0000>, IMM,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
+
+let Defs = [CCR] in {
+class MxBTST_RR<MxType TYPE>
+ : MxInst<(outs), (ins TYPE.ROp:$dst, TYPE.ROp:$bitno), "btst\t$bitno, $dst",
+ [(set CCR, (MxBt TYPE.VT:$dst, TYPE.VT:$bitno))],
+ MxBTSTEnc_R<MxBeadReg<1>, MxEncEAd_0, MxExtEmpty>>;
+
+class MxBTST_RI<MxType TYPE>
+ : MxInst<(outs), (ins TYPE.ROp:$dst, TYPE.IOp:$bitno), "btst\t$bitno, $dst",
+ [(set CCR, (MxBt TYPE.VT:$dst, TYPE.IPat:$bitno))],
+ MxBTSTEnc_I<MxBead8Imm<1>, MxEncEAd_0, MxExtEmpty>>;
+
+class MxBTST_MR<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
+ MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins MEMOpd:$dst, TYPE.ROp:$bitno), "btst\t$bitno, $dst",
+ [(set CCR, (MxBt (TYPE.Load MEMPat:$dst), TYPE.VT:$bitno))],
+ MxBTSTEnc_R<MxBeadReg<1>, EA, EXT>>;
+
+class MxBTST_MI<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat,
+ MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins MEMOpd:$dst, TYPE.IOp:$bitno), "btst\t$bitno, $dst",
+ [(set CCR, (MxBt (TYPE.Load MEMPat:$dst), TYPE.IPat:$bitno))],
+ MxBTSTEnc_I<MxBead8Imm<1>, EA, EXT>>;
+} // Defs = [CCR]
+
+// Register BTST limited to 32 bits only
+def BTST32dd : MxBTST_RR<MxType32d>;
+def BTST32di : MxBTST_RI<MxType32d>;
+
+// Memory BTST limited to 8 bits only
+def BTST8jd : MxBTST_MR<MxType8d, MxType8.JOp, MxType8.JPat,
+ MxEncEAj_0, MxExtEmpty>;
+def BTST8pd : MxBTST_MR<MxType8d, MxType8.POp, MxType8.PPat,
+ MxEncEAp_0, MxExtI16_0>;
+def BTST8fd : MxBTST_MR<MxType8d, MxType8.FOp, MxType8.FPat,
+ MxEncEAf_0, MxExtBrief_0>;
+def BTST8qd : MxBTST_MR<MxType8d, MxType8.QOp, MxType8.QPat,
+ MxEncEAq, MxExtI16_0>;
+def BTST8kd : MxBTST_MR<MxType8d, MxType8.KOp, MxType8.KPat,
+ MxEncEAk, MxExtBrief_0>;
+
+def BTST8ji : MxBTST_MI<MxType8d, MxType8.JOp, MxType8.JPat,
+ MxEncEAj_0, MxExtEmpty>;
+def BTST8pi : MxBTST_MI<MxType8d, MxType8.POp, MxType8.PPat,
+ MxEncEAp_0, MxExtI16_0>;
+def BTST8fi : MxBTST_MI<MxType8d, MxType8.FOp, MxType8.FPat,
+ MxEncEAf_0, MxExtBrief_0>;
+def BTST8qi : MxBTST_MI<MxType8d, MxType8.QOp, MxType8.QPat,
+ MxEncEAq, MxExtI16_0>;
+def BTST8ki : MxBTST_MI<MxType8d, MxType8.KOp, MxType8.KPat,
+ MxEncEAk, MxExtBrief_0>;
diff --git a/llvm/lib/Target/M68k/M68kInstrCompiler.td b/llvm/lib/Target/M68k/M68kInstrCompiler.td
new file mode 100644
index 000000000000..4d1d20745158
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kInstrCompiler.td
@@ -0,0 +1,128 @@
+//===-- M68kInstrCompiler.td - Pseudos and Patterns ------*- tablegen -*-===//
+//
+// 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 describes the various pseudo instructions used by the compiler,
+/// as well as Pat patterns used during instruction selection.
+///
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// ConstantPool, GlobalAddress, ExternalSymbol, and JumpTable
+//===----------------------------------------------------------------------===//
+
+def : Pat<(i32 (MxWrapper tconstpool :$src)), (MOV32ri tconstpool :$src)>;
+def : Pat<(i32 (MxWrapper tglobaladdr :$src)), (MOV32ri tglobaladdr :$src)>;
+def : Pat<(i32 (MxWrapper texternalsym :$src)), (MOV32ri texternalsym :$src)>;
+def : Pat<(i32 (MxWrapper tjumptable :$src)), (MOV32ri tjumptable :$src)>;
+def : Pat<(i32 (MxWrapper tblockaddress :$src)), (MOV32ri tblockaddress :$src)>;
+
+def : Pat<(add MxDRD32:$src, (MxWrapper tconstpool:$opd)),
+ (ADD32ri MxDRD32:$src, tconstpool:$opd)>;
+def : Pat<(add MxARD32:$src, (MxWrapper tjumptable:$opd)),
+ (ADD32ri MxARD32:$src, tjumptable:$opd)>;
+def : Pat<(add MxARD32:$src, (MxWrapper tglobaladdr :$opd)),
+ (ADD32ri MxARD32:$src, tglobaladdr:$opd)>;
+def : Pat<(add MxARD32:$src, (MxWrapper texternalsym:$opd)),
+ (ADD32ri MxARD32:$src, texternalsym:$opd)>;
+def : Pat<(add MxARD32:$src, (MxWrapper tblockaddress:$opd)),
+ (ADD32ri MxARD32:$src, tblockaddress:$opd)>;
+
+def : Pat<(store (i32 (MxWrapper tglobaladdr:$src)), iPTR:$dst),
+ (MOV32ji MxARI32:$dst, tglobaladdr:$src)>;
+def : Pat<(store (i32 (MxWrapper texternalsym:$src)), iPTR:$dst),
+ (MOV32ji MxARI32:$dst, texternalsym:$src)>;
+def : Pat<(store (i32 (MxWrapper tblockaddress:$src)), iPTR:$dst),
+ (MOV32ji MxARI32:$dst, tblockaddress:$src)>;
+
+def : Pat<(i32 (MxWrapperPC tconstpool :$src)), (LEA32q tconstpool :$src)>;
+def : Pat<(i32 (MxWrapperPC tglobaladdr :$src)), (LEA32q tglobaladdr :$src)>;
+def : Pat<(i32 (MxWrapperPC texternalsym :$src)), (LEA32q texternalsym :$src)>;
+def : Pat<(i32 (MxWrapperPC tjumptable :$src)), (LEA32q tjumptable :$src)>;
+def : Pat<(i32 (MxWrapperPC tblockaddress :$src)), (LEA32q tblockaddress :$src)>;
+
+
+//===----------------------------------------------------------------------===//
+// Conditional Move Pseudo Instructions
+//
+// CMOV* - Used to implement the SELECT DAG operation. Expanded after
+// instruction selection into a branch sequence.
+//===----------------------------------------------------------------------===//
+
+let usesCustomInserter = 1, Uses = [CCR] in
+class MxCMove<MxType TYPE>
+ : MxPseudo<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$t, TYPE.ROp:$f, i8imm:$cond),
+ "",
+ [(set TYPE.VT:$dst,
+ (TYPE.VT (MxCmov TYPE.VT:$t, TYPE.VT:$f, imm:$cond, CCR)))]>;
+
+def CMOV8d : MxCMove<MxType8d>;
+def CMOV16d : MxCMove<MxType16d>;
+def CMOV32r : MxCMove<MxType32r>;
+
+
+//===----------------------------------------------------------------------===//
+// Calls
+//===----------------------------------------------------------------------===//
+
+// ADJCALLSTACKDOWN/UP implicitly use/def %SP because they may be expanded into
+// a stack adjustment and the codegen must know that they may modify the stack
+// pointer before prolog-epilog rewriting occurs.
+// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
+// sub / add which can clobber CCR.
+let Defs = [SP, CCR], Uses = [SP] in {
+
+ def ADJCALLSTACKDOWN
+ : MxPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), "#ADJCALLSTACKDOWN",
+ [(MxCallSeqStart timm:$amt1, timm:$amt2)]>;
+
+ def ADJCALLSTACKUP
+ : MxPseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), "#ADJCALLSTACKUP",
+ [(MxCallSeqEnd timm:$amt1, timm:$amt2)]>;
+
+} // Defs
+
+//===----------------------------------------------------------------------===//
+// Tail Call
+//===----------------------------------------------------------------------===//
+
+// Tailcall stuff. The TCRETURN instructions execute after the epilog, so they
+// can never use callee-saved registers. That is the purpose of the XR32_TC
+// register classes.
+
+// FIXME TC is disabled for PIC mode because the global base
+// register which is part of the address mode may be assigned a
+// callee-saved register.
+def : Pat<(MxTCRet (load MxCP_ARII:$dst), imm:$adj),
+ (TCRETURNj (MOV32af_TC MxARII32:$dst), imm:$adj)>,
+ Requires<[IsNotPIC]>;
+
+def : Pat<(MxTCRet AR32_TC:$dst, imm:$adj),
+ (TCRETURNj MxARI32_TC:$dst, imm:$adj)>;
+
+def : Pat<(MxTCRet (i32 tglobaladdr:$dst), imm:$adj),
+ (TCRETURNq MxPCD32:$dst, imm:$adj)>;
+
+def : Pat<(MxTCRet (i32 texternalsym:$dst), imm:$adj),
+ (TCRETURNq MxPCD32:$dst, imm:$adj)>;
+
+
+//===----------------------------------------------------------------------===//
+// Segmented Stack
+//
+// When using segmented stacks these are lowered into instructions which first
+// check if the current stacklet has enough free memory. If it does, memory is
+// allocated by bumping the stack pointer. Otherwise memory is allocated from
+// the heap.
+//===----------------------------------------------------------------------===//
+
+let Defs = [SP, CCR], Uses = [SP] in
+let usesCustomInserter = 1 in
+def SALLOCA : MxPseudo<(outs MxARD32:$dst), (ins MxARD32:$size),
+ "# variable sized alloca for segmented stacks",
+ [(set iPTR:$dst, (MxSegAlloca iPTR:$size))]>;
diff --git a/llvm/lib/Target/M68k/M68kInstrControl.td b/llvm/lib/Target/M68k/M68kInstrControl.td
new file mode 100644
index 000000000000..567e6b0427fb
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kInstrControl.td
@@ -0,0 +1,317 @@
+//===-- M68kInstrControl.td - Control Flow Instructions --*- tablegen -*-===//
+//
+// 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 describes the M68k jump, return, call, and related instructions.
+/// Here is the current status of the file:
+///
+/// Machine:
+///
+/// BRA [x] BSR [ ] Bcc [ ] DBcc [ ] FBcc [ ]
+/// FDBcc [ ] FNOP [ ] FPn [ ] FScc [ ] FTST [ ]
+/// JMP [~] JSR [x] NOP [x] RTD [!] RTR [ ]
+/// RTS [x] Scc [x] TST [ ]
+///
+/// Pseudo:
+///
+/// RET [x]
+/// TCRETURNj [x] TCRETURNq [x]
+/// TAILJMPj [x] TAILJMPq [x]
+///
+/// Map:
+///
+/// [ ] - was not touched at all
+/// [!] - requires extarnal stuff implemented
+/// [~] - in progress but usable
+/// [x] - done
+///
+///
+/// NOTE
+/// Though branch and jump instructions are using memory operands they
+/// DO NOT read the jump address from memory, they just calculate EA
+/// and jump there.
+///
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// NOP
+//===----------------------------------------------------------------------===//
+
+let hasSideEffects = 0 in {
+ def NOP : MxInst<(outs), (ins), "nop", [], MxEncFixed<0x4E71>>;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Conditions
+//===----------------------------------------------------------------------===//
+
+/// CC—Carry clear GE—Greater than or equal
+/// LS—Lower or same PL—Plus
+/// CS—Carry set GT—Greater than
+/// LT—Less than T—Always true*
+/// EQ—Equal HI—Higher
+/// MI—Minus VC—Overflow clear
+/// F—Never true* LE—Less than or equal
+/// NE—Not equal VS—Overflow set
+///
+/// *Not applicable to the Bcc instructions.
+def MxCCt : MxBead4Bits<0b0000>;
+def MxCCf : MxBead4Bits<0b0001>;
+def MxCChi : MxBead4Bits<0b0010>;
+def MxCCls : MxBead4Bits<0b0011>;
+def MxCCcc : MxBead4Bits<0b0100>;
+def MxCCcs : MxBead4Bits<0b0101>;
+def MxCCne : MxBead4Bits<0b0110>;
+def MxCCeq : MxBead4Bits<0b0111>;
+def MxCCvc : MxBead4Bits<0b1000>;
+def MxCCvs : MxBead4Bits<0b1001>;
+def MxCCpl : MxBead4Bits<0b1010>;
+def MxCCmi : MxBead4Bits<0b1011>;
+def MxCCge : MxBead4Bits<0b1100>;
+def MxCClt : MxBead4Bits<0b1101>;
+def MxCCgt : MxBead4Bits<0b1110>;
+def MxCCle : MxBead4Bits<0b1111>;
+
+/// --------------------------------+---------+---------
+/// F E D C | B A 9 8 | 7 6 | 5 4 3 | 2 1 0
+/// --------------------------------+---------+---------
+/// 0 1 0 1 | CONDITION | 1 1 | MODE | REG
+/// ----------------------------------------------------
+class MxSccEncoding<MxEncEA EA, MxEncExt EXT, MxBead4Bits CC>
+ : MxEncoding<EA.Reg, EA.DA, EA.Mode, MxBead2Bits<0b11>, CC, MxBead4Bits<0b0101>,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
+
+let Uses = [CCR] in {
+class MxSccR<string CC>
+ : MxInst<(outs MxDRD8:$dst), (ins), "s"#CC#"\t$dst",
+ [(set i8:$dst, (MxSetCC !cast<PatLeaf>("MxCOND"#CC), CCR))],
+ MxSccEncoding<MxEncEAd_0, MxExtEmpty,
+ !cast<MxBead4Bits>("MxCC"#CC)>>;
+
+class MxSccM<string CC, MxOperand MEMOpd, ComplexPattern MEMPat,
+ MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins MEMOpd:$dst), "s"#CC#"\t$dst",
+ [(store (MxSetCC !cast<PatLeaf>("MxCOND"#CC), CCR), MEMPat:$dst)],
+ MxSccEncoding<EA, EXT, !cast<MxBead4Bits>("MxCC"#CC)>>;
+}
+
+foreach cc = [ "cc", "ls", "lt", "eq", "mi", "f", "ne", "ge",
+ "cs", "pl", "gt", "t", "hi", "vc", "le", "vs"] in {
+def SET#"d8"#cc : MxSccR<cc>;
+def SET#"j8"#cc : MxSccM<cc, MxType8.JOp, MxType8.JPat, MxEncEAj_0, MxExtEmpty>;
+def SET#"p8"#cc : MxSccM<cc, MxType8.POp, MxType8.PPat, MxEncEAp_0, MxExtI16_0>;
+}
+
+//===----------------------------------------------------------------------===//
+// Jumps
+//===----------------------------------------------------------------------===//
+
+///------------------------------+---------+---------
+/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0
+///------------------------------+---------+---------
+/// 0 1 0 0 1 1 1 0 1 1 | MODE | REG
+///------------------------------+---------+---------
+let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in
+class MxJMP<MxOperand LOCOp, ComplexPattern LOCPat, MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins LOCOp:$dst), "jmp\t$dst", [(brind iPTR:$dst)],
+ MxEncoding<EA.Reg, EA.DA, EA.Mode, MxBead2Bits<0b11>,
+ MxBead4Bits<0b1110>, MxBead4Bits<0b0100>,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
+
+def JMP32j : MxJMP<MxARI32, MxCP_ARI, MxEncEAj_0, MxExtEmpty>;
+
+
+// FIXME Support 16 bit indirect jump.
+// Currently M68k does not allow 16 bit indirect jumps use sext operands
+// def JMP16r : MxInst<(outs), (ins M68k_ARI16:$dst),
+// "jmp\t$dst",
+// [(brind AR16:$dst)]>;
+
+//===----------------------------------------------------------------------===//
+// Branches
+//===----------------------------------------------------------------------===//
+
+/// --------------------------------------------------
+/// F E D C | B A 9 8 | 7 6 5 4 3 2 1 0
+/// --------------------------------------------------
+/// 0 1 1 0 | CONDITION | 8-BIT DISPLACEMENT
+/// --------------------------------------------------
+/// 16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00
+/// --------------------------------------------------
+/// 32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF
+/// --------------------------------------------------
+let isBranch = 1, isTerminator = 1, Uses = [CCR] in
+class MxBcc<string cc, Operand TARGET, MxType TYPE, MxEncoding ENC = MxEncEmpty>
+ : MxInst<(outs), (ins TARGET:$dst), "b"#cc#"\t$dst", [], ENC>;
+
+foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
+ "cs", "pl", "gt", "hi", "vc", "le", "vs"] in {
+ def B#cc#"8"
+ : MxBcc<cc, MxBrTarget8, MxType8,
+ MxEncoding<MxBead8Disp<0>,
+ !cast<MxBead4Bits>("MxCC"#cc), MxBead4Bits<0x6>>>;
+ def B#cc#"16"
+ : MxBcc<cc, MxBrTarget16, MxType16,
+ MxEncoding<MxBead4Bits<0x0>,
+ MxBead4Bits<0x0>, !cast<MxBead4Bits>("MxCC"#cc),
+ MxBead4Bits<0x6>, MxBead16Imm<0>>>;
+}
+
+foreach cc = [ "cc", "ls", "lt", "eq", "mi", "ne", "ge",
+ "cs", "pl", "gt", "hi", "vc", "le", "vs"] in {
+def : Pat<(MxBrCond bb:$target, !cast<PatLeaf>("MxCOND"#cc), CCR),
+ (!cast<Instruction>("B"#cc#"8") MxBrTarget8:$target)>;
+}
+
+/// -------------------------------------------------
+/// F E D C B A 9 8 | 7 6 5 4 3 2 1 0
+/// -------------------------------------------------
+/// 0 1 1 0 0 0 0 0 | 8-BIT DISPLACEMENT
+/// -------------------------------------------------
+/// 16-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $00
+/// -------------------------------------------------
+/// 32-BIT DISPLACEMENT IF 8-BIT DISPLACEMENT = $FF
+/// -------------------------------------------------
+let isBranch = 1, isTerminator = 1, isBarrier=1 in
+class MxBra<Operand TARGET, MxType TYPE, MxEncoding ENC = MxEncEmpty>
+ : MxInst<(outs), (ins TARGET:$dst), "bra\t$dst", [], ENC>;
+
+def BRA8 : MxBra<MxBrTarget8, MxType8,
+ MxEncoding<MxBead8Disp<0>, MxBead4Bits<0x0>,
+ MxBead4Bits<0x6>>>;
+def BRA16 : MxBra<MxBrTarget16, MxType16,
+ MxEncoding<MxBead4Bits<0x0>, MxBead4Bits<0x0>,
+ MxBead4Bits<0x0>, MxBead4Bits<0x6>,
+ MxBead16Imm<0>>>;
+
+def : Pat<(br bb:$target), (BRA8 MxBrTarget8:$target)>;
+
+
+//===----------------------------------------------------------------------===//
+// Call
+//===----------------------------------------------------------------------===//
+
+// All calls clobber the non-callee saved registers. %SP is marked as
+// a use to prevent stack-pointer assignments that appear immediately
+// before calls from potentially appearing dead. Uses for argument
+// registers are added manually.
+let Uses = [SP] in
+let isCall = 1 in
+///------------------------------+---------+---------
+/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0
+///------------------------------+---------+---------
+/// 0 1 0 0 1 1 1 0 1 0 | MODE | REG
+///------------------------------+---------+---------
+class MxCall<MxOperand LOCOp, MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins LOCOp:$dst), "jsr\t$dst", [],
+ MxEncoding<EA.Reg, EA.DA, EA.Mode, MxBead2Bits<0b10>,
+ MxBead4Bits<0b1110>, MxBead4Bits<0b0100>,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
+
+def CALLk : MxCall<MxPCI32, MxEncEAk, MxExtBrief_0>;
+def CALLq : MxCall<MxPCD32, MxEncEAq, MxExtI16_0>;
+def CALLb : MxCall<MxAL32, MxEncEAb, MxExtI32_0>;
+def CALLj : MxCall<MxARI32, MxEncEAj_0, MxExtEmpty>;
+
+multiclass CallPat<MxCall callOp, Predicate pred> {
+ let Predicates = [pred] in {
+ def : Pat<(MxCall (i32 tglobaladdr:$dst)), (callOp tglobaladdr:$dst)>;
+ def : Pat<(MxCall (i32 texternalsym:$dst)), (callOp texternalsym:$dst)>;
+ def : Pat<(MxCall (i32 imm:$dst)), (callOp imm:$dst)>;
+ }
+}
+
+defm : CallPat<CALLq, IsPIC>;
+defm : CallPat<CALLb, IsNotPIC>;
+
+def : Pat<(MxCall iPTR:$dst), (CALLj MxARI32:$dst)>;
+
+//===----------------------------------------------------------------------===//
+// Tail Call
+//===----------------------------------------------------------------------===//
+
+let isCodeGenOnly = 1 in {
+let Uses = [SP] in {
+let isCall = 1, isTerminator = 1, isBarrier = 1 in {
+
+let isReturn = 1 in
+def TCRETURNq : MxPseudo<(outs), (ins MxPCD32:$dst, i32imm:$adj)>;
+def TAILJMPq : MxPseudo<(outs), (ins MxPCD32:$dst)>;
+
+// NOTE j does not mean load and jump M68k jmp just calculates EA and jumps
+// and it is using Mem form like (An) thus j letter.
+let isReturn = 1 in
+def TCRETURNj : MxPseudo<(outs), (ins MxARI32_TC:$dst, i32imm:$adj)>;
+def TAILJMPj : MxPseudo<(outs), (ins MxARI32_TC:$dst)>;
+} // isCall = 1, isTerminator = 1, isBarrier = 1
+} // Uses = [SP]
+} // isCodeGenOnly = 1
+
+//===----------------------------------------------------------------------===//
+// Return
+//===----------------------------------------------------------------------===//
+
+// TODO Implement LINK/UNLK
+
+let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in {
+
+def RTS : MxInst<(outs), (ins), "rts", [], MxEncFixed<0x4E75>>;
+
+let isCodeGenOnly = 1 in
+def RET : MxPseudo<(outs), (ins i32imm:$adj, variable_ops), "",
+ [(MxRet timm:$adj)]>;
+} // isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1
+
+//===----------------------------------------------------------------------===//
+// SETCC_C Patterns
+//===----------------------------------------------------------------------===//
+
+// Use subx to materialize carry bit.
+let Uses = [CCR], Defs = [CCR], isPseudo = 1 in {
+// FIXME These are pseudo ops that should be replaced with Pat<> patterns.
+// However, Pat<> can't replicate the destination reg into the inputs of the
+// result.
+def SETCS_C8d : MxPseudo<(outs MxDRD8:$dst), (ins), "",
+ [(set MxDRD8:$dst, (MxSetCC_C MxCONDcs, CCR))]>;
+def SETCS_C16d : MxPseudo<(outs MxDRD16:$dst), (ins), "",
+ [(set MxDRD16:$dst, (MxSetCC_C MxCONDcs, CCR))]>;
+def SETCS_C32d : MxPseudo<(outs MxXRD32:$dst), (ins), "",
+ [(set MxXRD32:$dst, (MxSetCC_C MxCONDcs, CCR))]>;
+} // Uses = [CCR], Defs = [CCR], isPseudo = 1
+
+
+def : Pat<(i16 (anyext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C16d)>;
+def : Pat<(i32 (anyext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C32d)>;
+
+def : Pat<(i16 (sext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C16d)>;
+def : Pat<(i32 (sext (i8 (MxSetCC_C MxCONDcs, CCR)))), (SETCS_C32d)>;
+
+// We canonicalize 'scs' to "(and (subx reg,reg), 1)" on the hope that the and
+// will be eliminated and that the subx can be extended up to a wider type. When
+// this happens, it is great. However, if we are left with an 8-bit subx and an
+// and, we might as well just match it as a setb.
+def : Pat<(and (i8 (MxSetCC_C MxCONDcs, CCR)), 1), (SETd8cs)>;
+
+// (add OP, SETB) -> (addx OP, (move 0))
+def : Pat<(add (and (i8 (MxSetCC_C MxCONDcs, CCR)), 1), MxDRD8:$op),
+ (ADDX8dd MxDRD8:$op, (MOV8di 0))>;
+def : Pat<(add (and (i32 (MxSetCC_C MxCONDcs, CCR)), 1), MxXRD32:$op),
+ (ADDX32dd MxDRD32:$op, (MOV32ri 0))>;
+
+// (sub OP, SETB) -> (subx OP, (move 0))
+def : Pat<(sub MxDRD8:$op, (and (i8 (MxSetCC_C MxCONDcs, CCR)), 1)),
+ (SUBX8dd MxDRD8:$op, (MOV8di 0))>;
+def : Pat<(sub MxXRD32:$op, (and (i32 (MxSetCC_C MxCONDcs, CCR)), 1)),
+ (SUBX32dd MxDRD32:$op, (MOV32ri 0))>;
+
+// (sub OP, SETCC_CARRY) -> (addx OP, (move 0))
+def : Pat<(sub MxDRD8:$op, (i8 (MxSetCC_C MxCONDcs, CCR))),
+ (ADDX8dd MxDRD8:$op, (MOV8di 0))>;
+def : Pat<(sub MxXRD32:$op, (i32 (MxSetCC_C MxCONDcs, CCR))),
+ (ADDX32dd MxDRD32:$op, (MOV32ri 0))>;
diff --git a/llvm/lib/Target/M68k/M68kInstrData.td b/llvm/lib/Target/M68k/M68kInstrData.td
new file mode 100644
index 000000000000..74db3a3daca5
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kInstrData.td
@@ -0,0 +1,712 @@
+//== M68kInstrData.td - M68k Data Movement Instructions -*- tablegen --===//
+//
+// 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 describes the Motorola 680x0 data movement instructions which are
+/// the basic means of transferring and storing addresses and data. Here is the
+/// current status of the file:
+///
+/// Machine:
+///
+/// EXG [ ] FMOVE [ ] FSMOVE [ ] FDMOVE [ ] FMOVEM [ ]
+/// LEA [~] PEA [ ] MOVE [~] MOVE16 [ ] MOVEA [ ]
+/// MOVEM [ ] MOVEP [ ] MOVEQ [ ] LINK [ ] UNLK [ ]
+///
+/// Pseudo:
+///
+/// MOVSX [x] MOVZX [x] MOVX [x]
+///
+/// Map:
+///
+/// [ ] - was not touched at all
+/// [!] - requires extarnal stuff implemented
+/// [~] - in progress but usable
+/// [x] - done
+///
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// MOVE
+//===----------------------------------------------------------------------===//
+
+/// -----------------------------------------------------
+/// F E | D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0
+/// -----------------------------------------------------
+/// | | DESTINATION | SOURCE
+/// 0 0 | SIZE | REG | MODE | MODE | REG
+/// -----------------------------------------------------
+///
+/// NOTE Move requires EA X version for direct register destination(0)
+class MxMoveEncoding<MxBead2Bits size,
+ MxEncEA srcEA, MxEncExt srcExt,
+ MxEncEA dstEA, MxEncExt dstExt>
+ : MxEncoding<srcEA.Reg, srcEA.DA, srcEA.Mode, dstEA.DA, dstEA.Mode, dstEA.Reg,
+ size, MxBead2Bits<0b00>,
+ srcExt.Imm, srcExt.B8, srcExt.Scale, srcExt.WL, srcExt.DAReg,
+ dstExt.Imm, dstExt.B8, dstExt.Scale, dstExt.WL, dstExt.DAReg>;
+
+/// MOVE has alternate size encoding
+class MxMoveSize<bits<2> value> : MxBead2Bits<value>;
+def MxMoveSize8 : MxMoveSize<0b01>;
+def MxMoveSize16 : MxMoveSize<0b11>;
+def MxMoveSize32 : MxMoveSize<0b10>;
+
+let Defs = [CCR] in
+class MxMove<string size, dag outs, dag ins, list<dag> pattern, MxEncoding enc>
+ : MxInst<outs, ins, "move."#size#"\t$src, $dst", pattern, enc>;
+
+class MxMove_RR<MxType DST, MxType SRC, MxMoveEncoding ENC>
+ : MxMove<DST.Prefix, (outs DST.ROp:$dst), (ins SRC.ROp:$src),
+ [(null_frag)], ENC>;
+
+let mayStore = 1 in {
+class MxMove_MR<MxOperand MEMOpd, ComplexPattern MEMPat, MxType REG,
+ MxMoveEncoding ENC>
+ : MxMove<REG.Prefix, (outs), (ins MEMOpd:$dst, REG.ROp:$src),
+ [(store REG.VT:$src, MEMPat:$dst)], ENC>;
+
+class MxMove_MI<MxOperand MEMOpd, ComplexPattern MEMPat, MxType TYPE,
+ MxMoveEncoding ENC>
+ : MxMove<TYPE.Prefix, (outs), (ins MEMOpd:$dst, TYPE.IOp:$src),
+ [(store TYPE.IPat:$src, MEMPat:$dst)], ENC>;
+} // let mayStore = 1
+
+class MxMove_RI<MxType DST, MxMoveEncoding ENC>
+ : MxMove<DST.Prefix, (outs DST.ROp:$dst), (ins DST.IOp:$src),
+ [(set DST.VT:$dst, DST.IPat:$src)], ENC>;
+
+
+let mayLoad = 1 in
+class MxMove_RM<MxType REG, MxOperand MEMOpd, ComplexPattern MEMPat,
+ MxBead2Bits SIZE,
+ MxEncEA SRCEA, MxEncExt SRCEXT,
+ MxEncEA DSTEA, MxEncExt DSTEXT>
+ : MxMove<REG.Prefix, (outs REG.ROp:$dst), (ins MEMOpd:$src),
+ [(set REG.VT:$dst, (REG.Load MEMPat:$src))],
+ MxMoveEncoding<SIZE, SRCEA, SRCEXT, DSTEA, DSTEXT>>;
+
+multiclass MMxMove_RM<MxType REG, MxMoveSize SIZE, MxEncEA EA_0> {
+
+ // REG <- (An)+
+ def NAME#REG.OOp.Letter#REG.Postfix : MxMove_RM<REG, REG.OOp, REG.OPat,
+ SIZE, MxEncEAo_1, MxExtEmpty, EA_0, MxExtEmpty>;
+
+ // REG <- -(An)
+ def NAME#REG.EOp.Letter#REG.Postfix : MxMove_RM<REG, REG.EOp, REG.EPat,
+ SIZE, MxEncEAe_1, MxExtEmpty, EA_0, MxExtEmpty>;
+
+ // REG <- (i,PC,Xn)
+ def NAME#REG.KOp.Letter#REG.Postfix : MxMove_RM<REG, REG.KOp, REG.KPat,
+ SIZE, MxEncEAk, MxExtBrief_1, EA_0, MxExtEmpty>;
+
+ // REG <- (i,PC)
+ def NAME#REG.QOp.Letter#REG.Postfix : MxMove_RM<REG, REG.QOp, REG.QPat,
+ SIZE, MxEncEAq, MxExtI16_1, EA_0, MxExtEmpty>;
+
+ // REG <- (i,An,Xn)
+ def NAME#REG.FOp.Letter#REG.Postfix : MxMove_RM<REG, REG.FOp, REG.FPat,
+ SIZE, MxEncEAf_1, MxExtBrief_1, EA_0, MxExtEmpty>;
+
+ // REG <- (i,An)
+ def NAME#REG.POp.Letter#REG.Postfix : MxMove_RM<REG, REG.POp, REG.PPat,
+ SIZE, MxEncEAp_1, MxExtI16_1, EA_0, MxExtEmpty>;
+
+ // REG <- (ABS)
+ def NAME#REG.BOp.Letter#REG.Postfix : MxMove_RM<REG, REG.BOp, REG.BPat,
+ SIZE, MxEncEAb, MxExtI32_1, EA_0, MxExtEmpty>;
+
+ // REG <- (An)
+ def NAME#REG.JOp.Letter#REG.Postfix : MxMove_RM<REG, REG.JOp, REG.JPat,
+ SIZE, MxEncEAj_1, MxExtEmpty, EA_0, MxExtEmpty>;
+}
+
+let mayLoad = 1, mayStore = 1 in {
+class MxMove_MM<string SIZE, PatFrag LOAD,
+ MxOperand DSTOpd, ComplexPattern DSTPat,
+ MxOperand SRCOpd, ComplexPattern SRCPat,
+ MxBead2Bits ESIZE,
+ MxEncEA SRCEA, MxEncExt SRCEXT,
+ MxEncEA DSTEA, MxEncExt DSTEXT>
+ : MxMove<SIZE, (outs), (ins DSTOpd:$dst, SRCOpd:$src),
+ [(store (LOAD SRCPat:$src), DSTPat:$dst)],
+ MxMoveEncoding<ESIZE, SRCEA, SRCEXT, DSTEA, DSTEXT>>;
+} // let mayLoad = 1, mayStore = 1
+
+multiclass MMxMove_MM<MxType TYPE, MxOperand DSTOpd, ComplexPattern DSTPat,
+ MxMoveSize SIZE, MxEncEA EA_0, MxEncExt EXT_0> {
+
+ // MEM <- (An)+
+ def NAME#TYPE.OOp.Letter#TYPE.Postfix
+ : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.OOp, TYPE.OPat,
+ SIZE, MxEncEAo_1, MxExtEmpty, EA_0, EXT_0>;
+
+ // MEM <- -(An)
+ def NAME#TYPE.EOp.Letter#TYPE.Postfix
+ : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.EOp, TYPE.EPat,
+ SIZE, MxEncEAe_1, MxExtEmpty, EA_0, EXT_0>;
+
+ // MEM <- (i,An)
+ def NAME#TYPE.POp.Letter#TYPE.Postfix
+ : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.POp, TYPE.PPat,
+ SIZE, MxEncEAp_1, MxExtI16_1, EA_0, EXT_0>;
+
+ // MEM <- (i,An,Xn)
+ def NAME#TYPE.FOp.Letter#TYPE.Postfix
+ : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.FOp, TYPE.FPat,
+ SIZE, MxEncEAf_1, MxExtBrief_1, EA_0, EXT_0>;
+
+ // MEM <- (i,PC,Xn)
+ def NAME#TYPE.KOp.Letter#TYPE.Postfix
+ : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.KOp, TYPE.KPat,
+ SIZE, MxEncEAk, MxExtBrief_1, EA_0, EXT_0>;
+
+ // MEM <- (i,PC)
+ def NAME#TYPE.QOp.Letter#TYPE.Postfix
+ : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.QOp, TYPE.QPat,
+ SIZE, MxEncEAq, MxExtI16_1, EA_0, EXT_0>;
+
+ // MEM <- (ABS)
+ def NAME#TYPE.BOp.Letter#TYPE.Postfix
+ : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.BOp, TYPE.BPat,
+ SIZE, MxEncEAb, MxExtI32_1, EA_0, EXT_0>;
+
+ // MEM <- (An)
+ def NAME#TYPE.JOp.Letter#TYPE.Postfix
+ : MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.JOp, TYPE.JPat,
+ SIZE, MxEncEAj_1, MxExtEmpty, EA_0, EXT_0>;
+}
+
+def MOV8dd
+ : MxMove_RR<MxType8d, MxType8d,
+ MxMoveEncoding<MxMoveSize8, MxEncEAd_1, MxExtEmpty, MxEncEAd_0, MxExtEmpty>>;
+
+// M <- R
+def MOV8fd : MxMove_MR<MxType8.FOp, MxType8.FPat, MxType8d,
+ MxMoveEncoding<MxMoveSize8,
+ /*src*/ MxEncEAd_1, MxExtEmpty,
+ /*dst*/ MxEncEAf_0, MxExtBrief_0>>;
+
+def MOV8pd : MxMove_MR<MxType8.POp, MxType8.PPat, MxType8d,
+ MxMoveEncoding<MxMoveSize8,
+ /*src*/ MxEncEAd_1, MxExtEmpty,
+ /*dst*/ MxEncEAp_0, MxExtI16_0>>;
+
+def MOV8ed : MxMove_MR<MxType8.EOp, MxType8.EPat, MxType8d,
+ MxMoveEncoding<MxMoveSize8,
+ /*src*/ MxEncEAd_1, MxExtEmpty,
+ /*dst*/ MxEncEAe_0, MxExtEmpty>>;
+
+def MOV8od : MxMove_MR<MxType8.OOp, MxType8.OPat, MxType8d,
+ MxMoveEncoding<MxMoveSize8,
+ /*src*/ MxEncEAd_1, MxExtEmpty,
+ /*dst*/ MxEncEAo_0, MxExtEmpty>>;
+
+def MOV8bd : MxMove_MR<MxType8.BOp, MxType8.BPat, MxType8d,
+ MxMoveEncoding<MxMoveSize8,
+ /*src*/ MxEncEAd_1, MxExtEmpty,
+ /*dst*/ MxEncEAb, MxExtI32_0>>;
+
+def MOV8jd : MxMove_MR<MxType8.JOp, MxType8.JPat, MxType8d,
+ MxMoveEncoding<MxMoveSize8,
+ /*src*/ MxEncEAd_1, MxExtEmpty,
+ /*dst*/ MxEncEAj_0, MxExtEmpty>>;
+
+
+// R <- I
+def MOV8di : MxMove_RI<MxType8d,
+ MxMoveEncoding<MxMoveSize8, MxEncEAi, MxExtI8_1, MxEncEAd_0, MxExtEmpty>>;
+
+foreach S = [16, 32] in {
+ foreach D = [ "r", "a" ] in {
+
+ foreach O = [ "r", "a" ] in {
+ def MOV#S#D#O : MxMove_RR<
+ !cast<MxType>("MxType"#S#D),
+ !cast<MxType>("MxType"#S#O),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
+ !cast<MxEncEA>("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>;
+ }
+
+ // M <- R
+ def MOV#S#"f"#D : MxMove_MR<
+ !cast<MxType>("MxType"#S).FOp,
+ !cast<MxType>("MxType"#S).FPat,
+ !cast<MxType>("MxType"#S#D),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
+ MxEncEAf_0, MxExtBrief_0>>;
+
+ def MOV#S#"p"#D : MxMove_MR<
+ !cast<MxType>("MxType"#S).POp,
+ !cast<MxType>("MxType"#S).PPat,
+ !cast<MxType>("MxType"#S#D),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
+ MxEncEAp_0, MxExtI16_0>>;
+
+ def MOV#S#"e"#D : MxMove_MR<
+ !cast<MxType>("MxType"#S).EOp,
+ !cast<MxType>("MxType"#S).EPat,
+ !cast<MxType>("MxType"#S#D),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
+ MxEncEAe_0, MxExtEmpty>>;
+
+ def MOV#S#"o"#D : MxMove_MR<
+ !cast<MxType>("MxType"#S).OOp,
+ !cast<MxType>("MxType"#S).OPat,
+ !cast<MxType>("MxType"#S#D),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
+ MxEncEAo_0, MxExtEmpty>>;
+
+ def MOV#S#"b"#D : MxMove_MR<
+ !cast<MxType>("MxType"#S).BOp,
+ !cast<MxType>("MxType"#S).BPat,
+ !cast<MxType>("MxType"#S#D),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
+ MxEncEAb, MxExtI32_0>>;
+
+ def MOV#S#"j"#D : MxMove_MR<
+ !cast<MxType>("MxType"#S).JOp,
+ !cast<MxType>("MxType"#S).JPat,
+ !cast<MxType>("MxType"#S#D),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ !cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
+ MxEncEAj_0, MxExtEmpty>>;
+
+
+ // R <- I
+ def MOV#S#D#"i" : MxMove_RI<
+ !cast<MxType>("MxType"#S#D),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
+ !cast<MxEncEA>("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>;
+ }
+}
+
+// M <- I
+foreach S = [8, 16, 32] in {
+ def MOV#S#"f"#"i" : MxMove_MI<
+ !cast<MxType>("MxType"#S).FOp,
+ !cast<MxType>("MxType"#S).FPat,
+ !cast<MxType>("MxType"#S),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
+ MxEncEAf_0, MxExtBrief_0>>;
+
+ def MOV#S#"p"#"i" : MxMove_MI<
+ !cast<MxType>("MxType"#S).POp,
+ !cast<MxType>("MxType"#S).PPat,
+ !cast<MxType>("MxType"#S),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
+ MxEncEAp_0, MxExtI16_0>>;
+
+ def MOV#S#"b"#"i" : MxMove_MI<
+ !cast<MxType>("MxType"#S).BOp,
+ !cast<MxType>("MxType"#S).BPat,
+ !cast<MxType>("MxType"#S),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
+ MxEncEAb, MxExtI32_0>>;
+
+ def MOV#S#"j"#"i" : MxMove_MI<
+ !cast<MxType>("MxType"#S).JOp,
+ !cast<MxType>("MxType"#S).JPat,
+ !cast<MxType>("MxType"#S),
+ MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
+ MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
+ MxEncEAj_0, MxExtEmpty>>;
+}
+
+// Store ABS(basically pointer) as Immdiate to Mem
+def : Pat<(store MxType32.BPat :$src, MxType32.PPat :$dst),
+ (MOV32pi MxType32.POp :$dst, MxType32.IOp :$src)>;
+
+def : Pat<(store MxType32.BPat :$src, MxType32.FPat :$dst),
+ (MOV32fi MxType32.FOp :$dst, MxType32.IOp :$src)>;
+
+def : Pat<(store MxType32.BPat :$src, MxType32.BPat :$dst),
+ (MOV32bi MxType32.BOp :$dst, MxType32.IOp :$src)>;
+
+def : Pat<(store MxType32.BPat :$src, MxType32.JPat :$dst),
+ (MOV32ji MxType32.JOp :$dst, MxType32.IOp :$src)>;
+
+// R <- M
+defm MOV8d : MMxMove_RM<MxType8d, MxMoveSize8, MxEncEAd_0>;
+
+defm MOV16r : MMxMove_RM<MxType16r, MxMoveSize16, MxEncEAr_0_reflected>;
+defm MOV16a : MMxMove_RM<MxType16a, MxMoveSize16, MxEncEAa_0>;
+
+defm MOV32r : MMxMove_RM<MxType32r, MxMoveSize32, MxEncEAr_0_reflected>;
+defm MOV32a : MMxMove_RM<MxType32a, MxMoveSize32, MxEncEAa_0>;
+
+let Pattern = [(null_frag)] in {
+defm MOV16r : MMxMove_RM<MxType16r_TC, MxMoveSize16, MxEncEAr_0_reflected>;
+defm MOV16a : MMxMove_RM<MxType16a_TC, MxMoveSize16, MxEncEAa_0>;
+
+defm MOV32r : MMxMove_RM<MxType32r_TC, MxMoveSize32, MxEncEAr_0_reflected>;
+defm MOV32a : MMxMove_RM<MxType32a_TC, MxMoveSize32, MxEncEAa_0>;
+} // Pattern
+
+// M <- M
+defm MOV8p : MMxMove_MM<MxType8, MxType8.POp, MxType8.PPat,
+ MxMoveSize8, MxEncEAp_0, MxExtI16_0>;
+defm MOV16p : MMxMove_MM<MxType16, MxType16.POp, MxType16.PPat,
+ MxMoveSize16, MxEncEAp_0, MxExtI16_0>;
+defm MOV32p : MMxMove_MM<MxType32, MxType32.POp, MxType32.PPat,
+ MxMoveSize32, MxEncEAp_0, MxExtI16_0>;
+
+defm MOV8f : MMxMove_MM<MxType8, MxType8.FOp, MxType8.FPat,
+ MxMoveSize8, MxEncEAf_0, MxExtBrief_0>;
+defm MOV16f : MMxMove_MM<MxType16, MxType16.FOp, MxType16.FPat,
+ MxMoveSize16, MxEncEAf_0, MxExtBrief_0>;
+defm MOV32f : MMxMove_MM<MxType32, MxType32.FOp, MxType32.FPat,
+ MxMoveSize32, MxEncEAf_0, MxExtBrief_0>;
+
+defm MOV8b : MMxMove_MM<MxType8, MxType8.BOp, MxType8.BPat,
+ MxMoveSize8, MxEncEAb, MxExtI32_0>;
+defm MOV16b : MMxMove_MM<MxType16, MxType16.BOp, MxType16.BPat,
+ MxMoveSize16, MxEncEAb, MxExtI32_0>;
+defm MOV32b : MMxMove_MM<MxType32, MxType32.BOp, MxType32.BPat,
+ MxMoveSize32, MxEncEAb, MxExtI32_0>;
+
+defm MOV8e : MMxMove_MM<MxType8, MxType8.EOp, MxType8.EPat,
+ MxMoveSize8, MxEncEAe_0, MxExtEmpty>;
+defm MOV16e : MMxMove_MM<MxType16, MxType16.EOp, MxType16.EPat,
+ MxMoveSize16, MxEncEAe_0, MxExtEmpty>;
+defm MOV32e : MMxMove_MM<MxType32, MxType32.EOp, MxType32.EPat,
+ MxMoveSize32, MxEncEAe_0, MxExtEmpty>;
+
+defm MOV8o : MMxMove_MM<MxType8, MxType8.OOp, MxType8.OPat,
+ MxMoveSize8, MxEncEAo_0, MxExtEmpty>;
+defm MOV16o : MMxMove_MM<MxType16, MxType16.OOp, MxType16.OPat,
+ MxMoveSize16, MxEncEAo_0, MxExtEmpty>;
+defm MOV32o : MMxMove_MM<MxType32, MxType32.OOp, MxType32.OPat,
+ MxMoveSize32, MxEncEAo_0, MxExtEmpty>;
+
+defm MOV8j : MMxMove_MM<MxType8, MxType8.JOp, MxType8.JPat,
+ MxMoveSize8, MxEncEAj_0, MxExtEmpty>;
+defm MOV16j : MMxMove_MM<MxType16, MxType16.JOp, MxType16.JPat,
+ MxMoveSize16, MxEncEAj_0, MxExtEmpty>;
+defm MOV32j : MMxMove_MM<MxType32, MxType32.JOp, MxType32.JPat,
+ MxMoveSize32, MxEncEAj_0, MxExtEmpty>;
+
+//===----------------------------------------------------------------------===//
+// MOVEM
+//
+// The mask is already pre-processed by the save/restore spill hook
+//===----------------------------------------------------------------------===//
+
+// Direction
+def MxMOVEM_MR : MxBead1Bit<0>;
+def MxMOVEM_RM : MxBead1Bit<1>;
+
+// Size
+def MxMOVEM_W : MxBead1Bit<0>;
+def MxMOVEM_L : MxBead1Bit<1>;
+
+/// ---------------+-------------+-------------+---------
+/// F E D C B | A | 9 8 7 | 6 | 5 4 3 | 2 1 0
+/// ---------------+---+---------+---+---------+---------
+/// 0 1 0 0 1 | D | 0 0 1 | S | MODE | REG
+/// ---------------+---+---------+---+---------+---------
+/// REGISTER LIST MASK
+/// -----------------------------------------------------
+/// D - direction(RM,MR)
+/// S - size(W,L)
+class MxMOVEMEncoding<MxEncEA EA, MxEncExt EXT, MxBead1Bit SIZE, MxBead1Bit DIR,
+ MxBead16Imm IMM>
+ : MxEncoding<EA.Reg, EA.DA, EA.Mode, SIZE, MxBead3Bits<0b001>, DIR,
+ MxBead1Bit<1>, MxBead4Bits<0b0100>, IMM,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
+
+let mayStore = 1 in
+class MxMOVEM_MR<MxType TYPE, MxBead1Bit SIZE,
+ MxOperand MEMOp, MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins MEMOp:$dst, MxMoveMask:$mask),
+ "movem."#TYPE.Prefix#"\t$mask, $dst", [],
+ MxMOVEMEncoding<EA, EXT, SIZE, MxMOVEM_MR, MxBead16Imm<1>>>;
+
+let mayLoad = 1 in
+class MxMOVEM_RM<MxType TYPE, MxBead1Bit SIZE,
+ MxOperand MEMOp, MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs), (ins MxMoveMask:$mask, MEMOp:$src),
+ "movem."#TYPE.Prefix#"\t$src, $mask", [],
+ MxMOVEMEncoding<EA, EXT, SIZE, MxMOVEM_RM, MxBead16Imm<0>>>;
+
+def MOVM32jm : MxMOVEM_MR<MxType32, MxMOVEM_L, MxType32.JOp, MxEncEAj_0, MxExtEmpty>;
+def MOVM32pm : MxMOVEM_MR<MxType32, MxMOVEM_L, MxType32.POp, MxEncEAp_0, MxExtI16_0>;
+
+def MOVM32mj : MxMOVEM_RM<MxType32, MxMOVEM_L, MxType32.JOp, MxEncEAj_1, MxExtEmpty>;
+def MOVM32mp : MxMOVEM_RM<MxType32, MxMOVEM_L, MxType32.POp, MxEncEAp_1, MxExtI16_1>;
+
+// Pseudo versions. These a required by virtual register spill/restore since
+// the mask requires real register to encode. These instruction will be expanded
+// into real MOVEM after RA finishes.
+let mayStore = 1 in
+class MxMOVEM_MR_Pseudo<MxType TYPE, MxOperand MEMOp>
+ : MxPseudo<(outs), (ins MEMOp:$dst, TYPE.ROp:$reg)>;
+let mayLoad = 1 in
+class MxMOVEM_RM_Pseudo<MxType TYPE, MxOperand MEMOp>
+ : MxPseudo<(outs TYPE.ROp:$dst), (ins MEMOp:$src)>;
+
+// Mem <- Reg
+def MOVM8jm_P : MxMOVEM_MR_Pseudo<MxType8d, MxType8.JOp>;
+def MOVM16jm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.JOp>;
+def MOVM32jm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.JOp>;
+
+def MOVM8pm_P : MxMOVEM_MR_Pseudo<MxType8d, MxType8.POp>;
+def MOVM16pm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.POp>;
+def MOVM32pm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.POp>;
+
+// Reg <- Mem
+def MOVM8mj_P : MxMOVEM_RM_Pseudo<MxType8d, MxType8.JOp>;
+def MOVM16mj_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.JOp>;
+def MOVM32mj_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.JOp>;
+
+def MOVM8mp_P : MxMOVEM_RM_Pseudo<MxType8d, MxType8.POp>;
+def MOVM16mp_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.POp>;
+def MOVM32mp_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.POp>;
+
+
+//===----------------------------------------------------------------------===//
+// MOVE to/from SR/CCR
+//
+// A special care must be taken working with to/from CCR since it is basically
+// word-size SR register truncated for user mode thus it only supports word-size
+// instructions. Plus the original M68000 does not support moves from CCR. So in
+// order to use CCR effectively one MUST use proper byte-size pseudo instructi-
+// ons that will be resolved sometime after RA pass.
+//===----------------------------------------------------------------------===//
+
+/// --------------------------------------------------
+/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0
+/// --------------------------------------------------
+/// | EFFECTIVE ADDRESS
+/// 0 1 0 0 0 1 0 0 1 1 | MODE | REG
+/// --------------------------------------------------
+let Defs = [CCR] in
+class MxMoveToCCR<dag INS, MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs CCRC:$dst), INS, "move.w\t$src, $dst", [],
+ MxEncoding<EA.Reg, EA.DA, EA.Mode,
+ MxBead4Bits<0b0011>, MxBead4Bits<0b0001>, MxBead2Bits<0b01>,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
+
+class MxMoveToCCRPseudo<dag INS> : MxPseudo<(outs CCRC:$dst), INS>;
+
+let mayLoad = 1 in {
+def MOV16cp : MxMoveToCCR<(ins MxType16d.POp:$src), MxEncEAp_1, MxExtI16_1>;
+def MOV8cp : MxMoveToCCRPseudo<(ins MxType8d.POp:$src)>;
+} // let mayLoad = 1
+
+def MOV16cd : MxMoveToCCR<(ins MxType16d.ROp:$src), MxEncEAd_1, MxExtEmpty>;
+def MOV8cd : MxMoveToCCRPseudo<(ins MxType8d.ROp:$src)>;
+
+/// Move from CCR
+/// --------------------------------------------------
+/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0
+/// --------------------------------------------------
+/// | EFFECTIVE ADDRESS
+/// 0 1 0 0 0 0 1 0 1 1 | MODE | REG
+/// --------------------------------------------------
+let Uses = [CCR] in
+class MxMoveFromCCR<dag OUTS, dag INS, MxEncEA EA, MxEncExt EXT>
+ : MxInst<OUTS, INS, "move.w\t$src, $dst", [],
+ MxEncoding<EA.Reg, EA.DA, EA.Mode,
+ MxBead4Bits<0b1011>, MxBead4Bits<0b0000>, MxBead2Bits<0b01>,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>,
+ Requires<[ IsM68010 ]>;
+
+class MxMoveFromCCRPseudo<dag INS> : MxPseudo<(outs), INS>;
+
+let mayStore = 1 in {
+def MOV16pc
+ : MxMoveFromCCR<(outs), (ins MxType16d.POp:$dst, CCRC:$src), MxEncEAp_0, MxExtI16_0>;
+def MOV8pc : MxMoveFromCCRPseudo<(ins MxType8d.POp:$dst, CCRC:$src)>;
+} // let mayStore = 1
+
+def MOV16dc
+ : MxMoveFromCCR<(outs MxType16d.ROp:$dst), (ins CCRC:$src), MxEncEAd_0, MxExtEmpty>;
+
+def MOV8dc : MxMoveFromCCRPseudo<(ins MxType8d.ROp:$dst, CCRC:$src)>;
+
+
+//===----------------------------------------------------------------------===//
+// LEA
+//===----------------------------------------------------------------------===//
+
+/// ----------------------------------------------------
+/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0
+/// ----------------------------------------------------
+/// 0 1 0 0 | DST REG | 1 1 1 | MODE | REG
+/// ----------------------------------------------------
+class MxLEA<MxOperand SRCOpd, ComplexPattern SRCPat, MxEncEA EA, MxEncExt EXT>
+ : MxInst<(outs MxARD32:$dst), (ins SRCOpd:$src),
+ "lea\t$src, $dst", [(set i32:$dst, SRCPat:$src)],
+ MxEncoding<EA.Reg, EA.DA, EA.Mode,
+ MxBead3Bits<0b111>, MxBeadReg<0>, MxBead4Bits<0x4>,
+ EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
+
+def LEA32p : MxLEA<MxARID32, MxCP_ARID, MxEncEAp_1, MxExtI16_1>;
+def LEA32f : MxLEA<MxARII32, MxCP_ARII, MxEncEAf_1, MxExtBrief_1>;
+def LEA32q : MxLEA<MxPCD32, MxCP_PCD, MxEncEAq, MxExtI16_1>;
+def LEA32b : MxLEA<MxAL32, MxCP_AL, MxEncEAb, MxExtI32_1>;
+
+
+//===----------------------------------------------------------------------===//
+// Pseudos
+//===----------------------------------------------------------------------===//
+
+/// Pushe/Pop to/from SP for simplicity
+let Uses = [SP], Defs = [SP], hasSideEffects = 0 in {
+
+// SP <- SP - <size>; (SP) <- Dn
+let mayStore = 1 in {
+def PUSH8d : MxPseudo<(outs), (ins DR8:$reg)>;
+def PUSH16d : MxPseudo<(outs), (ins DR16:$reg)>;
+def PUSH32r : MxPseudo<(outs), (ins XR32:$reg)>;
+} // let mayStore = 1
+
+// Dn <- (SP); SP <- SP + <size>
+let mayLoad = 1 in {
+def POP8d : MxPseudo<(outs DR8:$reg), (ins)>;
+def POP16d : MxPseudo<(outs DR16:$reg), (ins)>;
+def POP32r : MxPseudo<(outs XR32:$reg), (ins)>;
+} // let mayLoad = 1
+
+} // let Uses/Defs = [SP], hasSideEffects = 0
+
+
+let Defs = [CCR] in {
+class MxPseudoMove_RR<MxType DST, MxType SRC, list<dag> PAT = []>
+ : MxPseudo<(outs DST.ROp:$dst), (ins SRC.ROp:$src), "", PAT>;
+
+class MxPseudoMove_RM<MxType DST, MxOperand SRCOpd, list<dag> PAT = []>
+ : MxPseudo<(outs DST.ROp:$dst), (ins SRCOpd:$src), "", PAT>;
+}
+
+/// This group of Pseudos is analogues to the real x86 extending moves, but
+/// since M68k does not have those we need to emulate. These instructions
+/// will be expanded right after RA completed because we need to know precisely
+/// what registers are allocated for the operands and if they overlap we just
+/// extend the value if the registers are completely
diff erent we need to move
+/// first.
+foreach EXT = ["S", "Z"] in {
+ let hasSideEffects = 0 in {
+
+ def MOV#EXT#Xd16d8 : MxPseudoMove_RR<MxType16d, MxType8d>;
+ def MOV#EXT#Xd32d8 : MxPseudoMove_RR<MxType32d, MxType8d>;
+ def MOV#EXT#Xd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;
+
+ let mayLoad = 1 in {
+
+ def MOV#EXT#Xd16j8 : MxPseudoMove_RM<MxType16d, MxType8.JOp>;
+ def MOV#EXT#Xd32j8 : MxPseudoMove_RM<MxType32d, MxType8.JOp>;
+ def MOV#EXT#Xd32j16 : MxPseudoMove_RM<MxType32d, MxType16.JOp>;
+
+ def MOV#EXT#Xd16p8 : MxPseudoMove_RM<MxType16d, MxType8.POp>;
+ def MOV#EXT#Xd32p8 : MxPseudoMove_RM<MxType32d, MxType8.POp>;
+ def MOV#EXT#Xd32p16 : MxPseudoMove_RM<MxType32d, MxType16.POp>;
+
+ def MOV#EXT#Xd16f8 : MxPseudoMove_RM<MxType16d, MxType8.FOp>;
+ def MOV#EXT#Xd32f8 : MxPseudoMove_RM<MxType32d, MxType8.FOp>;
+ def MOV#EXT#Xd32f16 : MxPseudoMove_RM<MxType32d, MxType16.FOp>;
+
+ }
+ }
+}
+
+/// This group of instructions is similar to the group above but DOES NOT do
+/// any value extension, they just load a smaller register into the lower part
+/// of another register if operands' real registers are
diff erent or does
+/// nothing if they are the same.
+def MOVXd16d8 : MxPseudoMove_RR<MxType16d, MxType8d>;
+def MOVXd32d8 : MxPseudoMove_RR<MxType32d, MxType8d>;
+def MOVXd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;
+
+//===----------------------------------------------------------------------===//
+// Extend/Truncate Patterns
+//===----------------------------------------------------------------------===//
+
+// i16 <- sext i8
+def: Pat<(i16 (sext i8:$src)),
+ (EXTRACT_SUBREG (MOVSXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
+def: Pat<(MxSExtLoadi16i8 MxCP_ARI:$src),
+ (EXTRACT_SUBREG (MOVSXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
+def: Pat<(MxSExtLoadi16i8 MxCP_ARID:$src),
+ (EXTRACT_SUBREG (MOVSXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
+def: Pat<(MxSExtLoadi16i8 MxCP_ARII:$src),
+ (EXTRACT_SUBREG (MOVSXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
+
+// i32 <- sext i8
+def: Pat<(i32 (sext i8:$src)), (MOVSXd32d8 MxDRD8:$src)>;
+def: Pat<(MxSExtLoadi32i8 MxCP_ARI :$src), (MOVSXd32j8 MxARI8 :$src)>;
+def: Pat<(MxSExtLoadi32i8 MxCP_ARID:$src), (MOVSXd32p8 MxARID8:$src)>;
+def: Pat<(MxSExtLoadi32i8 MxCP_ARII:$src), (MOVSXd32f8 MxARII8:$src)>;
+
+// i32 <- sext i16
+def: Pat<(i32 (sext i16:$src)), (MOVSXd32d16 MxDRD16:$src)>;
+def: Pat<(MxSExtLoadi32i16 MxCP_ARI :$src), (MOVSXd32j16 MxARI16 :$src)>;
+def: Pat<(MxSExtLoadi32i16 MxCP_ARID:$src), (MOVSXd32p16 MxARID16:$src)>;
+def: Pat<(MxSExtLoadi32i16 MxCP_ARII:$src), (MOVSXd32f16 MxARII16:$src)>;
+
+// i16 <- zext i8
+def: Pat<(i16 (zext i8:$src)),
+ (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
+def: Pat<(MxZExtLoadi16i8 MxCP_ARI:$src),
+ (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
+def: Pat<(MxZExtLoadi16i8 MxCP_ARID:$src),
+ (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
+def: Pat<(MxZExtLoadi16i8 MxCP_ARII:$src),
+ (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
+
+// i32 <- zext i8
+def: Pat<(i32 (zext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;
+def: Pat<(MxZExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;
+def: Pat<(MxZExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;
+def: Pat<(MxZExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;
+
+// i32 <- zext i16
+def: Pat<(i32 (zext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;
+def: Pat<(MxZExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;
+def: Pat<(MxZExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;
+def: Pat<(MxZExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;
+
+// i16 <- anyext i8
+def: Pat<(i16 (anyext i8:$src)),
+ (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
+def: Pat<(MxExtLoadi16i8 MxCP_ARI:$src),
+ (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
+def: Pat<(MxExtLoadi16i8 MxCP_ARID:$src),
+ (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
+def: Pat<(MxExtLoadi16i8 MxCP_ARII:$src),
+ (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
+
+// i32 <- anyext i8
+def: Pat<(i32 (anyext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;
+def: Pat<(MxExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;
+def: Pat<(MxExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;
+def: Pat<(MxExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;
+
+// i32 <- anyext i16
+def: Pat<(i32 (anyext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;
+def: Pat<(MxExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;
+def: Pat<(MxExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;
+def: Pat<(MxExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;
+
+// trunc patterns
+def : Pat<(i16 (trunc i32:$src)),
+ (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex16Lo)>;
+def : Pat<(i8 (trunc i32:$src)),
+ (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex8Lo)>;
+def : Pat<(i8 (trunc i16:$src)),
+ (EXTRACT_SUBREG MxXRD16:$src, MxSubRegIndex8Lo)>;
diff --git a/llvm/lib/Target/M68k/M68kInstrFormats.td b/llvm/lib/Target/M68k/M68kInstrFormats.td
new file mode 100644
index 000000000000..b00db4915df2
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kInstrFormats.td
@@ -0,0 +1,370 @@
+//=== M68kInstrFormats.td - M68k Instruction Formats ---*- tablegen -*-===//
+// The LLVM Compiler Infrastructure
+// 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 instruction formats.
+///
+/// Since M68k has quite a lot memory addressing modes there are more
+/// instruction prefixes than just i, r and m:
+/// TSF Since Form Letter Description
+/// 00 M68000 Dn or An r any register
+/// 01 M68000 Dn d data register direct
+/// 02 M68000 An a address register direct
+/// 03 M68000 (An) j address register indirect
+/// 04 M68000 (An)+ o address register indirect with postincrement
+/// 05 M68000 -(An) e address register indirect with predecrement
+/// 06 M68000 (i,An) p address register indirect with displacement
+/// 10 M68000 (i,An,Xn.L) f address register indirect with index and scale = 1
+/// 07 M68000 (i,An,Xn.W) F address register indirect with index and scale = 1
+/// 12 M68020 (i,An,Xn.L,SCALE) g address register indirect with index
+/// 11 M68020 (i,An,Xn.W,SCALE) G address register indirect with index
+/// 14 M68020 ([bd,An],Xn.L,SCALE,od) u memory indirect postindexed mode
+/// 13 M68020 ([bd,An],Xn.W,SCALE,od) U memory indirect postindexed mode
+/// 16 M68020 ([bd,An,Xn.L,SCALE],od) v memory indirect preindexed mode
+/// 15 M68020 ([bd,An,Xn.W,SCALE],od) V memory indirect preindexed mode
+/// 20 M68000 abs.L b absolute long address
+/// 17 M68000 abs.W B absolute short address
+/// 21 M68000 (i,PC) q program counter with displacement
+/// 23 M68000 (i,PC,Xn.L) k program counter with index and scale = 1
+/// 22 M68000 (i,PC,Xn.W) K program counter with index and scale = 1
+/// 25 M68020 (i,PC,Xn.L,SCALE) l program counter with index
+/// 24 M68020 (i,PC,Xn.W,SCALE) L program counter with index
+/// 27 M68020 ([bd,PC],Xn.L,SCALE,od) x program counter memory indirect postindexed mode
+/// 26 M68020 ([bd,PC],Xn.W,SCALE,od) X program counter memory indirect postindexed mode
+/// 31 M68020 ([bd,PC,Xn.L,SCALE],od) y program counter memory indirect preindexed mode
+/// 30 M68020 ([bd,PC,Xn.W,SCALE],od) Y program counter memory indirect preindexed mode
+/// 32 M68000 #immediate i immediate data
+///
+/// NOTE that long form is always lowercase, word variants are capitalized
+///
+/// Operand can be qualified with size where appropriate to force a particular
+/// instruction encoding, e.g.:
+/// (i8,An,Xn.W) f8 1 extension word
+/// (i16,An,Xn.W) f16 2 extension words
+/// (i32,An,Xn.W) f32 3 extension words
+///
+/// Form without size qualifier will adapt to operand size automatically, e.g.:
+/// (i,An,Xn.W) f 1, 2 or 3 extension words
+///
+/// Some forms already imply a particular size of their operands, e.g.:
+/// (i,An) p 1 extension word and i is 16bit
+///
+/// Operand order follows x86 Intel order(destination before source), e.g.:
+/// MOV8df MOVE (4,A0,D0), D1
+///
+/// Number after instruction mnemonics determines the size of the data
+///
+//===----------------------------------------------------------------------===//
+
+/// ??? Is it possible to use this stuff for disassembling?
+/// NOTE 1: In case of conditional beads(DA, DAReg), cond part is able to
+/// consume any bit, though a more general instructions must be chosen, e.g.
+/// d -> r, a -> r
+
+//===----------------------------------------------------------------------===//
+// Encoding primitives
+//===----------------------------------------------------------------------===//
+
+class MxBead<bits<4> type, bit b4 = 0, bit b5 = 0, bit b6 = 0, bit b7 = 0> {
+ bits<8> Value = 0b00000000;
+ let Value{3-0} = type;
+ let Value{4} = b4;
+ let Value{5} = b5;
+ let Value{6} = b6;
+ let Value{7} = b7;
+}
+
+/// System beads, allow to control beading flow
+def MxBeadTerm : MxBead<0x0, 0, 0, 0, 0>;
+def MxBeadIgnore : MxBead<0x0, 1, 0, 0, 0>;
+
+/// Add plain bit to the instruction
+class MxBead1Bit <bits<1> b> : MxBead<0x1, b>;
+class MxBead2Bits <bits<2> b> : MxBead<0x2, b{0}, b{1}>;
+class MxBead3Bits <bits<3> b> : MxBead<0x3, b{0}, b{1}, b{2}>;
+class MxBead4Bits <bits<4> b> : MxBead<0x4, b{0}, b{1}, b{2}, b{3}>;
+
+/// bits<3> o - operand number
+/// bit a - use alternative, used to select index register or
+/// outer displacement/immediate
+/// suffix NP means non-padded
+class MxBeadDAReg <bits<3> o, bit a = 0> : MxBead<0x5, o{0}, o{1}, o{2}, a>;
+class MxBeadDA <bits<3> o, bit a = 0> : MxBead<0x6, o{0}, o{1}, o{2}, a>;
+class MxBeadReg <bits<3> o, bit a = 0> : MxBead<0x7, o{0}, o{1}, o{2}, a>;
+class MxBead8Disp <bits<3> o, bit a = 0> : MxBead<0x8, o{0}, o{1}, o{2}, a>;
+
+/// Add Immediate to the instruction. 8-bit version is padded with zeros to fit
+/// the word.
+class MxBead8Imm <bits<3> o, bit a = 0> : MxBead<0x9, o{0}, o{1}, o{2}, a>;
+class MxBead16Imm <bits<3> o, bit a = 0> : MxBead<0xA, o{0}, o{1}, o{2}, a>;
+class MxBead32Imm <bits<3> o, bit a = 0> : MxBead<0xB, o{0}, o{1}, o{2}, a>;
+
+/// Encodes an immediate 0-7(alt. 1-8) into 3 bit field
+class MxBead3Imm <bits<3> o, bit a = 0> : MxBead<0xC, o{0}, o{1}, o{2}, a>;
+
+
+class MxEncoding<MxBead n0 = MxBeadTerm, MxBead n1 = MxBeadTerm,
+ MxBead n2 = MxBeadTerm, MxBead n3 = MxBeadTerm,
+ MxBead n4 = MxBeadTerm, MxBead n5 = MxBeadTerm,
+ MxBead n6 = MxBeadTerm, MxBead n7 = MxBeadTerm,
+ MxBead n8 = MxBeadTerm, MxBead n9 = MxBeadTerm,
+ MxBead n10 = MxBeadTerm, MxBead n11 = MxBeadTerm,
+ MxBead n12 = MxBeadTerm, MxBead n13 = MxBeadTerm,
+ MxBead n14 = MxBeadTerm, MxBead n15 = MxBeadTerm,
+ MxBead n16 = MxBeadTerm, MxBead n17 = MxBeadTerm,
+ MxBead n18 = MxBeadTerm, MxBead n19 = MxBeadTerm,
+ MxBead n20 = MxBeadTerm, MxBead n21 = MxBeadTerm,
+ MxBead n22 = MxBeadTerm, MxBead n23 = MxBeadTerm> {
+ bits <192> Value;
+ let Value{7-0} = n0.Value;
+ let Value{15-8} = n1.Value;
+ let Value{23-16} = n2.Value;
+ let Value{31-24} = n3.Value;
+ let Value{39-32} = n4.Value;
+ let Value{47-40} = n5.Value;
+ let Value{55-48} = n6.Value;
+ let Value{63-56} = n7.Value;
+ let Value{71-64} = n8.Value;
+ let Value{79-72} = n9.Value;
+ let Value{87-80} = n10.Value;
+ let Value{95-88} = n11.Value;
+ let Value{103-96} = n12.Value;
+ let Value{111-104} = n13.Value;
+ let Value{119-112} = n14.Value;
+ let Value{127-120} = n15.Value;
+ let Value{135-128} = n16.Value;
+ let Value{143-136} = n17.Value;
+ let Value{151-144} = n18.Value;
+ let Value{159-152} = n19.Value;
+ let Value{167-160} = n20.Value;
+ let Value{175-168} = n21.Value;
+ let Value{183-176} = n22.Value;
+ let Value{191-184} = n23.Value;
+}
+
+class MxEncFixed<bits<16> value> : MxEncoding {
+ let Value{7-0} = MxBead4Bits<value{3-0}>.Value;
+ let Value{15-8} = MxBead4Bits<value{7-4}>.Value;
+ let Value{23-16} = MxBead4Bits<value{11-8}>.Value;
+ let Value{31-24} = MxBead4Bits<value{15-12}>.Value;
+}
+
+//===----------------------------------------------------------------------===//
+// Encoding composites
+//
+// These must be lowered to MxEncoding by instr specific wrappers
+//
+// HERE BE DRAGONS...
+//===----------------------------------------------------------------------===//
+
+class MxEncByte<bits<8> value> : MxEncoding {
+ MxBead4Bits LO = MxBead4Bits<value{3-0}>;
+ MxBead4Bits HI = MxBead4Bits<value{7-4}>;
+}
+
+def MxEncEmpty : MxEncoding;
+
+
+/// M68k Standard Effective Address layout:
+///
+/// :-------------------:
+/// | 5 4 3 | 2 1 0 |
+/// | mode | reg |
+/// :-------------------:
+///
+/// If the EA is a direct register mode, bits 4 and 5 are 0, and the register
+/// number will be encoded in bit 0 - 3. Since the first address register's
+/// (A0) register number is 8, we can easily tell data registers from
+/// address registers by only inspecting bit 3 (i.e. if bit 3 is set, it's an
+/// address register).
+///
+///
+/// But MOVE instruction uses reversed layout for destination EA:
+///
+/// :-------------------:
+/// | 5 4 3 | 2 1 0 |
+/// | reg | mode |
+/// :-------------------:
+///
+/// And this complicates things a bit because the DA bit is now separated from
+/// the register and we have to encode those separately using MxBeadDA<opN>
+///
+class MxEncEA<MxBead reg, MxBead mode, MxBead da = MxBeadIgnore> {
+ MxBead Reg = reg;
+ MxBead Mode = mode;
+ MxBead DA = da;
+}
+
+// FIXME: Is there a way to factorize the addressing mode suffix (i.e.
+// 'r', 'd', 'a' etc.) and use something like multiclass to replace?
+def MxEncEAr_0: MxEncEA<MxBeadDAReg<0>, MxBead2Bits<0b00>>;
+def MxEncEAd_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b00>, MxBead1Bit<0>>;
+def MxEncEAa_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b00>, MxBead1Bit<1>>;
+def MxEncEAj_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b01>, MxBead1Bit<0>>;
+def MxEncEAo_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b01>, MxBead1Bit<1>>;
+def MxEncEAe_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b10>, MxBead1Bit<0>>;
+def MxEncEAp_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b10>, MxBead1Bit<1>>;
+def MxEncEAf_0: MxEncEA<MxBeadReg<0>, MxBead2Bits<0b11>, MxBead1Bit<0>>;
+
+def MxEncEAa_0_reflected : MxEncEA<MxBeadReg<0>, MxBead3Bits<0b001>>;
+def MxEncEAr_0_reflected : MxEncEA<MxBeadReg<0>, MxBead2Bits<0b00>, MxBeadDA<0>>;
+
+def MxEncEAr_1: MxEncEA<MxBeadDAReg<1>, MxBead2Bits<0b00>>;
+def MxEncEAd_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b00>, MxBead1Bit<0>>;
+def MxEncEAa_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b00>, MxBead1Bit<1>>;
+def MxEncEAj_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b01>, MxBead1Bit<0>>;
+def MxEncEAo_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b01>, MxBead1Bit<1>>;
+def MxEncEAe_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b10>, MxBead1Bit<0>>;
+def MxEncEAp_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b10>, MxBead1Bit<1>>;
+def MxEncEAf_1: MxEncEA<MxBeadReg<1>, MxBead2Bits<0b11>, MxBead1Bit<0>>;
+
+def MxEncEAr_2: MxEncEA<MxBeadDAReg<2>, MxBead2Bits<0b00>>;
+def MxEncEAd_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b00>, MxBead1Bit<0>>;
+def MxEncEAa_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b00>, MxBead1Bit<1>>;
+def MxEncEAj_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b01>, MxBead1Bit<0>>;
+def MxEncEAo_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b01>, MxBead1Bit<1>>;
+def MxEncEAe_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b10>, MxBead1Bit<0>>;
+def MxEncEAp_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b10>, MxBead1Bit<1>>;
+def MxEncEAf_2: MxEncEA<MxBeadReg<2>, MxBead2Bits<0b11>, MxBead1Bit<0>>;
+
+def MxEncEAb : MxEncEA<MxBead3Bits<0b001>, MxBead2Bits<0b11>, MxBead1Bit<1>>;
+def MxEncEAq : MxEncEA<MxBead3Bits<0b010>, MxBead2Bits<0b11>, MxBead1Bit<1>>;
+def MxEncEAk : MxEncEA<MxBead3Bits<0b011>, MxBead2Bits<0b11>, MxBead1Bit<1>>;
+def MxEncEAi : MxEncEA<MxBead3Bits<0b100>, MxBead2Bits<0b11>, MxBead1Bit<1>>;
+
+// Allows you to specify each bit of opcode
+class MxEncOpMode<MxBead b0, MxBead b1 = MxBeadIgnore, MxBead b2 = MxBeadIgnore> {
+ MxBead B0 = b0;
+ MxBead B1 = b1;
+ MxBead B2 = b2;
+}
+
+// op EA, Dn
+def MxOpMode8dEA : MxEncOpMode<MxBead3Bits<0b000>>;
+def MxOpMode16dEA : MxEncOpMode<MxBead3Bits<0b001>>;
+def MxOpMode32dEA : MxEncOpMode<MxBead3Bits<0b010>>;
+
+// op EA, An
+def MxOpMode16aEA : MxEncOpMode<MxBead3Bits<0b110>>;
+def MxOpMode32aEA : MxEncOpMode<MxBead3Bits<0b111>>;
+
+// op EA, Rn
+// As you might noticed this guy is special... Since M68k
diff erentiates
+// between Data and Address registers we required to use
diff erent OPMODE codes
+// for Address registers DST operands. One way of dealing with it is to use
+// separate tablegen instructions, but in this case it would force Register
+// Allocator to use specific Register Classes and eventually will lead to
+// superfluous moves. Another approach is to use reg-variadic encoding which will
+// change OPMODE base on Register Class used. Luckily, all the bits that
diff er go
+// from 0 to 1 and can be encoded with MxBeadDA.
+// Basically, if the register used is of Data type these encodings will be
+// the same as MxOpMode{16,32}dEA above and used with regular instructions(e.g. ADD,
+// SUB), but if the register is of Address type the appropriate bits will flip and
+// the instructions become of *A type(e.g ADDA, SUBA).
+def MxOpMode16rEA : MxEncOpMode<MxBead1Bit<1>, MxBeadDA<0>, MxBead1Bit<0>>;
+def MxOpMode32rEA : MxEncOpMode<MxBeadDA<0>, MxBead1Bit<1>, MxBeadDA<0>>;
+
+// op Dn, EA
+def MxOpMode8EAd : MxEncOpMode<MxBead3Bits<0b100>>;
+def MxOpMode16EAd : MxEncOpMode<MxBead3Bits<0b101>>;
+def MxOpMode32EAd : MxEncOpMode<MxBead3Bits<0b110>>;
+
+
+// Represents two types of extension word:
+// - Imm extension word
+// - Brief extension word
+class MxEncExt<MxBead imm = MxBeadIgnore, MxBead b8 = MxBeadIgnore,
+ MxBead scale = MxBeadIgnore, MxBead wl = MxBeadIgnore,
+ MxBead daReg = MxBeadIgnore> {
+ MxBead Imm = imm;
+ MxBead B8 = b8;
+ MxBead Scale = scale;
+ MxBead WL = wl;
+ MxBead DAReg = daReg;
+}
+
+def MxExtEmpty : MxEncExt;
+
+// These handle encoding of displacement fields, absolute addresses and
+// immediate values, since encoding for these categories is mainly the same,
+// with exception of some weird immediates.
+def MxExtI8_0 : MxEncExt<MxBead8Imm<0>>;
+def MxExtI16_0 : MxEncExt<MxBead16Imm<0>>;
+def MxExtI32_0 : MxEncExt<MxBead32Imm<0>>;
+
+def MxExtI8_1 : MxEncExt<MxBead8Imm<1>>;
+def MxExtI16_1 : MxEncExt<MxBead16Imm<1>>;
+def MxExtI32_1 : MxEncExt<MxBead32Imm<1>>;
+
+def MxExtI8_2 : MxEncExt<MxBead8Imm<2>>;
+def MxExtI16_2 : MxEncExt<MxBead16Imm<2>>;
+def MxExtI32_2 : MxEncExt<MxBead32Imm<2>>;
+
+// NOTE They are all using Long Xn
+def MxExtBrief_0 : MxEncExt<MxBead8Disp<0>, MxBead1Bit<0b0>,
+ MxBead2Bits<0b00>, MxBead1Bit<1>,
+ MxBeadDAReg<0, 1>>;
+
+def MxExtBrief_1 : MxEncExt<MxBead8Disp<1>, MxBead1Bit<0b0>,
+ MxBead2Bits<0b00>, MxBead1Bit<1>,
+ MxBeadDAReg<1, 1>>;
+
+def MxExtBrief_2 : MxEncExt<MxBead8Disp<2>, MxBead1Bit<0b0>,
+ MxBead2Bits<0b00>, MxBead1Bit<1>,
+ MxBeadDAReg<2, 1>>;
+
+def MxExtBrief_3 : MxEncExt<MxBead8Disp<3>, MxBead1Bit<0b0>,
+ MxBead2Bits<0b00>, MxBead1Bit<1>,
+ MxBeadDAReg<3, 1>>;
+
+def MxExtBrief_4 : MxEncExt<MxBead8Disp<4>, MxBead1Bit<0b0>,
+ MxBead2Bits<0b00>, MxBead1Bit<1>,
+ MxBeadDAReg<4, 1>>;
+
+class MxEncSize<bits<2> value> : MxBead2Bits<value>;
+def MxEncSize8 : MxEncSize<0b00>;
+def MxEncSize16 : MxEncSize<0b01>;
+def MxEncSize32 : MxEncSize<0b10>;
+def MxEncSize64 : MxEncSize<0b11>;
+
+// M68k INSTRUCTION. Most instructions specify the location of an operand by
+// using the effective address field in the operation word. The effective address
+// is composed of two 3-bit fields: the mode field and the register field. The
+// value in the mode field selects the
diff erent address modes. The register
+// field contains the number of a register. The effective address field may
+// require additional information to fully specify the operand. This additional
+// information, called the effective address extension, is contained in the
+// following word or words and is considered part of the instruction. The
+// effective address modes are grouped into three categories: register direct,
+// memory addressing, and special.
+class MxInst<dag outs, dag ins,
+ string asmStr = "",
+ list<dag> pattern = [],
+ MxEncoding beads = MxEncEmpty,
+ InstrItinClass itin = NoItinerary>
+ : Instruction {
+ let Namespace = "M68k";
+ let OutOperandList = outs;
+ let InOperandList = ins;
+ let AsmString = asmStr;
+ let Pattern = pattern;
+ let Itinerary = itin;
+
+ // Byte stream
+ field bits<192> Beads = beads.Value;
+
+ // Number of bytes
+ let Size = 0;
+
+ let UseLogicalOperandMappings = 1;
+}
+
+// M68k PSEUDO INSTRUCTION
+class MxPseudo<dag outs, dag ins, string asmStr = "", list<dag> pattern = []>
+ : MxInst<outs, ins, asmStr, pattern> {
+ let isPseudo = 1;
+}
diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.td b/llvm/lib/Target/M68k/M68kInstrInfo.td
new file mode 100644
index 000000000000..e5d6783022ce
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.td
@@ -0,0 +1,665 @@
+//== M68kInstrInfo.td - Main M68k Instruction Definition -*- tablegen -*-=//
+//
+// 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 describes the M68k instruction set, defining the instructions
+/// and properties of the instructions which are needed for code generation,
+/// machine code emission, and analysis.
+///
+//===----------------------------------------------------------------------===//
+
+include "M68kInstrFormats.td"
+
+//===----------------------------------------------------------------------===//
+// Profiles
+//===----------------------------------------------------------------------===//
+
+def MxSDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+def MxSDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
+
+def MxSDT_Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
+
+def MxSDT_Ret : SDTypeProfile<0, -1, [
+ /* ADJ */ SDTCisVT<0, i32>
+]>;
+
+def MxSDT_TCRet : SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisVT<1, i32>]>;
+
+def MxSDT_Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
+
+def MxSDT_UnArithCCROut : SDTypeProfile<2, 1, [
+ /* RES */ SDTCisInt<0>,
+ /* CCR */ SDTCisVT<1, i8>,
+ /* OPD */ SDTCisSameAs<0, 2>
+]>;
+
+// RES, CCR <- op LHS, RHS
+def MxSDT_BiArithCCROut : SDTypeProfile<2, 2, [
+ /* RES */ SDTCisInt<0>,
+ /* CCR */ SDTCisVT<1, i8>,
+ /* LHS */ SDTCisSameAs<0, 2>,
+ /* RHS */ SDTCisSameAs<0, 3>
+]>;
+
+// RES, CCR <- op LHS, RHS, CCR
+def MxSDT_BiArithCCRInOut : SDTypeProfile<2, 3, [
+ /* RES 1 */ SDTCisInt<0>,
+ /* CCR */ SDTCisVT<1, i8>,
+ /* LHS */ SDTCisSameAs<0, 2>,
+ /* RHS */ SDTCisSameAs<0, 3>,
+ /* CCR */ SDTCisSameAs<1, 4>
+]>;
+
+// RES1, RES2, CCR <- op LHS, RHS
+def MxSDT_2BiArithCCROut : SDTypeProfile<3, 2, [
+ /* RES 1 */ SDTCisInt<0>,
+ /* RES 2 */ SDTCisSameAs<0, 1>,
+ /* CCR */ SDTCisVT<1, i8>,
+ /* LHS */ SDTCisSameAs<0, 2>,
+ /* RHS */ SDTCisSameAs<0, 3>
+]>;
+
+def MxSDT_CmpTest : SDTypeProfile<1, 2, [
+ /* CCR */ SDTCisVT<0, i8>,
+ /* Ops */ SDTCisSameAs<1, 2>
+]>;
+
+def MxSDT_Cmov : SDTypeProfile<1, 4, [
+ /* ARG */ SDTCisSameAs<0, 1>,
+ /* ARG */ SDTCisSameAs<1, 2>,
+ /* Cond */ SDTCisVT<3, i8>,
+ /* CCR */ SDTCisVT<4, i8>
+]>;
+
+def MxSDT_BrCond : SDTypeProfile<0, 3, [
+ /* Dest */ SDTCisVT<0, OtherVT>,
+ /* Cond */ SDTCisVT<1, i8>,
+ /* CCR */ SDTCisVT<2, i8>
+]>;
+
+def MxSDT_SetCC : SDTypeProfile<1, 2, [
+ /* BOOL */ SDTCisVT<0, i8>,
+ /* Cond */ SDTCisVT<1, i8>,
+ /* CCR */ SDTCisVT<2, i8>
+]>;
+
+def MxSDT_SetCC_C : SDTypeProfile<1, 2, [
+ /* BOOL */ SDTCisInt<0>,
+ /* Cond */ SDTCisVT<1, i8>,
+ /* CCR */ SDTCisVT<2, i8>
+]>;
+
+
+def MxSDT_SEG_ALLOCA : SDTypeProfile<1, 1,[
+ /* MEM */ SDTCisVT<0, iPTR>,
+ /* SIZE */ SDTCisVT<1, iPTR>
+]>;
+
+
+//===----------------------------------------------------------------------===//
+// Nodes
+//===----------------------------------------------------------------------===//
+
+def MxCallSeqStart : SDNode<"ISD::CALLSEQ_START", MxSDT_CallSeqStart,
+ [SDNPHasChain, SDNPOutGlue]>;
+
+def MxCallSeqEnd : SDNode<"ISD::CALLSEQ_END", MxSDT_CallSeqEnd,
+ [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
+
+def MxCall : SDNode<"M68kISD::CALL", MxSDT_Call,
+ [SDNPHasChain, SDNPOutGlue,
+ SDNPOptInGlue, SDNPVariadic]>;
+
+def MxRet : SDNode<"M68kISD::RET", MxSDT_Ret,
+ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
+
+def MxTCRet : SDNode<"M68kISD::TC_RETURN", MxSDT_TCRet,
+ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
+
+def MxWrapper : SDNode<"M68kISD::Wrapper", MxSDT_Wrapper>;
+def MxWrapperPC : SDNode<"M68kISD::WrapperPC", MxSDT_Wrapper>;
+
+def MxAdd : SDNode<"M68kISD::ADD", MxSDT_BiArithCCROut, [SDNPCommutative]>;
+def MxSub : SDNode<"M68kISD::SUB", MxSDT_BiArithCCROut>;
+def MxOr : SDNode<"M68kISD::OR", MxSDT_BiArithCCROut, [SDNPCommutative]>;
+def MxXor : SDNode<"M68kISD::XOR", MxSDT_BiArithCCROut, [SDNPCommutative]>;
+def MxAnd : SDNode<"M68kISD::AND", MxSDT_BiArithCCROut, [SDNPCommutative]>;
+
+def MxAddX : SDNode<"M68kISD::ADDX", MxSDT_BiArithCCRInOut>;
+def MxSubX : SDNode<"M68kISD::SUBX", MxSDT_BiArithCCRInOut>;
+
+def MxSMul : SDNode<"M68kISD::SMUL", MxSDT_BiArithCCROut, [SDNPCommutative]>;
+def MxUMul : SDNode<"M68kISD::UMUL", MxSDT_2BiArithCCROut, [SDNPCommutative]>;
+
+def MxCmp : SDNode<"M68kISD::CMP", MxSDT_CmpTest>;
+def MxBt : SDNode<"M68kISD::BT", MxSDT_CmpTest>;
+
+def MxCmov : SDNode<"M68kISD::CMOV", MxSDT_Cmov>;
+def MxBrCond : SDNode<"M68kISD::BRCOND", MxSDT_BrCond, [SDNPHasChain]>;
+def MxSetCC : SDNode<"M68kISD::SETCC", MxSDT_SetCC>;
+def MxSetCC_C : SDNode<"M68kISD::SETCC_CARRY", MxSDT_SetCC_C>;
+
+
+def MxSegAlloca : SDNode<"M68kISD::SEG_ALLOCA", MxSDT_SEG_ALLOCA,
+ [SDNPHasChain]>;
+
+
+//===----------------------------------------------------------------------===//
+// Operands
+//===----------------------------------------------------------------------===//
+
+/// Size is the size of the data, either bits of a register or number of bits
+/// addressed in memory. Size id is a letter that identifies size.
+class MxSize<int num, string id, string full> {
+ int Num = num;
+ string Id = id;
+ string Full = full;
+}
+
+def MxSize8 : MxSize<8, "b", "byte">;
+def MxSize16 : MxSize<16, "w", "word">;
+def MxSize32 : MxSize<32, "l", "long">;
+
+class MxOperand<ValueType vt, MxSize size, string letter, RegisterClass rc, dag pat = (null_frag)> {
+ ValueType VT = vt;
+ string Letter = letter;
+ MxSize Size = size;
+ RegisterClass RC = rc;
+ dag Pat = pat;
+}
+
+class MxRegOp<ValueType vt,
+ RegisterClass rc,
+ MxSize size,
+ string letter,
+ string pm = "printOperand">
+ : RegisterOperand<rc, pm>,
+ MxOperand<vt, size, letter, rc>;
+
+// REGISTER DIRECT. The operand is in the data register specified by
+// the effective address register field.
+def MxXRD16 : MxRegOp<i16, XR16, MxSize16, "r">;
+def MxXRD32 : MxRegOp<i32, XR32, MxSize32, "r">;
+
+def MxXRD16_TC : MxRegOp<i16, XR16_TC, MxSize16, "r">;
+def MxXRD32_TC : MxRegOp<i32, XR32_TC, MxSize32, "r">;
+
+// DATA REGISTER DIRECT. The operand is in the data register specified by
+// the effective address register field.
+def MxDRD8 : MxRegOp<i8, DR8, MxSize8, "d">;
+def MxDRD16 : MxRegOp<i16, DR16, MxSize16, "d">;
+def MxDRD32 : MxRegOp<i32, DR32, MxSize32, "d">;
+
+def MxDRD16_TC : MxRegOp<i16, DR16_TC, MxSize16, "d">;
+def MxDRD32_TC : MxRegOp<i32, DR32_TC, MxSize32, "d">;
+
+// ADDRESS REGISTER DIRECT. The operand is in the address register specified by
+// the effective address register field.
+def MxARD16 : MxRegOp<i16, AR16, MxSize16, "a">;
+def MxARD32 : MxRegOp<i32, AR32, MxSize32, "a">;
+
+def MxARD16_TC : MxRegOp<i16, AR16_TC, MxSize16, "a">;
+def MxARD32_TC : MxRegOp<i32, AR32_TC, MxSize32, "a">;
+
+// TODO finish parser wiring
+def MxMemAsmOperand : AsmOperandClass {
+ let Name = "MxMemOp";
+}
+
+class MxMemOp<dag ops, MxSize size, string letter,
+ string printMethod = "printOperand",
+ AsmOperandClass parserMatchClass = MxMemAsmOperand>
+ : Operand<iPTR>, MxOperand<iPTR, size, letter, ?> {
+ let PrintMethod = printMethod;
+ let MIOperandInfo = ops;
+ let ParserMatchClass = parserMatchClass;
+ let OperandType = "OPERAND_MEMORY";
+}
+
+// ADDRESS REGISTER INDIRECT. The address of the operand is in the address
+// register specified by the register field. The reference is classified as
+// a data reference with the exception of the jump and jump-to-subroutine
+// instructions.
+def MxARI8 : MxMemOp<(ops AR32), MxSize8, "j", "printARI8Mem">;
+def MxARI16 : MxMemOp<(ops AR32), MxSize16, "j", "printARI16Mem">;
+def MxARI32 : MxMemOp<(ops AR32), MxSize32, "j", "printARI32Mem">;
+
+def MxARI8_TC : MxMemOp<(ops AR32_TC), MxSize8, "j", "printARI8Mem">;
+def MxARI16_TC : MxMemOp<(ops AR32_TC), MxSize16, "j", "printARI16Mem">;
+def MxARI32_TC : MxMemOp<(ops AR32_TC), MxSize32, "j", "printARI32Mem">;
+
+// ADDRESS REGISTER INDIRECT WITH POSTINCREMENT. The address of the operand is
+// in the address register specified by the register field. After the operand
+// address is used, it is incremented by one, two, or four depending upon whether
+// the size of the operand is byte, word, or long word. If the address register
+// is the stack pointer and the operand size is byte, the address is incremented
+// by two rather than one to keep the stack pointer on a word boundary.
+// The reference is classified as a data reference.
+def MxARIPI8 : MxMemOp<(ops AR32), MxSize8, "o", "printARIPI8Mem">;
+def MxARIPI16 : MxMemOp<(ops AR32), MxSize16, "o", "printARIPI16Mem">;
+def MxARIPI32 : MxMemOp<(ops AR32), MxSize32, "o", "printARIPI32Mem">;
+
+def MxARIPI8_TC : MxMemOp<(ops AR32_TC), MxSize8, "o", "printARIPI8Mem">;
+def MxARIPI16_TC : MxMemOp<(ops AR32_TC), MxSize16, "o", "printARIPI16Mem">;
+def MxARIPI32_TC : MxMemOp<(ops AR32_TC), MxSize32, "o", "printARIPI32Mem">;
+
+// ADDRESS REGISTER INDIRECT WITH PREDECREMENT. The address of the operand is in
+// the address register specified by the register field. Before the operand
+// address is used, it is decremented by one, two, or four depending upon whether
+// the operand size is byte, word, or long word. If the address register is
+// the stack pointer and the operand size is byte, the address is decremented by
+// two rather than one to keep the stack pointer on a word boundary.
+// The reference is classified as a data reference.
+def MxARIPD8 : MxMemOp<(ops AR32), MxSize8, "e", "printARIPD8Mem">;
+def MxARIPD16 : MxMemOp<(ops AR32), MxSize16, "e", "printARIPD16Mem">;
+def MxARIPD32 : MxMemOp<(ops AR32), MxSize32, "e", "printARIPD32Mem">;
+
+def MxARIPD8_TC : MxMemOp<(ops AR32_TC), MxSize8, "e", "printARIPD8Mem">;
+def MxARIPD16_TC : MxMemOp<(ops AR32_TC), MxSize16, "e", "printARIPD16Mem">;
+def MxARIPD32_TC : MxMemOp<(ops AR32_TC), MxSize32, "e", "printARIPD32Mem">;
+
+// ADDRESS REGISTER INDIRECT WITH DISPLACEMENT. This addressing mode requires one
+// word of extension. The address of the operand is the sum of the address in
+// the address register and the sign-extended 16-bit displacement integer in the
+// extension word. The reference is classified as a data reference with the
+// exception of the jump and jump-to-subroutine instructions.
+def MxARID8 : MxMemOp<(ops i16imm, AR32), MxSize8, "p", "printARID8Mem">;
+def MxARID16 : MxMemOp<(ops i16imm, AR32), MxSize16, "p", "printARID16Mem">;
+def MxARID32 : MxMemOp<(ops i16imm, AR32), MxSize32, "p", "printARID32Mem">;
+
+def MxARID8_TC : MxMemOp<(ops i16imm, AR32_TC), MxSize8, "p", "printARID8Mem">;
+def MxARID16_TC : MxMemOp<(ops i16imm, AR32_TC), MxSize16, "p", "printARID16Mem">;
+def MxARID32_TC : MxMemOp<(ops i16imm, AR32_TC), MxSize32, "p", "printARID32Mem">;
+
+// ADDRESS REGISTER INDIRECT WITH INDEX. This addressing mode requires one word
+// of extension. The address of the operand is the sum of the address in the
+// address register, the signextended displacement integer in the low order eight
+// bits of the extension word, and the contents of the index register.
+// The reference is classified as a data reference with the exception of the
+// jump and jump-to-subroutine instructions
+def MxARII8 : MxMemOp<(ops i8imm, AR32, XR32), MxSize8, "f", "printARII8Mem">;
+def MxARII16 : MxMemOp<(ops i8imm, AR32, XR32), MxSize16, "f", "printARII16Mem">;
+def MxARII32 : MxMemOp<(ops i8imm, AR32, XR32), MxSize32, "f", "printARII32Mem">;
+
+def MxARII8_TC : MxMemOp<(ops i8imm, AR32_TC, XR32_TC), MxSize8, "f", "printARII8Mem">;
+def MxARII16_TC : MxMemOp<(ops i8imm, AR32_TC, XR32_TC), MxSize16, "f", "printARII16Mem">;
+def MxARII32_TC : MxMemOp<(ops i8imm, AR32_TC, XR32_TC), MxSize32, "f", "printARII32Mem">;
+
+// ABSOLUTE SHORT ADDRESS. This addressing mode requires one word of extension.
+// The address of the operand is the extension word. The 16-bit address is sign
+// extended before it is used. The reference is classified as a data reference
+// with the exception of the jump and jump-tosubroutine instructions.
+def MxAS8 : MxMemOp<(ops OtherVT), MxSize8, "B", "printAS8Mem">;
+def MxAS16 : MxMemOp<(ops OtherVT), MxSize16, "B", "printAS16Mem">;
+def MxAS32 : MxMemOp<(ops OtherVT), MxSize32, "B", "printAS32Mem">;
+
+// ABSOLUTE LONG ADDRESS. This addressing mode requires two words of extension.
+// The address of the operand is developed by the concatenation of the extension
+// words. The high order part of the address is the first extension word; the low
+// order part of the address is the second extension word. The reference is
+// classified as a data reference with the exception of the jump and jump
+// to-subroutine instructions.
+def MxAL8 : MxMemOp<(ops OtherVT), MxSize8, "b", "printAL8Mem">;
+def MxAL16 : MxMemOp<(ops OtherVT), MxSize16, "b", "printAL16Mem">;
+def MxAL32 : MxMemOp<(ops OtherVT), MxSize32, "b", "printAL32Mem">;
+
+let OperandType = "OPERAND_PCREL" in {
+// PROGRAM COUNTER WITH DISPLACEMENT. This addressing mode requires one word of
+// extension. The address of the operand is the sum of the address in the program
+// counter and the Sign-extended 16-bit displacement integer in the extension
+// word. The value in the program counter is the address of the extension word.
+// The reference is classified as a program reference.
+def MxPCD8 : MxMemOp<(ops i16imm), MxSize8, "q", "printPCD8Mem">;
+def MxPCD16 : MxMemOp<(ops i16imm), MxSize16, "q", "printPCD16Mem">;
+def MxPCD32 : MxMemOp<(ops i16imm), MxSize32, "q", "printPCD32Mem">;
+
+// PROGRAM COUNTER WITH INDEX. This addressing mode requires one word of
+// extension. The address is the sum of the address in the program counter, the
+// sign-extended displacement integer in the lower eight bits of the extension
+// word, and the contents of the index register. The value in the program
+// counter is the address of the extension word. This reference is classified as
+// a program reference.
+def MxPCI8 : MxMemOp<(ops i8imm, XR32), MxSize8, "k", "printPCI8Mem">;
+def MxPCI16 : MxMemOp<(ops i8imm, XR32), MxSize16, "k", "printPCI16Mem">;
+def MxPCI32 : MxMemOp<(ops i8imm, XR32), MxSize32, "k", "printPCI32Mem">;
+} // OPERAND_PCREL
+
+class MxOp<ValueType vt, MxSize size, string letter>
+ : Operand<vt>,
+ MxOperand<vt, size, letter, ?>;
+
+let OperandType = "OPERAND_IMMEDIATE",
+ PrintMethod = "printImmediate" in {
+// IMMEDIATE DATA. This addressing mode requires either one or two words of
+// extension depending on the size of the operation.
+// Byte Operation - operand is low order byte of extension word
+// Word Operation - operand is extension word
+// Long Word Operation - operand is in the two extension words,
+// high order 16 bits are in the first
+// extension word, low order 16 bits are
+// in the second extension word.
+def Mxi8imm : MxOp<i8, MxSize8, "i">;
+def Mxi16imm : MxOp<i16, MxSize16, "i">;
+def Mxi32imm : MxOp<i32, MxSize32, "i">;
+} // OPERAND_IMMEDIATE
+
+let OperandType = "OPERAND_PCREL",
+ PrintMethod = "printPCRelImm" in {
+
+// Branch targets have OtherVT type and print as pc-relative values.
+def MxBrTarget8 : Operand<OtherVT>;
+def MxBrTarget16 : Operand<OtherVT>;
+def MxBrTarget32 : Operand<OtherVT>;
+
+} // OPERAND_PCREL
+
+// Used with MOVEM
+def MxMoveMask : MxOp<i16, MxSize16, "m"> {
+ let OperandType = "OPERAND_IMMEDIATE";
+ let PrintMethod = "printMoveMask";
+}
+
+
+//===----------------------------------------------------------------------===//
+// Predicates
+//===----------------------------------------------------------------------===//
+
+def SmallCode : Predicate<"TM.getCodeModel() == CodeModel::Small">;
+def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">;
+def FarData : Predicate<"TM.getCodeModel() != CodeModel::Small &&"
+ "TM.getCodeModel() != CodeModel::Kernel">;
+def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||"
+ "TM.getCodeModel() == CodeModel::Kernel">;
+def IsPIC : Predicate<"TM.isPositionIndependent()">;
+def IsNotPIC : Predicate<"!TM.isPositionIndependent()">;
+def IsM68000 : Predicate<"Subtarget.IsM68000()">;
+def IsM68010 : Predicate<"Subtarget.IsM68010()">;
+def IsM68020 : Predicate<"Subtarget.IsM68020()">;
+def IsM68030 : Predicate<"Subtarget.IsM68030()">;
+def IsM68040 : Predicate<"Subtarget.IsM68040()">;
+
+
+//===----------------------------------------------------------------------===//
+// Condition Codes
+//
+// These MUST be kept in sync with codes enum in M68kInstrInfo.h
+//===----------------------------------------------------------------------===//
+
+def MxCONDt : PatLeaf<(i8 0)>; // True
+def MxCONDf : PatLeaf<(i8 1)>; // False
+def MxCONDhi : PatLeaf<(i8 2)>; // High
+def MxCONDls : PatLeaf<(i8 3)>; // Less or Same
+def MxCONDcc : PatLeaf<(i8 4)>; // Carry Clear
+def MxCONDcs : PatLeaf<(i8 5)>; // Carry Set
+def MxCONDne : PatLeaf<(i8 6)>; // Not Equal
+def MxCONDeq : PatLeaf<(i8 7)>; // Equal
+def MxCONDvc : PatLeaf<(i8 8)>; // Overflow Clear
+def MxCONDvs : PatLeaf<(i8 9)>; // Overflow Set
+def MxCONDpl : PatLeaf<(i8 10)>; // Plus
+def MxCONDmi : PatLeaf<(i8 11)>; // Minus
+def MxCONDge : PatLeaf<(i8 12)>; // Greater or Equal
+def MxCONDlt : PatLeaf<(i8 13)>; // Less Than
+def MxCONDgt : PatLeaf<(i8 14)>; // Greater Than
+def MxCONDle : PatLeaf<(i8 15)>; // Less or Equal
+
+
+//===----------------------------------------------------------------------===//
+// Complex Patterns
+//===----------------------------------------------------------------------===//
+
+// NOTE Though this CP is not strictly necessarily it will simplify instruciton
+// definitions
+def MxCP_ARI : ComplexPattern<iPTR, 1, "SelectARI",
+ [], [SDNPWantParent]>;
+
+def MxCP_ARIPI : ComplexPattern<iPTR, 1, "SelectARIPI",
+ [], [SDNPWantParent]>;
+
+def MxCP_ARIPD : ComplexPattern<iPTR, 1, "SelectARIPD",
+ [], [SDNPWantParent]>;
+
+def MxCP_ARID : ComplexPattern<iPTR, 2, "SelectARID",
+ [add, sub, mul, or, shl, frameindex],
+ [SDNPWantParent]>;
+
+def MxCP_ARII : ComplexPattern<iPTR, 3, "SelectARII",
+ [add, sub, mul, or, shl, frameindex],
+ [SDNPWantParent]>;
+
+def MxCP_AL : ComplexPattern<iPTR, 1, "SelectAL",
+ [add, sub, mul, or, shl],
+ [SDNPWantParent]>;
+
+def MxCP_PCD : ComplexPattern<iPTR, 1, "SelectPCD",
+ [add, sub, mul, or, shl],
+ [SDNPWantParent]>;
+
+def MxCP_PCI : ComplexPattern<iPTR, 2, "SelectPCI",
+ [add, sub, mul, or, shl], [SDNPWantParent]>;
+
+
+//===----------------------------------------------------------------------===//
+// Pattern Fragments
+//===----------------------------------------------------------------------===//
+
+def MximmSExt8 : PatLeaf<(i8 imm)>;
+def MximmSExt16 : PatLeaf<(i16 imm)>;
+def MximmSExt32 : PatLeaf<(i32 imm)>;
+
+// Used for Shifts and Rotations, since M68k immediates in these instructions
+// are 1 <= i <= 8. Generally, if immediate is bigger than 8 it will be moved
+// to a register and then an operation is performed.
+//
+// TODO Need to evaluate whether splitting one big shift(or rotate)
+// into a few smaller is faster than doing a move, if so do custom lowering
+def Mximm8_1to8 : ImmLeaf<i8, [{ return Imm >= 1 && Imm <= 8; }]>;
+def Mximm16_1to8 : ImmLeaf<i16, [{ return Imm >= 1 && Imm <= 8; }]>;
+def Mximm32_1to8 : ImmLeaf<i32, [{ return Imm >= 1 && Imm <= 8; }]>;
+
+// Helper fragments for loads.
+// It's always safe to treat a anyext i16 load as a i32 load if the i16 is
+// known to be 32-bit aligned or better. Ditto for i8 to i16.
+def Mxloadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{
+ LoadSDNode *LD = cast<LoadSDNode>(N);
+ ISD::LoadExtType ExtType = LD->getExtensionType();
+ if (ExtType == ISD::NON_EXTLOAD)
+ return true;
+ if (ExtType == ISD::EXTLOAD)
+ return LD->getAlignment() >= 2 && !LD->isSimple();
+ return false;
+}]>;
+
+def Mxloadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{
+ LoadSDNode *LD = cast<LoadSDNode>(N);
+ ISD::LoadExtType ExtType = LD->getExtensionType();
+ if (ExtType == ISD::NON_EXTLOAD)
+ return true;
+ if (ExtType == ISD::EXTLOAD)
+ return LD->getAlignment() >= 4 && !LD->isSimple();
+ return false;
+}]>;
+
+def Mxloadi8 : PatFrag<(ops node:$ptr), (i8 (load node:$ptr))>;
+
+def MxSExtLoadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>;
+def MxSExtLoadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>;
+def MxSExtLoadi32i16 : PatFrag<(ops node:$ptr), (i32 (sextloadi16 node:$ptr))>;
+
+def MxZExtLoadi8i1 : PatFrag<(ops node:$ptr), (i8 (zextloadi1 node:$ptr))>;
+def MxZExtLoadi16i1 : PatFrag<(ops node:$ptr), (i16 (zextloadi1 node:$ptr))>;
+def MxZExtLoadi32i1 : PatFrag<(ops node:$ptr), (i32 (zextloadi1 node:$ptr))>;
+def MxZExtLoadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>;
+def MxZExtLoadi32i8 : PatFrag<(ops node:$ptr), (i32 (zextloadi8 node:$ptr))>;
+def MxZExtLoadi32i16 : PatFrag<(ops node:$ptr), (i32 (zextloadi16 node:$ptr))>;
+
+def MxExtLoadi8i1 : PatFrag<(ops node:$ptr), (i8 (extloadi1 node:$ptr))>;
+def MxExtLoadi16i1 : PatFrag<(ops node:$ptr), (i16 (extloadi1 node:$ptr))>;
+def MxExtLoadi32i1 : PatFrag<(ops node:$ptr), (i32 (extloadi1 node:$ptr))>;
+def MxExtLoadi16i8 : PatFrag<(ops node:$ptr), (i16 (extloadi8 node:$ptr))>;
+def MxExtLoadi32i8 : PatFrag<(ops node:$ptr), (i32 (extloadi8 node:$ptr))>;
+def MxExtLoadi32i16 : PatFrag<(ops node:$ptr), (i32 (extloadi16 node:$ptr))>;
+
+
+//===----------------------------------------------------------------------===//
+// Type Fixtures
+//
+// Type Fixtures are ValueType related information sets that usually go together
+//===----------------------------------------------------------------------===//
+
+// TODO make it folded like MxType8.F.Op nad MxType8.F.Pat
+// TODO move strings into META subclass
+// vt: Type of data this fixture refers to
+// prefix: Prefix used to identify type
+// postfix: Prefix used to qualify type
+class MxType<ValueType vt, string prefix, string postfix,
+ // rLet: Register letter
+ // rOp: Supported any register operand
+ string rLet, MxOperand rOp,
+ // jOp: Supported ARI operand
+ // jPat: What ARI pattern to use
+ MxOperand jOp, ComplexPattern jPat,
+ // oOp: Supported ARIPI operand
+ // oPat: What ARIPI pattern is used
+ MxOperand oOp, ComplexPattern oPat,
+ // eOp: Supported ARIPD operand
+ // ePat: What ARIPD pattern is used
+ MxOperand eOp, ComplexPattern ePat,
+ // pOp: Supported ARID operand
+ // pPat: What ARID pattern is used
+ MxOperand pOp, ComplexPattern pPat,
+ // fOp: Supported ARII operand
+ // fPat: What ARII pattern is used
+ MxOperand fOp, ComplexPattern fPat,
+ // bOp: Supported absolute operand
+ // bPat: What absolute pattern is used
+ MxOperand bOp, ComplexPattern bPat,
+ // qOp: Supported PCD operand
+ // qPat: What PCD pattern is used
+ MxOperand qOp, ComplexPattern qPat,
+ // kOp: Supported PCD operand
+ // kPat: What PCD pattern is used
+ MxOperand kOp, ComplexPattern kPat,
+ // iOp: Supported immediate operand
+ // iPat: What immediate pattern is used
+ MxOperand iOp, PatFrag iPat,
+ // load: What load operation is used with MEM
+ PatFrag load> {
+ int Size = vt.Size;
+ ValueType VT = vt;
+ string Prefix = prefix;
+ string Postfix = postfix;
+
+ string RLet = rLet;
+ MxOperand ROp = rOp;
+
+ MxOperand JOp = jOp;
+ ComplexPattern JPat = jPat;
+
+ MxOperand OOp = oOp;
+ ComplexPattern OPat = oPat;
+
+ MxOperand EOp = eOp;
+ ComplexPattern EPat = ePat;
+
+ MxOperand POp = pOp;
+ ComplexPattern PPat = pPat;
+
+ MxOperand FOp = fOp;
+ ComplexPattern FPat = fPat;
+
+ MxOperand BOp = bOp;
+ ComplexPattern BPat = bPat;
+
+ MxOperand QOp = qOp;
+ ComplexPattern QPat = qPat;
+
+ MxOperand KOp = kOp;
+ ComplexPattern KPat = kPat;
+
+ MxOperand IOp = iOp;
+ PatFrag IPat = iPat;
+
+ PatFrag Load = load;
+}
+
+class MxType8Class<string rLet, MxOperand reg>
+ : MxType<i8, "b", "", rLet, reg,
+ MxARI8, MxCP_ARI,
+ MxARIPI8, MxCP_ARIPI,
+ MxARIPD8, MxCP_ARIPD,
+ MxARID8, MxCP_ARID,
+ MxARII8, MxCP_ARII,
+ MxAL8, MxCP_AL,
+ MxPCD8, MxCP_PCD,
+ MxPCI8, MxCP_PCI,
+ Mxi8imm, MximmSExt8,
+ Mxloadi8>;
+
+def MxType8 : MxType8Class<?,?>;
+
+class MxType16Class<string rLet, MxOperand reg>
+ : MxType<i16, "w", "", rLet, reg,
+ MxARI16, MxCP_ARI,
+ MxARIPI16, MxCP_ARIPI,
+ MxARIPD16, MxCP_ARIPD,
+ MxARID16, MxCP_ARID,
+ MxARII16, MxCP_ARII,
+ MxAL16, MxCP_AL,
+ MxPCD16, MxCP_PCD,
+ MxPCI16, MxCP_PCI,
+ Mxi16imm, MximmSExt16,
+ Mxloadi16>;
+
+def MxType16 : MxType16Class<?,?>;
+
+class MxType32Class<string rLet, MxOperand reg>
+ : MxType<i32, "l", "", rLet, reg,
+ MxARI32, MxCP_ARI,
+ MxARIPI32, MxCP_ARIPI,
+ MxARIPD32, MxCP_ARIPD,
+ MxARID32, MxCP_ARID,
+ MxARII32, MxCP_ARII,
+ MxAL32, MxCP_AL,
+ MxPCD32, MxCP_PCD,
+ MxPCI32, MxCP_PCI,
+ Mxi32imm, MximmSExt32,
+ Mxloadi32>;
+
+def MxType32 : MxType32Class<?,?>;
+
+
+def MxType8d : MxType8Class<"d", MxDRD8>;
+
+def MxType16d : MxType16Class<"d", MxDRD16>;
+def MxType16a : MxType16Class<"a", MxARD16>;
+def MxType16r : MxType16Class<"r", MxXRD16>;
+def MxType32d : MxType32Class<"d", MxDRD32>;
+def MxType32a : MxType32Class<"a", MxARD32>;
+def MxType32r : MxType32Class<"r", MxXRD32>;
+
+let Postfix = "_TC" in {
+def MxType16d_TC : MxType16Class<"d", MxDRD16_TC>;
+def MxType16a_TC : MxType16Class<"a", MxARD16_TC>;
+def MxType16r_TC : MxType16Class<"r", MxXRD16_TC>;
+def MxType32d_TC : MxType32Class<"d", MxDRD32_TC>;
+def MxType32a_TC : MxType32Class<"a", MxARD32_TC>;
+def MxType32r_TC : MxType32Class<"r", MxXRD32_TC>;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Subsystems
+//===----------------------------------------------------------------------===//
+
+include "M68kInstrData.td"
+include "M68kInstrShiftRotate.td"
+include "M68kInstrBits.td"
+include "M68kInstrArithmetic.td"
+include "M68kInstrControl.td"
+
+include "M68kInstrCompiler.td"
diff --git a/llvm/lib/Target/M68k/M68kInstrShiftRotate.td b/llvm/lib/Target/M68k/M68kInstrShiftRotate.td
new file mode 100644
index 000000000000..f777a5d33e21
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kInstrShiftRotate.td
@@ -0,0 +1,92 @@
+//===------ M68kInstrShiftRotate.td - Logical Instrs -----*- tablegen -*-===//
+//
+// 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 describes the logical instructions in the M68k architecture.
+/// Here is the current status of the file:
+///
+/// Machine:
+///
+/// SHL [~] ASR [~] LSR [~] SWAP [ ]
+/// ROL [~] ROR [~] ROXL [ ] ROXR [ ]
+///
+/// Map:
+///
+/// [ ] - was not touched at all
+/// [!] - requires extarnal stuff implemented
+/// [~] - in progress but usable
+/// [x] - done
+///
+//===----------------------------------------------------------------------===//
+
+def MxRODI_R : MxBead1Bit<0>;
+def MxRODI_L : MxBead1Bit<1>;
+
+def MxROOP_AS : MxBead2Bits<0b00>;
+def MxROOP_LS : MxBead2Bits<0b01>;
+def MxROOP_ROX : MxBead2Bits<0b10>;
+def MxROOP_RO : MxBead2Bits<0b11>;
+
+/// ------------+---------+---+------+---+------+---------
+/// F E D C | B A 9 | 8 | 7 6 | 5 | 4 3 | 2 1 0
+/// ------------+---------+---+------+---+------+---------
+/// 1 1 1 0 | REG/IMM | D | SIZE |R/I| OP | REG
+/// ------------+---------+---+------+---+------+---------
+class MxSREncoding_R<MxBead1Bit DIRECTION, MxBead2Bits ROOP, MxEncSize SIZE>
+ : MxEncoding<MxBeadReg<0>, ROOP, MxBead1Bit<1>, SIZE, DIRECTION,
+ MxBeadReg<2>, MxBead4Bits<0b1110>>;
+
+class MxSREncoding_I<MxBead1Bit DIRECTION, MxBead2Bits ROOP, MxEncSize SIZE>
+ : MxEncoding<MxBeadReg<0>, ROOP, MxBead1Bit<0>, SIZE, DIRECTION,
+ MxBead3Imm<2, 1>, MxBead4Bits<0b1110>>;
+
+// $reg <- $reg op $reg
+class MxSR_DD<string MN, MxType TYPE, SDNode NODE,
+ MxBead1Bit RODI, MxBead2Bits ROOP>
+ : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd),
+ MN#"."#TYPE.Prefix#"\t$opd, $dst",
+ [(set TYPE.VT:$dst, (NODE TYPE.VT:$src, TYPE.VT:$opd))],
+ MxSREncoding_R<RODI, ROOP,
+ !cast<MxEncSize>("MxEncSize"#TYPE.Size)>>;
+
+// $reg <- $reg op $imm
+class MxSR_DI<string MN, MxType TYPE, SDNode NODE,
+ MxBead1Bit RODI, MxBead2Bits ROOP>
+ : MxInst<(outs TYPE.ROp:$dst),
+ (ins TYPE.ROp:$src, !cast<Operand>("Mxi"#TYPE.Size#"imm"):$opd),
+ MN#"."#TYPE.Prefix#"\t$opd, $dst",
+ [(set TYPE.VT:$dst,
+ (NODE TYPE.VT:$src,
+ !cast<ImmLeaf>("Mximm"#TYPE.Size#"_1to8"):$opd))],
+ MxSREncoding_I<RODI, ROOP,
+ !cast<MxEncSize>("MxEncSize"#TYPE.Size)>>;
+
+multiclass MxSROp<string MN, SDNode NODE, MxBead1Bit RODI, MxBead2Bits ROOP> {
+
+ let Defs = [CCR] in {
+ let Constraints = "$src = $dst" in {
+
+ def NAME#"8dd" : MxSR_DD<MN, MxType8d, NODE, RODI, ROOP>;
+ def NAME#"16dd" : MxSR_DD<MN, MxType16d, NODE, RODI, ROOP>;
+ def NAME#"32dd" : MxSR_DD<MN, MxType32d, NODE, RODI, ROOP>;
+
+ def NAME#"8di" : MxSR_DI<MN, MxType8d, NODE, RODI, ROOP>;
+ def NAME#"16di" : MxSR_DI<MN, MxType16d, NODE, RODI, ROOP>;
+ def NAME#"32di" : MxSR_DI<MN, MxType32d, NODE, RODI, ROOP>;
+
+ } // $src = $dst
+ } // Defs = [CCR]
+
+} // MxBiArOp_RF
+
+defm SHL : MxSROp<"lsl", shl, MxRODI_L, MxROOP_LS>;
+defm LSR : MxSROp<"lsr", srl, MxRODI_R, MxROOP_LS>;
+defm ASR : MxSROp<"asr", sra, MxRODI_R, MxROOP_AS>;
+
+defm ROL : MxSROp<"rol", rotl, MxRODI_L, MxROOP_RO>;
+defm ROR : MxSROp<"ror", rotr, MxRODI_R, MxROOP_RO>;
diff --git a/llvm/lib/Target/M68k/M68kRegisterInfo.td b/llvm/lib/Target/M68k/M68kRegisterInfo.td
new file mode 100644
index 000000000000..76e762c718b0
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kRegisterInfo.td
@@ -0,0 +1,130 @@
+//== M68kRegisterInfo.td - M68k register definitions ----*- tablegen -*-==//
+//
+// 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 describes the M68k Register file, defining the registers
+/// aliases between the registers, and the register classes built out of the
+/// registers.
+///
+//===----------------------------------------------------------------------===//
+
+class MxReg<string N, bits<16> ENC,
+ list<Register> SUBREGS = [], list<SubRegIndex> SUBIDX,
+ list<int> DWREGS = []>
+ : Register<N>, DwarfRegNum<DWREGS> {
+ let Namespace = "M68k";
+ let HWEncoding = ENC;
+ let SubRegs = SUBREGS;
+ let SubRegIndices = SUBIDX;
+}
+
+// Subregister indices.
+let Namespace = "M68k" in {
+ def MxSubRegIndex8Lo : SubRegIndex<8, 0>;
+ def MxSubRegIndex16Lo : SubRegIndex<16, 0>;
+}
+
+// Generate Data registers and theirs smaller variants
+foreach Index = 0-7 in {
+ def "BD"#Index : MxReg<"d"#Index, Index, [], [], [Index]>;
+
+ def "WD"#Index
+ : MxReg<"d"#Index, Index,
+ [!cast<Register>("BD"#Index)], [MxSubRegIndex8Lo],
+ [Index]>;
+
+ def "D"#Index
+ : MxReg<"d"#Index, Index,
+ [!cast<Register>("WD"#Index)], [MxSubRegIndex16Lo],
+ [Index]>;
+
+} // foreach
+
+// Generate Address registers and theirs smaller variants
+foreach Index = 0-7 in {
+ def "WA"#Index
+ : MxReg<"a"#Index, Index, [], [], [!add(8,Index)]>;
+
+ def "A"#Index
+ : MxReg<"a"#Index, Index,
+ [!cast<Register>("WA"#Index)], [MxSubRegIndex16Lo],
+ [!add(8,Index)]>;
+}
+
+// Alias Registers
+class MxAliasReg<string N, MxReg REG>
+ : MxReg<N, REG.HWEncoding, [], [], REG.DwarfNumbers> {
+ let Aliases = [REG];
+}
+
+def BP : MxAliasReg<"bp", A5>;
+def FP : MxAliasReg<"fp", A6>;
+def SP : MxAliasReg<"sp", A7>;
+
+def USP : MxAliasReg<"usp", A7>;
+def SSP : MxAliasReg<"ssp", A7>;
+def ISP : MxAliasReg<"isp", A7>;
+
+// Pseudo Registers
+class MxPseudoReg<string N, list<Register> SUBREGS = [], list<SubRegIndex> SUBIDX = []>
+ : MxReg<N, 0, SUBREGS, SUBIDX>;
+
+def CCR : MxPseudoReg<"ccr">;
+def SR : MxPseudoReg<"sr">;
+
+def PC : MxPseudoReg<"pc">;
+
+//===----------------------------------------------------------------------===//
+// Register Classes
+//===----------------------------------------------------------------------===//
+
+class MxRegClass<list<ValueType> regTypes, int alignment, dag regList>
+ : RegisterClass<"M68k", regTypes, alignment, regList>;
+
+// Data Registers
+def DR8 : MxRegClass<[i8], 16, (sequence "BD%u", 0, 7)>;
+def DR16 : MxRegClass<[i16], 16, (sequence "WD%u", 0, 7)>;
+def DR32 : MxRegClass<[i32], 32, (sequence "D%u", 0, 7)>;
+
+// Address Registers
+def AR16 : MxRegClass<[i16], 16, (sequence "WA%u", 0, 6)>;
+def AR32 : MxRegClass<[i32], 32, (add (sequence "A%u", 0, 6), SP)>;
+
+def AR32_NOSP : MxRegClass<[i32], 32, (add (sequence "A%u", 0, 6))>;
+
+// Index Register Classes
+// FIXME try alternative ordering like `D0, D1, A0, A1, ...`
+def XR16 : MxRegClass<[i16], 16, (add DR16, AR16)>;
+def XR32 : MxRegClass<[i32], 32, (add DR32, AR32)>;
+
+def SPC : MxRegClass<[i32], 32, (add SP)>;
+
+let CopyCost = -1 in {
+ def CCRC : MxRegClass<[i8], 16, (add CCR)>;
+ def SRC : MxRegClass<[i16], 16, (add SR)>;
+}
+
+let isAllocatable = 0 in {
+ def PCC : MxRegClass<[i32], 32, (add PC)>;
+}
+
+// Register used with tail call
+def DR16_TC : MxRegClass<[i16], 16, (add D0, D1)>;
+def DR32_TC : MxRegClass<[i32], 32, (add D0, D1)>;
+
+def AR16_TC : MxRegClass<[i16], 16, (add A0, A1)>;
+def AR32_TC : MxRegClass<[i32], 32, (add A0, A1)>;
+
+def XR16_TC : MxRegClass<[i16], 16, (add DR16_TC, AR16_TC)>;
+def XR32_TC : MxRegClass<[i32], 32, (add DR32_TC, AR32_TC)>;
+
+// These classes provide spill/restore order if used with MOVEM instruction
+def SPILL : MxRegClass<[i32], 32, (add (add (sequence "D%u", 0, 7),
+ (sequence "A%u", 0, 6)), SP)>;
+def SPILL_R : MxRegClass<[i32], 32, (add SP, (add (sequence "A%u", 6, 0),
+ (sequence "D%u", 7, 0)))>;
diff --git a/llvm/lib/Target/M68k/M68kSchedule.td b/llvm/lib/Target/M68k/M68kSchedule.td
new file mode 100644
index 000000000000..a94cd8f31e2e
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kSchedule.td
@@ -0,0 +1,23 @@
+//===-- M68kSchedule.td - M68k Scheduling Definitions --*- tablegen -*-===//
+//
+// 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 scheduler definitions.
+///
+//===----------------------------------------------------------------------===//
+
+/// This is a very general M68k Scheduling Model and best suited for the very
+/// first M68000 CPU, other model must override these characteristics
+class M68kSchedModel : SchedMachineModel {
+ let LoadLatency = 4; // Word (Rn)
+ let HighLatency = 16; // Long ABS
+ let PostRAScheduler = 0;
+ let CompleteModel = 0;
+}
+
+def GenericM68kModel : M68kSchedModel;
diff --git a/llvm/lib/Target/M68k/M68kTargetMachine.cpp b/llvm/lib/Target/M68k/M68kTargetMachine.cpp
new file mode 100644
index 000000000000..a40ae10a832b
--- /dev/null
+++ b/llvm/lib/Target/M68k/M68kTargetMachine.cpp
@@ -0,0 +1,17 @@
+//===-- M68kTargetMachine.cpp - M68k target machine ---------*- 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 implementation for M68k target machine.
+///
+//===----------------------------------------------------------------------===//
+
+/// This is just a placeholder to make current
+/// commit buildable. Body of this function will
+/// be filled in later commits
+extern "C" void LLVMInitializeM68kTarget() {}
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/M68k/MCTargetDesc/CMakeLists.txt
new file mode 100644
index 000000000000..dadb6919d928
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_llvm_component_library(LLVMM68kDesc
+ M68kMCTargetDesc.cpp
+
+ LINK_COMPONENTS
+ MC
+ MCDisassembler
+ Support
+ M68kInfo
+
+ ADD_TO_COMPONENT
+ M68k
+)
diff --git a/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.cpp b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.cpp
new file mode 100644
index 000000000000..7a1fe4580148
--- /dev/null
+++ b/llvm/lib/Target/M68k/MCTargetDesc/M68kMCTargetDesc.cpp
@@ -0,0 +1,17 @@
+//===-- M68kMCTargetDesc.cpp - 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 target specific descriptions.
+///
+//===----------------------------------------------------------------------===//
+
+/// This is just a placeholder to make current
+/// commit buildable. Body of this function will
+/// be filled in later commits
+extern "C" void LLVMInitializeM68kTargetMC() {}
diff --git a/llvm/lib/Target/M68k/TargetInfo/CMakeLists.txt b/llvm/lib/Target/M68k/TargetInfo/CMakeLists.txt
new file mode 100644
index 000000000000..d376dcd7d12b
--- /dev/null
+++ b/llvm/lib/Target/M68k/TargetInfo/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_llvm_component_library(LLVMM68kInfo
+ M68kTargetInfo.cpp
+
+ LINK_COMPONENTS
+ Support
+
+ ADD_TO_COMPONENT
+ M68k
+)
diff --git a/llvm/lib/Target/M68k/TargetInfo/M68kTargetInfo.cpp b/llvm/lib/Target/M68k/TargetInfo/M68kTargetInfo.cpp
new file mode 100644
index 000000000000..faedeb1deadd
--- /dev/null
+++ b/llvm/lib/Target/M68k/TargetInfo/M68kTargetInfo.cpp
@@ -0,0 +1,17 @@
+//===-- M68kTargetInfo.cpp - M68k Target Implementation -----*- 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 target initializer.
+///
+//===----------------------------------------------------------------------===//
+
+/// This is just a placeholder to make current
+/// commit buildable. Body of this function will
+/// be filled in later commits
+extern "C" void LLVMInitializeM68kTargetInfo() {}
More information about the llvm-commits
mailing list