diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-12-03 12:12:10 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-12-03 12:12:10 -0800 |
commit | f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2 (patch) | |
tree | 582e5d7b377b6e973666a71960b28a7d11d72b07 /gcc/common | |
parent | 8d703821c69062c0cd255787d793e44f1a95d463 (diff) | |
parent | 3089f5feef36810c625b5813370a97b4ecc841f8 (diff) | |
download | gcc-f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2.zip gcc-f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2.tar.gz gcc-f012991e2db06cc95f7aac8ecb74a1ac5f51f3d2.tar.bz2 |
Merge from trunk revision 3089f5feef36810c625b5813370a97b4ecc841f8
Diffstat (limited to 'gcc/common')
-rw-r--r-- | gcc/common/config/i386/cpuinfo.h | 2 | ||||
-rw-r--r-- | gcc/common/config/i386/i386-common.c | 20 | ||||
-rw-r--r-- | gcc/common/config/i386/i386-cpuinfo.h | 1 | ||||
-rw-r--r-- | gcc/common/config/i386/i386-isas.h | 1 | ||||
-rw-r--r-- | gcc/common/config/riscv/riscv-common.c | 458 |
5 files changed, 410 insertions, 72 deletions
diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h index 7a93e17..41728a2 100644 --- a/gcc/common/config/i386/cpuinfo.h +++ b/gcc/common/config/i386/cpuinfo.h @@ -713,6 +713,8 @@ get_available_features (struct __processor_model *cpu_model, set_feature (FEATURE_AVX512BF16); if (eax & bit_HRESET) set_feature (FEATURE_HRESET); + if (eax & bit_AVXVNNI) + set_feature (FEATURE_AVXVNNI); } } diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c index e29320d..8f809c1 100644 --- a/gcc/common/config/i386/i386-common.c +++ b/gcc/common/config/i386/i386-common.c @@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see (OPTION_MASK_ISA_AVX512VBMI2 | OPTION_MASK_ISA_AVX512F_SET) #define OPTION_MASK_ISA_AVX512VNNI_SET \ (OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512F_SET) +#define OPTION_MASK_ISA2_AVXVNNI_SET OPTION_MASK_ISA2_AVXVNNI #define OPTION_MASK_ISA_AVX512VPOPCNTDQ_SET \ (OPTION_MASK_ISA_AVX512VPOPCNTDQ | OPTION_MASK_ISA_AVX512F_SET) #define OPTION_MASK_ISA_AVX512BITALG_SET \ @@ -206,6 +207,8 @@ along with GCC; see the file COPYING3. If not see #define OPTION_MASK_ISA_XSAVEOPT_UNSET OPTION_MASK_ISA_XSAVEOPT #define OPTION_MASK_ISA_AVX2_UNSET \ (OPTION_MASK_ISA_AVX2 | OPTION_MASK_ISA_AVX512F_UNSET) +#define OPTION_MASK_ISA2_AVX2_UNSET \ + (OPTION_MASK_ISA2_AVXVNNI_UNSET | OPTION_MASK_ISA2_AVX512F_UNSET) #define OPTION_MASK_ISA_AVX512F_UNSET \ (OPTION_MASK_ISA_AVX512F | OPTION_MASK_ISA_AVX512CD_UNSET \ | OPTION_MASK_ISA_AVX512PF_UNSET | OPTION_MASK_ISA_AVX512ER_UNSET \ @@ -228,6 +231,7 @@ along with GCC; see the file COPYING3. If not see #define OPTION_MASK_ISA2_AVX5124VNNIW_UNSET OPTION_MASK_ISA2_AVX5124VNNIW #define OPTION_MASK_ISA_AVX512VBMI2_UNSET OPTION_MASK_ISA_AVX512VBMI2 #define OPTION_MASK_ISA_AVX512VNNI_UNSET OPTION_MASK_ISA_AVX512VNNI +#define OPTION_MASK_ISA2_AVXVNNI_UNSET OPTION_MASK_ISA2_AVXVNNI #define OPTION_MASK_ISA_AVX512VPOPCNTDQ_UNSET OPTION_MASK_ISA_AVX512VPOPCNTDQ #define OPTION_MASK_ISA_AVX512BITALG_UNSET OPTION_MASK_ISA_AVX512BITALG #define OPTION_MASK_ISA2_AVX512BF16_UNSET OPTION_MASK_ISA2_AVX512BF16 @@ -310,7 +314,6 @@ along with GCC; see the file COPYING3. If not see | OPTION_MASK_ISA2_AVX512VP2INTERSECT_UNSET) #define OPTION_MASK_ISA2_GENERAL_REGS_ONLY_UNSET \ (OPTION_MASK_ISA2_AVX512F_UNSET) -#define OPTION_MASK_ISA2_AVX2_UNSET OPTION_MASK_ISA2_AVX512F_UNSET #define OPTION_MASK_ISA2_AVX_UNSET OPTION_MASK_ISA2_AVX2_UNSET #define OPTION_MASK_ISA2_SSE4_2_UNSET OPTION_MASK_ISA2_AVX_UNSET #define OPTION_MASK_ISA2_SSE4_1_UNSET OPTION_MASK_ISA2_SSE4_2_UNSET @@ -882,6 +885,21 @@ ix86_handle_option (struct gcc_options *opts, } return true; + case OPT_mavxvnni: + if (value) + { + opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AVXVNNI_SET; + opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVXVNNI_SET; + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX2_SET; + opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX2_SET; + } + else + { + opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVXVNNI_UNSET; + opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVXVNNI_UNSET; + } + return true; + case OPT_msgx: if (value) { diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h index 2138220..af02be5 100644 --- a/gcc/common/config/i386/i386-cpuinfo.h +++ b/gcc/common/config/i386/i386-cpuinfo.h @@ -224,6 +224,7 @@ enum processor_features FEATURE_KL, FEATURE_AESKLE, FEATURE_WIDEKL, + FEATURE_AVXVNNI, CPU_FEATURE_MAX }; diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h index 921db06..c4fd036 100644 --- a/gcc/common/config/i386/i386-isas.h +++ b/gcc/common/config/i386/i386-isas.h @@ -168,4 +168,5 @@ ISA_NAMES_TABLE_START ISA_NAMES_TABLE_ENTRY("kl", FEATURE_KL, P_NONE, "-mkl") ISA_NAMES_TABLE_ENTRY("aeskle", FEATURE_AESKLE, P_NONE, NULL) ISA_NAMES_TABLE_ENTRY("widekl", FEATURE_WIDEKL, P_NONE, "-mwidekl") + ISA_NAMES_TABLE_ENTRY("avxvnni", FEATURE_AVXVNNI, P_NONE, "-mavxvnni") ISA_NAMES_TABLE_END diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c index 9a576eb..5e3ddcf 100644 --- a/gcc/common/config/riscv/riscv-common.c +++ b/gcc/common/config/riscv/riscv-common.c @@ -44,6 +44,7 @@ struct riscv_subset_t struct riscv_subset_t *next; bool explicit_version_p; + bool implied_p; }; /* Type for implied ISA info. */ @@ -57,9 +58,63 @@ struct riscv_implied_info_t static const riscv_implied_info_t riscv_implied_info[] = { {"d", "f"}, + {"f", "zicsr"}, + {"d", "zicsr"}, {NULL, NULL} }; +/* This structure holds version information for specific ISA version. */ + +struct riscv_ext_version +{ + const char *name; + enum riscv_isa_spec_class isa_spec_class; + int major_version; + int minor_version; +}; + +/* All standard extensions defined in all supported ISA spec. */ +static const struct riscv_ext_version riscv_ext_version_table[] = +{ + /* name, ISA spec, major version, minor_version. */ + {"e", ISA_SPEC_CLASS_20191213, 1, 9}, + {"e", ISA_SPEC_CLASS_20190608, 1, 9}, + {"e", ISA_SPEC_CLASS_2P2, 1, 9}, + + {"i", ISA_SPEC_CLASS_20191213, 2, 1}, + {"i", ISA_SPEC_CLASS_20190608, 2, 1}, + {"i", ISA_SPEC_CLASS_2P2, 2, 0}, + + {"m", ISA_SPEC_CLASS_20191213, 2, 0}, + {"m", ISA_SPEC_CLASS_20190608, 2, 0}, + {"m", ISA_SPEC_CLASS_2P2, 2, 0}, + + {"a", ISA_SPEC_CLASS_20191213, 2, 1}, + {"a", ISA_SPEC_CLASS_20190608, 2, 0}, + {"a", ISA_SPEC_CLASS_2P2, 2, 0}, + + {"f", ISA_SPEC_CLASS_20191213, 2, 2}, + {"f", ISA_SPEC_CLASS_20190608, 2, 2}, + {"f", ISA_SPEC_CLASS_2P2, 2, 0}, + + {"d", ISA_SPEC_CLASS_20191213, 2, 2}, + {"d", ISA_SPEC_CLASS_20190608, 2, 2}, + {"d", ISA_SPEC_CLASS_2P2, 2, 0}, + + {"c", ISA_SPEC_CLASS_20191213, 2, 0}, + {"c", ISA_SPEC_CLASS_20190608, 2, 0}, + {"c", ISA_SPEC_CLASS_2P2, 2, 0}, + + {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0}, + {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0}, + + {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0}, + {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0}, + + /* Terminate the list. */ + {NULL, ISA_SPEC_CLASS_NONE, 0, 0} +}; + static const riscv_cpu_info riscv_cpu_tables[] = { #define RISCV_CORE(CORE_NAME, ARCH, TUNE) \ @@ -89,20 +144,22 @@ private: riscv_subset_list (const char *, location_t); - const char *parsing_subset_version (const char *, unsigned *, unsigned *, - unsigned, unsigned, bool, bool *); + const char *parsing_subset_version (const char *, const char *, unsigned *, + unsigned *, bool, bool *); const char *parse_std_ext (const char *); const char *parse_multiletter_ext (const char *, const char *, const char *); - void handle_implied_ext (const char *, int, int, bool); + void handle_implied_ext (riscv_subset_t *); public: ~riscv_subset_list (); - void add (const char *, int, int, bool); + void add (const char *, int, int, bool, bool); + + void add (const char *, bool); riscv_subset_t *lookup (const char *, int major_version = RISCV_DONT_CARE_VERSION, @@ -122,7 +179,7 @@ static riscv_subset_list *current_subset_list = NULL; riscv_subset_t::riscv_subset_t () : name (), major_version (0), minor_version (0), next (NULL), - explicit_version_p (false) + explicit_version_p (false), implied_p (false) { } @@ -145,13 +202,160 @@ riscv_subset_list::~riscv_subset_list () } } +/* Get the rank for single-letter subsets, lower value meaning higher + priority. */ + +static int +single_letter_subset_rank (char ext) +{ + int rank; + + switch (ext) + { + case 'i': + return 0; + case 'e': + return 1; + default: + break; + } + + const char *all_ext = riscv_supported_std_ext (); + const char *ext_pos = strchr (all_ext, ext); + if (ext_pos == NULL) + /* If got an unknown extension letter, then give it an alphabetical + order, but after all known standard extension. */ + rank = strlen (all_ext) + ext - 'a'; + else + rank = (int)(ext_pos - all_ext) + 2 /* e and i has higher rank. */; + + return rank; +} + +/* Get the rank for multi-letter subsets, lower value meaning higher + priority. */ + +static int +multi_letter_subset_rank (const std::string &subset) +{ + gcc_assert (subset.length () >= 2); + int high_order = -1; + int low_order = 0; + /* The order between multi-char extensions: s -> h -> z -> x. */ + char multiletter_class = subset[0]; + switch (multiletter_class) + { + case 's': + high_order = 0; + break; + case 'h': + high_order = 1; + break; + case 'z': + gcc_assert (subset.length () > 2); + high_order = 2; + break; + case 'x': + high_order = 3; + break; + default: + gcc_unreachable (); + return -1; + } + + if (multiletter_class == 'z') + /* Order for z extension on spec: If multiple "Z" extensions are named, they + should be ordered first by category, then alphabetically within a + category - for example, "Zicsr_Zifencei_Zam". */ + low_order = single_letter_subset_rank (subset[1]); + else + low_order = 0; + + return (high_order << 8) + low_order; +} + +/* subset compare + + Returns an integral value indicating the relationship between the subsets: + Return value indicates + -1 B has higher order than A. + 0 A and B are same subset. + 1 A has higher order than B. + +*/ + +static int +subset_cmp (const std::string &a, const std::string &b) +{ + if (a == b) + return 0; + + size_t a_len = a.length (); + size_t b_len = b.length (); + + /* Single-letter extension always get higher order than + multi-letter extension. */ + if (a_len == 1 && b_len != 1) + return 1; + + if (a_len != 1 && b_len == 1) + return -1; + + if (a_len == 1 && b_len == 1) + { + int rank_a = single_letter_subset_rank (a[0]); + int rank_b = single_letter_subset_rank (b[0]); + + if (rank_a < rank_b) + return 1; + else + return -1; + } + else + { + int rank_a = multi_letter_subset_rank(a); + int rank_b = multi_letter_subset_rank(b); + + /* Using alphabetical/lexicographical order if they have same rank. */ + if (rank_a == rank_b) + /* The return value of strcmp has opposite meaning. */ + return -strcmp (a.c_str (), b.c_str ()); + else + return (rank_a < rank_b) ? 1 : -1; + } +} + /* Add new subset to list. */ void riscv_subset_list::add (const char *subset, int major_version, - int minor_version, bool explicit_version_p) + int minor_version, bool explicit_version_p, + bool implied_p) { + riscv_subset_t *ext = lookup (subset); + + if (ext) + { + if (ext->implied_p) + { + /* We won't add impiled `ext` if it already in list. */ + gcc_assert (!implied_p); + ext->implied_p = implied_p; + ext->major_version = major_version; + ext->minor_version = minor_version; + } + else + error_at ( + m_loc, + "%<-march=%s%>: Extension `%s' appear more than one time.", + m_arch, + subset); + + return; + } + riscv_subset_t *s = new riscv_subset_t (); + riscv_subset_t *itr; if (m_head == NULL) m_head = s; @@ -160,14 +364,88 @@ riscv_subset_list::add (const char *subset, int major_version, s->major_version = major_version; s->minor_version = minor_version; s->explicit_version_p = explicit_version_p; + s->implied_p = implied_p; s->next = NULL; - if (m_tail != NULL) - m_tail->next = s; + if (m_tail == NULL) + { + m_tail = s; + return; + } + + /* e, i or g should be first subext, never come here. */ + gcc_assert (subset[0] != 'e' + && subset[0] != 'i' + && subset[0] != 'g'); + + if (m_tail == m_head) + { + gcc_assert (m_head->next == NULL); + m_head->next = s; + m_tail = s; + return; + } + + gcc_assert (m_head->next != NULL); + + /* Subset list must in canonical order, but implied subset won't + add in canonical order. */ + for (itr = m_head; itr->next != NULL; itr = itr->next) + { + riscv_subset_t *next = itr->next; + int cmp = subset_cmp (s->name, next->name); + gcc_assert (cmp != 0); + + if (cmp > 0) + { + s->next = next; + itr->next = s; + return; + } + } + /* Insert at tail of the list. */ + itr->next = s; m_tail = s; } +static void +get_default_version (const char *ext, + unsigned int *major_version, + unsigned int *minor_version) +{ + const riscv_ext_version *ext_ver; + for (ext_ver = &riscv_ext_version_table[0]; + ext_ver->name != NULL; + ++ext_ver) + if (strcmp (ext, ext_ver->name) == 0) + { + if ((ext_ver->isa_spec_class == riscv_isa_spec) || + (ext_ver->isa_spec_class == ISA_SPEC_CLASS_NONE)) + { + *major_version = ext_ver->major_version; + *minor_version = ext_ver->minor_version; + return; + } + } + + /* Not found version info. */ + *major_version = 0; + *minor_version = 0; +} + +/* Add new subset to list, but using default version from ISA spec version. */ + +void +riscv_subset_list::add (const char *subset, bool implied_p) +{ + unsigned int major_version = 0, minor_version = 0; + + get_default_version (subset, &major_version, &minor_version); + + add (subset, major_version, minor_version, false, implied_p); +} + /* Convert subset info to string with explicit version info, VERSION_P to determine append version info or not. */ @@ -178,10 +456,37 @@ riscv_subset_list::to_string (bool version_p) const oss << "rv" << m_xlen; bool first = true; - riscv_subset_t *subset = m_head; + riscv_subset_t *subset; + + bool skip_zifencei = false; + bool skip_zicsr = false; + + /* For RISC-V ISA version 2.2 or earlier version, zicsr and zifencei is + included in the base ISA. */ + if (riscv_isa_spec == ISA_SPEC_CLASS_2P2) + { + skip_zifencei = true; + skip_zicsr = true; + } - while (subset != NULL) +#ifndef HAVE_AS_MISA_SPEC + /* Skip since older binutils doesn't recognize zicsr. */ + skip_zicsr = true; +#endif +#ifndef HAVE_AS_MARCH_ZIFENCE + /* Skip since older binutils doesn't recognize zifencei, we made + a mistake in that binutils 2.35 supports zicsr but not zifencei. */ + skip_zifencei = true; +#endif + + for (subset = m_head; subset != NULL; subset = subset->next) { + if (subset->implied_p && skip_zifencei && subset->name == "zifencei") + continue; + + if (subset->implied_p && skip_zicsr && subset->name == "zicsr") + continue; + /* For !version_p, we only separate extension with underline for multi-letter extension. */ if (!first && @@ -193,12 +498,12 @@ riscv_subset_list::to_string (bool version_p) const oss << subset->name; - if (version_p || subset->explicit_version_p) + /* Let binutils decide the extension version if we don't know. */ + if ((version_p || subset->explicit_version_p) && + (subset->major_version != 0 || subset->minor_version != 0)) oss << subset->major_version << 'p' << subset->minor_version; - - subset = subset->next; } return oss.str (); @@ -246,23 +551,21 @@ riscv_supported_std_ext (void) Points to the end of version Arguments: + `ext`: This extension. `p`: Current parsing position. `major_version`: Parsing result of major version, using default_major_version if version is not present in arch string. `minor_version`: Parsing result of minor version, set to 0 if version is not present in arch string, but set to `default_minor_version` if `major_version` using default_major_version. - `default_major_version`: Default major version. - `default_minor_version`: Default minor version. `std_ext_p`: True if parsing std extension. `explicit_version_p`: True if this subset is not using default version. */ const char * -riscv_subset_list::parsing_subset_version (const char *p, +riscv_subset_list::parsing_subset_version (const char *ext, + const char *p, unsigned *major_version, unsigned *minor_version, - unsigned default_major_version, - unsigned default_minor_version, bool std_ext_p, bool *explicit_version_p) { @@ -313,11 +616,7 @@ riscv_subset_list::parsing_subset_version (const char *p, minor = version; if (major == 0 && minor == 0) - { - /* We didn't find any version string, use default version. */ - *major_version = default_major_version; - *minor_version = default_minor_version; - } + get_default_version (ext, major_version, minor_version); else { *explicit_version_p = true; @@ -351,23 +650,17 @@ riscv_subset_list::parse_std_ext (const char *p) { case 'i': p++; - p = parsing_subset_version (p, &major_version, &minor_version, - /* default_major_version= */ 2, - /* default_minor_version= */ 0, - /* std_ext_p= */ true, - &explicit_version_p); - add ("i", major_version, minor_version, explicit_version_p); + p = parsing_subset_version ("i", p, &major_version, &minor_version, + /* std_ext_p= */ true, &explicit_version_p); + add ("i", major_version, minor_version, explicit_version_p, false); break; case 'e': p++; - p = parsing_subset_version (p, &major_version, &minor_version, - /* default_major_version= */ 1, - /* default_minor_version= */ 9, - /* std_ext_p= */ true, - &explicit_version_p); + p = parsing_subset_version ("e", p, &major_version, &minor_version, + /* std_ext_p= */ true, &explicit_version_p); - add ("e", major_version, minor_version, explicit_version_p); + add ("e", major_version, minor_version, explicit_version_p, false); if (m_xlen > 32) { @@ -379,18 +672,26 @@ riscv_subset_list::parse_std_ext (const char *p) case 'g': p++; - p = parsing_subset_version (p, &major_version, &minor_version, - /* default_major_version= */ 2, - /* default_minor_version= */ 0, - /* std_ext_p= */ true, - &explicit_version_p); - add ("i", major_version, minor_version, explicit_version_p); - - for (; *std_exts != 'q'; std_exts++) + p = parsing_subset_version ("g", p, &major_version, &minor_version, + /* std_ext_p= */ true, &explicit_version_p); + if (major_version != 0 || minor_version != 0) { - const char subset[] = {*std_exts, '\0'}; - add (subset, major_version, minor_version, explicit_version_p); + warning_at (m_loc, 0, "version of `g` will be omitted, please " + "specify version for individual extension."); } + + /* We have special rule for G, we disallow rv32gm2p but allow rv32g_zicsr + here, basically we treating G expand to imafd and implied zicsr and + zifencei. */ + + add ("i", false); + add ("m", false); + add ("a", false); + add ("f", false); + add ("d", false); + add ("zicsr", true); + add ("zifencei", true); + break; default: @@ -433,47 +734,47 @@ riscv_subset_list::parse_std_ext (const char *p) std_exts++; p++; - p = parsing_subset_version (p, &major_version, &minor_version, - /* default_major_version= */ 2, - /* default_minor_version= */ 0, - /* std_ext_p= */ true, - &explicit_version_p); - subset[0] = std_ext; - handle_implied_ext (subset, major_version, - minor_version, explicit_version_p); + p = parsing_subset_version (subset, p, &major_version, &minor_version, + /* std_ext_p= */ true, &explicit_version_p); - add (subset, major_version, minor_version, explicit_version_p); + add (subset, major_version, minor_version, explicit_version_p, false); } return p; } -/* Check any implied extensions for EXT with version - MAJOR_VERSION.MINOR_VERSION, EXPLICIT_VERSION_P indicate the version is - explicitly given by user or not. */ +/* Check any implied extensions for EXT. */ void -riscv_subset_list::handle_implied_ext (const char *ext, - int major_version, - int minor_version, - bool explicit_version_p) +riscv_subset_list::handle_implied_ext (riscv_subset_t *ext) { const riscv_implied_info_t *implied_info; for (implied_info = &riscv_implied_info[0]; implied_info->ext; ++implied_info) { - if (strcmp (ext, implied_info->ext) != 0) + if (strcmp (ext->name.c_str (), implied_info->ext) != 0) continue; /* Skip if implied extension already present. */ if (lookup (implied_info->implied_ext)) continue; - /* TODO: Implied extension might use different version. */ - add (implied_info->implied_ext, major_version, minor_version, - explicit_version_p); + /* Version of implied extension will get from current ISA spec + version. */ + add (implied_info->implied_ext, true); + } + + /* For RISC-V ISA version 2.2 or earlier version, zicsr and zifence is + included in the base ISA. */ + if (riscv_isa_spec == ISA_SPEC_CLASS_2P2) + { + if (lookup ("zicsr") == NULL) + add ("zicsr", true); + + if (lookup ("zifencei") == NULL) + add ("zifencei", true); } } @@ -511,16 +812,21 @@ riscv_subset_list::parse_multiletter_ext (const char *p, char *q = subset; const char *end_of_version; bool explicit_version_p = false; + char *ext; + char backup; while (*++q != '\0' && *q != '_' && !ISDIGIT (*q)) ; + backup = *q; + *q = '\0'; + ext = xstrdup (subset); + *q = backup; + end_of_version - = parsing_subset_version (q, &major_version, &minor_version, - /* default_major_version= */ 2, - /* default_minor_version= */ 0, - /* std_ext_p= */ FALSE, - &explicit_version_p); + = parsing_subset_version (ext, q, &major_version, &minor_version, + /* std_ext_p= */ false, &explicit_version_p); + free (ext); *q = '\0'; @@ -532,7 +838,7 @@ riscv_subset_list::parse_multiletter_ext (const char *p, return NULL; } - add (subset, major_version, minor_version, explicit_version_p); + add (subset, major_version, minor_version, explicit_version_p, false); free (subset); p += end_of_version - subset; @@ -553,6 +859,7 @@ riscv_subset_list * riscv_subset_list::parse (const char *arch, location_t loc) { riscv_subset_list *subset_list = new riscv_subset_list (arch, loc); + riscv_subset_t *itr; const char *p = arch; if (strncmp (p, "rv32", 4) == 0) { @@ -608,6 +915,11 @@ riscv_subset_list::parse (const char *arch, location_t loc) goto fail; } + for (itr = subset_list->m_head; itr != NULL; itr = itr->next) + { + subset_list->handle_implied_ext (itr); + } + return subset_list; fail: @@ -645,6 +957,10 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] = {"f", &gcc_options::x_target_flags, MASK_HARD_FLOAT}, {"d", &gcc_options::x_target_flags, MASK_DOUBLE_FLOAT}, {"c", &gcc_options::x_target_flags, MASK_RVC}, + + {"zicsr", &gcc_options::x_riscv_zi_subext, MASK_ZICSR}, + {"zifencei", &gcc_options::x_riscv_zi_subext, MASK_ZIFENCEI}, + {NULL, NULL, 0} }; |