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     {{"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
107 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 
117 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 
126 void SparcTargetInfo::fillValidCPUList(
127     SmallVectorImpl<StringRef> &Values) const {
128   for (const SparcCPUInfo &Info : CPUInfo)
129     Values.push_back(Info.Name);
130 }
131 
132 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 
141 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 
165 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 
183 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