1 //===--- CSKY.cpp - Implement CSKY 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 CSKY TargetInfo objects.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "CSKY.h"
14 
15 using namespace clang;
16 using namespace clang::targets;
17 
18 bool CSKYTargetInfo::isValidCPUName(StringRef Name) const {
19   return llvm::CSKY::parseCPUArch(Name) != llvm::CSKY::ArchKind::INVALID;
20 }
21 
22 bool CSKYTargetInfo::setCPU(const std::string &Name) {
23   llvm::CSKY::ArchKind archKind = llvm::CSKY::parseCPUArch(Name);
24   bool isValid = (archKind != llvm::CSKY::ArchKind::INVALID);
25 
26   if (isValid) {
27     CPU = Name;
28     Arch = archKind;
29   }
30 
31   return isValid;
32 }
33 
34 void CSKYTargetInfo::getTargetDefines(const LangOptions &Opts,
35                                       MacroBuilder &Builder) const {
36   Builder.defineMacro("__ELF__");
37   Builder.defineMacro("__csky__", "2");
38   Builder.defineMacro("__CSKY__", "2");
39   Builder.defineMacro("__ckcore__", "2");
40   Builder.defineMacro("__CKCORE__", "2");
41 
42   Builder.defineMacro("__CSKYABI__", ABI == "abiv2" ? "2" : "1");
43   Builder.defineMacro("__cskyabi__", ABI == "abiv2" ? "2" : "1");
44 
45   StringRef ArchName = "ck810";
46   StringRef CPUName = "ck810";
47 
48   if (Arch != llvm::CSKY::ArchKind::INVALID) {
49     ArchName = llvm::CSKY::getArchName(Arch);
50     CPUName = CPU;
51   }
52 
53   Builder.defineMacro("__" + ArchName.upper() + "__");
54   Builder.defineMacro("__" + ArchName.lower() + "__");
55   Builder.defineMacro("__" + CPUName.upper() + "__");
56   Builder.defineMacro("__" + CPUName.lower() + "__");
57 
58   // TODO: Add support for BE if BE was supported later
59   StringRef endian = "__cskyLE__";
60 
61   Builder.defineMacro(endian);
62   Builder.defineMacro(endian.upper());
63   Builder.defineMacro(endian.lower());
64 
65   if (DSPV2) {
66     StringRef dspv2 = "__CSKY_DSPV2__";
67     Builder.defineMacro(dspv2);
68     Builder.defineMacro(dspv2.lower());
69   }
70 
71   if (VDSPV2) {
72     StringRef vdspv2 = "__CSKY_VDSPV2__";
73     Builder.defineMacro(vdspv2);
74     Builder.defineMacro(vdspv2.lower());
75 
76     if (HardFloat) {
77       StringRef vdspv2_f = "__CSKY_VDSPV2_F__";
78       Builder.defineMacro(vdspv2_f);
79       Builder.defineMacro(vdspv2_f.lower());
80     }
81   }
82   if (VDSPV1) {
83     StringRef vdspv1_64 = "__CSKY_VDSP64__";
84     StringRef vdspv1_128 = "__CSKY_VDSP128__";
85 
86     Builder.defineMacro(vdspv1_64);
87     Builder.defineMacro(vdspv1_64.lower());
88     Builder.defineMacro(vdspv1_128);
89     Builder.defineMacro(vdspv1_128.lower());
90   }
91   if (is3E3R1) {
92     StringRef is3e3r1 = "__CSKY_3E3R1__";
93     Builder.defineMacro(is3e3r1);
94     Builder.defineMacro(is3e3r1.lower());
95   }
96 }
97 
98 bool CSKYTargetInfo::hasFeature(StringRef Feature) const {
99   return llvm::StringSwitch<bool>(Feature)
100       .Case("hard-float", HardFloat)
101       .Case("hard-float-abi", HardFloatABI)
102       .Case("fpuv2_sf", FPUV2_SF)
103       .Case("fpuv2_df", FPUV2_DF)
104       .Case("fpuv3_sf", FPUV3_SF)
105       .Case("fpuv3_df", FPUV3_DF)
106       .Case("vdspv2", VDSPV2)
107       .Case("dspv2", DSPV2)
108       .Case("vdspv1", VDSPV1)
109       .Case("3e3r1", is3E3R1)
110       .Default(false);
111 }
112 
113 bool CSKYTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
114                                           DiagnosticsEngine &Diags) {
115   for (const auto &Feature : Features) {
116     if (Feature == "+hard-float")
117       HardFloat = true;
118     if (Feature == "+hard-float-abi")
119       HardFloatABI = true;
120     if (Feature == "+fpuv2_sf")
121       FPUV2_SF = true;
122     if (Feature == "+fpuv2_df")
123       FPUV2_DF = true;
124     if (Feature == "+fpuv3_sf")
125       FPUV3_SF = true;
126     if (Feature == "+fpuv3_df")
127       FPUV3_DF = true;
128     if (Feature == "+vdspv2")
129       VDSPV2 = true;
130     if (Feature == "+dspv2")
131       DSPV2 = true;
132     if (Feature == "+vdspv1")
133       VDSPV1 = true;
134     if (Feature == "+3e3r1")
135       is3E3R1 = true;
136   }
137 
138   return true;
139 }
140 
141 ArrayRef<Builtin::Info> CSKYTargetInfo::getTargetBuiltins() const {
142   return ArrayRef<Builtin::Info>();
143 }
144 
145 ArrayRef<const char *> CSKYTargetInfo::getGCCRegNames() const {
146   static const char *const GCCRegNames[] = {
147       // Integer registers
148       "r0",
149       "r1",
150       "r2",
151       "r3",
152       "r4",
153       "r5",
154       "r6",
155       "r7",
156       "r8",
157       "r9",
158       "r10",
159       "r11",
160       "r12",
161       "r13",
162       "r14",
163       "r15",
164       "r16",
165       "r17",
166       "r18",
167       "r19",
168       "r20",
169       "r21",
170       "r22",
171       "r23",
172       "r24",
173       "r25",
174       "r26",
175       "r27",
176       "r28",
177       "r29",
178       "r30",
179       "r31",
180 
181       // Floating point registers
182       "fr0",
183       "fr1",
184       "fr2",
185       "fr3",
186       "fr4",
187       "fr5",
188       "fr6",
189       "fr7",
190       "fr8",
191       "fr9",
192       "fr10",
193       "fr11",
194       "fr12",
195       "fr13",
196       "fr14",
197       "fr15",
198       "fr16",
199       "fr17",
200       "fr18",
201       "fr19",
202       "fr20",
203       "fr21",
204       "fr22",
205       "fr23",
206       "fr24",
207       "fr25",
208       "fr26",
209       "fr27",
210       "fr28",
211       "fr29",
212       "fr30",
213       "fr31",
214 
215   };
216   return llvm::ArrayRef(GCCRegNames);
217 }
218 
219 ArrayRef<TargetInfo::GCCRegAlias> CSKYTargetInfo::getGCCRegAliases() const {
220   static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
221       {{"a0"}, "r0"},
222       {{"a1"}, "r1"},
223       {{"a2"}, "r2"},
224       {{"a3"}, "r3"},
225       {{"l0"}, "r4"},
226       {{"l1"}, "r5"},
227       {{"l2"}, "r6"},
228       {{"l3"}, "r7"},
229       {{"l4"}, "r8"},
230       {{"l5"}, "r9"},
231       {{"l6"}, "r10"},
232       {{"l7"}, "r11"},
233       {{"t0"}, "r12"},
234       {{"t1"}, "r13"},
235       {{"sp"}, "r14"},
236       {{"lr"}, "r15"},
237       {{"l8"}, "r16"},
238       {{"l9"}, "r17"},
239       {{"t2"}, "r18"},
240       {{"t3"}, "r19"},
241       {{"t4"}, "r20"},
242       {{"t5"}, "r21"},
243       {{"t6"}, "r22"},
244       {{"t7", "fp"}, "r23"},
245       {{"t8", "top"}, "r24"},
246       {{"t9", "bsp"}, "r25"},
247       {{"r26"}, "r26"},
248       {{"r27"}, "r27"},
249       {{"gb", "rgb", "rdb"}, "r28"},
250       {{"tb", "rtb"}, "r29"},
251       {{"svbr"}, "r30"},
252       {{"tls"}, "r31"},
253 
254       {{"vr0"}, "fr0"},
255       {{"vr1"}, "fr1"},
256       {{"vr2"}, "fr2"},
257       {{"vr3"}, "fr3"},
258       {{"vr4"}, "fr4"},
259       {{"vr5"}, "fr5"},
260       {{"vr6"}, "fr6"},
261       {{"vr7"}, "fr7"},
262       {{"vr8"}, "fr8"},
263       {{"vr9"}, "fr9"},
264       {{"vr10"}, "fr10"},
265       {{"vr11"}, "fr11"},
266       {{"vr12"}, "fr12"},
267       {{"vr13"}, "fr13"},
268       {{"vr14"}, "fr14"},
269       {{"vr15"}, "fr15"},
270       {{"vr16"}, "fr16"},
271       {{"vr17"}, "fr17"},
272       {{"vr18"}, "fr18"},
273       {{"vr19"}, "fr19"},
274       {{"vr20"}, "fr20"},
275       {{"vr21"}, "fr21"},
276       {{"vr22"}, "fr22"},
277       {{"vr23"}, "fr23"},
278       {{"vr24"}, "fr24"},
279       {{"vr25"}, "fr25"},
280       {{"vr26"}, "fr26"},
281       {{"vr27"}, "fr27"},
282       {{"vr28"}, "fr28"},
283       {{"vr29"}, "fr29"},
284       {{"vr30"}, "fr30"},
285       {{"vr31"}, "fr31"},
286 
287   };
288   return llvm::ArrayRef(GCCRegAliases);
289 }
290 
291 bool CSKYTargetInfo::validateAsmConstraint(
292     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
293   switch (*Name) {
294   default:
295     return false;
296   case 'a':
297   case 'b':
298   case 'c':
299   case 'y':
300   case 'l':
301   case 'h':
302   case 'w':
303   case 'v': // A floating-point and vector register.
304   case 'z':
305     Info.setAllowsRegister();
306     return true;
307   }
308 }
309 
310 unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size) const {
311   if (Size >= 32)
312     return 32;
313   return 0;
314 }
315