104eeddc0SDimitry Andric //===-- M68kTargetMachine.cpp - M68k Target Machine -------------*- C++ -*-===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric ///
9fe6060f1SDimitry Andric /// \file
10fe6060f1SDimitry Andric /// This file contains implementation for M68k target machine.
11fe6060f1SDimitry Andric ///
12fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
13fe6060f1SDimitry Andric
14fe6060f1SDimitry Andric #include "M68kTargetMachine.h"
15fe6060f1SDimitry Andric #include "M68k.h"
16bdd1243dSDimitry Andric #include "M68kMachineFunction.h"
17fe6060f1SDimitry Andric #include "M68kSubtarget.h"
18fe6060f1SDimitry Andric #include "M68kTargetObjectFile.h"
19fe6060f1SDimitry Andric #include "TargetInfo/M68kTargetInfo.h"
20fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
21fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
22fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/Legalizer.h"
23fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
24fe6060f1SDimitry Andric #include "llvm/CodeGen/Passes.h"
25fe6060f1SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
26fe6060f1SDimitry Andric #include "llvm/InitializePasses.h"
27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
28fe6060f1SDimitry Andric #include "llvm/PassRegistry.h"
29fe6060f1SDimitry Andric #include <memory>
30bdd1243dSDimitry Andric #include <optional>
31fe6060f1SDimitry Andric
32fe6060f1SDimitry Andric using namespace llvm;
33fe6060f1SDimitry Andric
34fe6060f1SDimitry Andric #define DEBUG_TYPE "m68k"
35fe6060f1SDimitry Andric
LLVMInitializeM68kTarget()36fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kTarget() {
37fe6060f1SDimitry Andric RegisterTargetMachine<M68kTargetMachine> X(getTheM68kTarget());
38fe6060f1SDimitry Andric auto *PR = PassRegistry::getPassRegistry();
39fe6060f1SDimitry Andric initializeGlobalISel(*PR);
40*0fca6ea1SDimitry Andric initializeM68kDAGToDAGISelLegacyPass(*PR);
4106c3fb27SDimitry Andric initializeM68kExpandPseudoPass(*PR);
4206c3fb27SDimitry Andric initializeM68kGlobalBaseRegPass(*PR);
4306c3fb27SDimitry Andric initializeM68kCollapseMOVEMPass(*PR);
44fe6060f1SDimitry Andric }
45fe6060f1SDimitry Andric
46fe6060f1SDimitry Andric namespace {
47fe6060f1SDimitry Andric
computeDataLayout(const Triple & TT,StringRef CPU,const TargetOptions & Options)48fe6060f1SDimitry Andric std::string computeDataLayout(const Triple &TT, StringRef CPU,
49fe6060f1SDimitry Andric const TargetOptions &Options) {
50fe6060f1SDimitry Andric std::string Ret = "";
51fe6060f1SDimitry Andric // M68k is Big Endian
52fe6060f1SDimitry Andric Ret += "E";
53fe6060f1SDimitry Andric
54fe6060f1SDimitry Andric // FIXME how to wire it with the used object format?
55fe6060f1SDimitry Andric Ret += "-m:e";
56fe6060f1SDimitry Andric
5769ade1e0SDimitry Andric // M68k pointers are always 32 bit wide even for 16-bit CPUs.
5869ade1e0SDimitry Andric // The ABI only specifies 16-bit alignment.
5969ade1e0SDimitry Andric // On at least the 68020+ with a 32-bit bus, there is a performance benefit
6069ade1e0SDimitry Andric // to having 32-bit alignment.
6169ade1e0SDimitry Andric Ret += "-p:32:16:32";
62fe6060f1SDimitry Andric
6369ade1e0SDimitry Andric // Bytes do not require special alignment, words are word aligned and
6469ade1e0SDimitry Andric // long words are word aligned at minimum.
65fe6060f1SDimitry Andric Ret += "-i8:8:8-i16:16:16-i32:16:32";
66fe6060f1SDimitry Andric
67fe6060f1SDimitry Andric // FIXME no floats at the moment
68fe6060f1SDimitry Andric
69fe6060f1SDimitry Andric // The registers can hold 8, 16, 32 bits
70fe6060f1SDimitry Andric Ret += "-n8:16:32";
71fe6060f1SDimitry Andric
72fe6060f1SDimitry Andric Ret += "-a:0:16-S16";
73fe6060f1SDimitry Andric
74fe6060f1SDimitry Andric return Ret;
75fe6060f1SDimitry Andric }
76fe6060f1SDimitry Andric
getEffectiveRelocModel(const Triple & TT,std::optional<Reloc::Model> RM)77fe6060f1SDimitry Andric Reloc::Model getEffectiveRelocModel(const Triple &TT,
78bdd1243dSDimitry Andric std::optional<Reloc::Model> RM) {
79fe6060f1SDimitry Andric // If not defined we default to static
80bdd1243dSDimitry Andric if (!RM.has_value())
81fe6060f1SDimitry Andric return Reloc::Static;
82fe6060f1SDimitry Andric
83fe6060f1SDimitry Andric return *RM;
84fe6060f1SDimitry Andric }
85fe6060f1SDimitry Andric
getEffectiveCodeModel(std::optional<CodeModel::Model> CM,bool JIT)86bdd1243dSDimitry Andric CodeModel::Model getEffectiveCodeModel(std::optional<CodeModel::Model> CM,
87fe6060f1SDimitry Andric bool JIT) {
88fe6060f1SDimitry Andric if (!CM) {
89fe6060f1SDimitry Andric return CodeModel::Small;
90fe6060f1SDimitry Andric } else if (CM == CodeModel::Large) {
91fe6060f1SDimitry Andric llvm_unreachable("Large code model is not supported");
92fe6060f1SDimitry Andric } else if (CM == CodeModel::Kernel) {
93fe6060f1SDimitry Andric llvm_unreachable("Kernel code model is not implemented yet");
94fe6060f1SDimitry Andric }
95bdd1243dSDimitry Andric return CM.value();
96fe6060f1SDimitry Andric }
97fe6060f1SDimitry Andric } // end anonymous namespace
98fe6060f1SDimitry Andric
M68kTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOptLevel OL,bool JIT)99fe6060f1SDimitry Andric M68kTargetMachine::M68kTargetMachine(const Target &T, const Triple &TT,
100fe6060f1SDimitry Andric StringRef CPU, StringRef FS,
101fe6060f1SDimitry Andric const TargetOptions &Options,
102bdd1243dSDimitry Andric std::optional<Reloc::Model> RM,
103bdd1243dSDimitry Andric std::optional<CodeModel::Model> CM,
1045f757f3fSDimitry Andric CodeGenOptLevel OL, bool JIT)
105fe6060f1SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options), TT, CPU, FS,
106fe6060f1SDimitry Andric Options, getEffectiveRelocModel(TT, RM),
107fe6060f1SDimitry Andric ::getEffectiveCodeModel(CM, JIT), OL),
108fe6060f1SDimitry Andric TLOF(std::make_unique<M68kELFTargetObjectFile>()),
109fe6060f1SDimitry Andric Subtarget(TT, CPU, FS, *this) {
110fe6060f1SDimitry Andric initAsmInfo();
111fe6060f1SDimitry Andric }
112fe6060f1SDimitry Andric
~M68kTargetMachine()113fe6060f1SDimitry Andric M68kTargetMachine::~M68kTargetMachine() {}
114fe6060f1SDimitry Andric
115fe6060f1SDimitry Andric const M68kSubtarget *
getSubtargetImpl(const Function & F) const116fe6060f1SDimitry Andric M68kTargetMachine::getSubtargetImpl(const Function &F) const {
117fe6060f1SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu");
118fe6060f1SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features");
119fe6060f1SDimitry Andric
120fe6060f1SDimitry Andric auto CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
121fe6060f1SDimitry Andric auto FS = FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
122fe6060f1SDimitry Andric
123fe6060f1SDimitry Andric auto &I = SubtargetMap[CPU + FS];
124fe6060f1SDimitry Andric if (!I) {
125fe6060f1SDimitry Andric // This needs to be done before we create a new subtarget since any
126fe6060f1SDimitry Andric // creation will depend on the TM and the code generation flags on the
127fe6060f1SDimitry Andric // function that reside in TargetOptions.
128fe6060f1SDimitry Andric resetTargetOptions(F);
129fe6060f1SDimitry Andric I = std::make_unique<M68kSubtarget>(TargetTriple, CPU, FS, *this);
130fe6060f1SDimitry Andric }
131fe6060f1SDimitry Andric return I.get();
132fe6060f1SDimitry Andric }
133fe6060f1SDimitry Andric
createMachineFunctionInfo(BumpPtrAllocator & Allocator,const Function & F,const TargetSubtargetInfo * STI) const134bdd1243dSDimitry Andric MachineFunctionInfo *M68kTargetMachine::createMachineFunctionInfo(
135bdd1243dSDimitry Andric BumpPtrAllocator &Allocator, const Function &F,
136bdd1243dSDimitry Andric const TargetSubtargetInfo *STI) const {
137bdd1243dSDimitry Andric return M68kMachineFunctionInfo::create<M68kMachineFunctionInfo>(Allocator, F,
138bdd1243dSDimitry Andric STI);
139bdd1243dSDimitry Andric }
140bdd1243dSDimitry Andric
141fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
142fe6060f1SDimitry Andric // Pass Pipeline Configuration
143fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
144fe6060f1SDimitry Andric
145fe6060f1SDimitry Andric namespace {
146fe6060f1SDimitry Andric class M68kPassConfig : public TargetPassConfig {
147fe6060f1SDimitry Andric public:
M68kPassConfig(M68kTargetMachine & TM,PassManagerBase & PM)148fe6060f1SDimitry Andric M68kPassConfig(M68kTargetMachine &TM, PassManagerBase &PM)
149fe6060f1SDimitry Andric : TargetPassConfig(TM, PM) {}
150fe6060f1SDimitry Andric
getM68kTargetMachine() const151fe6060f1SDimitry Andric M68kTargetMachine &getM68kTargetMachine() const {
152fe6060f1SDimitry Andric return getTM<M68kTargetMachine>();
153fe6060f1SDimitry Andric }
154fe6060f1SDimitry Andric
getM68kSubtarget() const155fe6060f1SDimitry Andric const M68kSubtarget &getM68kSubtarget() const {
156fe6060f1SDimitry Andric return *getM68kTargetMachine().getSubtargetImpl();
157fe6060f1SDimitry Andric }
158bdd1243dSDimitry Andric void addIRPasses() override;
159fe6060f1SDimitry Andric bool addIRTranslator() override;
160fe6060f1SDimitry Andric bool addLegalizeMachineIR() override;
161fe6060f1SDimitry Andric bool addRegBankSelect() override;
162fe6060f1SDimitry Andric bool addGlobalInstructionSelect() override;
163fe6060f1SDimitry Andric bool addInstSelector() override;
164fe6060f1SDimitry Andric void addPreSched2() override;
165fe6060f1SDimitry Andric void addPreEmitPass() override;
166fe6060f1SDimitry Andric };
167fe6060f1SDimitry Andric } // namespace
168fe6060f1SDimitry Andric
createPassConfig(PassManagerBase & PM)169fe6060f1SDimitry Andric TargetPassConfig *M68kTargetMachine::createPassConfig(PassManagerBase &PM) {
170fe6060f1SDimitry Andric return new M68kPassConfig(*this, PM);
171fe6060f1SDimitry Andric }
172fe6060f1SDimitry Andric
addIRPasses()173bdd1243dSDimitry Andric void M68kPassConfig::addIRPasses() {
174*0fca6ea1SDimitry Andric addPass(createAtomicExpandLegacyPass());
175bdd1243dSDimitry Andric TargetPassConfig::addIRPasses();
176bdd1243dSDimitry Andric }
177bdd1243dSDimitry Andric
addInstSelector()178fe6060f1SDimitry Andric bool M68kPassConfig::addInstSelector() {
179fe6060f1SDimitry Andric // Install an instruction selector.
180fe6060f1SDimitry Andric addPass(createM68kISelDag(getM68kTargetMachine()));
181fe6060f1SDimitry Andric addPass(createM68kGlobalBaseRegPass());
182fe6060f1SDimitry Andric return false;
183fe6060f1SDimitry Andric }
184fe6060f1SDimitry Andric
addIRTranslator()185fe6060f1SDimitry Andric bool M68kPassConfig::addIRTranslator() {
186fe6060f1SDimitry Andric addPass(new IRTranslator());
187fe6060f1SDimitry Andric return false;
188fe6060f1SDimitry Andric }
189fe6060f1SDimitry Andric
addLegalizeMachineIR()190fe6060f1SDimitry Andric bool M68kPassConfig::addLegalizeMachineIR() {
191fe6060f1SDimitry Andric addPass(new Legalizer());
192fe6060f1SDimitry Andric return false;
193fe6060f1SDimitry Andric }
194fe6060f1SDimitry Andric
addRegBankSelect()195fe6060f1SDimitry Andric bool M68kPassConfig::addRegBankSelect() {
196fe6060f1SDimitry Andric addPass(new RegBankSelect());
197fe6060f1SDimitry Andric return false;
198fe6060f1SDimitry Andric }
199fe6060f1SDimitry Andric
addGlobalInstructionSelect()200fe6060f1SDimitry Andric bool M68kPassConfig::addGlobalInstructionSelect() {
201fe6060f1SDimitry Andric addPass(new InstructionSelect());
202fe6060f1SDimitry Andric return false;
203fe6060f1SDimitry Andric }
204fe6060f1SDimitry Andric
addPreSched2()205fe6060f1SDimitry Andric void M68kPassConfig::addPreSched2() { addPass(createM68kExpandPseudoPass()); }
206fe6060f1SDimitry Andric
addPreEmitPass()207fe6060f1SDimitry Andric void M68kPassConfig::addPreEmitPass() {
208fe6060f1SDimitry Andric addPass(createM68kCollapseMOVEMPass());
209fe6060f1SDimitry Andric }
210