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
15using namespace clang;
16using namespace clang::targets;
17
18bool CSKYTargetInfo::isValidCPUName(StringRef Name) const {
19  return llvm::CSKY::parseCPUArch(Name) != llvm::CSKY::ArchKind::INVALID;
20}
21
22bool 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
34void 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
99bool 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
114bool 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
142ArrayRef<Builtin::Info> CSKYTargetInfo::getTargetBuiltins() const {
143  return ArrayRef<Builtin::Info>();
144}
145
146ArrayRef<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
220ArrayRef<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
292bool 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
311unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size) const {
312  if (Size >= 32)
313    return 32;
314  return 0;
315}
316