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::makeArrayRef(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::makeArrayRef(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("__sparcv9");
160       Builder.defineMacro("__sparcv9__");
161       Builder.defineMacro("__sparc_v9__");
162       break;
163     }
164   }
165   if (getTriple().getVendor() == llvm::Triple::Myriad) {
166     std::string MyriadArchValue, Myriad2Value;
167     Builder.defineMacro("__sparc_v8__");
168     Builder.defineMacro("__leon__");
169     switch (CPU) {
170     case CK_MYRIAD2100:
171       MyriadArchValue = "__ma2100";
172       Myriad2Value = "1";
173       break;
174     case CK_MYRIAD2150:
175       MyriadArchValue = "__ma2150";
176       Myriad2Value = "2";
177       break;
178     case CK_MYRIAD2155:
179       MyriadArchValue = "__ma2155";
180       Myriad2Value = "2";
181       break;
182     case CK_MYRIAD2450:
183       MyriadArchValue = "__ma2450";
184       Myriad2Value = "2";
185       break;
186     case CK_MYRIAD2455:
187       MyriadArchValue = "__ma2455";
188       Myriad2Value = "2";
189       break;
190     case CK_MYRIAD2x5x:
191       Myriad2Value = "2";
192       break;
193     case CK_MYRIAD2080:
194       MyriadArchValue = "__ma2080";
195       Myriad2Value = "3";
196       break;
197     case CK_MYRIAD2085:
198       MyriadArchValue = "__ma2085";
199       Myriad2Value = "3";
200       break;
201     case CK_MYRIAD2480:
202       MyriadArchValue = "__ma2480";
203       Myriad2Value = "3";
204       break;
205     case CK_MYRIAD2485:
206       MyriadArchValue = "__ma2485";
207       Myriad2Value = "3";
208       break;
209     case CK_MYRIAD2x8x:
210       Myriad2Value = "3";
211       break;
212     default:
213       MyriadArchValue = "__ma2100";
214       Myriad2Value = "1";
215       break;
216     }
217     if (!MyriadArchValue.empty()) {
218       Builder.defineMacro(MyriadArchValue, "1");
219       Builder.defineMacro(MyriadArchValue + "__", "1");
220     }
221     if (Myriad2Value == "2") {
222       Builder.defineMacro("__ma2x5x", "1");
223       Builder.defineMacro("__ma2x5x__", "1");
224     } else if (Myriad2Value == "3") {
225       Builder.defineMacro("__ma2x8x", "1");
226       Builder.defineMacro("__ma2x8x__", "1");
227     }
228     Builder.defineMacro("__myriad2__", Myriad2Value);
229     Builder.defineMacro("__myriad2", Myriad2Value);
230   }
231   if (getCPUGeneration(CPU) == CG_V9) {
232     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
233     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
234     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
235     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
236   }
237 }
238 
239 void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
240                                          MacroBuilder &Builder) const {
241   SparcTargetInfo::getTargetDefines(Opts, Builder);
242   Builder.defineMacro("__sparcv9");
243   Builder.defineMacro("__arch64__");
244   // Solaris doesn't need these variants, but the BSDs do.
245   if (getTriple().getOS() != llvm::Triple::Solaris) {
246     Builder.defineMacro("__sparc64__");
247     Builder.defineMacro("__sparc_v9__");
248     Builder.defineMacro("__sparcv9__");
249   }
250 
251   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
252   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
253   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
254   Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
255 }
256 
257 void SparcV9TargetInfo::fillValidCPUList(
258     SmallVectorImpl<StringRef> &Values) const {
259   for (const SparcCPUInfo &Info : CPUInfo)
260     if (Info.Generation == CG_V9)
261       Values.push_back(Info.Name);
262 }
263