1fe6060f1SDimitry 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" 16fe6060f1SDimitry Andric #include "M68kSubtarget.h" 17fe6060f1SDimitry Andric #include "M68kTargetObjectFile.h" 18fe6060f1SDimitry Andric #include "TargetInfo/M68kTargetInfo.h" 19fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/IRTranslator.h" 20fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" 21fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/Legalizer.h" 22fe6060f1SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" 23fe6060f1SDimitry Andric #include "llvm/CodeGen/Passes.h" 24fe6060f1SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 25fe6060f1SDimitry Andric #include "llvm/IR/LegacyPassManager.h" 26fe6060f1SDimitry Andric #include "llvm/InitializePasses.h" 27fe6060f1SDimitry Andric #include "llvm/PassRegistry.h" 28fe6060f1SDimitry Andric #include "llvm/Support/TargetRegistry.h" 29fe6060f1SDimitry Andric #include <memory> 30fe6060f1SDimitry Andric 31fe6060f1SDimitry Andric using namespace llvm; 32fe6060f1SDimitry Andric 33fe6060f1SDimitry Andric #define DEBUG_TYPE "m68k" 34fe6060f1SDimitry Andric 35fe6060f1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kTarget() { 36fe6060f1SDimitry Andric RegisterTargetMachine<M68kTargetMachine> X(getTheM68kTarget()); 37fe6060f1SDimitry Andric auto *PR = PassRegistry::getPassRegistry(); 38fe6060f1SDimitry Andric initializeGlobalISel(*PR); 39fe6060f1SDimitry Andric } 40fe6060f1SDimitry Andric 41fe6060f1SDimitry Andric namespace { 42fe6060f1SDimitry Andric 43fe6060f1SDimitry Andric std::string computeDataLayout(const Triple &TT, StringRef CPU, 44fe6060f1SDimitry Andric const TargetOptions &Options) { 45fe6060f1SDimitry Andric std::string Ret = ""; 46fe6060f1SDimitry Andric // M68k is Big Endian 47fe6060f1SDimitry Andric Ret += "E"; 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric // FIXME how to wire it with the used object format? 50fe6060f1SDimitry Andric Ret += "-m:e"; 51fe6060f1SDimitry Andric 52*69ade1e0SDimitry Andric // M68k pointers are always 32 bit wide even for 16-bit CPUs. 53*69ade1e0SDimitry Andric // The ABI only specifies 16-bit alignment. 54*69ade1e0SDimitry Andric // On at least the 68020+ with a 32-bit bus, there is a performance benefit 55*69ade1e0SDimitry Andric // to having 32-bit alignment. 56*69ade1e0SDimitry Andric Ret += "-p:32:16:32"; 57fe6060f1SDimitry Andric 58*69ade1e0SDimitry Andric // Bytes do not require special alignment, words are word aligned and 59*69ade1e0SDimitry Andric // long words are word aligned at minimum. 60fe6060f1SDimitry Andric Ret += "-i8:8:8-i16:16:16-i32:16:32"; 61fe6060f1SDimitry Andric 62fe6060f1SDimitry Andric // FIXME no floats at the moment 63fe6060f1SDimitry Andric 64fe6060f1SDimitry Andric // The registers can hold 8, 16, 32 bits 65fe6060f1SDimitry Andric Ret += "-n8:16:32"; 66fe6060f1SDimitry Andric 67fe6060f1SDimitry Andric Ret += "-a:0:16-S16"; 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric return Ret; 70fe6060f1SDimitry Andric } 71fe6060f1SDimitry Andric 72fe6060f1SDimitry Andric Reloc::Model getEffectiveRelocModel(const Triple &TT, 73fe6060f1SDimitry Andric Optional<Reloc::Model> RM) { 74fe6060f1SDimitry Andric // If not defined we default to static 75fe6060f1SDimitry Andric if (!RM.hasValue()) { 76fe6060f1SDimitry Andric return Reloc::Static; 77fe6060f1SDimitry Andric } 78fe6060f1SDimitry Andric 79fe6060f1SDimitry Andric return *RM; 80fe6060f1SDimitry Andric } 81fe6060f1SDimitry Andric 82fe6060f1SDimitry Andric CodeModel::Model getEffectiveCodeModel(Optional<CodeModel::Model> CM, 83fe6060f1SDimitry Andric bool JIT) { 84fe6060f1SDimitry Andric if (!CM) { 85fe6060f1SDimitry Andric return CodeModel::Small; 86fe6060f1SDimitry Andric } else if (CM == CodeModel::Large) { 87fe6060f1SDimitry Andric llvm_unreachable("Large code model is not supported"); 88fe6060f1SDimitry Andric } else if (CM == CodeModel::Kernel) { 89fe6060f1SDimitry Andric llvm_unreachable("Kernel code model is not implemented yet"); 90fe6060f1SDimitry Andric } 91fe6060f1SDimitry Andric return CM.getValue(); 92fe6060f1SDimitry Andric } 93fe6060f1SDimitry Andric } // end anonymous namespace 94fe6060f1SDimitry Andric 95fe6060f1SDimitry Andric M68kTargetMachine::M68kTargetMachine(const Target &T, const Triple &TT, 96fe6060f1SDimitry Andric StringRef CPU, StringRef FS, 97fe6060f1SDimitry Andric const TargetOptions &Options, 98fe6060f1SDimitry Andric Optional<Reloc::Model> RM, 99fe6060f1SDimitry Andric Optional<CodeModel::Model> CM, 100fe6060f1SDimitry Andric CodeGenOpt::Level OL, bool JIT) 101fe6060f1SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options), TT, CPU, FS, 102fe6060f1SDimitry Andric Options, getEffectiveRelocModel(TT, RM), 103fe6060f1SDimitry Andric ::getEffectiveCodeModel(CM, JIT), OL), 104fe6060f1SDimitry Andric TLOF(std::make_unique<M68kELFTargetObjectFile>()), 105fe6060f1SDimitry Andric Subtarget(TT, CPU, FS, *this) { 106fe6060f1SDimitry Andric initAsmInfo(); 107fe6060f1SDimitry Andric } 108fe6060f1SDimitry Andric 109fe6060f1SDimitry Andric M68kTargetMachine::~M68kTargetMachine() {} 110fe6060f1SDimitry Andric 111fe6060f1SDimitry Andric const M68kSubtarget * 112fe6060f1SDimitry Andric M68kTargetMachine::getSubtargetImpl(const Function &F) const { 113fe6060f1SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 114fe6060f1SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 115fe6060f1SDimitry Andric 116fe6060f1SDimitry Andric auto CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 117fe6060f1SDimitry Andric auto FS = FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 118fe6060f1SDimitry Andric 119fe6060f1SDimitry Andric auto &I = SubtargetMap[CPU + FS]; 120fe6060f1SDimitry Andric if (!I) { 121fe6060f1SDimitry Andric // This needs to be done before we create a new subtarget since any 122fe6060f1SDimitry Andric // creation will depend on the TM and the code generation flags on the 123fe6060f1SDimitry Andric // function that reside in TargetOptions. 124fe6060f1SDimitry Andric resetTargetOptions(F); 125fe6060f1SDimitry Andric I = std::make_unique<M68kSubtarget>(TargetTriple, CPU, FS, *this); 126fe6060f1SDimitry Andric } 127fe6060f1SDimitry Andric return I.get(); 128fe6060f1SDimitry Andric } 129fe6060f1SDimitry Andric 130fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 131fe6060f1SDimitry Andric // Pass Pipeline Configuration 132fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 133fe6060f1SDimitry Andric 134fe6060f1SDimitry Andric namespace { 135fe6060f1SDimitry Andric class M68kPassConfig : public TargetPassConfig { 136fe6060f1SDimitry Andric public: 137fe6060f1SDimitry Andric M68kPassConfig(M68kTargetMachine &TM, PassManagerBase &PM) 138fe6060f1SDimitry Andric : TargetPassConfig(TM, PM) {} 139fe6060f1SDimitry Andric 140fe6060f1SDimitry Andric M68kTargetMachine &getM68kTargetMachine() const { 141fe6060f1SDimitry Andric return getTM<M68kTargetMachine>(); 142fe6060f1SDimitry Andric } 143fe6060f1SDimitry Andric 144fe6060f1SDimitry Andric const M68kSubtarget &getM68kSubtarget() const { 145fe6060f1SDimitry Andric return *getM68kTargetMachine().getSubtargetImpl(); 146fe6060f1SDimitry Andric } 147fe6060f1SDimitry Andric bool addIRTranslator() override; 148fe6060f1SDimitry Andric bool addLegalizeMachineIR() override; 149fe6060f1SDimitry Andric bool addRegBankSelect() override; 150fe6060f1SDimitry Andric bool addGlobalInstructionSelect() override; 151fe6060f1SDimitry Andric bool addInstSelector() override; 152fe6060f1SDimitry Andric void addPreSched2() override; 153fe6060f1SDimitry Andric void addPreEmitPass() override; 154fe6060f1SDimitry Andric }; 155fe6060f1SDimitry Andric } // namespace 156fe6060f1SDimitry Andric 157fe6060f1SDimitry Andric TargetPassConfig *M68kTargetMachine::createPassConfig(PassManagerBase &PM) { 158fe6060f1SDimitry Andric return new M68kPassConfig(*this, PM); 159fe6060f1SDimitry Andric } 160fe6060f1SDimitry Andric 161fe6060f1SDimitry Andric bool M68kPassConfig::addInstSelector() { 162fe6060f1SDimitry Andric // Install an instruction selector. 163fe6060f1SDimitry Andric addPass(createM68kISelDag(getM68kTargetMachine())); 164fe6060f1SDimitry Andric addPass(createM68kGlobalBaseRegPass()); 165fe6060f1SDimitry Andric return false; 166fe6060f1SDimitry Andric } 167fe6060f1SDimitry Andric 168fe6060f1SDimitry Andric bool M68kPassConfig::addIRTranslator() { 169fe6060f1SDimitry Andric addPass(new IRTranslator()); 170fe6060f1SDimitry Andric return false; 171fe6060f1SDimitry Andric } 172fe6060f1SDimitry Andric 173fe6060f1SDimitry Andric bool M68kPassConfig::addLegalizeMachineIR() { 174fe6060f1SDimitry Andric addPass(new Legalizer()); 175fe6060f1SDimitry Andric return false; 176fe6060f1SDimitry Andric } 177fe6060f1SDimitry Andric 178fe6060f1SDimitry Andric bool M68kPassConfig::addRegBankSelect() { 179fe6060f1SDimitry Andric addPass(new RegBankSelect()); 180fe6060f1SDimitry Andric return false; 181fe6060f1SDimitry Andric } 182fe6060f1SDimitry Andric 183fe6060f1SDimitry Andric bool M68kPassConfig::addGlobalInstructionSelect() { 184fe6060f1SDimitry Andric addPass(new InstructionSelect()); 185fe6060f1SDimitry Andric return false; 186fe6060f1SDimitry Andric } 187fe6060f1SDimitry Andric 188fe6060f1SDimitry Andric void M68kPassConfig::addPreSched2() { addPass(createM68kExpandPseudoPass()); } 189fe6060f1SDimitry Andric 190fe6060f1SDimitry Andric void M68kPassConfig::addPreEmitPass() { 191fe6060f1SDimitry Andric addPass(createM68kCollapseMOVEMPass()); 192fe6060f1SDimitry Andric } 193