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::handleTargetFeatures(std::vector<std::string> &Features,
99                                           DiagnosticsEngine &Diags) {
100   HardFloat = false;
101   VDSPV2 = false;
102   VDSPV1 = false;
103   DSPV2 = false;
104   is3E3R1 = false;
105 
106   for (const auto &Feature : Features) {
107     if (Feature == "+hard-float")
108       HardFloat = true;
109     if (Feature == "+vdspv2")
110       VDSPV2 = true;
111     if (Feature == "+dspv2")
112       DSPV2 = true;
113     if (Feature == "+vdspv1")
114       VDSPV1 = true;
115     if (Feature == "+3e3r1")
116       is3E3R1 = true;
117   }
118 
119   return true;
120 }
121 
122 ArrayRef<Builtin::Info> CSKYTargetInfo::getTargetBuiltins() const {
123   return ArrayRef<Builtin::Info>();
124 }
125 
126 ArrayRef<const char *> CSKYTargetInfo::getGCCRegNames() const {
127   static const char *const GCCRegNames[] = {
128       // Integer registers
129       "r0",
130       "r1",
131       "r2",
132       "r3",
133       "r4",
134       "r5",
135       "r6",
136       "r7",
137       "r8",
138       "r9",
139       "r10",
140       "r11",
141       "r12",
142       "r13",
143       "r14",
144       "r15",
145       "r16",
146       "r17",
147       "r18",
148       "r19",
149       "r20",
150       "r21",
151       "r22",
152       "r23",
153       "r24",
154       "r25",
155       "r26",
156       "r27",
157       "r28",
158       "r29",
159       "r30",
160       "r31",
161 
162       // Floating point registers
163       "fr0",
164       "fr1",
165       "fr2",
166       "fr3",
167       "fr4",
168       "fr5",
169       "fr6",
170       "fr7",
171       "fr8",
172       "fr9",
173       "fr10",
174       "fr11",
175       "fr12",
176       "fr13",
177       "fr14",
178       "fr15",
179       "fr16",
180       "fr17",
181       "fr18",
182       "fr19",
183       "fr20",
184       "fr21",
185       "fr22",
186       "fr23",
187       "fr24",
188       "fr25",
189       "fr26",
190       "fr27",
191       "fr28",
192       "fr29",
193       "fr30",
194       "fr31",
195 
196   };
197   return llvm::makeArrayRef(GCCRegNames);
198 }
199 
200 ArrayRef<TargetInfo::GCCRegAlias> CSKYTargetInfo::getGCCRegAliases() const {
201   static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
202       {{"a0"}, "r0"},
203       {{"a1"}, "r1"},
204       {{"a2"}, "r2"},
205       {{"a3"}, "r3"},
206       {{"l0"}, "r4"},
207       {{"l1"}, "r5"},
208       {{"l2"}, "r6"},
209       {{"l3"}, "r7"},
210       {{"l4"}, "r8"},
211       {{"l5"}, "r9"},
212       {{"l6"}, "r10"},
213       {{"l7"}, "r11"},
214       {{"t0"}, "r12"},
215       {{"t1"}, "r13"},
216       {{"sp"}, "r14"},
217       {{"lr"}, "r15"},
218       {{"l8"}, "r16"},
219       {{"l9"}, "r17"},
220       {{"t2"}, "r18"},
221       {{"t3"}, "r19"},
222       {{"t4"}, "r20"},
223       {{"t5"}, "r21"},
224       {{"t6"}, "r22"},
225       {{"t7", "fp"}, "r23"},
226       {{"t8", "top"}, "r24"},
227       {{"t9", "bsp"}, "r25"},
228       {{"r26"}, "r26"},
229       {{"r27"}, "r27"},
230       {{"gb", "rgb", "rdb"}, "r28"},
231       {{"tb", "rtb"}, "r29"},
232       {{"svbr"}, "r30"},
233       {{"tls"}, "r31"},
234 
235       {{"vr0"}, "fr0"},
236       {{"vr1"}, "fr1"},
237       {{"vr2"}, "fr2"},
238       {{"vr3"}, "fr3"},
239       {{"vr4"}, "fr4"},
240       {{"vr5"}, "fr5"},
241       {{"vr6"}, "fr6"},
242       {{"vr7"}, "fr7"},
243       {{"vr8"}, "fr8"},
244       {{"vr9"}, "fr9"},
245       {{"vr10"}, "fr10"},
246       {{"vr11"}, "fr11"},
247       {{"vr12"}, "fr12"},
248       {{"vr13"}, "fr13"},
249       {{"vr14"}, "fr14"},
250       {{"vr15"}, "fr15"},
251       {{"vr16"}, "fr16"},
252       {{"vr17"}, "fr17"},
253       {{"vr18"}, "fr18"},
254       {{"vr19"}, "fr19"},
255       {{"vr20"}, "fr20"},
256       {{"vr21"}, "fr21"},
257       {{"vr22"}, "fr22"},
258       {{"vr23"}, "fr23"},
259       {{"vr24"}, "fr24"},
260       {{"vr25"}, "fr25"},
261       {{"vr26"}, "fr26"},
262       {{"vr27"}, "fr27"},
263       {{"vr28"}, "fr28"},
264       {{"vr29"}, "fr29"},
265       {{"vr30"}, "fr30"},
266       {{"vr31"}, "fr31"},
267 
268   };
269   return llvm::makeArrayRef(GCCRegAliases);
270 }
271 
272 bool CSKYTargetInfo::validateAsmConstraint(
273     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
274   switch (*Name) {
275   default:
276     return false;
277   case 'a':
278   case 'b':
279   case 'c':
280   case 'y':
281   case 'l':
282   case 'h':
283   case 'w':
284   case 'v': // A floating-point and vector register.
285   case 'z':
286     Info.setAllowsRegister();
287     return true;
288   }
289 }
290 
291 unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size) const {
292   if (Size >= 32)
293     return 32;
294   return 0;
295 }
296