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