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 if (LongDoubleWidth == 128)
170 Builder.defineMacro(Name: "__LONG_DOUBLE_128__");
171}
172
173void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
174 MacroBuilder &Builder) const {
175 SparcTargetInfo::getTargetDefines(Opts, Builder);
176 Builder.defineMacro(Name: "__sparcv9");
177 Builder.defineMacro(Name: "__arch64__");
178 // Solaris doesn't need these variants, but the BSDs do.
179 if (!getTriple().isOSSolaris()) {
180 Builder.defineMacro(Name: "__sparc64__");
181 Builder.defineMacro(Name: "__sparc_v9__");
182 Builder.defineMacro(Name: "__sparcv9__");
183 }
184
185 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
186 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
187 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
188 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
189}
190
191void SparcV9TargetInfo::fillValidCPUList(
192 SmallVectorImpl<StringRef> &Values) const {
193 for (const SparcCPUInfo &Info : CPUInfo)
194 if (Info.Generation == CG_V9)
195 Values.push_back(Elt: Info.Name);
196}
197