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
getGCCRegNames() const35 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
getGCCRegAliases() const50 ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const {
51 return llvm::makeArrayRef(GCCRegAliases);
52 }
53
hasFeature(StringRef Feature) const54 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
getCPUGeneration(CPUKind Kind) const113 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
getCPUKind(StringRef Name) const123 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
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const132 void SparcTargetInfo::fillValidCPUList(
133 SmallVectorImpl<StringRef> &Values) const {
134 for (const SparcCPUInfo &Info : CPUInfo)
135 Values.push_back(Info.Name);
136 }
137
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const138 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
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const147 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
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const239 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
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const257 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