1e5dd7070Spatrick //===--- Hexagon.cpp - Implement Hexagon target feature support -----------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements Hexagon TargetInfo objects.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick
13e5dd7070Spatrick #include "Hexagon.h"
14e5dd7070Spatrick #include "Targets.h"
15e5dd7070Spatrick #include "clang/Basic/MacroBuilder.h"
16e5dd7070Spatrick #include "clang/Basic/TargetBuiltins.h"
17e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
18e5dd7070Spatrick
19e5dd7070Spatrick using namespace clang;
20e5dd7070Spatrick using namespace clang::targets;
21e5dd7070Spatrick
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const22e5dd7070Spatrick void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
23e5dd7070Spatrick MacroBuilder &Builder) const {
24e5dd7070Spatrick Builder.defineMacro("__qdsp6__", "1");
25e5dd7070Spatrick Builder.defineMacro("__hexagon__", "1");
26e5dd7070Spatrick
27ec727ea7Spatrick Builder.defineMacro("__ELF__");
28ec727ea7Spatrick
29ec727ea7Spatrick // The macro __HVXDBL__ is deprecated.
30ec727ea7Spatrick bool DefineHvxDbl = false;
31ec727ea7Spatrick
32e5dd7070Spatrick if (CPU == "hexagonv5") {
33e5dd7070Spatrick Builder.defineMacro("__HEXAGON_V5__");
34e5dd7070Spatrick Builder.defineMacro("__HEXAGON_ARCH__", "5");
35e5dd7070Spatrick if (Opts.HexagonQdsp6Compat) {
36e5dd7070Spatrick Builder.defineMacro("__QDSP6_V5__");
37e5dd7070Spatrick Builder.defineMacro("__QDSP6_ARCH__", "5");
38e5dd7070Spatrick }
39e5dd7070Spatrick } else if (CPU == "hexagonv55") {
40e5dd7070Spatrick Builder.defineMacro("__HEXAGON_V55__");
41e5dd7070Spatrick Builder.defineMacro("__HEXAGON_ARCH__", "55");
42e5dd7070Spatrick Builder.defineMacro("__QDSP6_V55__");
43e5dd7070Spatrick Builder.defineMacro("__QDSP6_ARCH__", "55");
44e5dd7070Spatrick } else if (CPU == "hexagonv60") {
45ec727ea7Spatrick DefineHvxDbl = true;
46e5dd7070Spatrick Builder.defineMacro("__HEXAGON_V60__");
47e5dd7070Spatrick Builder.defineMacro("__HEXAGON_ARCH__", "60");
48e5dd7070Spatrick Builder.defineMacro("__QDSP6_V60__");
49e5dd7070Spatrick Builder.defineMacro("__QDSP6_ARCH__", "60");
50e5dd7070Spatrick } else if (CPU == "hexagonv62") {
51ec727ea7Spatrick DefineHvxDbl = true;
52e5dd7070Spatrick Builder.defineMacro("__HEXAGON_V62__");
53e5dd7070Spatrick Builder.defineMacro("__HEXAGON_ARCH__", "62");
54e5dd7070Spatrick } else if (CPU == "hexagonv65") {
55ec727ea7Spatrick DefineHvxDbl = true;
56e5dd7070Spatrick Builder.defineMacro("__HEXAGON_V65__");
57e5dd7070Spatrick Builder.defineMacro("__HEXAGON_ARCH__", "65");
58e5dd7070Spatrick } else if (CPU == "hexagonv66") {
59ec727ea7Spatrick DefineHvxDbl = true;
60e5dd7070Spatrick Builder.defineMacro("__HEXAGON_V66__");
61e5dd7070Spatrick Builder.defineMacro("__HEXAGON_ARCH__", "66");
62ec727ea7Spatrick } else if (CPU == "hexagonv67") {
63ec727ea7Spatrick Builder.defineMacro("__HEXAGON_V67__");
64ec727ea7Spatrick Builder.defineMacro("__HEXAGON_ARCH__", "67");
65ec727ea7Spatrick } else if (CPU == "hexagonv67t") {
66ec727ea7Spatrick Builder.defineMacro("__HEXAGON_V67T__");
67ec727ea7Spatrick Builder.defineMacro("__HEXAGON_ARCH__", "67");
68a9ac8606Spatrick } else if (CPU == "hexagonv68") {
69a9ac8606Spatrick Builder.defineMacro("__HEXAGON_V68__");
70a9ac8606Spatrick Builder.defineMacro("__HEXAGON_ARCH__", "68");
71*12c85518Srobert } else if (CPU == "hexagonv69") {
72*12c85518Srobert Builder.defineMacro("__HEXAGON_V69__");
73*12c85518Srobert Builder.defineMacro("__HEXAGON_ARCH__", "69");
74*12c85518Srobert } else if (CPU == "hexagonv71") {
75*12c85518Srobert Builder.defineMacro("__HEXAGON_V71__");
76*12c85518Srobert Builder.defineMacro("__HEXAGON_ARCH__", "71");
77*12c85518Srobert } else if (CPU == "hexagonv71t") {
78*12c85518Srobert Builder.defineMacro("__HEXAGON_V71T__");
79*12c85518Srobert Builder.defineMacro("__HEXAGON_ARCH__", "71");
80*12c85518Srobert } else if (CPU == "hexagonv73") {
81*12c85518Srobert Builder.defineMacro("__HEXAGON_V73__");
82*12c85518Srobert Builder.defineMacro("__HEXAGON_ARCH__", "73");
83e5dd7070Spatrick }
84e5dd7070Spatrick
85e5dd7070Spatrick if (hasFeature("hvx-length64b")) {
86e5dd7070Spatrick Builder.defineMacro("__HVX__");
87e5dd7070Spatrick Builder.defineMacro("__HVX_ARCH__", HVXVersion);
88e5dd7070Spatrick Builder.defineMacro("__HVX_LENGTH__", "64");
89e5dd7070Spatrick }
90e5dd7070Spatrick
91e5dd7070Spatrick if (hasFeature("hvx-length128b")) {
92e5dd7070Spatrick Builder.defineMacro("__HVX__");
93e5dd7070Spatrick Builder.defineMacro("__HVX_ARCH__", HVXVersion);
94e5dd7070Spatrick Builder.defineMacro("__HVX_LENGTH__", "128");
95ec727ea7Spatrick if (DefineHvxDbl)
96e5dd7070Spatrick Builder.defineMacro("__HVXDBL__");
97e5dd7070Spatrick }
98ec727ea7Spatrick
99ec727ea7Spatrick if (hasFeature("audio")) {
100ec727ea7Spatrick Builder.defineMacro("__HEXAGON_AUDIO__");
101ec727ea7Spatrick }
102ec727ea7Spatrick
103ec727ea7Spatrick std::string NumPhySlots = isTinyCore() ? "3" : "4";
104ec727ea7Spatrick Builder.defineMacro("__HEXAGON_PHYSICAL_SLOTS__", NumPhySlots);
105*12c85518Srobert
106*12c85518Srobert Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
107*12c85518Srobert Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
108*12c85518Srobert Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
109*12c85518Srobert Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
110e5dd7070Spatrick }
111e5dd7070Spatrick
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const112e5dd7070Spatrick bool HexagonTargetInfo::initFeatureMap(
113e5dd7070Spatrick llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
114e5dd7070Spatrick const std::vector<std::string> &FeaturesVec) const {
115ec727ea7Spatrick if (isTinyCore())
116ec727ea7Spatrick Features["audio"] = true;
117ec727ea7Spatrick
118ec727ea7Spatrick StringRef CPUFeature = CPU;
119ec727ea7Spatrick CPUFeature.consume_front("hexagon");
120ec727ea7Spatrick CPUFeature.consume_back("t");
121a9ac8606Spatrick if (!CPUFeature.empty())
122ec727ea7Spatrick Features[CPUFeature] = true;
123ec727ea7Spatrick
124e5dd7070Spatrick Features["long-calls"] = false;
125e5dd7070Spatrick
126e5dd7070Spatrick return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
127e5dd7070Spatrick }
128e5dd7070Spatrick
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)129e5dd7070Spatrick bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
130e5dd7070Spatrick DiagnosticsEngine &Diags) {
131e5dd7070Spatrick for (auto &F : Features) {
132e5dd7070Spatrick if (F == "+hvx-length64b")
133e5dd7070Spatrick HasHVX = HasHVX64B = true;
134e5dd7070Spatrick else if (F == "+hvx-length128b")
135e5dd7070Spatrick HasHVX = HasHVX128B = true;
136e5dd7070Spatrick else if (F.find("+hvxv") != std::string::npos) {
137e5dd7070Spatrick HasHVX = true;
138e5dd7070Spatrick HVXVersion = F.substr(std::string("+hvxv").length());
139e5dd7070Spatrick } else if (F == "-hvx")
140e5dd7070Spatrick HasHVX = HasHVX64B = HasHVX128B = false;
141e5dd7070Spatrick else if (F == "+long-calls")
142e5dd7070Spatrick UseLongCalls = true;
143e5dd7070Spatrick else if (F == "-long-calls")
144e5dd7070Spatrick UseLongCalls = false;
145ec727ea7Spatrick else if (F == "+audio")
146ec727ea7Spatrick HasAudio = true;
147e5dd7070Spatrick }
148*12c85518Srobert if (CPU.compare("hexagonv68") >= 0) {
149*12c85518Srobert HasLegalHalfType = true;
150*12c85518Srobert HasFloat16 = true;
151*12c85518Srobert }
152e5dd7070Spatrick return true;
153e5dd7070Spatrick }
154e5dd7070Spatrick
155e5dd7070Spatrick const char *const HexagonTargetInfo::GCCRegNames[] = {
156a9ac8606Spatrick // Scalar registers:
157a9ac8606Spatrick "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
158a9ac8606Spatrick "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
159a9ac8606Spatrick "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
160e5dd7070Spatrick "r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14",
161e5dd7070Spatrick "r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28",
162a9ac8606Spatrick "r31:30",
163a9ac8606Spatrick // Predicate registers:
164a9ac8606Spatrick "p0", "p1", "p2", "p3",
165a9ac8606Spatrick // Control registers:
166a9ac8606Spatrick "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11",
167a9ac8606Spatrick "c12", "c13", "c14", "c15", "c16", "c17", "c18", "c19", "c20", "c21",
168a9ac8606Spatrick "c22", "c23", "c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31",
169a9ac8606Spatrick "c1:0", "c3:2", "c5:4", "c7:6", "c9:8", "c11:10", "c13:12", "c15:14",
170a9ac8606Spatrick "c17:16", "c19:18", "c21:20", "c23:22", "c25:24", "c27:26", "c29:28",
171a9ac8606Spatrick "c31:30",
172a9ac8606Spatrick // Control register aliases:
173a9ac8606Spatrick "sa0", "lc0", "sa1", "lc1", "p3:0", "m0", "m1", "usr", "pc", "ugp",
174a9ac8606Spatrick "gp", "cs0", "cs1", "upcyclelo", "upcyclehi", "framelimit", "framekey",
175a9ac8606Spatrick "pktcountlo", "pktcounthi", "utimerlo", "utimerhi",
176a9ac8606Spatrick "upcycle", "pktcount", "utimer",
177a9ac8606Spatrick // HVX vector registers:
178a9ac8606Spatrick "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
179a9ac8606Spatrick "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
180a9ac8606Spatrick "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
181a9ac8606Spatrick "v1:0", "v3:2", "v5:4", "v7:6", "v9:8", "v11:10", "v13:12", "v15:14",
182a9ac8606Spatrick "v17:16", "v19:18", "v21:20", "v23:22", "v25:24", "v27:26", "v29:28",
183a9ac8606Spatrick "v31:30",
184a9ac8606Spatrick "v3:0", "v7:4", "v11:8", "v15:12", "v19:16", "v23:20", "v27:24", "v31:28",
185a9ac8606Spatrick // HVX vector predicates:
186a9ac8606Spatrick "q0", "q1", "q2", "q3",
187e5dd7070Spatrick };
188e5dd7070Spatrick
getGCCRegNames() const189e5dd7070Spatrick ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
190*12c85518Srobert return llvm::ArrayRef(GCCRegNames);
191e5dd7070Spatrick }
192e5dd7070Spatrick
193e5dd7070Spatrick const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
194e5dd7070Spatrick {{"sp"}, "r29"},
195e5dd7070Spatrick {{"fp"}, "r30"},
196e5dd7070Spatrick {{"lr"}, "r31"},
197e5dd7070Spatrick };
198e5dd7070Spatrick
getGCCRegAliases() const199e5dd7070Spatrick ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
200*12c85518Srobert return llvm::ArrayRef(GCCRegAliases);
201e5dd7070Spatrick }
202e5dd7070Spatrick
203*12c85518Srobert static constexpr Builtin::Info BuiltinInfo[] = {
204e5dd7070Spatrick #define BUILTIN(ID, TYPE, ATTRS) \
205*12c85518Srobert {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
206e5dd7070Spatrick #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
207*12c85518Srobert {#ID, TYPE, ATTRS, nullptr, HEADER, ALL_LANGUAGES},
208ec727ea7Spatrick #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
209*12c85518Srobert {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
210e5dd7070Spatrick #include "clang/Basic/BuiltinsHexagon.def"
211e5dd7070Spatrick };
212e5dd7070Spatrick
hasFeature(StringRef Feature) const213e5dd7070Spatrick bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
214e5dd7070Spatrick std::string VS = "hvxv" + HVXVersion;
215e5dd7070Spatrick if (Feature == VS)
216e5dd7070Spatrick return true;
217e5dd7070Spatrick
218e5dd7070Spatrick return llvm::StringSwitch<bool>(Feature)
219e5dd7070Spatrick .Case("hexagon", true)
220e5dd7070Spatrick .Case("hvx", HasHVX)
221e5dd7070Spatrick .Case("hvx-length64b", HasHVX64B)
222e5dd7070Spatrick .Case("hvx-length128b", HasHVX128B)
223e5dd7070Spatrick .Case("long-calls", UseLongCalls)
224ec727ea7Spatrick .Case("audio", HasAudio)
225e5dd7070Spatrick .Default(false);
226e5dd7070Spatrick }
227e5dd7070Spatrick
228e5dd7070Spatrick struct CPUSuffix {
229e5dd7070Spatrick llvm::StringLiteral Name;
230e5dd7070Spatrick llvm::StringLiteral Suffix;
231e5dd7070Spatrick };
232e5dd7070Spatrick
233e5dd7070Spatrick static constexpr CPUSuffix Suffixes[] = {
234e5dd7070Spatrick {{"hexagonv5"}, {"5"}}, {{"hexagonv55"}, {"55"}},
235e5dd7070Spatrick {{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}},
236e5dd7070Spatrick {{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}},
237ec727ea7Spatrick {{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}},
238*12c85518Srobert {{"hexagonv68"}, {"68"}}, {{"hexagonv69"}, {"69"}},
239*12c85518Srobert {{"hexagonv71"}, {"71"}}, {{"hexagonv71t"}, {"71t"}},
240*12c85518Srobert {{"hexagonv73"}, {"73"}},
241e5dd7070Spatrick };
242e5dd7070Spatrick
getHexagonCPUSuffix(StringRef Name)243e5dd7070Spatrick const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
244e5dd7070Spatrick const CPUSuffix *Item = llvm::find_if(
245e5dd7070Spatrick Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
246e5dd7070Spatrick if (Item == std::end(Suffixes))
247e5dd7070Spatrick return nullptr;
248e5dd7070Spatrick return Item->Suffix.data();
249e5dd7070Spatrick }
250e5dd7070Spatrick
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const251e5dd7070Spatrick void HexagonTargetInfo::fillValidCPUList(
252e5dd7070Spatrick SmallVectorImpl<StringRef> &Values) const {
253e5dd7070Spatrick for (const CPUSuffix &Suffix : Suffixes)
254e5dd7070Spatrick Values.push_back(Suffix.Name);
255e5dd7070Spatrick }
256e5dd7070Spatrick
getTargetBuiltins() const257e5dd7070Spatrick ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
258*12c85518Srobert return llvm::ArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
259e5dd7070Spatrick Builtin::FirstTSBuiltin);
260e5dd7070Spatrick }
261