1 //===--- Sparc.cpp - Implement Sparc target feature support ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements Sparc TargetInfo objects.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "Sparc.h"
14 #include "Targets.h"
15 #include "clang/Basic/MacroBuilder.h"
16 #include "llvm/ADT/StringSwitch.h"
17 
18 using namespace clang;
19 using namespace clang::targets;
20 
21 const char *const SparcTargetInfo::GCCRegNames[] = {
22     // Integer registers
23     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",  "r9",  "r10",
24     "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
25     "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
26 
27     // Floating-point registers
28     "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",  "f8",  "f9",  "f10",
29     "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21",
30     "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32",
31     "f34", "f36", "f38", "f40", "f42", "f44", "f46", "f48", "f50", "f52", "f54",
32     "f56", "f58", "f60", "f62",
33 };
34 
35 ArrayRef<const char *> SparcTargetInfo::getGCCRegNames() const {
36   return llvm::ArrayRef(GCCRegNames);
37 }
38 
39 const TargetInfo::GCCRegAlias SparcTargetInfo::GCCRegAliases[] = {
40     {{"g0"}, "r0"},  {{"g1"}, "r1"},  {{"g2"}, "r2"},        {{"g3"}, "r3"},
41     {{"g4"}, "r4"},  {{"g5"}, "r5"},  {{"g6"}, "r6"},        {{"g7"}, "r7"},
42     {{"o0"}, "r8"},  {{"o1"}, "r9"},  {{"o2"}, "r10"},       {{"o3"}, "r11"},
43     {{"o4"}, "r12"}, {{"o5"}, "r13"}, {{"o6", "sp"}, "r14"}, {{"o7"}, "r15"},
44     {{"l0"}, "r16"}, {{"l1"}, "r17"}, {{"l2"}, "r18"},       {{"l3"}, "r19"},
45     {{"l4"}, "r20"}, {{"l5"}, "r21"}, {{"l6"}, "r22"},       {{"l7"}, "r23"},
46     {{"i0"}, "r24"}, {{"i1"}, "r25"}, {{"i2"}, "r26"},       {{"i3"}, "r27"},
47     {{"i4"}, "r28"}, {{"i5"}, "r29"}, {{"i6", "fp"}, "r30"}, {{"i7"}, "r31"},
48 };
49 
50 ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const {
51   return llvm::ArrayRef(GCCRegAliases);
52 }
53 
54 bool SparcTargetInfo::hasFeature(StringRef Feature) const {
55   return llvm::StringSwitch<bool>(Feature)
56       .Case("softfloat", SoftFloat)
57       .Case("sparc", true)
58       .Default(false);
59 }
60 
61 struct SparcCPUInfo {
62   llvm::StringLiteral Name;
63   SparcTargetInfo::CPUKind Kind;
64   SparcTargetInfo::CPUGeneration Generation;
65 };
66 
67 static constexpr SparcCPUInfo CPUInfo[] = {
68     {{"v8"}, SparcTargetInfo::CK_V8, SparcTargetInfo::CG_V8},
69     {{"supersparc"}, SparcTargetInfo::CK_SUPERSPARC, SparcTargetInfo::CG_V8},
70     {{"sparclite"}, SparcTargetInfo::CK_SPARCLITE, SparcTargetInfo::CG_V8},
71     {{"f934"}, SparcTargetInfo::CK_F934, SparcTargetInfo::CG_V8},
72     {{"hypersparc"}, SparcTargetInfo::CK_HYPERSPARC, SparcTargetInfo::CG_V8},
73     {{"sparclite86x"},
74      SparcTargetInfo::CK_SPARCLITE86X,
75      SparcTargetInfo::CG_V8},
76     {{"sparclet"}, SparcTargetInfo::CK_SPARCLET, SparcTargetInfo::CG_V8},
77     {{"tsc701"}, SparcTargetInfo::CK_TSC701, SparcTargetInfo::CG_V8},
78     {{"v9"}, SparcTargetInfo::CK_V9, SparcTargetInfo::CG_V9},
79     {{"ultrasparc"}, SparcTargetInfo::CK_ULTRASPARC, SparcTargetInfo::CG_V9},
80     {{"ultrasparc3"}, SparcTargetInfo::CK_ULTRASPARC3, SparcTargetInfo::CG_V9},
81     {{"niagara"}, SparcTargetInfo::CK_NIAGARA, SparcTargetInfo::CG_V9},
82     {{"niagara2"}, SparcTargetInfo::CK_NIAGARA2, SparcTargetInfo::CG_V9},
83     {{"niagara3"}, SparcTargetInfo::CK_NIAGARA3, SparcTargetInfo::CG_V9},
84     {{"niagara4"}, SparcTargetInfo::CK_NIAGARA4, SparcTargetInfo::CG_V9},
85     {{"ma2100"}, SparcTargetInfo::CK_MYRIAD2100, SparcTargetInfo::CG_V8},
86     {{"ma2150"}, SparcTargetInfo::CK_MYRIAD2150, SparcTargetInfo::CG_V8},
87     {{"ma2155"}, SparcTargetInfo::CK_MYRIAD2155, SparcTargetInfo::CG_V8},
88     {{"ma2450"}, SparcTargetInfo::CK_MYRIAD2450, SparcTargetInfo::CG_V8},
89     {{"ma2455"}, SparcTargetInfo::CK_MYRIAD2455, SparcTargetInfo::CG_V8},
90     {{"ma2x5x"}, SparcTargetInfo::CK_MYRIAD2x5x, SparcTargetInfo::CG_V8},
91     {{"ma2080"}, SparcTargetInfo::CK_MYRIAD2080, SparcTargetInfo::CG_V8},
92     {{"ma2085"}, SparcTargetInfo::CK_MYRIAD2085, SparcTargetInfo::CG_V8},
93     {{"ma2480"}, SparcTargetInfo::CK_MYRIAD2480, SparcTargetInfo::CG_V8},
94     {{"ma2485"}, SparcTargetInfo::CK_MYRIAD2485, SparcTargetInfo::CG_V8},
95     {{"ma2x8x"}, SparcTargetInfo::CK_MYRIAD2x8x, SparcTargetInfo::CG_V8},
96     // FIXME: the myriad2[.n] spellings are obsolete,
97     // but a grace period is needed to allow updating dependent builds.
98     {{"myriad2"}, SparcTargetInfo::CK_MYRIAD2x5x, SparcTargetInfo::CG_V8},
99     {{"myriad2.1"}, SparcTargetInfo::CK_MYRIAD2100, SparcTargetInfo::CG_V8},
100     {{"myriad2.2"}, SparcTargetInfo::CK_MYRIAD2x5x, SparcTargetInfo::CG_V8},
101     {{"myriad2.3"}, SparcTargetInfo::CK_MYRIAD2x8x, SparcTargetInfo::CG_V8},
102     {{"leon2"}, SparcTargetInfo::CK_LEON2, SparcTargetInfo::CG_V8},
103     {{"at697e"}, SparcTargetInfo::CK_LEON2_AT697E, SparcTargetInfo::CG_V8},
104     {{"at697f"}, SparcTargetInfo::CK_LEON2_AT697F, SparcTargetInfo::CG_V8},
105     {{"leon3"}, SparcTargetInfo::CK_LEON3, SparcTargetInfo::CG_V8},
106     {{"ut699"}, SparcTargetInfo::CK_LEON3_UT699, SparcTargetInfo::CG_V8},
107     {{"gr712rc"}, SparcTargetInfo::CK_LEON3_GR712RC, SparcTargetInfo::CG_V8},
108     {{"leon4"}, SparcTargetInfo::CK_LEON4, SparcTargetInfo::CG_V8},
109     {{"gr740"}, SparcTargetInfo::CK_LEON4_GR740, SparcTargetInfo::CG_V8},
110 };
111 
112 SparcTargetInfo::CPUGeneration
113 SparcTargetInfo::getCPUGeneration(CPUKind Kind) const {
114   if (Kind == CK_GENERIC)
115     return CG_V8;
116   const SparcCPUInfo *Item = llvm::find_if(
117       CPUInfo, [Kind](const SparcCPUInfo &Info) { return Info.Kind == Kind; });
118   if (Item == std::end(CPUInfo))
119     llvm_unreachable("Unexpected CPU kind");
120   return Item->Generation;
121 }
122 
123 SparcTargetInfo::CPUKind SparcTargetInfo::getCPUKind(StringRef Name) const {
124   const SparcCPUInfo *Item = llvm::find_if(
125       CPUInfo, [Name](const SparcCPUInfo &Info) { return Info.Name == Name; });
126 
127   if (Item == std::end(CPUInfo))
128     return CK_GENERIC;
129   return Item->Kind;
130 }
131 
132 void SparcTargetInfo::fillValidCPUList(
133     SmallVectorImpl<StringRef> &Values) const {
134   for (const SparcCPUInfo &Info : CPUInfo)
135     Values.push_back(Info.Name);
136 }
137 
138 void SparcTargetInfo::getTargetDefines(const LangOptions &Opts,
139                                        MacroBuilder &Builder) const {
140   DefineStd(Builder, "sparc", Opts);
141   Builder.defineMacro("__REGISTER_PREFIX__", "");
142 
143   if (SoftFloat)
144     Builder.defineMacro("SOFT_FLOAT", "1");
145 }
146 
147 void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
148                                          MacroBuilder &Builder) const {
149   SparcTargetInfo::getTargetDefines(Opts, Builder);
150   if (getTriple().getOS() == llvm::Triple::Solaris)
151     Builder.defineMacro("__sparcv8");
152   else {
153     switch (getCPUGeneration(CPU)) {
154     case CG_V8:
155       Builder.defineMacro("__sparcv8");
156       Builder.defineMacro("__sparcv8__");
157       break;
158     case CG_V9:
159       Builder.defineMacro("__sparc_v9__");
160       break;
161     }
162   }
163   if (getTriple().getVendor() == llvm::Triple::Myriad) {
164     std::string MyriadArchValue, Myriad2Value;
165     Builder.defineMacro("__sparc_v8__");
166     Builder.defineMacro("__leon__");
167     switch (CPU) {
168     case CK_MYRIAD2100:
169       MyriadArchValue = "__ma2100";
170       Myriad2Value = "1";
171       break;
172     case CK_MYRIAD2150:
173       MyriadArchValue = "__ma2150";
174       Myriad2Value = "2";
175       break;
176     case CK_MYRIAD2155:
177       MyriadArchValue = "__ma2155";
178       Myriad2Value = "2";
179       break;
180     case CK_MYRIAD2450:
181       MyriadArchValue = "__ma2450";
182       Myriad2Value = "2";
183       break;
184     case CK_MYRIAD2455:
185       MyriadArchValue = "__ma2455";
186       Myriad2Value = "2";
187       break;
188     case CK_MYRIAD2x5x:
189       Myriad2Value = "2";
190       break;
191     case CK_MYRIAD2080:
192       MyriadArchValue = "__ma2080";
193       Myriad2Value = "3";
194       break;
195     case CK_MYRIAD2085:
196       MyriadArchValue = "__ma2085";
197       Myriad2Value = "3";
198       break;
199     case CK_MYRIAD2480:
200       MyriadArchValue = "__ma2480";
201       Myriad2Value = "3";
202       break;
203     case CK_MYRIAD2485:
204       MyriadArchValue = "__ma2485";
205       Myriad2Value = "3";
206       break;
207     case CK_MYRIAD2x8x:
208       Myriad2Value = "3";
209       break;
210     default:
211       MyriadArchValue = "__ma2100";
212       Myriad2Value = "1";
213       break;
214     }
215     if (!MyriadArchValue.empty()) {
216       Builder.defineMacro(MyriadArchValue, "1");
217       Builder.defineMacro(MyriadArchValue + "__", "1");
218     }
219     if (Myriad2Value == "2") {
220       Builder.defineMacro("__ma2x5x", "1");
221       Builder.defineMacro("__ma2x5x__", "1");
222     } else if (Myriad2Value == "3") {
223       Builder.defineMacro("__ma2x8x", "1");
224       Builder.defineMacro("__ma2x8x__", "1");
225     }
226     Builder.defineMacro("__myriad2__", Myriad2Value);
227     Builder.defineMacro("__myriad2", Myriad2Value);
228   }
229   if (getCPUGeneration(CPU) == CG_V9) {
230     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
231     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
232     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
233     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
234   }
235 }
236 
237 void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
238                                          MacroBuilder &Builder) const {
239   SparcTargetInfo::getTargetDefines(Opts, Builder);
240   Builder.defineMacro("__sparcv9");
241   Builder.defineMacro("__arch64__");
242   // Solaris doesn't need these variants, but the BSDs do.
243   if (getTriple().getOS() != llvm::Triple::Solaris) {
244     Builder.defineMacro("__sparc64__");
245     Builder.defineMacro("__sparc_v9__");
246     Builder.defineMacro("__sparcv9__");
247   }
248 
249   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
250   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
251   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
252   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
253 }
254 
255 void SparcV9TargetInfo::fillValidCPUList(
256     SmallVectorImpl<StringRef> &Values) const {
257   for (const SparcCPUInfo &Info : CPUInfo)
258     if (Info.Generation == CG_V9)
259       Values.push_back(Info.Name);
260 }
261