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 | {.Aliases: {"g0" }, .Register: "r0" }, {.Aliases: {"g1" }, .Register: "r1" }, {.Aliases: {"g2" }, .Register: "r2" }, {.Aliases: {"g3" }, .Register: "r3" }, |
41 | {.Aliases: {"g4" }, .Register: "r4" }, {.Aliases: {"g5" }, .Register: "r5" }, {.Aliases: {"g6" }, .Register: "r6" }, {.Aliases: {"g7" }, .Register: "r7" }, |
42 | {.Aliases: {"o0" }, .Register: "r8" }, {.Aliases: {"o1" }, .Register: "r9" }, {.Aliases: {"o2" }, .Register: "r10" }, {.Aliases: {"o3" }, .Register: "r11" }, |
43 | {.Aliases: {"o4" }, .Register: "r12" }, {.Aliases: {"o5" }, .Register: "r13" }, {.Aliases: {"o6" , "sp" }, .Register: "r14" }, {.Aliases: {"o7" }, .Register: "r15" }, |
44 | {.Aliases: {"l0" }, .Register: "r16" }, {.Aliases: {"l1" }, .Register: "r17" }, {.Aliases: {"l2" }, .Register: "r18" }, {.Aliases: {"l3" }, .Register: "r19" }, |
45 | {.Aliases: {"l4" }, .Register: "r20" }, {.Aliases: {"l5" }, .Register: "r21" }, {.Aliases: {"l6" }, .Register: "r22" }, {.Aliases: {"l7" }, .Register: "r23" }, |
46 | {.Aliases: {"i0" }, .Register: "r24" }, {.Aliases: {"i1" }, .Register: "r25" }, {.Aliases: {"i2" }, .Register: "r26" }, {.Aliases: {"i3" }, .Register: "r27" }, |
47 | {.Aliases: {"i4" }, .Register: "r28" }, {.Aliases: {"i5" }, .Register: "r29" }, {.Aliases: {"i6" , "fp" }, .Register: "r30" }, {.Aliases: {"i7" }, .Register: "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(S: "softfloat" , Value: SoftFloat) |
57 | .Case(S: "sparc" , Value: true) |
58 | .Default(Value: 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 | {.Name: {"v8" }, .Kind: SparcTargetInfo::CK_V8, .Generation: SparcTargetInfo::CG_V8}, |
69 | {.Name: {"supersparc" }, .Kind: SparcTargetInfo::CK_SUPERSPARC, .Generation: SparcTargetInfo::CG_V8}, |
70 | {.Name: {"sparclite" }, .Kind: SparcTargetInfo::CK_SPARCLITE, .Generation: SparcTargetInfo::CG_V8}, |
71 | {.Name: {"f934" }, .Kind: SparcTargetInfo::CK_F934, .Generation: SparcTargetInfo::CG_V8}, |
72 | {.Name: {"hypersparc" }, .Kind: SparcTargetInfo::CK_HYPERSPARC, .Generation: SparcTargetInfo::CG_V8}, |
73 | {.Name: {"sparclite86x" }, |
74 | .Kind: SparcTargetInfo::CK_SPARCLITE86X, |
75 | .Generation: SparcTargetInfo::CG_V8}, |
76 | {.Name: {"sparclet" }, .Kind: SparcTargetInfo::CK_SPARCLET, .Generation: SparcTargetInfo::CG_V8}, |
77 | {.Name: {"tsc701" }, .Kind: SparcTargetInfo::CK_TSC701, .Generation: SparcTargetInfo::CG_V8}, |
78 | {.Name: {"v9" }, .Kind: SparcTargetInfo::CK_V9, .Generation: SparcTargetInfo::CG_V9}, |
79 | {.Name: {"ultrasparc" }, .Kind: SparcTargetInfo::CK_ULTRASPARC, .Generation: SparcTargetInfo::CG_V9}, |
80 | {.Name: {"ultrasparc3" }, .Kind: SparcTargetInfo::CK_ULTRASPARC3, .Generation: SparcTargetInfo::CG_V9}, |
81 | {.Name: {"niagara" }, .Kind: SparcTargetInfo::CK_NIAGARA, .Generation: SparcTargetInfo::CG_V9}, |
82 | {.Name: {"niagara2" }, .Kind: SparcTargetInfo::CK_NIAGARA2, .Generation: SparcTargetInfo::CG_V9}, |
83 | {.Name: {"niagara3" }, .Kind: SparcTargetInfo::CK_NIAGARA3, .Generation: SparcTargetInfo::CG_V9}, |
84 | {.Name: {"niagara4" }, .Kind: SparcTargetInfo::CK_NIAGARA4, .Generation: SparcTargetInfo::CG_V9}, |
85 | {.Name: {"ma2100" }, .Kind: SparcTargetInfo::CK_MYRIAD2100, .Generation: SparcTargetInfo::CG_V8}, |
86 | {.Name: {"ma2150" }, .Kind: SparcTargetInfo::CK_MYRIAD2150, .Generation: SparcTargetInfo::CG_V8}, |
87 | {.Name: {"ma2155" }, .Kind: SparcTargetInfo::CK_MYRIAD2155, .Generation: SparcTargetInfo::CG_V8}, |
88 | {.Name: {"ma2450" }, .Kind: SparcTargetInfo::CK_MYRIAD2450, .Generation: SparcTargetInfo::CG_V8}, |
89 | {.Name: {"ma2455" }, .Kind: SparcTargetInfo::CK_MYRIAD2455, .Generation: SparcTargetInfo::CG_V8}, |
90 | {.Name: {"ma2x5x" }, .Kind: SparcTargetInfo::CK_MYRIAD2x5x, .Generation: SparcTargetInfo::CG_V8}, |
91 | {.Name: {"ma2080" }, .Kind: SparcTargetInfo::CK_MYRIAD2080, .Generation: SparcTargetInfo::CG_V8}, |
92 | {.Name: {"ma2085" }, .Kind: SparcTargetInfo::CK_MYRIAD2085, .Generation: SparcTargetInfo::CG_V8}, |
93 | {.Name: {"ma2480" }, .Kind: SparcTargetInfo::CK_MYRIAD2480, .Generation: SparcTargetInfo::CG_V8}, |
94 | {.Name: {"ma2485" }, .Kind: SparcTargetInfo::CK_MYRIAD2485, .Generation: SparcTargetInfo::CG_V8}, |
95 | {.Name: {"ma2x8x" }, .Kind: SparcTargetInfo::CK_MYRIAD2x8x, .Generation: SparcTargetInfo::CG_V8}, |
96 | {.Name: {"leon2" }, .Kind: SparcTargetInfo::CK_LEON2, .Generation: SparcTargetInfo::CG_V8}, |
97 | {.Name: {"at697e" }, .Kind: SparcTargetInfo::CK_LEON2_AT697E, .Generation: SparcTargetInfo::CG_V8}, |
98 | {.Name: {"at697f" }, .Kind: SparcTargetInfo::CK_LEON2_AT697F, .Generation: SparcTargetInfo::CG_V8}, |
99 | {.Name: {"leon3" }, .Kind: SparcTargetInfo::CK_LEON3, .Generation: SparcTargetInfo::CG_V8}, |
100 | {.Name: {"ut699" }, .Kind: SparcTargetInfo::CK_LEON3_UT699, .Generation: SparcTargetInfo::CG_V8}, |
101 | {.Name: {"gr712rc" }, .Kind: SparcTargetInfo::CK_LEON3_GR712RC, .Generation: SparcTargetInfo::CG_V8}, |
102 | {.Name: {"leon4" }, .Kind: SparcTargetInfo::CK_LEON4, .Generation: SparcTargetInfo::CG_V8}, |
103 | {.Name: {"gr740" }, .Kind: SparcTargetInfo::CK_LEON4_GR740, .Generation: 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 | Range: CPUInfo, P: [Kind](const SparcCPUInfo &Info) { return Info.Kind == Kind; }); |
112 | if (Item == std::end(arr: 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 | Range: CPUInfo, P: [Name](const SparcCPUInfo &Info) { return Info.Name == Name; }); |
120 | |
121 | if (Item == std::end(arr: 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(Elt: Info.Name); |
130 | } |
131 | |
132 | void SparcTargetInfo::getTargetDefines(const LangOptions &Opts, |
133 | MacroBuilder &Builder) const { |
134 | DefineStd(Builder, MacroName: "sparc" , Opts); |
135 | Builder.defineMacro(Name: "__REGISTER_PREFIX__" , Value: "" ); |
136 | |
137 | if (SoftFloat) |
138 | Builder.defineMacro(Name: "SOFT_FLOAT" , Value: "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(Name: "__sparcv8" ); |
146 | else { |
147 | switch (getCPUGeneration(Kind: CPU)) { |
148 | case CG_V8: |
149 | Builder.defineMacro(Name: "__sparcv8" ); |
150 | Builder.defineMacro(Name: "__sparcv8__" ); |
151 | break; |
152 | case CG_V9: |
153 | Builder.defineMacro(Name: "__sparc_v9__" ); |
154 | break; |
155 | } |
156 | } |
157 | if (getCPUGeneration(Kind: CPU) == CG_V9) { |
158 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1" ); |
159 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2" ); |
160 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" ); |
161 | Builder.defineMacro(Name: "__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(Name: "__sparcv9" ); |
169 | Builder.defineMacro(Name: "__arch64__" ); |
170 | // Solaris doesn't need these variants, but the BSDs do. |
171 | if (!getTriple().isOSSolaris()) { |
172 | Builder.defineMacro(Name: "__sparc64__" ); |
173 | Builder.defineMacro(Name: "__sparc_v9__" ); |
174 | Builder.defineMacro(Name: "__sparcv9__" ); |
175 | } |
176 | |
177 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1" ); |
178 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2" ); |
179 | Builder.defineMacro(Name: "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" ); |
180 | Builder.defineMacro(Name: "__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(Elt: Info.Name); |
188 | } |
189 | |