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 // clang-format off
23 // Integer registers
24 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
25 "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
26 "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
27
28 // Floating-point registers
29 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10",
30 "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21",
31 "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32",
32 "f34", "f36", "f38", "f40", "f42", "f44", "f46", "f48", "f50", "f52", "f54",
33 "f56", "f58", "f60", "f62",
34
35 // Condition code registers
36 "icc", "fcc0", "fcc1", "fcc2", "fcc3",
37 // clang-format on
38};
39
40ArrayRef<const char *> SparcTargetInfo::getGCCRegNames() const {
41 return llvm::ArrayRef(GCCRegNames);
42}
43
44const TargetInfo::GCCRegAlias SparcTargetInfo::GCCRegAliases[] = {
45 {.Aliases: {"g0"}, .Register: "r0"}, {.Aliases: {"g1"}, .Register: "r1"}, {.Aliases: {"g2"}, .Register: "r2"}, {.Aliases: {"g3"}, .Register: "r3"},
46 {.Aliases: {"g4"}, .Register: "r4"}, {.Aliases: {"g5"}, .Register: "r5"}, {.Aliases: {"g6"}, .Register: "r6"}, {.Aliases: {"g7"}, .Register: "r7"},
47 {.Aliases: {"o0"}, .Register: "r8"}, {.Aliases: {"o1"}, .Register: "r9"}, {.Aliases: {"o2"}, .Register: "r10"}, {.Aliases: {"o3"}, .Register: "r11"},
48 {.Aliases: {"o4"}, .Register: "r12"}, {.Aliases: {"o5"}, .Register: "r13"}, {.Aliases: {"o6", "sp"}, .Register: "r14"}, {.Aliases: {"o7"}, .Register: "r15"},
49 {.Aliases: {"l0"}, .Register: "r16"}, {.Aliases: {"l1"}, .Register: "r17"}, {.Aliases: {"l2"}, .Register: "r18"}, {.Aliases: {"l3"}, .Register: "r19"},
50 {.Aliases: {"l4"}, .Register: "r20"}, {.Aliases: {"l5"}, .Register: "r21"}, {.Aliases: {"l6"}, .Register: "r22"}, {.Aliases: {"l7"}, .Register: "r23"},
51 {.Aliases: {"i0"}, .Register: "r24"}, {.Aliases: {"i1"}, .Register: "r25"}, {.Aliases: {"i2"}, .Register: "r26"}, {.Aliases: {"i3"}, .Register: "r27"},
52 {.Aliases: {"i4"}, .Register: "r28"}, {.Aliases: {"i5"}, .Register: "r29"}, {.Aliases: {"i6", "fp"}, .Register: "r30"}, {.Aliases: {"i7"}, .Register: "r31"},
53};
54
55ArrayRef<TargetInfo::GCCRegAlias> SparcTargetInfo::getGCCRegAliases() const {
56 return llvm::ArrayRef(GCCRegAliases);
57}
58
59bool SparcTargetInfo::hasFeature(StringRef Feature) const {
60 return llvm::StringSwitch<bool>(Feature)
61 .Case(S: "softfloat", Value: SoftFloat)
62 .Case(S: "sparc", Value: true)
63 .Default(Value: false);
64}
65
66struct SparcCPUInfo {
67 llvm::StringLiteral Name;
68 SparcTargetInfo::CPUKind Kind;
69 SparcTargetInfo::CPUGeneration Generation;
70};
71
72static constexpr SparcCPUInfo CPUInfo[] = {
73 {.Name: {"v8"}, .Kind: SparcTargetInfo::CK_V8, .Generation: SparcTargetInfo::CG_V8},
74 {.Name: {"supersparc"}, .Kind: SparcTargetInfo::CK_SUPERSPARC, .Generation: SparcTargetInfo::CG_V8},
75 {.Name: {"sparclite"}, .Kind: SparcTargetInfo::CK_SPARCLITE, .Generation: SparcTargetInfo::CG_V8},
76 {.Name: {"f934"}, .Kind: SparcTargetInfo::CK_F934, .Generation: SparcTargetInfo::CG_V8},
77 {.Name: {"hypersparc"}, .Kind: SparcTargetInfo::CK_HYPERSPARC, .Generation: SparcTargetInfo::CG_V8},
78 {.Name: {"sparclite86x"},
79 .Kind: SparcTargetInfo::CK_SPARCLITE86X,
80 .Generation: SparcTargetInfo::CG_V8},
81 {.Name: {"sparclet"}, .Kind: SparcTargetInfo::CK_SPARCLET, .Generation: SparcTargetInfo::CG_V8},
82 {.Name: {"tsc701"}, .Kind: SparcTargetInfo::CK_TSC701, .Generation: SparcTargetInfo::CG_V8},
83 {.Name: {"v9"}, .Kind: SparcTargetInfo::CK_V9, .Generation: SparcTargetInfo::CG_V9},
84 {.Name: {"ultrasparc"}, .Kind: SparcTargetInfo::CK_ULTRASPARC, .Generation: SparcTargetInfo::CG_V9},
85 {.Name: {"ultrasparc3"}, .Kind: SparcTargetInfo::CK_ULTRASPARC3, .Generation: SparcTargetInfo::CG_V9},
86 {.Name: {"niagara"}, .Kind: SparcTargetInfo::CK_NIAGARA, .Generation: SparcTargetInfo::CG_V9},
87 {.Name: {"niagara2"}, .Kind: SparcTargetInfo::CK_NIAGARA2, .Generation: SparcTargetInfo::CG_V9},
88 {.Name: {"niagara3"}, .Kind: SparcTargetInfo::CK_NIAGARA3, .Generation: SparcTargetInfo::CG_V9},
89 {.Name: {"niagara4"}, .Kind: SparcTargetInfo::CK_NIAGARA4, .Generation: SparcTargetInfo::CG_V9},
90 {.Name: {"ma2100"}, .Kind: SparcTargetInfo::CK_MYRIAD2100, .Generation: SparcTargetInfo::CG_V8},
91 {.Name: {"ma2150"}, .Kind: SparcTargetInfo::CK_MYRIAD2150, .Generation: SparcTargetInfo::CG_V8},
92 {.Name: {"ma2155"}, .Kind: SparcTargetInfo::CK_MYRIAD2155, .Generation: SparcTargetInfo::CG_V8},
93 {.Name: {"ma2450"}, .Kind: SparcTargetInfo::CK_MYRIAD2450, .Generation: SparcTargetInfo::CG_V8},
94 {.Name: {"ma2455"}, .Kind: SparcTargetInfo::CK_MYRIAD2455, .Generation: SparcTargetInfo::CG_V8},
95 {.Name: {"ma2x5x"}, .Kind: SparcTargetInfo::CK_MYRIAD2x5x, .Generation: SparcTargetInfo::CG_V8},
96 {.Name: {"ma2080"}, .Kind: SparcTargetInfo::CK_MYRIAD2080, .Generation: SparcTargetInfo::CG_V8},
97 {.Name: {"ma2085"}, .Kind: SparcTargetInfo::CK_MYRIAD2085, .Generation: SparcTargetInfo::CG_V8},
98 {.Name: {"ma2480"}, .Kind: SparcTargetInfo::CK_MYRIAD2480, .Generation: SparcTargetInfo::CG_V8},
99 {.Name: {"ma2485"}, .Kind: SparcTargetInfo::CK_MYRIAD2485, .Generation: SparcTargetInfo::CG_V8},
100 {.Name: {"ma2x8x"}, .Kind: SparcTargetInfo::CK_MYRIAD2x8x, .Generation: SparcTargetInfo::CG_V8},
101 {.Name: {"leon2"}, .Kind: SparcTargetInfo::CK_LEON2, .Generation: SparcTargetInfo::CG_V8},
102 {.Name: {"at697e"}, .Kind: SparcTargetInfo::CK_LEON2_AT697E, .Generation: SparcTargetInfo::CG_V8},
103 {.Name: {"at697f"}, .Kind: SparcTargetInfo::CK_LEON2_AT697F, .Generation: SparcTargetInfo::CG_V8},
104 {.Name: {"leon3"}, .Kind: SparcTargetInfo::CK_LEON3, .Generation: SparcTargetInfo::CG_V8},
105 {.Name: {"ut699"}, .Kind: SparcTargetInfo::CK_LEON3_UT699, .Generation: SparcTargetInfo::CG_V8},
106 {.Name: {"gr712rc"}, .Kind: SparcTargetInfo::CK_LEON3_GR712RC, .Generation: SparcTargetInfo::CG_V8},
107 {.Name: {"leon4"}, .Kind: SparcTargetInfo::CK_LEON4, .Generation: SparcTargetInfo::CG_V8},
108 {.Name: {"gr740"}, .Kind: SparcTargetInfo::CK_LEON4_GR740, .Generation: SparcTargetInfo::CG_V8},
109 {.Name: {"leon5"}, .Kind: SparcTargetInfo::CK_LEON5, .Generation: 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 Range: CPUInfo, P: [Kind](const SparcCPUInfo &Info) { return Info.Kind == Kind; });
118 if (Item == std::end(arr: 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 Range: CPUInfo, P: [Name](const SparcCPUInfo &Info) { return Info.Name == Name; });
126
127 if (Item == std::end(arr: 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(Elt: Info.Name);
136}
137
138void SparcTargetInfo::getTargetDefines(const LangOptions &Opts,
139 MacroBuilder &Builder) const {
140 DefineStd(Builder, MacroName: "sparc", Opts);
141 Builder.defineMacro(Name: "__REGISTER_PREFIX__", Value: "");
142
143 if (SoftFloat)
144 Builder.defineMacro(Name: "SOFT_FLOAT", Value: "1");
145}
146
147void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
148 MacroBuilder &Builder) const {
149 SparcTargetInfo::getTargetDefines(Opts, Builder);
150 if (getTriple().isOSSolaris())
151 Builder.defineMacro(Name: "__sparcv8");
152 else {
153 switch (getCPUGeneration(Kind: CPU)) {
154 case CG_V8:
155 Builder.defineMacro(Name: "__sparcv8");
156 Builder.defineMacro(Name: "__sparcv8__");
157 break;
158 case CG_V9:
159 Builder.defineMacro(Name: "__sparc_v9__");
160 break;
161 }
162 }
163 if (getCPUGeneration(Kind: CPU) == CG_V9) {
164 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
165 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
166 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
167 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
168 }
169 Builder.defineMacro(Name: "__LONG_DOUBLE_128__");
170}
171
172void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
173 MacroBuilder &Builder) const {
174 SparcTargetInfo::getTargetDefines(Opts, Builder);
175 Builder.defineMacro(Name: "__sparcv9");
176 Builder.defineMacro(Name: "__arch64__");
177 // Solaris doesn't need these variants, but the BSDs do.
178 if (!getTriple().isOSSolaris()) {
179 Builder.defineMacro(Name: "__sparc64__");
180 Builder.defineMacro(Name: "__sparc_v9__");
181 Builder.defineMacro(Name: "__sparcv9__");
182 }
183
184 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
185 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
186 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
187 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
188}
189
190void SparcV9TargetInfo::fillValidCPUList(
191 SmallVectorImpl<StringRef> &Values) const {
192 for (const SparcCPUInfo &Info : CPUInfo)
193 if (Info.Generation == CG_V9)
194 Values.push_back(Elt: Info.Name);
195}
196