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 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 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 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 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 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 113fe6060f1SDimitry Andric M68kTargetMachine::~M68kTargetMachine() {} 114fe6060f1SDimitry Andric 115fe6060f1SDimitry Andric const M68kSubtarget * 116fe6060f1SDimitry 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 134bdd1243dSDimitry 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: 148fe6060f1SDimitry Andric M68kPassConfig(M68kTargetMachine &TM, PassManagerBase &PM) 149fe6060f1SDimitry Andric : TargetPassConfig(TM, PM) {} 150fe6060f1SDimitry Andric 151fe6060f1SDimitry Andric M68kTargetMachine &getM68kTargetMachine() const { 152fe6060f1SDimitry Andric return getTM<M68kTargetMachine>(); 153fe6060f1SDimitry Andric } 154fe6060f1SDimitry Andric 155fe6060f1SDimitry 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 169fe6060f1SDimitry Andric TargetPassConfig *M68kTargetMachine::createPassConfig(PassManagerBase &PM) { 170fe6060f1SDimitry Andric return new M68kPassConfig(*this, PM); 171fe6060f1SDimitry Andric } 172fe6060f1SDimitry Andric 173bdd1243dSDimitry Andric void M68kPassConfig::addIRPasses() { 174*0fca6ea1SDimitry Andric addPass(createAtomicExpandLegacyPass()); 175bdd1243dSDimitry Andric TargetPassConfig::addIRPasses(); 176bdd1243dSDimitry Andric } 177bdd1243dSDimitry Andric 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 185fe6060f1SDimitry Andric bool M68kPassConfig::addIRTranslator() { 186fe6060f1SDimitry Andric addPass(new IRTranslator()); 187fe6060f1SDimitry Andric return false; 188fe6060f1SDimitry Andric } 189fe6060f1SDimitry Andric 190fe6060f1SDimitry Andric bool M68kPassConfig::addLegalizeMachineIR() { 191fe6060f1SDimitry Andric addPass(new Legalizer()); 192fe6060f1SDimitry Andric return false; 193fe6060f1SDimitry Andric } 194fe6060f1SDimitry Andric 195fe6060f1SDimitry Andric bool M68kPassConfig::addRegBankSelect() { 196fe6060f1SDimitry Andric addPass(new RegBankSelect()); 197fe6060f1SDimitry Andric return false; 198fe6060f1SDimitry Andric } 199fe6060f1SDimitry Andric 200fe6060f1SDimitry Andric bool M68kPassConfig::addGlobalInstructionSelect() { 201fe6060f1SDimitry Andric addPass(new InstructionSelect()); 202fe6060f1SDimitry Andric return false; 203fe6060f1SDimitry Andric } 204fe6060f1SDimitry Andric 205fe6060f1SDimitry Andric void M68kPassConfig::addPreSched2() { addPass(createM68kExpandPseudoPass()); } 206fe6060f1SDimitry Andric 207fe6060f1SDimitry Andric void M68kPassConfig::addPreEmitPass() { 208fe6060f1SDimitry Andric addPass(createM68kCollapseMOVEMPass()); 209fe6060f1SDimitry Andric } 210