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