aboutsummaryrefslogtreecommitdiff
path: root/gcc/common
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-12-03 12:12:10 -0800
committerIan Lance Taylor <iant@golang.org>2020-12-03 12:12:10 -0800
commitf012991e2db06cc95f7aac8ecb74a1ac5f51f3d2 (patch)
tree582e5d7b377b6e973666a71960b28a7d11d72b07 /gcc/common
parent8d703821c69062c0cd255787d793e44f1a95d463 (diff)
parent3089f5feef36810c625b5813370a97b4ecc841f8 (diff)
downloadgcc-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.h2
-rw-r--r--gcc/common/config/i386/i386-common.c20
-rw-r--r--gcc/common/config/i386/i386-cpuinfo.h1
-rw-r--r--gcc/common/config/i386/i386-isas.h1
-rw-r--r--gcc/common/config/riscv/riscv-common.c458
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}
};