1fe6060f1SDimitry Andric //===--- M68k.cpp - M68k Helpers for Tools -------------------*- 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 #include "M68k.h"
10fe6060f1SDimitry Andric #include "ToolChains/CommonArgs.h"
11fe6060f1SDimitry Andric #include "clang/Driver/Driver.h"
12fe6060f1SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
13fe6060f1SDimitry Andric #include "clang/Driver/Options.h"
14fe6060f1SDimitry Andric #include "llvm/ADT/SmallVector.h"
15fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
16fe6060f1SDimitry Andric #include "llvm/Option/ArgList.h"
17fe6060f1SDimitry Andric #include "llvm/Support/Regex.h"
18*06c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
19fe6060f1SDimitry Andric #include <sstream>
20fe6060f1SDimitry Andric
21fe6060f1SDimitry Andric using namespace clang::driver;
22fe6060f1SDimitry Andric using namespace clang::driver::tools;
23fe6060f1SDimitry Andric using namespace clang;
24fe6060f1SDimitry Andric using namespace llvm::opt;
25fe6060f1SDimitry Andric
26fe6060f1SDimitry Andric /// getM68kTargetCPU - Get the (LLVM) name of the 68000 cpu we are targeting.
getM68kTargetCPU(const ArgList & Args)27fe6060f1SDimitry Andric std::string m68k::getM68kTargetCPU(const ArgList &Args) {
28fe6060f1SDimitry Andric if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
29fe6060f1SDimitry Andric // The canonical CPU name is captalize. However, we allow
30fe6060f1SDimitry Andric // starting with lower case or numbers only
31fe6060f1SDimitry Andric StringRef CPUName = A->getValue();
32fe6060f1SDimitry Andric
33fe6060f1SDimitry Andric if (CPUName == "native") {
34fe6060f1SDimitry Andric std::string CPU = std::string(llvm::sys::getHostCPUName());
35fe6060f1SDimitry Andric if (!CPU.empty() && CPU != "generic")
36fe6060f1SDimitry Andric return CPU;
37fe6060f1SDimitry Andric }
38fe6060f1SDimitry Andric
39fe6060f1SDimitry Andric if (CPUName == "common")
40fe6060f1SDimitry Andric return "generic";
41fe6060f1SDimitry Andric
42fe6060f1SDimitry Andric return llvm::StringSwitch<std::string>(CPUName)
43fe6060f1SDimitry Andric .Cases("m68000", "68000", "M68000")
44fe6060f1SDimitry Andric .Cases("m68010", "68010", "M68010")
45fe6060f1SDimitry Andric .Cases("m68020", "68020", "M68020")
46fe6060f1SDimitry Andric .Cases("m68030", "68030", "M68030")
47fe6060f1SDimitry Andric .Cases("m68040", "68040", "M68040")
48fe6060f1SDimitry Andric .Cases("m68060", "68060", "M68060")
49fe6060f1SDimitry Andric .Default(CPUName.str());
50fe6060f1SDimitry Andric }
51fe6060f1SDimitry Andric // FIXME: Throw error when multiple sub-architecture flag exist
52fe6060f1SDimitry Andric if (Args.hasArg(clang::driver::options::OPT_m68000))
53fe6060f1SDimitry Andric return "M68000";
54fe6060f1SDimitry Andric if (Args.hasArg(clang::driver::options::OPT_m68010))
55fe6060f1SDimitry Andric return "M68010";
56fe6060f1SDimitry Andric if (Args.hasArg(clang::driver::options::OPT_m68020))
57fe6060f1SDimitry Andric return "M68020";
58fe6060f1SDimitry Andric if (Args.hasArg(clang::driver::options::OPT_m68030))
59fe6060f1SDimitry Andric return "M68030";
60fe6060f1SDimitry Andric if (Args.hasArg(clang::driver::options::OPT_m68040))
61fe6060f1SDimitry Andric return "M68040";
62fe6060f1SDimitry Andric if (Args.hasArg(clang::driver::options::OPT_m68060))
63fe6060f1SDimitry Andric return "M68060";
64fe6060f1SDimitry Andric
65fe6060f1SDimitry Andric return "";
66fe6060f1SDimitry Andric }
67fe6060f1SDimitry Andric
addFloatABIFeatures(const llvm::opt::ArgList & Args,std::vector<llvm::StringRef> & Features)68*06c3fb27SDimitry Andric static void addFloatABIFeatures(const llvm::opt::ArgList &Args,
69*06c3fb27SDimitry Andric std::vector<llvm::StringRef> &Features) {
70*06c3fb27SDimitry Andric Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
71*06c3fb27SDimitry Andric options::OPT_m68881);
72*06c3fb27SDimitry Andric // Opt out FPU even for newer CPUs.
73*06c3fb27SDimitry Andric if (A && A->getOption().matches(options::OPT_msoft_float)) {
74*06c3fb27SDimitry Andric Features.push_back("-isa-68881");
75*06c3fb27SDimitry Andric Features.push_back("-isa-68882");
76*06c3fb27SDimitry Andric return;
77*06c3fb27SDimitry Andric }
78*06c3fb27SDimitry Andric
79*06c3fb27SDimitry Andric std::string CPU = m68k::getM68kTargetCPU(Args);
80*06c3fb27SDimitry Andric // Only enable M68881 for CPU < 68020 if the related flags are present.
81*06c3fb27SDimitry Andric if ((A && (CPU == "M68000" || CPU == "M68010")) ||
82*06c3fb27SDimitry Andric // Otherwise, by default we assume newer CPUs have M68881/2.
83*06c3fb27SDimitry Andric CPU == "M68020")
84*06c3fb27SDimitry Andric Features.push_back("+isa-68881");
85*06c3fb27SDimitry Andric else if (CPU == "M68030" || CPU == "M68040" || CPU == "M68060")
86*06c3fb27SDimitry Andric // Note that although CPU >= M68040 imply M68882, we still add `isa-68882`
87*06c3fb27SDimitry Andric // anyway so that it's easier to add or not add the corresponding macro
88*06c3fb27SDimitry Andric // definitions later, in case we want to disable 68881/2 in newer CPUs
89*06c3fb27SDimitry Andric // (with -msoft-float, for instance).
90*06c3fb27SDimitry Andric Features.push_back("+isa-68882");
91*06c3fb27SDimitry Andric }
92*06c3fb27SDimitry Andric
getM68kTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features)93fe6060f1SDimitry Andric void m68k::getM68kTargetFeatures(const Driver &D, const llvm::Triple &Triple,
94fe6060f1SDimitry Andric const ArgList &Args,
95fe6060f1SDimitry Andric std::vector<StringRef> &Features) {
96*06c3fb27SDimitry Andric addFloatABIFeatures(Args, Features);
97fe6060f1SDimitry Andric
98fe6060f1SDimitry Andric // Handle '-ffixed-<register>' flags
99fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_a0))
100fe6060f1SDimitry Andric Features.push_back("+reserve-a0");
101fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_a1))
102fe6060f1SDimitry Andric Features.push_back("+reserve-a1");
103fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_a2))
104fe6060f1SDimitry Andric Features.push_back("+reserve-a2");
105fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_a3))
106fe6060f1SDimitry Andric Features.push_back("+reserve-a3");
107fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_a4))
108fe6060f1SDimitry Andric Features.push_back("+reserve-a4");
109fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_a5))
110fe6060f1SDimitry Andric Features.push_back("+reserve-a5");
111fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_a6))
112fe6060f1SDimitry Andric Features.push_back("+reserve-a6");
113fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_d0))
114fe6060f1SDimitry Andric Features.push_back("+reserve-d0");
115fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_d1))
116fe6060f1SDimitry Andric Features.push_back("+reserve-d1");
117fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_d2))
118fe6060f1SDimitry Andric Features.push_back("+reserve-d2");
119fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_d3))
120fe6060f1SDimitry Andric Features.push_back("+reserve-d3");
121fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_d4))
122fe6060f1SDimitry Andric Features.push_back("+reserve-d4");
123fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_d5))
124fe6060f1SDimitry Andric Features.push_back("+reserve-d5");
125fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_d6))
126fe6060f1SDimitry Andric Features.push_back("+reserve-d6");
127fe6060f1SDimitry Andric if (Args.hasArg(options::OPT_ffixed_d7))
128fe6060f1SDimitry Andric Features.push_back("+reserve-d7");
129fe6060f1SDimitry Andric }
130