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