xref: /llvm-project/clang/lib/Basic/Targets/Sparc.cpp (revision 1bc7b753a5cd1599ecf0575d629460ba08f7121e)
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