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};
110
111SparcTargetInfo::CPUGeneration
112SparcTargetInfo::getCPUGeneration(CPUKind Kind) const {
113 if (Kind == CK_GENERIC)
114 return CG_V8;
115 const SparcCPUInfo *Item = llvm::find_if(
116 Range: CPUInfo, P: [Kind](const SparcCPUInfo &Info) { return Info.Kind == Kind; });
117 if (Item == std::end(arr: CPUInfo))
118 llvm_unreachable("Unexpected CPU kind");
119 return Item->Generation;
120}
121
122SparcTargetInfo::CPUKind SparcTargetInfo::getCPUKind(StringRef Name) const {
123 const SparcCPUInfo *Item = llvm::find_if(
124 Range: CPUInfo, P: [Name](const SparcCPUInfo &Info) { return Info.Name == Name; });
125
126 if (Item == std::end(arr: CPUInfo))
127 return CK_GENERIC;
128 return Item->Kind;
129}
130
131void SparcTargetInfo::fillValidCPUList(
132 SmallVectorImpl<StringRef> &Values) const {
133 for (const SparcCPUInfo &Info : CPUInfo)
134 Values.push_back(Elt: Info.Name);
135}
136
137void SparcTargetInfo::getTargetDefines(const LangOptions &Opts,
138 MacroBuilder &Builder) const {
139 DefineStd(Builder, MacroName: "sparc", Opts);
140 Builder.defineMacro(Name: "__REGISTER_PREFIX__", Value: "");
141
142 if (SoftFloat)
143 Builder.defineMacro(Name: "SOFT_FLOAT", Value: "1");
144}
145
146void SparcV8TargetInfo::getTargetDefines(const LangOptions &Opts,
147 MacroBuilder &Builder) const {
148 SparcTargetInfo::getTargetDefines(Opts, Builder);
149 if (getTriple().isOSSolaris())
150 Builder.defineMacro(Name: "__sparcv8");
151 else {
152 switch (getCPUGeneration(Kind: CPU)) {
153 case CG_V8:
154 Builder.defineMacro(Name: "__sparcv8");
155 Builder.defineMacro(Name: "__sparcv8__");
156 break;
157 case CG_V9:
158 Builder.defineMacro(Name: "__sparc_v9__");
159 break;
160 }
161 }
162 if (getCPUGeneration(Kind: CPU) == CG_V9) {
163 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
164 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
165 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
166 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
167 }
168 Builder.defineMacro(Name: "__LONG_DOUBLE_128__");
169}
170
171void SparcV9TargetInfo::getTargetDefines(const LangOptions &Opts,
172 MacroBuilder &Builder) const {
173 SparcTargetInfo::getTargetDefines(Opts, Builder);
174 Builder.defineMacro(Name: "__sparcv9");
175 Builder.defineMacro(Name: "__arch64__");
176 // Solaris doesn't need these variants, but the BSDs do.
177 if (!getTriple().isOSSolaris()) {
178 Builder.defineMacro(Name: "__sparc64__");
179 Builder.defineMacro(Name: "__sparc_v9__");
180 Builder.defineMacro(Name: "__sparcv9__");
181 }
182
183 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
184 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
185 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
186 Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
187}
188
189void SparcV9TargetInfo::fillValidCPUList(
190 SmallVectorImpl<StringRef> &Values) const {
191 for (const SparcCPUInfo &Info : CPUInfo)
192 if (Info.Generation == CG_V9)
193 Values.push_back(Elt: Info.Name);
194}
195