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