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
18using namespace clang;
19using namespace clang::targets;
20
21const 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
35ArrayRef<const char *> SparcTargetInfo::getGCCRegNames() const {
36  return llvm::makeArrayRef(GCCRegNames);
37}
38
39const 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
50ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const {
51  return llvm::makeArrayRef(GCCRegAliases);
52}
53
54bool SparcTargetInfo::hasFeature(StringRef Feature) const {
55  return llvm::StringSwitch<bool>(Feature)
56      .Case("softfloat", SoftFloat)
57      .Case("sparc", true)
58      .Default(false);
59}
60
61struct SparcCPUInfo {
62  llvm::StringLiteral Name;
63  SparcTargetInfo::CPUKind Kind;
64  SparcTargetInfo::CPUGeneration Generation;
65};
66
67static 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
112SparcTargetInfo::CPUGeneration
113SparcTargetInfo::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
123SparcTargetInfo::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
132void SparcTargetInfo::fillValidCPUList(
133    SmallVectorImpl<StringRef> &Values) const {
134  for (const SparcCPUInfo &Info : CPUInfo)
135    Values.push_back(Info.Name);
136}
137
138void 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
147void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
148                                         MacroBuilder &Builder) const {
149  SparcTargetInfo::getTargetDefines(Opts, Builder);
150  switch (getCPUGeneration(CPU)) {
151  case CG_V8:
152    Builder.defineMacro("__sparcv8");
153    if (getTriple().getOS() != llvm::Triple::Solaris)
154      Builder.defineMacro("__sparcv8__");
155    break;
156  case CG_V9:
157    Builder.defineMacro("__sparcv9");
158    if (getTriple().getOS() != llvm::Triple::Solaris) {
159      Builder.defineMacro("__sparcv9__");
160      Builder.defineMacro("__sparc_v9__");
161    }
162    break;
163  }
164  if (getTriple().getVendor() == llvm::Triple::Myriad) {
165    std::string MyriadArchValue, Myriad2Value;
166    Builder.defineMacro("__sparc_v8__");
167    Builder.defineMacro("__leon__");
168    switch (CPU) {
169    case CK_MYRIAD2100:
170      MyriadArchValue = "__ma2100";
171      Myriad2Value = "1";
172      break;
173    case CK_MYRIAD2150:
174      MyriadArchValue = "__ma2150";
175      Myriad2Value = "2";
176      break;
177    case CK_MYRIAD2155:
178      MyriadArchValue = "__ma2155";
179      Myriad2Value = "2";
180      break;
181    case CK_MYRIAD2450:
182      MyriadArchValue = "__ma2450";
183      Myriad2Value = "2";
184      break;
185    case CK_MYRIAD2455:
186      MyriadArchValue = "__ma2455";
187      Myriad2Value = "2";
188      break;
189    case CK_MYRIAD2x5x:
190      Myriad2Value = "2";
191      break;
192    case CK_MYRIAD2080:
193      MyriadArchValue = "__ma2080";
194      Myriad2Value = "3";
195      break;
196    case CK_MYRIAD2085:
197      MyriadArchValue = "__ma2085";
198      Myriad2Value = "3";
199      break;
200    case CK_MYRIAD2480:
201      MyriadArchValue = "__ma2480";
202      Myriad2Value = "3";
203      break;
204    case CK_MYRIAD2485:
205      MyriadArchValue = "__ma2485";
206      Myriad2Value = "3";
207      break;
208    case CK_MYRIAD2x8x:
209      Myriad2Value = "3";
210      break;
211    default:
212      MyriadArchValue = "__ma2100";
213      Myriad2Value = "1";
214      break;
215    }
216    if (!MyriadArchValue.empty()) {
217      Builder.defineMacro(MyriadArchValue, "1");
218      Builder.defineMacro(MyriadArchValue + "__", "1");
219    }
220    if (Myriad2Value == "2") {
221      Builder.defineMacro("__ma2x5x", "1");
222      Builder.defineMacro("__ma2x5x__", "1");
223    } else if (Myriad2Value == "3") {
224      Builder.defineMacro("__ma2x8x", "1");
225      Builder.defineMacro("__ma2x8x__", "1");
226    }
227    Builder.defineMacro("__myriad2__", Myriad2Value);
228    Builder.defineMacro("__myriad2", Myriad2Value);
229  }
230}
231
232void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
233                                         MacroBuilder &Builder) const {
234  SparcTargetInfo::getTargetDefines(Opts, Builder);
235  Builder.defineMacro("__sparcv9");
236  Builder.defineMacro("__arch64__");
237  // Solaris doesn't need these variants, but the BSDs do.
238  if (getTriple().getOS() != llvm::Triple::Solaris) {
239    Builder.defineMacro("__sparc64__");
240    Builder.defineMacro("__sparc_v9__");
241    Builder.defineMacro("__sparcv9__");
242  }
243}
244
245void SparcV9TargetInfo::fillValidCPUList(
246    SmallVectorImpl<StringRef> &Values) const {
247  for (const SparcCPUInfo &Info : CPUInfo)
248    if (Info.Generation == CG_V9)
249      Values.push_back(Info.Name);
250}
251