1 /* Common hooks for RISC-V.
2 Copyright (C) 2016-2021 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include <sstream>
21
22 #define INCLUDE_STRING
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "common/common-target.h"
28 #include "common/common-target-def.h"
29 #include "opts.h"
30 #include "flags.h"
31 #include "diagnostic-core.h"
32 #include "config/riscv/riscv-protos.h"
33 #include "config/riscv/riscv-subset.h"
34
35 #ifdef TARGET_BIG_ENDIAN_DEFAULT
36 #undef TARGET_DEFAULT_TARGET_FLAGS
37 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_ENDIAN)
38 #endif
39
40 /* Type for implied ISA info. */
41 struct riscv_implied_info_t
42 {
43 const char *ext;
44 const char *implied_ext;
45 };
46
47 /* Implied ISA info, must end with NULL sentinel. */
48 static const riscv_implied_info_t riscv_implied_info[] =
49 {
50 {"d", "f"},
51 {"f", "zicsr"},
52 {"d", "zicsr"},
53 {"zk", "zkn"},
54 {"zk", "zkr"},
55 {"zk", "zkt"},
56 {"zkn", "zbkb"},
57 {"zkn", "zbkc"},
58 {"zkn", "zbkx"},
59 {"zkn", "zkne"},
60 {"zkn", "zknd"},
61 {"zkn", "zknh"},
62 {"zks", "zbkb"},
63 {"zks", "zbkc"},
64 {"zks", "zbkx"},
65 {"zks", "zksed"},
66 {"zks", "zksh"},
67 {NULL, NULL}
68 };
69
70 /* This structure holds version information for specific ISA version. */
71
72 struct riscv_ext_version
73 {
74 const char *name;
75 enum riscv_isa_spec_class isa_spec_class;
76 int major_version;
77 int minor_version;
78 };
79
80 /* All standard extensions defined in all supported ISA spec. */
81 static const struct riscv_ext_version riscv_ext_version_table[] =
82 {
83 /* name, ISA spec, major version, minor_version. */
84 {"e", ISA_SPEC_CLASS_20191213, 1, 9},
85 {"e", ISA_SPEC_CLASS_20190608, 1, 9},
86 {"e", ISA_SPEC_CLASS_2P2, 1, 9},
87
88 {"i", ISA_SPEC_CLASS_20191213, 2, 1},
89 {"i", ISA_SPEC_CLASS_20190608, 2, 1},
90 {"i", ISA_SPEC_CLASS_2P2, 2, 0},
91
92 {"m", ISA_SPEC_CLASS_20191213, 2, 0},
93 {"m", ISA_SPEC_CLASS_20190608, 2, 0},
94 {"m", ISA_SPEC_CLASS_2P2, 2, 0},
95
96 {"a", ISA_SPEC_CLASS_20191213, 2, 1},
97 {"a", ISA_SPEC_CLASS_20190608, 2, 0},
98 {"a", ISA_SPEC_CLASS_2P2, 2, 0},
99
100 {"f", ISA_SPEC_CLASS_20191213, 2, 2},
101 {"f", ISA_SPEC_CLASS_20190608, 2, 2},
102 {"f", ISA_SPEC_CLASS_2P2, 2, 0},
103
104 {"d", ISA_SPEC_CLASS_20191213, 2, 2},
105 {"d", ISA_SPEC_CLASS_20190608, 2, 2},
106 {"d", ISA_SPEC_CLASS_2P2, 2, 0},
107
108 {"c", ISA_SPEC_CLASS_20191213, 2, 0},
109 {"c", ISA_SPEC_CLASS_20190608, 2, 0},
110 {"c", ISA_SPEC_CLASS_2P2, 2, 0},
111
112 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0},
113 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0},
114
115 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0},
116 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0},
117
118 {"zba", ISA_SPEC_CLASS_NONE, 1, 0},
119 {"zbb", ISA_SPEC_CLASS_NONE, 1, 0},
120 {"zbc", ISA_SPEC_CLASS_NONE, 1, 0},
121 {"zbs", ISA_SPEC_CLASS_NONE, 1, 0},
122
123 {"zbkb", ISA_SPEC_CLASS_NONE, 1, 0},
124 {"zbkc", ISA_SPEC_CLASS_NONE, 1, 0},
125 {"zbkx", ISA_SPEC_CLASS_NONE, 1, 0},
126 {"zkne", ISA_SPEC_CLASS_NONE, 1, 0},
127 {"zknd", ISA_SPEC_CLASS_NONE, 1, 0},
128 {"zknh", ISA_SPEC_CLASS_NONE, 1, 0},
129 {"zkr", ISA_SPEC_CLASS_NONE, 1, 0},
130 {"zksed", ISA_SPEC_CLASS_NONE, 1, 0},
131 {"zksh", ISA_SPEC_CLASS_NONE, 1, 0},
132 {"zkt", ISA_SPEC_CLASS_NONE, 1, 0},
133
134 /* Terminate the list. */
135 {NULL, ISA_SPEC_CLASS_NONE, 0, 0}
136 };
137
138 static const riscv_cpu_info riscv_cpu_tables[] =
139 {
140 #define RISCV_CORE(CORE_NAME, ARCH, TUNE) \
141 {CORE_NAME, ARCH, TUNE},
142 #include "../../../config/riscv/riscv-cores.def"
143 {NULL, NULL, NULL}
144 };
145
146 static const char *riscv_supported_std_ext (void);
147
148 static riscv_subset_list *current_subset_list = NULL;
149
riscv_current_subset_list()150 const riscv_subset_list *riscv_current_subset_list ()
151 {
152 return current_subset_list;
153 }
154
riscv_subset_t()155 riscv_subset_t::riscv_subset_t ()
156 : name (), major_version (0), minor_version (0), next (NULL),
157 explicit_version_p (false), implied_p (false)
158 {
159 }
160
riscv_subset_list(const char * arch,location_t loc)161 riscv_subset_list::riscv_subset_list (const char *arch, location_t loc)
162 : m_arch (arch), m_loc (loc), m_head (NULL), m_tail (NULL), m_xlen (0)
163 {
164 }
165
~riscv_subset_list()166 riscv_subset_list::~riscv_subset_list ()
167 {
168 if (!m_head)
169 return;
170
171 riscv_subset_t *item = this->m_head;
172 while (item != NULL)
173 {
174 riscv_subset_t *next = item->next;
175 delete item;
176 item = next;
177 }
178 }
179
180 /* Get the rank for single-letter subsets, lower value meaning higher
181 priority. */
182
183 static int
single_letter_subset_rank(char ext)184 single_letter_subset_rank (char ext)
185 {
186 int rank;
187
188 switch (ext)
189 {
190 case 'i':
191 return 0;
192 case 'e':
193 return 1;
194 default:
195 break;
196 }
197
198 const char *all_ext = riscv_supported_std_ext ();
199 const char *ext_pos = strchr (all_ext, ext);
200 if (ext_pos == NULL)
201 /* If got an unknown extension letter, then give it an alphabetical
202 order, but after all known standard extension. */
203 rank = strlen (all_ext) + ext - 'a';
204 else
205 rank = (int)(ext_pos - all_ext) + 2 /* e and i has higher rank. */;
206
207 return rank;
208 }
209
210 /* Get the rank for multi-letter subsets, lower value meaning higher
211 priority. */
212
213 static int
multi_letter_subset_rank(const std::string & subset)214 multi_letter_subset_rank (const std::string &subset)
215 {
216 gcc_assert (subset.length () >= 2);
217 int high_order = -1;
218 int low_order = 0;
219 /* The order between multi-char extensions: s -> h -> z -> x. */
220 char multiletter_class = subset[0];
221 switch (multiletter_class)
222 {
223 case 's':
224 high_order = 0;
225 break;
226 case 'h':
227 high_order = 1;
228 break;
229 case 'z':
230 high_order = 2;
231 break;
232 case 'x':
233 high_order = 3;
234 break;
235 default:
236 gcc_unreachable ();
237 return -1;
238 }
239
240 if (multiletter_class == 'z')
241 /* Order for z extension on spec: If multiple "Z" extensions are named, they
242 should be ordered first by category, then alphabetically within a
243 category - for example, "Zicsr_Zifencei_Zam". */
244 low_order = single_letter_subset_rank (subset[1]);
245 else
246 low_order = 0;
247
248 return (high_order << 8) + low_order;
249 }
250
251 /* subset compare
252
253 Returns an integral value indicating the relationship between the subsets:
254 Return value indicates
255 -1 B has higher order than A.
256 0 A and B are same subset.
257 1 A has higher order than B.
258
259 */
260
261 static int
subset_cmp(const std::string & a,const std::string & b)262 subset_cmp (const std::string &a, const std::string &b)
263 {
264 if (a == b)
265 return 0;
266
267 size_t a_len = a.length ();
268 size_t b_len = b.length ();
269
270 /* Single-letter extension always get higher order than
271 multi-letter extension. */
272 if (a_len == 1 && b_len != 1)
273 return 1;
274
275 if (a_len != 1 && b_len == 1)
276 return -1;
277
278 if (a_len == 1 && b_len == 1)
279 {
280 int rank_a = single_letter_subset_rank (a[0]);
281 int rank_b = single_letter_subset_rank (b[0]);
282
283 if (rank_a < rank_b)
284 return 1;
285 else
286 return -1;
287 }
288 else
289 {
290 int rank_a = multi_letter_subset_rank(a);
291 int rank_b = multi_letter_subset_rank(b);
292
293 /* Using alphabetical/lexicographical order if they have same rank. */
294 if (rank_a == rank_b)
295 /* The return value of strcmp has opposite meaning. */
296 return -strcmp (a.c_str (), b.c_str ());
297 else
298 return (rank_a < rank_b) ? 1 : -1;
299 }
300 }
301
302 /* Add new subset to list. */
303
304 void
add(const char * subset,int major_version,int minor_version,bool explicit_version_p,bool implied_p)305 riscv_subset_list::add (const char *subset, int major_version,
306 int minor_version, bool explicit_version_p,
307 bool implied_p)
308 {
309 riscv_subset_t *ext = lookup (subset);
310
311 if (ext)
312 {
313 if (ext->implied_p)
314 {
315 /* We won't add impiled `ext` if it already in list. */
316 gcc_assert (!implied_p);
317 ext->implied_p = implied_p;
318 ext->major_version = major_version;
319 ext->minor_version = minor_version;
320 }
321 else
322 error_at (
323 m_loc,
324 "%<-march=%s%>: Extension `%s' appear more than one time.",
325 m_arch,
326 subset);
327
328 return;
329 }
330
331 riscv_subset_t *s = new riscv_subset_t ();
332 riscv_subset_t *itr;
333
334 if (m_head == NULL)
335 m_head = s;
336
337 s->name = subset;
338 s->major_version = major_version;
339 s->minor_version = minor_version;
340 s->explicit_version_p = explicit_version_p;
341 s->implied_p = implied_p;
342 s->next = NULL;
343
344 if (m_tail == NULL)
345 {
346 m_tail = s;
347 return;
348 }
349
350 /* e, i or g should be first subext, never come here. */
351 gcc_assert (subset[0] != 'e'
352 && subset[0] != 'i'
353 && subset[0] != 'g');
354
355 if (m_tail == m_head)
356 {
357 gcc_assert (m_head->next == NULL);
358 m_head->next = s;
359 m_tail = s;
360 return;
361 }
362
363 gcc_assert (m_head->next != NULL);
364
365 /* Subset list must in canonical order, but implied subset won't
366 add in canonical order. */
367 for (itr = m_head; itr->next != NULL; itr = itr->next)
368 {
369 riscv_subset_t *next = itr->next;
370 int cmp = subset_cmp (s->name, next->name);
371 gcc_assert (cmp != 0);
372
373 if (cmp > 0)
374 {
375 s->next = next;
376 itr->next = s;
377 return;
378 }
379 }
380
381 /* Insert at tail of the list. */
382 itr->next = s;
383 m_tail = s;
384 }
385
386 static void
get_default_version(const char * ext,unsigned int * major_version,unsigned int * minor_version)387 get_default_version (const char *ext,
388 unsigned int *major_version,
389 unsigned int *minor_version)
390 {
391 const riscv_ext_version *ext_ver;
392 for (ext_ver = &riscv_ext_version_table[0];
393 ext_ver->name != NULL;
394 ++ext_ver)
395 if (strcmp (ext, ext_ver->name) == 0)
396 {
397 if ((ext_ver->isa_spec_class == riscv_isa_spec) ||
398 (ext_ver->isa_spec_class == ISA_SPEC_CLASS_NONE))
399 {
400 *major_version = ext_ver->major_version;
401 *minor_version = ext_ver->minor_version;
402 return;
403 }
404 }
405
406 /* Not found version info. */
407 *major_version = 0;
408 *minor_version = 0;
409 }
410
411 /* Add new subset to list, but using default version from ISA spec version. */
412
413 void
add(const char * subset,bool implied_p)414 riscv_subset_list::add (const char *subset, bool implied_p)
415 {
416 unsigned int major_version = 0, minor_version = 0;
417
418 get_default_version (subset, &major_version, &minor_version);
419
420 add (subset, major_version, minor_version, false, implied_p);
421 }
422
423 /* Convert subset info to string with explicit version info,
424 VERSION_P to determine append version info or not. */
425
426 std::string
to_string(bool version_p)427 riscv_subset_list::to_string (bool version_p) const
428 {
429 std::ostringstream oss;
430 oss << "rv" << m_xlen;
431
432 bool first = true;
433 riscv_subset_t *subset;
434
435 bool skip_zifencei = false;
436 bool skip_zicsr = false;
437
438 /* For RISC-V ISA version 2.2 or earlier version, zicsr and zifencei is
439 included in the base ISA. */
440 if (riscv_isa_spec == ISA_SPEC_CLASS_2P2)
441 {
442 skip_zifencei = true;
443 skip_zicsr = true;
444 }
445
446 #ifndef HAVE_AS_MISA_SPEC
447 /* Skip since older binutils doesn't recognize zicsr. */
448 skip_zicsr = true;
449 #endif
450 #ifndef HAVE_AS_MARCH_ZIFENCEI
451 /* Skip since older binutils doesn't recognize zifencei, we made
452 a mistake in that binutils 2.35 supports zicsr but not zifencei. */
453 skip_zifencei = true;
454 #endif
455
456 for (subset = m_head; subset != NULL; subset = subset->next)
457 {
458 if (subset->implied_p && skip_zifencei && subset->name == "zifencei")
459 continue;
460
461 if (subset->implied_p && skip_zicsr && subset->name == "zicsr")
462 continue;
463
464 /* For !version_p, we only separate extension with underline for
465 multi-letter extension. */
466 if (!first &&
467 (version_p
468 || subset->explicit_version_p
469 || subset->name.length() > 1))
470 oss << '_';
471 first = false;
472
473 oss << subset->name;
474
475 /* Let binutils decide the extension version if we don't know. */
476 if ((version_p || subset->explicit_version_p) &&
477 (subset->major_version != 0 || subset->minor_version != 0))
478 oss << subset->major_version
479 << 'p'
480 << subset->minor_version;
481 }
482
483 return oss.str ();
484 }
485
486 /* Find subset in list with version checking, return NULL if not found.
487 major/minor version checking can be ignored if major_version/minor_version
488 is RISCV_DONT_CARE_VERSION. */
489
490 riscv_subset_t *
lookup(const char * subset,int major_version,int minor_version)491 riscv_subset_list::lookup (const char *subset, int major_version,
492 int minor_version) const
493 {
494 riscv_subset_t *s;
495
496 for (s = m_head; s != NULL; s = s->next)
497 if (strcasecmp (s->name.c_str (), subset) == 0)
498 {
499 if ((major_version != RISCV_DONT_CARE_VERSION)
500 && (s->major_version != major_version))
501 return NULL;
502
503 if ((minor_version != RISCV_DONT_CARE_VERSION)
504 && (s->minor_version != minor_version))
505 return NULL;
506
507 return s;
508 }
509
510 return s;
511 }
512
513 /* Return string which contains all supported standard extensions in
514 canonical order. */
515
516 static const char *
riscv_supported_std_ext(void)517 riscv_supported_std_ext (void)
518 {
519 return "mafdqlcbjktpvn";
520 }
521
522 /* Parsing subset version.
523
524 Return Value:
525 Points to the end of version
526
527 Arguments:
528 `ext`: This extension.
529 `p`: Current parsing position.
530 `major_version`: Parsing result of major version, using
531 default_major_version if version is not present in arch string.
532 `minor_version`: Parsing result of minor version, set to 0 if version is
533 not present in arch string, but set to `default_minor_version` if
534 `major_version` using default_major_version.
535 `std_ext_p`: True if parsing std extension.
536 `explicit_version_p`: True if this subset is not using default version. */
537
538 const char *
parsing_subset_version(const char * ext,const char * p,unsigned * major_version,unsigned * minor_version,bool std_ext_p,bool * explicit_version_p)539 riscv_subset_list::parsing_subset_version (const char *ext,
540 const char *p,
541 unsigned *major_version,
542 unsigned *minor_version,
543 bool std_ext_p,
544 bool *explicit_version_p)
545 {
546 bool major_p = true;
547 unsigned version = 0;
548 unsigned major = 0;
549 unsigned minor = 0;
550 *explicit_version_p = false;
551
552 /* If we got `p`, that means we are still parsing standard extension. */
553 gcc_assert (std_ext_p || *p != 'p');
554
555 if (*p != 'p') {
556 for (; *p; ++p)
557 {
558 if (*p == 'p')
559 {
560 if (!ISDIGIT (*(p+1)))
561 {
562 error_at (m_loc, "%<-march=%s%>: Expect number "
563 "after %<%dp%>.", m_arch, version);
564 return NULL;
565 }
566 if (!major_p)
567 {
568 error_at (m_loc, "%<-march=%s%>: For %<%s%dp%dp?%>, version "
569 "number with more than 2 level is not supported.",
570 m_arch, ext, major, version);
571 return NULL;
572 }
573 major = version;
574 major_p = false;
575 version = 0;
576 }
577 else if (ISDIGIT (*p))
578 version = (version * 10) + (*p - '0');
579 else
580 break;
581 }
582 }
583
584 if (major_p)
585 major = version;
586 else
587 minor = version;
588
589 if (major == 0 && minor == 0)
590 get_default_version (ext, major_version, minor_version);
591 else
592 {
593 *explicit_version_p = true;
594 *major_version = major;
595 *minor_version = minor;
596 }
597 return p;
598 }
599
600 /* Parsing function for standard extensions.
601
602 Return Value:
603 Points to the end of extensions.
604
605 Arguments:
606 `p`: Current parsing position. */
607
608 const char *
parse_std_ext(const char * p)609 riscv_subset_list::parse_std_ext (const char *p)
610 {
611 const char *all_std_exts = riscv_supported_std_ext ();
612 const char *std_exts = all_std_exts;
613
614 unsigned major_version = 0;
615 unsigned minor_version = 0;
616 char std_ext = '\0';
617 bool explicit_version_p = false;
618
619 /* First letter must start with i, e or g. */
620 switch (*p)
621 {
622 case 'i':
623 p++;
624 p = parsing_subset_version ("i", p, &major_version, &minor_version,
625 /* std_ext_p= */ true, &explicit_version_p);
626 add ("i", major_version, minor_version, explicit_version_p, false);
627 break;
628
629 case 'e':
630 p++;
631 p = parsing_subset_version ("e", p, &major_version, &minor_version,
632 /* std_ext_p= */ true, &explicit_version_p);
633
634 add ("e", major_version, minor_version, explicit_version_p, false);
635
636 if (m_xlen > 32)
637 {
638 error_at (m_loc, "%<-march=%s%>: rv%de is not a valid base ISA",
639 m_arch, m_xlen);
640 return NULL;
641 }
642 break;
643
644 case 'g':
645 p++;
646 p = parsing_subset_version ("g", p, &major_version, &minor_version,
647 /* std_ext_p= */ true, &explicit_version_p);
648 if (major_version != 0 || minor_version != 0)
649 {
650 warning_at (m_loc, 0, "version of `g` will be omitted, please "
651 "specify version for individual extension.");
652 }
653
654 /* We have special rule for G, we disallow rv32gm2p but allow rv32g_zicsr
655 here, basically we treating G expand to imafd and implied zicsr and
656 zifencei. */
657
658 add ("i", false);
659 add ("m", false);
660 add ("a", false);
661 add ("f", false);
662 add ("d", false);
663 add ("zicsr", true);
664 add ("zifencei", true);
665
666 break;
667
668 default:
669 error_at (m_loc, "%<-march=%s%>: first ISA subset must be %<e%>, "
670 "%<i%> or %<g%>", m_arch);
671 return NULL;
672 }
673
674 while (p != NULL && *p)
675 {
676 char subset[2] = {0, 0};
677
678 if (*p == 'x' || *p == 's' || *p == 'h' || *p == 'z')
679 break;
680
681 if (*p == '_')
682 {
683 p++;
684 continue;
685 }
686
687 std_ext = *p;
688
689 /* Checking canonical order. */
690 while (*std_exts && std_ext != *std_exts)
691 std_exts++;
692
693 if (std_ext != *std_exts)
694 {
695 if (strchr (all_std_exts, std_ext) == NULL)
696 error_at (m_loc, "%<-march=%s%>: unsupported ISA subset %<%c%>",
697 m_arch, *p);
698 else
699 error_at (m_loc,
700 "%<-march=%s%>: ISA string is not in canonical order. "
701 "%<%c%>", m_arch, *p);
702 return NULL;
703 }
704
705 std_exts++;
706
707 p++;
708 subset[0] = std_ext;
709
710 p = parsing_subset_version (subset, p, &major_version, &minor_version,
711 /* std_ext_p= */ true, &explicit_version_p);
712
713 add (subset, major_version, minor_version, explicit_version_p, false);
714 }
715 return p;
716 }
717
718
719 /* Check any implied extensions for EXT. */
720 void
handle_implied_ext(riscv_subset_t * ext)721 riscv_subset_list::handle_implied_ext (riscv_subset_t *ext)
722 {
723 const riscv_implied_info_t *implied_info;
724 for (implied_info = &riscv_implied_info[0];
725 implied_info->ext;
726 ++implied_info)
727 {
728 if (strcmp (ext->name.c_str (), implied_info->ext) != 0)
729 continue;
730
731 /* Skip if implied extension already present. */
732 if (lookup (implied_info->implied_ext))
733 continue;
734
735 /* Version of implied extension will get from current ISA spec
736 version. */
737 add (implied_info->implied_ext, true);
738 }
739
740 /* For RISC-V ISA version 2.2 or earlier version, zicsr and zifence is
741 included in the base ISA. */
742 if (riscv_isa_spec == ISA_SPEC_CLASS_2P2)
743 {
744 if (lookup ("zicsr") == NULL)
745 add ("zicsr", true);
746
747 if (lookup ("zifencei") == NULL)
748 add ("zifencei", true);
749 }
750 }
751
752 /* Parsing function for multi-letter extensions.
753
754 Return Value:
755 Points to the end of extensions.
756
757 Arguments:
758 `p`: Current parsing position.
759 `ext_type`: What kind of extensions, 's', 'h', 'z' or 'x'.
760 `ext_type_str`: Full name for kind of extension. */
761
762 const char *
parse_multiletter_ext(const char * p,const char * ext_type,const char * ext_type_str)763 riscv_subset_list::parse_multiletter_ext (const char *p,
764 const char *ext_type,
765 const char *ext_type_str)
766 {
767 unsigned major_version = 0;
768 unsigned minor_version = 0;
769 size_t ext_type_len = strlen (ext_type);
770
771 while (*p)
772 {
773 if (*p == '_')
774 {
775 p++;
776 continue;
777 }
778
779 if (strncmp (p, ext_type, ext_type_len) != 0)
780 break;
781
782 char *subset = xstrdup (p);
783 char *q = subset;
784 const char *end_of_version;
785 bool explicit_version_p = false;
786 char *ext;
787 char backup;
788
789 while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
790 ;
791
792 backup = *q;
793 *q = '\0';
794 ext = xstrdup (subset);
795 *q = backup;
796
797 end_of_version
798 = parsing_subset_version (ext, q, &major_version, &minor_version,
799 /* std_ext_p= */ false, &explicit_version_p);
800 free (ext);
801
802 if (end_of_version == NULL)
803 return NULL;
804
805 *q = '\0';
806
807 if (strlen (subset) == 1)
808 {
809 error_at (m_loc, "%<-march=%s%>: name of %s must be more than 1 letter",
810 m_arch, ext_type_str);
811 free (subset);
812 return NULL;
813 }
814
815 add (subset, major_version, minor_version, explicit_version_p, false);
816 free (subset);
817 p += end_of_version - subset;
818
819 if (*p != '\0' && *p != '_')
820 {
821 error_at (m_loc, "%<-march=%s%>: %s must separate with _",
822 m_arch, ext_type_str);
823 return NULL;
824 }
825 }
826
827 return p;
828 }
829
830 /* Parsing arch string to subset list, return NULL if parsing failed. */
831
832 riscv_subset_list *
parse(const char * arch,location_t loc)833 riscv_subset_list::parse (const char *arch, location_t loc)
834 {
835 riscv_subset_list *subset_list = new riscv_subset_list (arch, loc);
836 riscv_subset_t *itr;
837 const char *p = arch;
838 if (startswith (p, "rv32"))
839 {
840 subset_list->m_xlen = 32;
841 p += 4;
842 }
843 else if (startswith (p, "rv64"))
844 {
845 subset_list->m_xlen = 64;
846 p += 4;
847 }
848 else
849 {
850 error_at (loc, "%<-march=%s%>: ISA string must begin with rv32 or rv64",
851 arch);
852 goto fail;
853 }
854
855 /* Parsing standard extension. */
856 p = subset_list->parse_std_ext (p);
857
858 if (p == NULL)
859 goto fail;
860
861 /* Parsing supervisor extension. */
862 p = subset_list->parse_multiletter_ext (p, "s", "supervisor extension");
863
864 if (p == NULL)
865 goto fail;
866
867 /* Parsing hypervisor extension. */
868 p = subset_list->parse_multiletter_ext (p, "h", "hypervisor extension");
869
870 if (p == NULL)
871 goto fail;
872
873 /* Parsing sub-extensions. */
874 p = subset_list->parse_multiletter_ext (p, "z", "sub-extension");
875
876 if (p == NULL)
877 goto fail;
878
879 /* Parsing non-standard extension. */
880 p = subset_list->parse_multiletter_ext (p, "x", "non-standard extension");
881
882 if (p == NULL)
883 goto fail;
884
885 if (*p != '\0')
886 {
887 error_at (loc, "%<-march=%s%>: unexpected ISA string at end: %qs",
888 arch, p);
889 goto fail;
890 }
891
892 for (itr = subset_list->m_head; itr != NULL; itr = itr->next)
893 {
894 subset_list->handle_implied_ext (itr);
895 }
896
897 return subset_list;
898
899 fail:
900 delete subset_list;
901 return NULL;
902 }
903
904 /* Return the current arch string. */
905
906 std::string
riscv_arch_str(bool version_p)907 riscv_arch_str (bool version_p)
908 {
909 if (current_subset_list)
910 return current_subset_list->to_string (version_p);
911 else
912 return std::string();
913 }
914
915 /* Type for pointer to member of gcc_options. */
916 typedef int (gcc_options::*opt_var_ref_t);
917
918 /* Types for recording extension to internal flag. */
919 struct riscv_ext_flag_table_t {
920 const char *ext;
921 opt_var_ref_t var_ref;
922 int mask;
923 };
924
925 /* Mapping table between extension to internal flag. */
926 static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
927 {
928 {"e", &gcc_options::x_target_flags, MASK_RVE},
929 {"m", &gcc_options::x_target_flags, MASK_MUL},
930 {"a", &gcc_options::x_target_flags, MASK_ATOMIC},
931 {"f", &gcc_options::x_target_flags, MASK_HARD_FLOAT},
932 {"d", &gcc_options::x_target_flags, MASK_DOUBLE_FLOAT},
933 {"c", &gcc_options::x_target_flags, MASK_RVC},
934
935 {"zicsr", &gcc_options::x_riscv_zi_subext, MASK_ZICSR},
936 {"zifencei", &gcc_options::x_riscv_zi_subext, MASK_ZIFENCEI},
937
938 {"zba", &gcc_options::x_riscv_zb_subext, MASK_ZBA},
939 {"zbb", &gcc_options::x_riscv_zb_subext, MASK_ZBB},
940 {"zbc", &gcc_options::x_riscv_zb_subext, MASK_ZBC},
941 {"zbs", &gcc_options::x_riscv_zb_subext, MASK_ZBS},
942
943 {"zbkb", &gcc_options::x_riscv_zk_subext, MASK_ZBKB},
944 {"zbkc", &gcc_options::x_riscv_zk_subext, MASK_ZBKC},
945 {"zbkx", &gcc_options::x_riscv_zk_subext, MASK_ZBKX},
946 {"zknd", &gcc_options::x_riscv_zk_subext, MASK_ZKND},
947 {"zkne", &gcc_options::x_riscv_zk_subext, MASK_ZKNE},
948 {"zknh", &gcc_options::x_riscv_zk_subext, MASK_ZKNH},
949 {"zkr", &gcc_options::x_riscv_zk_subext, MASK_ZKR},
950 {"zksed", &gcc_options::x_riscv_zk_subext, MASK_ZKSED},
951 {"zksh", &gcc_options::x_riscv_zk_subext, MASK_ZKSH},
952 {"zkt", &gcc_options::x_riscv_zk_subext, MASK_ZKT},
953
954 {NULL, NULL, 0}
955 };
956
957 /* Parse a RISC-V ISA string into an option mask. Must clear or set all arch
958 dependent mask bits, in case more than one -march string is passed. */
959
960 static void
riscv_parse_arch_string(const char * isa,struct gcc_options * opts,location_t loc)961 riscv_parse_arch_string (const char *isa,
962 struct gcc_options *opts,
963 location_t loc)
964 {
965 riscv_subset_list *subset_list;
966 subset_list = riscv_subset_list::parse (isa, loc);
967 if (!subset_list)
968 return;
969
970 if (opts)
971 {
972 const riscv_ext_flag_table_t *arch_ext_flag_tab;
973 /* Clean up target flags before we set. */
974 for (arch_ext_flag_tab = &riscv_ext_flag_table[0];
975 arch_ext_flag_tab->ext;
976 ++arch_ext_flag_tab)
977 opts->*arch_ext_flag_tab->var_ref &= ~arch_ext_flag_tab->mask;
978
979 if (subset_list->xlen () == 32)
980 opts->x_target_flags &= ~MASK_64BIT;
981 else if (subset_list->xlen () == 64)
982 opts->x_target_flags |= MASK_64BIT;
983
984
985 for (arch_ext_flag_tab = &riscv_ext_flag_table[0];
986 arch_ext_flag_tab->ext;
987 ++arch_ext_flag_tab)
988 {
989 if (subset_list->lookup (arch_ext_flag_tab->ext))
990 opts->*arch_ext_flag_tab->var_ref |= arch_ext_flag_tab->mask;
991 }
992 }
993
994 if (current_subset_list)
995 delete current_subset_list;
996
997 current_subset_list = subset_list;
998 }
999
1000 /* Return the riscv_cpu_info entry for CPU, NULL if not found. */
1001
1002 const riscv_cpu_info *
riscv_find_cpu(const char * cpu)1003 riscv_find_cpu (const char *cpu)
1004 {
1005 const riscv_cpu_info *cpu_info = &riscv_cpu_tables[0];
1006 for (;cpu_info->name != NULL; ++cpu_info)
1007 {
1008 const char *name = cpu_info->name;
1009 if (strcmp (cpu, name) == 0)
1010 return cpu_info;
1011 }
1012 return NULL;
1013 }
1014
1015 /* Implement TARGET_HANDLE_OPTION. */
1016
1017 static bool
riscv_handle_option(struct gcc_options * opts,struct gcc_options * opts_set ATTRIBUTE_UNUSED,const struct cl_decoded_option * decoded,location_t loc)1018 riscv_handle_option (struct gcc_options *opts,
1019 struct gcc_options *opts_set ATTRIBUTE_UNUSED,
1020 const struct cl_decoded_option *decoded,
1021 location_t loc)
1022 {
1023 switch (decoded->opt_index)
1024 {
1025 case OPT_march_:
1026 riscv_parse_arch_string (decoded->arg, opts, loc);
1027 return true;
1028
1029 case OPT_mcpu_:
1030 if (riscv_find_cpu (decoded->arg) == NULL)
1031 error_at (loc, "%<-mcpu=%s%>: unknown CPU",
1032 decoded->arg);
1033 return true;
1034
1035 default:
1036 return true;
1037 }
1038 }
1039
1040 /* Expand arch string with implied extensions. */
1041
1042 const char *
riscv_expand_arch(int argc ATTRIBUTE_UNUSED,const char ** argv)1043 riscv_expand_arch (int argc ATTRIBUTE_UNUSED,
1044 const char **argv)
1045 {
1046 gcc_assert (argc == 1);
1047 location_t loc = UNKNOWN_LOCATION;
1048 riscv_parse_arch_string (argv[0], NULL, loc);
1049 const std::string arch = riscv_arch_str (false);
1050 if (arch.length())
1051 return xasprintf ("-march=%s", arch.c_str());
1052 else
1053 return "";
1054 }
1055
1056 /* Expand default -mtune option from -mcpu option, use default --with-tune value
1057 if -mcpu don't have valid value. */
1058
1059 const char *
riscv_default_mtune(int argc,const char ** argv)1060 riscv_default_mtune (int argc, const char **argv)
1061 {
1062 gcc_assert (argc == 2);
1063 const riscv_cpu_info *cpu = riscv_find_cpu (argv[0]);
1064 const char *default_mtune = argv[1];
1065 if (cpu)
1066 return cpu->tune;
1067 else
1068 return default_mtune;
1069 }
1070
1071 /* Expand arch string with implied extensions from -mcpu option. */
1072
1073 const char *
riscv_expand_arch_from_cpu(int argc ATTRIBUTE_UNUSED,const char ** argv)1074 riscv_expand_arch_from_cpu (int argc ATTRIBUTE_UNUSED,
1075 const char **argv)
1076 {
1077 gcc_assert (argc > 0 && argc <= 2);
1078 const char *default_arch_str = NULL;
1079 const char *arch_str = NULL;
1080 if (argc >= 2)
1081 default_arch_str = argv[1];
1082
1083 const riscv_cpu_info *cpu = riscv_find_cpu (argv[0]);
1084
1085 if (cpu == NULL)
1086 {
1087 if (default_arch_str == NULL)
1088 return "";
1089 else
1090 arch_str = default_arch_str;
1091 }
1092 else
1093 arch_str = cpu->arch;
1094
1095 location_t loc = UNKNOWN_LOCATION;
1096
1097 riscv_parse_arch_string (arch_str, NULL, loc);
1098 const std::string arch = riscv_arch_str (false);
1099 return xasprintf ("-march=%s", arch.c_str());
1100 }
1101
1102
1103 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
1104 static const struct default_options riscv_option_optimization_table[] =
1105 {
1106 { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 },
1107 { OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 },
1108 { OPT_LEVELS_NONE, 0, NULL, 0 }
1109 };
1110
1111 #undef TARGET_OPTION_OPTIMIZATION_TABLE
1112 #define TARGET_OPTION_OPTIMIZATION_TABLE riscv_option_optimization_table
1113
1114 #undef TARGET_HANDLE_OPTION
1115 #define TARGET_HANDLE_OPTION riscv_handle_option
1116
1117 struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
1118