10b57cec5SDimitry Andric //===--- Hexagon.cpp - Implement Hexagon target feature support -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements Hexagon TargetInfo objects.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "Hexagon.h"
140b57cec5SDimitry Andric #include "Targets.h"
150b57cec5SDimitry Andric #include "clang/Basic/MacroBuilder.h"
160b57cec5SDimitry Andric #include "clang/Basic/TargetBuiltins.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric using namespace clang;
200b57cec5SDimitry Andric using namespace clang::targets;
210b57cec5SDimitry Andric
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const220b57cec5SDimitry Andric void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
230b57cec5SDimitry Andric MacroBuilder &Builder) const {
240b57cec5SDimitry Andric Builder.defineMacro("__qdsp6__", "1");
250b57cec5SDimitry Andric Builder.defineMacro("__hexagon__", "1");
260b57cec5SDimitry Andric
275ffd83dbSDimitry Andric // The macro __HVXDBL__ is deprecated.
285ffd83dbSDimitry Andric bool DefineHvxDbl = false;
295ffd83dbSDimitry Andric
300b57cec5SDimitry Andric if (CPU == "hexagonv5") {
310b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_V5__");
320b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "5");
330b57cec5SDimitry Andric if (Opts.HexagonQdsp6Compat) {
340b57cec5SDimitry Andric Builder.defineMacro("__QDSP6_V5__");
350b57cec5SDimitry Andric Builder.defineMacro("__QDSP6_ARCH__", "5");
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric } else if (CPU == "hexagonv55") {
380b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_V55__");
390b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "55");
400b57cec5SDimitry Andric Builder.defineMacro("__QDSP6_V55__");
410b57cec5SDimitry Andric Builder.defineMacro("__QDSP6_ARCH__", "55");
420b57cec5SDimitry Andric } else if (CPU == "hexagonv60") {
435ffd83dbSDimitry Andric DefineHvxDbl = true;
440b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_V60__");
450b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "60");
460b57cec5SDimitry Andric Builder.defineMacro("__QDSP6_V60__");
470b57cec5SDimitry Andric Builder.defineMacro("__QDSP6_ARCH__", "60");
480b57cec5SDimitry Andric } else if (CPU == "hexagonv62") {
495ffd83dbSDimitry Andric DefineHvxDbl = true;
500b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_V62__");
510b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "62");
520b57cec5SDimitry Andric } else if (CPU == "hexagonv65") {
535ffd83dbSDimitry Andric DefineHvxDbl = true;
540b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_V65__");
550b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "65");
560b57cec5SDimitry Andric } else if (CPU == "hexagonv66") {
575ffd83dbSDimitry Andric DefineHvxDbl = true;
580b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_V66__");
590b57cec5SDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "66");
605ffd83dbSDimitry Andric } else if (CPU == "hexagonv67") {
615ffd83dbSDimitry Andric Builder.defineMacro("__HEXAGON_V67__");
625ffd83dbSDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "67");
635ffd83dbSDimitry Andric } else if (CPU == "hexagonv67t") {
645ffd83dbSDimitry Andric Builder.defineMacro("__HEXAGON_V67T__");
655ffd83dbSDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "67");
66fe6060f1SDimitry Andric } else if (CPU == "hexagonv68") {
67fe6060f1SDimitry Andric Builder.defineMacro("__HEXAGON_V68__");
68fe6060f1SDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "68");
690eae32dcSDimitry Andric } else if (CPU == "hexagonv69") {
700eae32dcSDimitry Andric Builder.defineMacro("__HEXAGON_V69__");
710eae32dcSDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "69");
72bdd1243dSDimitry Andric } else if (CPU == "hexagonv71") {
73bdd1243dSDimitry Andric Builder.defineMacro("__HEXAGON_V71__");
74bdd1243dSDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "71");
75bdd1243dSDimitry Andric } else if (CPU == "hexagonv71t") {
76bdd1243dSDimitry Andric Builder.defineMacro("__HEXAGON_V71T__");
77bdd1243dSDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "71");
78bdd1243dSDimitry Andric } else if (CPU == "hexagonv73") {
79bdd1243dSDimitry Andric Builder.defineMacro("__HEXAGON_V73__");
80bdd1243dSDimitry Andric Builder.defineMacro("__HEXAGON_ARCH__", "73");
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric if (hasFeature("hvx-length64b")) {
840b57cec5SDimitry Andric Builder.defineMacro("__HVX__");
850b57cec5SDimitry Andric Builder.defineMacro("__HVX_ARCH__", HVXVersion);
860b57cec5SDimitry Andric Builder.defineMacro("__HVX_LENGTH__", "64");
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric if (hasFeature("hvx-length128b")) {
900b57cec5SDimitry Andric Builder.defineMacro("__HVX__");
910b57cec5SDimitry Andric Builder.defineMacro("__HVX_ARCH__", HVXVersion);
920b57cec5SDimitry Andric Builder.defineMacro("__HVX_LENGTH__", "128");
935ffd83dbSDimitry Andric if (DefineHvxDbl)
940b57cec5SDimitry Andric Builder.defineMacro("__HVXDBL__");
950b57cec5SDimitry Andric }
965ffd83dbSDimitry Andric
975ffd83dbSDimitry Andric if (hasFeature("audio")) {
985ffd83dbSDimitry Andric Builder.defineMacro("__HEXAGON_AUDIO__");
995ffd83dbSDimitry Andric }
1005ffd83dbSDimitry Andric
1015ffd83dbSDimitry Andric std::string NumPhySlots = isTinyCore() ? "3" : "4";
1025ffd83dbSDimitry Andric Builder.defineMacro("__HEXAGON_PHYSICAL_SLOTS__", NumPhySlots);
103bdd1243dSDimitry Andric
104bdd1243dSDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
105bdd1243dSDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
106bdd1243dSDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
107bdd1243dSDimitry Andric Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
initFeatureMap(llvm::StringMap<bool> & Features,DiagnosticsEngine & Diags,StringRef CPU,const std::vector<std::string> & FeaturesVec) const1100b57cec5SDimitry Andric bool HexagonTargetInfo::initFeatureMap(
1110b57cec5SDimitry Andric llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
1120b57cec5SDimitry Andric const std::vector<std::string> &FeaturesVec) const {
1135ffd83dbSDimitry Andric if (isTinyCore())
1145ffd83dbSDimitry Andric Features["audio"] = true;
1155ffd83dbSDimitry Andric
1165ffd83dbSDimitry Andric StringRef CPUFeature = CPU;
1175ffd83dbSDimitry Andric CPUFeature.consume_front("hexagon");
1185ffd83dbSDimitry Andric CPUFeature.consume_back("t");
119e8d8bef9SDimitry Andric if (!CPUFeature.empty())
1205ffd83dbSDimitry Andric Features[CPUFeature] = true;
1215ffd83dbSDimitry Andric
1220b57cec5SDimitry Andric Features["long-calls"] = false;
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
handleTargetFeatures(std::vector<std::string> & Features,DiagnosticsEngine & Diags)1270b57cec5SDimitry Andric bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
1280b57cec5SDimitry Andric DiagnosticsEngine &Diags) {
1290b57cec5SDimitry Andric for (auto &F : Features) {
1300b57cec5SDimitry Andric if (F == "+hvx-length64b")
1310b57cec5SDimitry Andric HasHVX = HasHVX64B = true;
1320b57cec5SDimitry Andric else if (F == "+hvx-length128b")
1330b57cec5SDimitry Andric HasHVX = HasHVX128B = true;
1340b57cec5SDimitry Andric else if (F.find("+hvxv") != std::string::npos) {
1350b57cec5SDimitry Andric HasHVX = true;
1360b57cec5SDimitry Andric HVXVersion = F.substr(std::string("+hvxv").length());
1370b57cec5SDimitry Andric } else if (F == "-hvx")
1380b57cec5SDimitry Andric HasHVX = HasHVX64B = HasHVX128B = false;
1390b57cec5SDimitry Andric else if (F == "+long-calls")
1400b57cec5SDimitry Andric UseLongCalls = true;
1410b57cec5SDimitry Andric else if (F == "-long-calls")
1420b57cec5SDimitry Andric UseLongCalls = false;
1435ffd83dbSDimitry Andric else if (F == "+audio")
1445ffd83dbSDimitry Andric HasAudio = true;
1450b57cec5SDimitry Andric }
1460eae32dcSDimitry Andric if (CPU.compare("hexagonv68") >= 0) {
1470eae32dcSDimitry Andric HasLegalHalfType = true;
1480eae32dcSDimitry Andric HasFloat16 = true;
1490eae32dcSDimitry Andric }
1500b57cec5SDimitry Andric return true;
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric const char *const HexagonTargetInfo::GCCRegNames[] = {
154fe6060f1SDimitry Andric // Scalar registers:
155fe6060f1SDimitry Andric "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
156fe6060f1SDimitry Andric "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
157fe6060f1SDimitry Andric "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
158480093f4SDimitry Andric "r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14",
159480093f4SDimitry Andric "r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28",
160fe6060f1SDimitry Andric "r31:30",
161fe6060f1SDimitry Andric // Predicate registers:
162fe6060f1SDimitry Andric "p0", "p1", "p2", "p3",
163fe6060f1SDimitry Andric // Control registers:
164fe6060f1SDimitry Andric "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11",
165fe6060f1SDimitry Andric "c12", "c13", "c14", "c15", "c16", "c17", "c18", "c19", "c20", "c21",
166fe6060f1SDimitry Andric "c22", "c23", "c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31",
167fe6060f1SDimitry Andric "c1:0", "c3:2", "c5:4", "c7:6", "c9:8", "c11:10", "c13:12", "c15:14",
168fe6060f1SDimitry Andric "c17:16", "c19:18", "c21:20", "c23:22", "c25:24", "c27:26", "c29:28",
169fe6060f1SDimitry Andric "c31:30",
170fe6060f1SDimitry Andric // Control register aliases:
171fe6060f1SDimitry Andric "sa0", "lc0", "sa1", "lc1", "p3:0", "m0", "m1", "usr", "pc", "ugp",
172fe6060f1SDimitry Andric "gp", "cs0", "cs1", "upcyclelo", "upcyclehi", "framelimit", "framekey",
173fe6060f1SDimitry Andric "pktcountlo", "pktcounthi", "utimerlo", "utimerhi",
174fe6060f1SDimitry Andric "upcycle", "pktcount", "utimer",
175fe6060f1SDimitry Andric // HVX vector registers:
176fe6060f1SDimitry Andric "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
177fe6060f1SDimitry Andric "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
178fe6060f1SDimitry Andric "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
179fe6060f1SDimitry Andric "v1:0", "v3:2", "v5:4", "v7:6", "v9:8", "v11:10", "v13:12", "v15:14",
180fe6060f1SDimitry Andric "v17:16", "v19:18", "v21:20", "v23:22", "v25:24", "v27:26", "v29:28",
181fe6060f1SDimitry Andric "v31:30",
182fe6060f1SDimitry Andric "v3:0", "v7:4", "v11:8", "v15:12", "v19:16", "v23:20", "v27:24", "v31:28",
183fe6060f1SDimitry Andric // HVX vector predicates:
184fe6060f1SDimitry Andric "q0", "q1", "q2", "q3",
1850b57cec5SDimitry Andric };
1860b57cec5SDimitry Andric
getGCCRegNames() const1870b57cec5SDimitry Andric ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
188bdd1243dSDimitry Andric return llvm::ArrayRef(GCCRegNames);
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
1920b57cec5SDimitry Andric {{"sp"}, "r29"},
1930b57cec5SDimitry Andric {{"fp"}, "r30"},
1940b57cec5SDimitry Andric {{"lr"}, "r31"},
1950b57cec5SDimitry Andric };
1960b57cec5SDimitry Andric
getGCCRegAliases() const1970b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
198bdd1243dSDimitry Andric return llvm::ArrayRef(GCCRegAliases);
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric
201bdd1243dSDimitry Andric static constexpr Builtin::Info BuiltinInfo[] = {
2020b57cec5SDimitry Andric #define BUILTIN(ID, TYPE, ATTRS) \
203bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
2040b57cec5SDimitry Andric #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
205bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, nullptr, HEADER, ALL_LANGUAGES},
2065ffd83dbSDimitry Andric #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
207bdd1243dSDimitry Andric {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
2080b57cec5SDimitry Andric #include "clang/Basic/BuiltinsHexagon.def"
2090b57cec5SDimitry Andric };
2100b57cec5SDimitry Andric
hasFeature(StringRef Feature) const2110b57cec5SDimitry Andric bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
2120b57cec5SDimitry Andric std::string VS = "hvxv" + HVXVersion;
2130b57cec5SDimitry Andric if (Feature == VS)
2140b57cec5SDimitry Andric return true;
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric return llvm::StringSwitch<bool>(Feature)
2170b57cec5SDimitry Andric .Case("hexagon", true)
2180b57cec5SDimitry Andric .Case("hvx", HasHVX)
2190b57cec5SDimitry Andric .Case("hvx-length64b", HasHVX64B)
2200b57cec5SDimitry Andric .Case("hvx-length128b", HasHVX128B)
2210b57cec5SDimitry Andric .Case("long-calls", UseLongCalls)
2225ffd83dbSDimitry Andric .Case("audio", HasAudio)
2230b57cec5SDimitry Andric .Default(false);
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric
2260b57cec5SDimitry Andric struct CPUSuffix {
2270b57cec5SDimitry Andric llvm::StringLiteral Name;
2280b57cec5SDimitry Andric llvm::StringLiteral Suffix;
2290b57cec5SDimitry Andric };
2300b57cec5SDimitry Andric
2310b57cec5SDimitry Andric static constexpr CPUSuffix Suffixes[] = {
2320b57cec5SDimitry Andric {{"hexagonv5"}, {"5"}}, {{"hexagonv55"}, {"55"}},
2330b57cec5SDimitry Andric {{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}},
2340b57cec5SDimitry Andric {{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}},
2355ffd83dbSDimitry Andric {{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}},
2360eae32dcSDimitry Andric {{"hexagonv68"}, {"68"}}, {{"hexagonv69"}, {"69"}},
237bdd1243dSDimitry Andric {{"hexagonv71"}, {"71"}}, {{"hexagonv71t"}, {"71t"}},
238bdd1243dSDimitry Andric {{"hexagonv73"}, {"73"}},
2390b57cec5SDimitry Andric };
2400b57cec5SDimitry Andric
getHexagonCPURev(StringRef Name)241*0fca6ea1SDimitry Andric std::optional<unsigned> HexagonTargetInfo::getHexagonCPURev(StringRef Name) {
242*0fca6ea1SDimitry Andric StringRef Arch = Name;
243*0fca6ea1SDimitry Andric Arch.consume_front("hexagonv");
244*0fca6ea1SDimitry Andric Arch.consume_back("t");
245*0fca6ea1SDimitry Andric
246*0fca6ea1SDimitry Andric unsigned Val;
247*0fca6ea1SDimitry Andric if (!Arch.getAsInteger(0, Val))
248*0fca6ea1SDimitry Andric return Val;
249*0fca6ea1SDimitry Andric
250*0fca6ea1SDimitry Andric return std::nullopt;
251*0fca6ea1SDimitry Andric }
252*0fca6ea1SDimitry Andric
getHexagonCPUSuffix(StringRef Name)2530b57cec5SDimitry Andric const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
2540b57cec5SDimitry Andric const CPUSuffix *Item = llvm::find_if(
2550b57cec5SDimitry Andric Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
2560b57cec5SDimitry Andric if (Item == std::end(Suffixes))
2570b57cec5SDimitry Andric return nullptr;
2580b57cec5SDimitry Andric return Item->Suffix.data();
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const2610b57cec5SDimitry Andric void HexagonTargetInfo::fillValidCPUList(
2620b57cec5SDimitry Andric SmallVectorImpl<StringRef> &Values) const {
2630b57cec5SDimitry Andric for (const CPUSuffix &Suffix : Suffixes)
2640b57cec5SDimitry Andric Values.push_back(Suffix.Name);
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric
getTargetBuiltins() const2670b57cec5SDimitry Andric ArrayRef<Builtin::Info> HexagonTargetInfo::getTargetBuiltins() const {
268bdd1243dSDimitry Andric return llvm::ArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin -
2690b57cec5SDimitry Andric Builtin::FirstTSBuiltin);
2700b57cec5SDimitry Andric }
271