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::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
getGCCRegAliases() const50 ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const {
51 return llvm::ArrayRef(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 {{"leon2"}, SparcTargetInfo::CK_LEON2, SparcTargetInfo::CG_V8},
97 {{"at697e"}, SparcTargetInfo::CK_LEON2_AT697E, SparcTargetInfo::CG_V8},
98 {{"at697f"}, SparcTargetInfo::CK_LEON2_AT697F, SparcTargetInfo::CG_V8},
99 {{"leon3"}, SparcTargetInfo::CK_LEON3, SparcTargetInfo::CG_V8},
100 {{"ut699"}, SparcTargetInfo::CK_LEON3_UT699, SparcTargetInfo::CG_V8},
101 {{"gr712rc"}, SparcTargetInfo::CK_LEON3_GR712RC, SparcTargetInfo::CG_V8},
102 {{"leon4"}, SparcTargetInfo::CK_LEON4, SparcTargetInfo::CG_V8},
103 {{"gr740"}, SparcTargetInfo::CK_LEON4_GR740, SparcTargetInfo::CG_V8},
104 };
105
106 SparcTargetInfo::CPUGeneration
getCPUGeneration(CPUKind Kind) const107 SparcTargetInfo::getCPUGeneration(CPUKind Kind) const {
108 if (Kind == CK_GENERIC)
109 return CG_V8;
110 const SparcCPUInfo *Item = llvm::find_if(
111 CPUInfo, [Kind](const SparcCPUInfo &Info) { return Info.Kind == Kind; });
112 if (Item == std::end(CPUInfo))
113 llvm_unreachable("Unexpected CPU kind");
114 return Item->Generation;
115 }
116
getCPUKind(StringRef Name) const117 SparcTargetInfo::CPUKind SparcTargetInfo::getCPUKind(StringRef Name) const {
118 const SparcCPUInfo *Item = llvm::find_if(
119 CPUInfo, [Name](const SparcCPUInfo &Info) { return Info.Name == Name; });
120
121 if (Item == std::end(CPUInfo))
122 return CK_GENERIC;
123 return Item->Kind;
124 }
125
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const126 void SparcTargetInfo::fillValidCPUList(
127 SmallVectorImpl<StringRef> &Values) const {
128 for (const SparcCPUInfo &Info : CPUInfo)
129 Values.push_back(Info.Name);
130 }
131
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const132 void SparcTargetInfo::getTargetDefines(const LangOptions &Opts,
133 MacroBuilder &Builder) const {
134 DefineStd(Builder, "sparc", Opts);
135 Builder.defineMacro("__REGISTER_PREFIX__", "");
136
137 if (SoftFloat)
138 Builder.defineMacro("SOFT_FLOAT", "1");
139 }
140
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const141 void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
142 MacroBuilder &Builder) const {
143 SparcTargetInfo::getTargetDefines(Opts, Builder);
144 if (getTriple().isOSSolaris())
145 Builder.defineMacro("__sparcv8");
146 else {
147 switch (getCPUGeneration(CPU)) {
148 case CG_V8:
149 Builder.defineMacro("__sparcv8");
150 Builder.defineMacro("__sparcv8__");
151 break;
152 case CG_V9:
153 Builder.defineMacro("__sparc_v9__");
154 break;
155 }
156 }
157 if (getCPUGeneration(CPU) == CG_V9) {
158 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
159 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
160 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
161 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
162 }
163 }
164
getTargetDefines(const LangOptions & Opts,MacroBuilder & Builder) const165 void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
166 MacroBuilder &Builder) const {
167 SparcTargetInfo::getTargetDefines(Opts, Builder);
168 Builder.defineMacro("__sparcv9");
169 Builder.defineMacro("__arch64__");
170 // Solaris doesn't need these variants, but the BSDs do.
171 if (!getTriple().isOSSolaris()) {
172 Builder.defineMacro("__sparc64__");
173 Builder.defineMacro("__sparc_v9__");
174 Builder.defineMacro("__sparcv9__");
175 }
176
177 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
178 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
179 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
180 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
181 }
182
fillValidCPUList(SmallVectorImpl<StringRef> & Values) const183 void SparcV9TargetInfo::fillValidCPUList(
184 SmallVectorImpl<StringRef> &Values) const {
185 for (const SparcCPUInfo &Info : CPUInfo)
186 if (Info.Generation == CG_V9)
187 Values.push_back(Info.Name);
188 }
189