1*6bf22ae4SJim Lin //===-- M68kTargetMachine.cpp - M68k Target Machine -------------*- C++ -*-===//
2bec7b166SMin-Yih Hsu //
3bec7b166SMin-Yih Hsu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bec7b166SMin-Yih Hsu // See https://llvm.org/LICENSE.txt for license information.
5bec7b166SMin-Yih Hsu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bec7b166SMin-Yih Hsu //
7bec7b166SMin-Yih Hsu //===----------------------------------------------------------------------===//
8bec7b166SMin-Yih Hsu ///
9bec7b166SMin-Yih Hsu /// \file
10bec7b166SMin-Yih Hsu /// This file contains implementation for M68k target machine.
11bec7b166SMin-Yih Hsu ///
12bec7b166SMin-Yih Hsu //===----------------------------------------------------------------------===//
13bec7b166SMin-Yih Hsu 
145ac19e0aSMin-Yih Hsu #include "M68kTargetMachine.h"
155ac19e0aSMin-Yih Hsu #include "M68k.h"
165ac19e0aSMin-Yih Hsu #include "M68kSubtarget.h"
175ac19e0aSMin-Yih Hsu #include "M68kTargetObjectFile.h"
182193347eSSushma Unnibhavi #include "TargetInfo/M68kTargetInfo.h"
192193347eSSushma Unnibhavi #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
202193347eSSushma Unnibhavi #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
212193347eSSushma Unnibhavi #include "llvm/CodeGen/GlobalISel/Legalizer.h"
222193347eSSushma Unnibhavi #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
235ac19e0aSMin-Yih Hsu #include "llvm/CodeGen/Passes.h"
245ac19e0aSMin-Yih Hsu #include "llvm/CodeGen/TargetPassConfig.h"
255ac19e0aSMin-Yih Hsu #include "llvm/IR/LegacyPassManager.h"
262193347eSSushma Unnibhavi #include "llvm/InitializePasses.h"
2789b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
282193347eSSushma Unnibhavi #include "llvm/PassRegistry.h"
295ac19e0aSMin-Yih Hsu #include <memory>
305ac19e0aSMin-Yih Hsu 
315ac19e0aSMin-Yih Hsu using namespace llvm;
325ac19e0aSMin-Yih Hsu 
335ac19e0aSMin-Yih Hsu #define DEBUG_TYPE "m68k"
345ac19e0aSMin-Yih Hsu 
LLVMInitializeM68kTarget()3562a94b72SJohn Paul Adrian Glaubitz extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kTarget() {
369f015757SRicky Taylor   RegisterTargetMachine<M68kTargetMachine> X(getTheM68kTarget());
372193347eSSushma Unnibhavi   auto *PR = PassRegistry::getPassRegistry();
382193347eSSushma Unnibhavi   initializeGlobalISel(*PR);
395ac19e0aSMin-Yih Hsu }
405ac19e0aSMin-Yih Hsu 
415ac19e0aSMin-Yih Hsu namespace {
425ac19e0aSMin-Yih Hsu 
computeDataLayout(const Triple & TT,StringRef CPU,const TargetOptions & Options)435ac19e0aSMin-Yih Hsu std::string computeDataLayout(const Triple &TT, StringRef CPU,
445ac19e0aSMin-Yih Hsu                               const TargetOptions &Options) {
455ac19e0aSMin-Yih Hsu   std::string Ret = "";
465ac19e0aSMin-Yih Hsu   // M68k is Big Endian
475ac19e0aSMin-Yih Hsu   Ret += "E";
485ac19e0aSMin-Yih Hsu 
495ac19e0aSMin-Yih Hsu   // FIXME how to wire it with the used object format?
505ac19e0aSMin-Yih Hsu   Ret += "-m:e";
515ac19e0aSMin-Yih Hsu 
528d3f112fSRicky Taylor   // M68k pointers are always 32 bit wide even for 16-bit CPUs.
538d3f112fSRicky Taylor   // The ABI only specifies 16-bit alignment.
548d3f112fSRicky Taylor   // On at least the 68020+ with a 32-bit bus, there is a performance benefit
558d3f112fSRicky Taylor   // to having 32-bit alignment.
568d3f112fSRicky Taylor   Ret += "-p:32:16:32";
575ac19e0aSMin-Yih Hsu 
588d3f112fSRicky Taylor   // Bytes do not require special alignment, words are word aligned and
598d3f112fSRicky Taylor   // long words are word aligned at minimum.
605ac19e0aSMin-Yih Hsu   Ret += "-i8:8:8-i16:16:16-i32:16:32";
615ac19e0aSMin-Yih Hsu 
625ac19e0aSMin-Yih Hsu   // FIXME no floats at the moment
635ac19e0aSMin-Yih Hsu 
645ac19e0aSMin-Yih Hsu   // The registers can hold 8, 16, 32 bits
655ac19e0aSMin-Yih Hsu   Ret += "-n8:16:32";
665ac19e0aSMin-Yih Hsu 
675ac19e0aSMin-Yih Hsu   Ret += "-a:0:16-S16";
685ac19e0aSMin-Yih Hsu 
695ac19e0aSMin-Yih Hsu   return Ret;
705ac19e0aSMin-Yih Hsu }
715ac19e0aSMin-Yih Hsu 
getEffectiveRelocModel(const Triple & TT,Optional<Reloc::Model> RM)725ac19e0aSMin-Yih Hsu Reloc::Model getEffectiveRelocModel(const Triple &TT,
735ac19e0aSMin-Yih Hsu                                     Optional<Reloc::Model> RM) {
745ac19e0aSMin-Yih Hsu   // If not defined we default to static
755ac19e0aSMin-Yih Hsu   if (!RM.hasValue()) {
765ac19e0aSMin-Yih Hsu     return Reloc::Static;
775ac19e0aSMin-Yih Hsu   }
785ac19e0aSMin-Yih Hsu 
795ac19e0aSMin-Yih Hsu   return *RM;
805ac19e0aSMin-Yih Hsu }
815ac19e0aSMin-Yih Hsu 
getEffectiveCodeModel(Optional<CodeModel::Model> CM,bool JIT)825ac19e0aSMin-Yih Hsu CodeModel::Model getEffectiveCodeModel(Optional<CodeModel::Model> CM,
835ac19e0aSMin-Yih Hsu                                        bool JIT) {
845ac19e0aSMin-Yih Hsu   if (!CM) {
855ac19e0aSMin-Yih Hsu     return CodeModel::Small;
865ac19e0aSMin-Yih Hsu   } else if (CM == CodeModel::Large) {
875ac19e0aSMin-Yih Hsu     llvm_unreachable("Large code model is not supported");
885ac19e0aSMin-Yih Hsu   } else if (CM == CodeModel::Kernel) {
895ac19e0aSMin-Yih Hsu     llvm_unreachable("Kernel code model is not implemented yet");
905ac19e0aSMin-Yih Hsu   }
915ac19e0aSMin-Yih Hsu   return CM.getValue();
925ac19e0aSMin-Yih Hsu }
935ac19e0aSMin-Yih Hsu } // end anonymous namespace
945ac19e0aSMin-Yih Hsu 
M68kTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,Optional<Reloc::Model> RM,Optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)955ac19e0aSMin-Yih Hsu M68kTargetMachine::M68kTargetMachine(const Target &T, const Triple &TT,
965ac19e0aSMin-Yih Hsu                                      StringRef CPU, StringRef FS,
975ac19e0aSMin-Yih Hsu                                      const TargetOptions &Options,
985ac19e0aSMin-Yih Hsu                                      Optional<Reloc::Model> RM,
995ac19e0aSMin-Yih Hsu                                      Optional<CodeModel::Model> CM,
1005ac19e0aSMin-Yih Hsu                                      CodeGenOpt::Level OL, bool JIT)
1015ac19e0aSMin-Yih Hsu     : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options), TT, CPU, FS,
1025ac19e0aSMin-Yih Hsu                         Options, getEffectiveRelocModel(TT, RM),
1035ac19e0aSMin-Yih Hsu                         ::getEffectiveCodeModel(CM, JIT), OL),
1045ac19e0aSMin-Yih Hsu       TLOF(std::make_unique<M68kELFTargetObjectFile>()),
1055ac19e0aSMin-Yih Hsu       Subtarget(TT, CPU, FS, *this) {
1065ac19e0aSMin-Yih Hsu   initAsmInfo();
1075ac19e0aSMin-Yih Hsu }
1085ac19e0aSMin-Yih Hsu 
~M68kTargetMachine()1095ac19e0aSMin-Yih Hsu M68kTargetMachine::~M68kTargetMachine() {}
1105ac19e0aSMin-Yih Hsu 
1115ac19e0aSMin-Yih Hsu const M68kSubtarget *
getSubtargetImpl(const Function & F) const1125ac19e0aSMin-Yih Hsu M68kTargetMachine::getSubtargetImpl(const Function &F) const {
1135ac19e0aSMin-Yih Hsu   Attribute CPUAttr = F.getFnAttribute("target-cpu");
1145ac19e0aSMin-Yih Hsu   Attribute FSAttr = F.getFnAttribute("target-features");
1155ac19e0aSMin-Yih Hsu 
1165ac19e0aSMin-Yih Hsu   auto CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
1175ac19e0aSMin-Yih Hsu   auto FS = FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
1185ac19e0aSMin-Yih Hsu 
1195ac19e0aSMin-Yih Hsu   auto &I = SubtargetMap[CPU + FS];
1205ac19e0aSMin-Yih Hsu   if (!I) {
1215ac19e0aSMin-Yih Hsu     // This needs to be done before we create a new subtarget since any
1225ac19e0aSMin-Yih Hsu     // creation will depend on the TM and the code generation flags on the
1235ac19e0aSMin-Yih Hsu     // function that reside in TargetOptions.
1245ac19e0aSMin-Yih Hsu     resetTargetOptions(F);
1255ac19e0aSMin-Yih Hsu     I = std::make_unique<M68kSubtarget>(TargetTriple, CPU, FS, *this);
1265ac19e0aSMin-Yih Hsu   }
1275ac19e0aSMin-Yih Hsu   return I.get();
1285ac19e0aSMin-Yih Hsu }
1295ac19e0aSMin-Yih Hsu 
1305ac19e0aSMin-Yih Hsu //===----------------------------------------------------------------------===//
1315ac19e0aSMin-Yih Hsu // Pass Pipeline Configuration
1325ac19e0aSMin-Yih Hsu //===----------------------------------------------------------------------===//
1335ac19e0aSMin-Yih Hsu 
1345ac19e0aSMin-Yih Hsu namespace {
1355ac19e0aSMin-Yih Hsu class M68kPassConfig : public TargetPassConfig {
1365ac19e0aSMin-Yih Hsu public:
M68kPassConfig(M68kTargetMachine & TM,PassManagerBase & PM)1375ac19e0aSMin-Yih Hsu   M68kPassConfig(M68kTargetMachine &TM, PassManagerBase &PM)
1385ac19e0aSMin-Yih Hsu       : TargetPassConfig(TM, PM) {}
1395ac19e0aSMin-Yih Hsu 
getM68kTargetMachine() const1405ac19e0aSMin-Yih Hsu   M68kTargetMachine &getM68kTargetMachine() const {
1415ac19e0aSMin-Yih Hsu     return getTM<M68kTargetMachine>();
1425ac19e0aSMin-Yih Hsu   }
1435ac19e0aSMin-Yih Hsu 
getM68kSubtarget() const1445ac19e0aSMin-Yih Hsu   const M68kSubtarget &getM68kSubtarget() const {
1455ac19e0aSMin-Yih Hsu     return *getM68kTargetMachine().getSubtargetImpl();
1465ac19e0aSMin-Yih Hsu   }
1472193347eSSushma Unnibhavi   bool addIRTranslator() override;
1482193347eSSushma Unnibhavi   bool addLegalizeMachineIR() override;
1492193347eSSushma Unnibhavi   bool addRegBankSelect() override;
1502193347eSSushma Unnibhavi   bool addGlobalInstructionSelect() override;
1515ac19e0aSMin-Yih Hsu   bool addInstSelector() override;
1525ac19e0aSMin-Yih Hsu   void addPreSched2() override;
1535ac19e0aSMin-Yih Hsu   void addPreEmitPass() override;
1545ac19e0aSMin-Yih Hsu };
1555ac19e0aSMin-Yih Hsu } // namespace
1565ac19e0aSMin-Yih Hsu 
createPassConfig(PassManagerBase & PM)1575ac19e0aSMin-Yih Hsu TargetPassConfig *M68kTargetMachine::createPassConfig(PassManagerBase &PM) {
1585ac19e0aSMin-Yih Hsu   return new M68kPassConfig(*this, PM);
1595ac19e0aSMin-Yih Hsu }
1605ac19e0aSMin-Yih Hsu 
addInstSelector()1615ac19e0aSMin-Yih Hsu bool M68kPassConfig::addInstSelector() {
1625ac19e0aSMin-Yih Hsu   // Install an instruction selector.
1635ac19e0aSMin-Yih Hsu   addPass(createM68kISelDag(getM68kTargetMachine()));
1645ac19e0aSMin-Yih Hsu   addPass(createM68kGlobalBaseRegPass());
1655ac19e0aSMin-Yih Hsu   return false;
1665ac19e0aSMin-Yih Hsu }
1675ac19e0aSMin-Yih Hsu 
addIRTranslator()1682193347eSSushma Unnibhavi bool M68kPassConfig::addIRTranslator() {
1692193347eSSushma Unnibhavi   addPass(new IRTranslator());
1702193347eSSushma Unnibhavi   return false;
1712193347eSSushma Unnibhavi }
1722193347eSSushma Unnibhavi 
addLegalizeMachineIR()1732193347eSSushma Unnibhavi bool M68kPassConfig::addLegalizeMachineIR() {
1742193347eSSushma Unnibhavi   addPass(new Legalizer());
1752193347eSSushma Unnibhavi   return false;
1762193347eSSushma Unnibhavi }
1772193347eSSushma Unnibhavi 
addRegBankSelect()1782193347eSSushma Unnibhavi bool M68kPassConfig::addRegBankSelect() {
1792193347eSSushma Unnibhavi   addPass(new RegBankSelect());
1802193347eSSushma Unnibhavi   return false;
1812193347eSSushma Unnibhavi }
1822193347eSSushma Unnibhavi 
addGlobalInstructionSelect()1832193347eSSushma Unnibhavi bool M68kPassConfig::addGlobalInstructionSelect() {
1842193347eSSushma Unnibhavi   addPass(new InstructionSelect());
1852193347eSSushma Unnibhavi   return false;
1862193347eSSushma Unnibhavi }
1872193347eSSushma Unnibhavi 
addPreSched2()1885ac19e0aSMin-Yih Hsu void M68kPassConfig::addPreSched2() { addPass(createM68kExpandPseudoPass()); }
1895ac19e0aSMin-Yih Hsu 
addPreEmitPass()1905ac19e0aSMin-Yih Hsu void M68kPassConfig::addPreEmitPass() {
1915ac19e0aSMin-Yih Hsu   addPass(createM68kCollapseMOVEMPass());
1925ac19e0aSMin-Yih Hsu }
193