public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/3] RISC-V: Support version controling for ISA standard extensions
@ 2020-11-13  7:29 Kito Cheng
  2020-11-13  7:29 ` [PATCH 1/3] RISC-V: Handle implied extension in canonical ordering Kito Cheng
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Kito Cheng @ 2020-11-13  7:29 UTC (permalink / raw)
  To: gcc-patches, kito.cheng

Current GCC implementation is RISC-V ISA 2.2, this patch set implement v20190608 and v20191213, and also add option -misa-spec=[2.2|20190608|20191213] to change the default ISA spec version.

There is one major incompatible

That option will effect the default version of each sub-extension, for example I-extension is 2.0 for 2.2 and 2.1 for v20190608 and v20191213.

We also update the -march parser to fit the latest standard, the canonical ordering for multi-letter, drop version support for G extension, and we also omitted the version for unrecognized extension.

And we add an special rule for G extension, imafd can't appear again if G extension is present, but zicsr and zifencei can.

The default ISA spec will keep on 2.2, and change that in next GCC release.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/3] RISC-V: Handle implied extension in canonical ordering.
  2020-11-13  7:29 [PATCH 0/3] RISC-V: Support version controling for ISA standard extensions Kito Cheng
@ 2020-11-13  7:29 ` Kito Cheng
  2020-11-13  7:29 ` [PATCH 2/3] RISC-V: Support zicsr and zifencei extension for -march Kito Cheng
  2020-11-13  7:29 ` [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions Kito Cheng
  2 siblings, 0 replies; 12+ messages in thread
From: Kito Cheng @ 2020-11-13  7:29 UTC (permalink / raw)
  To: gcc-patches, kito.cheng; +Cc: Kito Cheng

 - ISA spec has specify the order between multi-letter extensions, implied
   extension also need to follow store in canonical ordering, so
   most easy way is we keep that in-order during insertion.

gcc/ChangeLog:

	* common/config/riscv/riscv-common.c (single_letter_subset_rank): New.
	(multi_letter_subset_rank): Ditto.
	(subset_cmp): Ditto.
	(riscv_subset_list::add): Insert subext in canonical ordering.
	(riscv_subset_list::parse_std_ext): Move handle_implied_ext to ...
	(riscv_subset_list::parse): ... here.
---
 gcc/common/config/riscv/riscv-common.c | 177 ++++++++++++++++++++++++-
 1 file changed, 172 insertions(+), 5 deletions(-)

diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index 9a576eb689b..f5f7be3cfff 100644
--- a/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/common/config/riscv/riscv-common.c
@@ -145,6 +145,129 @@ 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
@@ -152,6 +275,7 @@ riscv_subset_list::add (const char *subset, int major_version,
 			int minor_version, bool explicit_version_p)
 {
   riscv_subset_t *s = new riscv_subset_t ();
+  riscv_subset_t *itr;
 
   if (m_head == NULL)
     m_head = s;
@@ -162,9 +286,45 @@ riscv_subset_list::add (const char *subset, int major_version,
   s->explicit_version_p = explicit_version_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;
 }
 
@@ -441,9 +601,6 @@ riscv_subset_list::parse_std_ext (const char *p)
 
       subset[0] = std_ext;
 
-      handle_implied_ext (subset, major_version,
-			  minor_version, explicit_version_p);
-
       add (subset, major_version, minor_version, explicit_version_p);
     }
   return p;
@@ -553,6 +710,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 +766,15 @@ 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->name.c_str (),
+	itr->major_version,
+	itr->minor_version,
+	itr->explicit_version_p);
+    }
+
   return subset_list;
 
 fail:
-- 
2.29.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 2/3] RISC-V: Support zicsr and zifencei extension for -march.
  2020-11-13  7:29 [PATCH 0/3] RISC-V: Support version controling for ISA standard extensions Kito Cheng
  2020-11-13  7:29 ` [PATCH 1/3] RISC-V: Handle implied extension in canonical ordering Kito Cheng
@ 2020-11-13  7:29 ` Kito Cheng
  2020-11-17 21:23   ` Jim Wilson
  2020-11-13  7:29 ` [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions Kito Cheng
  2 siblings, 1 reply; 12+ messages in thread
From: Kito Cheng @ 2020-11-13  7:29 UTC (permalink / raw)
  To: gcc-patches, kito.cheng; +Cc: Kito Cheng

 - CSR related instructions and fence instructions has to be splitted from
   baseline ISA, zicsr and zifencei are corresponding sub-extension.

gcc/ChangeLog:

	* common/config/riscv/riscv-common.c (riscv_implied_info):
	d and f implied zicsr.
	(riscv_ext_flag_table): Handle zicsr and zifencei.
	* config/riscv/riscv-opts.h (MASK_ZICSR): New.
	(MASK_ZIFENCEI): Ditto.
	(TARGET_ZICSR): Ditto.
	(TARGET_ZIFENCEI): Ditto.
	* config/riscv/riscv.c (riscv_memmodel_needs_release_fence):
	Check fence is available by TARGET_ZIFENCEI.
	* config/riscv/riscv.opt (riscv_zi_subext): New.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/arch-8.c: New.
	* gcc.target/riscv/attribute-14.c: Ditto.
---
 gcc/common/config/riscv/riscv-common.c        | 6 ++++++
 gcc/config/riscv/riscv-opts.h                 | 6 ++++++
 gcc/config/riscv/riscv.c                      | 3 +++
 gcc/config/riscv/riscv.md                     | 7 ++++---
 gcc/config/riscv/riscv.opt                    | 3 +++
 gcc/testsuite/gcc.target/riscv/arch-8.c       | 5 +++++
 gcc/testsuite/gcc.target/riscv/attribute-14.c | 6 ++++++
 7 files changed, 33 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-14.c

diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index f5f7be3cfff..ca88ca1dacd 100644
--- a/gcc/common/config/riscv/riscv-common.c
+++ b/gcc/common/config/riscv/riscv-common.c
@@ -57,6 +57,8 @@ struct riscv_implied_info_t
 static const riscv_implied_info_t riscv_implied_info[] =
 {
   {"d", "f"},
+  {"f", "zicsr"},
+  {"d", "zicsr"},
   {NULL, NULL}
 };
 
@@ -812,6 +814,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}
 };
 
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 2a3f9d9eef5..de8ac0e038d 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -57,4 +57,10 @@ enum stack_protector_guard {
   SSP_GLOBAL			/* global canary */
 };
 
+#define MASK_ZICSR    (1 << 0)
+#define MASK_ZIFENCEI (1 << 1)
+
+#define TARGET_ZICSR    ((riscv_zi_subext & MASK_ZICSR) != 0)
+#define TARGET_ZIFENCEI ((riscv_zi_subext & MASK_ZIFENCEI) != 0)
+
 #endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 738556539f6..2aaa8e96451 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -3337,6 +3337,9 @@ riscv_memmodel_needs_amo_acquire (enum memmodel model)
 static bool
 riscv_memmodel_needs_release_fence (enum memmodel model)
 {
+  if (!TARGET_ZIFENCEI)
+    return false;
+
   switch (model)
     {
       case MEMMODEL_ACQ_REL:
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index f15bad3b29e..756b35fb8c0 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1543,19 +1543,20 @@
 		     LCT_NORMAL, VOIDmode, operands[0], Pmode,
 		     operands[1], Pmode, const0_rtx, Pmode);
 #else
-  emit_insn (gen_fence_i ());
+  if (TARGET_ZIFENCEI)
+    emit_insn (gen_fence_i ());
 #endif
   DONE;
 })
 
 (define_insn "fence"
   [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
-  ""
+  "TARGET_ZIFENCEI"
   "%|fence%-")
 
 (define_insn "fence_i"
   [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
-  ""
+  "TARGET_ZIFENCEI"
   "fence.i")
 
 ;;
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 808b4a04405..ca2fc7c8021 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -183,3 +183,6 @@ Use the given offset for addressing the stack-protector guard.
 
 TargetVariable
 long riscv_stack_protector_guard_offset = 0
+
+TargetVariable
+int riscv_zi_subext
diff --git a/gcc/testsuite/gcc.target/riscv/arch-8.c b/gcc/testsuite/gcc.target/riscv/arch-8.c
new file mode 100644
index 00000000000..d7760fc576f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-8.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O -march=rv32id_zicsr_zifence -mabi=ilp32" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-14.c b/gcc/testsuite/gcc.target/riscv/attribute-14.c
new file mode 100644
index 00000000000..48456277152
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-14.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32if -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_f2p0_zicsr2p0\"" } } */
-- 
2.29.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions
  2020-11-13  7:29 [PATCH 0/3] RISC-V: Support version controling for ISA standard extensions Kito Cheng
  2020-11-13  7:29 ` [PATCH 1/3] RISC-V: Handle implied extension in canonical ordering Kito Cheng
  2020-11-13  7:29 ` [PATCH 2/3] RISC-V: Support zicsr and zifencei extension for -march Kito Cheng
@ 2020-11-13  7:29 ` Kito Cheng
  2020-11-13  7:34   ` Kito Cheng
  2020-12-15  8:08   ` Gerald Pfeifer
  2 siblings, 2 replies; 12+ messages in thread
From: Kito Cheng @ 2020-11-13  7:29 UTC (permalink / raw)
  To: gcc-patches, kito.cheng; +Cc: Kito Cheng

 - New option -misa-spec support: -misa-spec=[2.2|20190608|20191213] and
   corresponding configuration option --with-isa-spec.

 - Current default ISA spec set to 2.2, but we intend to bump this to
   20191213 or later in next release.

gcc/ChangeLog:

	* common/config/riscv/riscv-common.c (riscv_ext_version): New.
	(riscv_ext_version_table): Ditto.
	(get_default_version): Ditto.
	(riscv_subset_t::implied_p): New field.
	(riscv_subset_t::riscv_subset_t): Init implied_p.
	(riscv_subset_list::add): New.
	(riscv_subset_list::handle_implied_ext): Pass riscv_subset_t
	instead of separated argument.
	(riscv_subset_list::to_string): Handle zifencei and zicsr, and
	omit version if version is unknown.
	(riscv_subset_list::parsing_subset_version): New argument `ext`,
	remove default_major_version and default_minor_version, get
	default version info via get_default_version.
	(riscv_subset_list::parse_std_ext): Update argument for
	parsing_subset_version calls.
	Handle 2.2 ISA spec, always enable zicsr and zifencei, they are
	included in baseline ISA in that time.
	(riscv_subset_list::parse_multiletter_ext): Update argument for
	`parsing_subset_version` and `add` calls.
	(riscv_subset_list::parse): Adjust argument for
	riscv_subset_list::handle_implied_ext call.
	* config.gcc (riscv*-*-*): Handle --with-isa-spec=.
	* config.in (HAVE_AS_MISA_SPEC): New.
	(HAVE_AS_MARCH_ZIFENCEI): Ditto.
	* config/riscv/riscv-opts.h (riscv_isa_spec_class): New.
	(riscv_isa_spec): Ditto.
	* config/riscv/riscv.h (HAVE_AS_MISA_SPEC): New.
	(ASM_SPEC): Pass -misa-spec if gas supported.
	* config/riscv/riscv.opt (riscv_isa_spec_class) New.
	* configure.ac (HAVE_AS_MARCH_ZIFENCEI): New test.
	(HAVE_AS_MISA_SPEC): Ditto.
	* configure: Regen.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/arch-9.c: New.
	* gcc.target/riscv/arch-10.c: Ditto.
	* gcc.target/riscv/arch-11.c: Ditto.
	* gcc.target/riscv/attribute-6.c: Remove, we don't support G
	with version anymore.
	* gcc.target/riscv/attribute-8.c: Reorder arch string to fit canonical
	ordering.
	* gcc.target/riscv/attribute-9.c: We don't emit version for
	unknown extensions now.
	* gcc.target/riscv/attribute-11.c: Add -misa-spec=2.2 flags.
	* gcc.target/riscv/attribute-12.c: Ditto.
	* gcc.target/riscv/attribute-13.c: Ditto.
	* gcc.target/riscv/attribute-14.c: Ditto.
	* gcc.target/riscv/attribute-15.c: New.
	* gcc.target/riscv/attribute-16.c: Ditto.
	* gcc.target/riscv/attribute-17.c: Ditto.
---
 gcc/common/config/riscv/riscv-common.c        | 288 +++++++++++++-----
 gcc/config.gcc                                |  17 +-
 gcc/config.in                                 |  12 +
 gcc/config/riscv/riscv-opts.h                 |  10 +
 gcc/config/riscv/riscv.h                      |   9 +-
 gcc/config/riscv/riscv.opt                    |  17 ++
 gcc/configure                                 |  62 ++++
 gcc/configure.ac                              |  10 +
 gcc/testsuite/gcc.target/riscv/arch-10.c      |   6 +
 gcc/testsuite/gcc.target/riscv/arch-11.c      |   5 +
 gcc/testsuite/gcc.target/riscv/arch-9.c       |   6 +
 gcc/testsuite/gcc.target/riscv/attribute-11.c |   2 +-
 gcc/testsuite/gcc.target/riscv/attribute-12.c |   2 +-
 gcc/testsuite/gcc.target/riscv/attribute-13.c |   2 +-
 gcc/testsuite/gcc.target/riscv/attribute-14.c |   4 +-
 gcc/testsuite/gcc.target/riscv/attribute-15.c |   6 +
 gcc/testsuite/gcc.target/riscv/attribute-16.c |   6 +
 gcc/testsuite/gcc.target/riscv/attribute-17.c |   6 +
 gcc/testsuite/gcc.target/riscv/attribute-6.c  |   6 -
 gcc/testsuite/gcc.target/riscv/attribute-8.c  |   4 +-
 gcc/testsuite/gcc.target/riscv/attribute-9.c  |   2 +-
 21 files changed, 394 insertions(+), 88 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-11.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-9.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-15.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-16.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-17.c
 delete mode 100644 gcc/testsuite/gcc.target/riscv/attribute-6.c

diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index ca88ca1dacd..ea2d516bb36 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.  */
@@ -62,6 +63,58 @@ static const riscv_implied_info_t riscv_implied_info[] =
   {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) \
@@ -91,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,
@@ -124,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)
 {
 }
 
@@ -274,8 +329,31 @@ subset_cmp (const std::string &a, const std::string &b)
 
 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;
 
@@ -286,6 +364,7 @@ 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)
@@ -330,6 +409,43 @@ riscv_subset_list::add (const char *subset, int major_version,
   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.  */
 
@@ -340,10 +456,38 @@ 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 don't recognize zicsr.  */
+  skip_zicsr = true;
+#endif
+#ifndef HAVE_AS_MARCH_ZIFENCE
+  /* Skip since older binutils don't recognize zifencei,
+     we mad a mistake that is binutils 2.35 support zicsr but not support
+     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 &&
@@ -355,12 +499,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 ();
@@ -408,23 +552,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)
 {
@@ -475,11 +617,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;
@@ -513,23 +651,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)
 	{
@@ -541,18 +673,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:
@@ -595,44 +735,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;
 
-      add (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, 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);
     }
 }
 
@@ -670,16 +813,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';
 
@@ -691,7 +839,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;
 
@@ -770,11 +918,7 @@ riscv_subset_list::parse (const char *arch, location_t loc)
 
   for (itr = subset_list->m_head; itr != NULL; itr = itr->next)
     {
-      subset_list->handle_implied_ext (
-	itr->name.c_str (),
-	itr->major_version,
-	itr->minor_version,
-	itr->explicit_version_p);
+      subset_list->handle_implied_ext (itr);
     }
 
   return subset_list;
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 15318b20ce0..556d138f06e 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4524,7 +4524,7 @@ case "${target}" in
 		;;
 
 	riscv*-*-*)
-		supported_defaults="abi arch tune riscv_attribute"
+		supported_defaults="abi arch tune riscv_attribute isa_spec"
 
 		case "${target}" in
 		riscv-* | riscv32*) xlen=32 ;;
@@ -4532,6 +4532,21 @@ case "${target}" in
 		*) echo "Unsupported RISC-V target ${target}" 1>&2; exit 1 ;;
 		esac
 
+		case "${with_isa_spec}" in
+		""|default|2.2)
+			tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_2P2"
+			;;
+		20191213 | 201912)
+			tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20191213"
+			;;
+		20190608 | 201906)
+			tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20190608"
+			;;
+		*)
+			echo "--with-isa-spec only accept 2.2, 20191213, 201912, 20190608 or 201906" 1>&2
+			exit 1
+		esac
+
 		case "${with_riscv_attribute}" in
 		yes)
 			tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=1"
diff --git a/gcc/config.in b/gcc/config.in
index b7c3107bfe3..6fae7b769b8 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -643,6 +643,18 @@
 #endif
 
 
+/* Define if your assembler supports -misa-spec=. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MISA_SPEC
+#endif
+
+
+/* Define if your assembler supports -march=rv*_zifencei. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MARCH_ZIFENCEI
+#endif
+
+
 /* Define if your assembler supports relocs needed by -fpic. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_SMALL_PIC_RELOCS
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index de8ac0e038d..0b83f17b78f 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -39,6 +39,16 @@ enum riscv_code_model {
 };
 extern enum riscv_code_model riscv_cmodel;
 
+enum riscv_isa_spec_class {
+  ISA_SPEC_CLASS_NONE,
+
+  ISA_SPEC_CLASS_2P2,
+  ISA_SPEC_CLASS_20190608,
+  ISA_SPEC_CLASS_20191213
+};
+
+extern enum riscv_isa_spec_class riscv_isa_spec;
+
 /* Keep this list in sync with define_attr "tune" in riscv.md.  */
 enum riscv_microarchitecture_type {
   generic,
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 172c7ca7c98..9dec5415eab 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -70,13 +70,20 @@ extern const char *riscv_default_mtune (int argc, const char **argv);
 #define TARGET_64BIT           (__riscv_xlen == 64)
 #endif /* IN_LIBGCC2 */
 
+#ifdef HAVE_AS_MISA_SPEC
+#define ASM_MISA_SPEC ""
+#else
+#define ASM_MISA_SPEC "%{misa-spec=*}"
+#endif
+
 #undef ASM_SPEC
 #define ASM_SPEC "\
 %(subtarget_asm_debugging_spec) \
 %{" FPIE_OR_FPIC_SPEC ":-fpic} \
 %{march=*} \
 %{mabi=*} \
-%(subtarget_asm_spec)"
+%(subtarget_asm_spec)" \
+ASM_MISA_SPEC
 
 #undef DRIVER_SELF_SPECS
 #define DRIVER_SELF_SPECS					\
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index ca2fc7c8021..9cf14bb1bae 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -186,3 +186,20 @@ long riscv_stack_protector_guard_offset = 0
 
 TargetVariable
 int riscv_zi_subext
+
+Enum
+Name(isa_spec_class) Type(enum riscv_isa_spec_class)
+Supported ISA specs (for use with the -misa-spec= option):
+
+EnumValue
+Enum(isa_spec_class) String(2.2) Value(ISA_SPEC_CLASS_2P2)
+
+EnumValue
+Enum(isa_spec_class) String(20190608) Value(ISA_SPEC_CLASS_20190608)
+
+EnumValue
+Enum(isa_spec_class) String(20191213) Value(ISA_SPEC_CLASS_20191213)
+
+misa-spec=
+Target Report RejectNegative Joined Enum(isa_spec_class) Var(riscv_isa_spec) Init(TARGET_DEFAULT_ISA_SPEC)
+Set the version of RISC-V ISA spec.
diff --git a/gcc/configure b/gcc/configure
index dbda4415a17..ba69f73ed9c 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -28136,6 +28136,68 @@ if test $gcc_cv_as_riscv_attribute = yes; then
 
 $as_echo "#define HAVE_AS_RISCV_ATTRIBUTE 1" >>confdefs.h
 
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -misa-spec= support" >&5
+$as_echo_n "checking assembler for -misa-spec= support... " >&6; }
+if ${gcc_cv_as_riscv_isa_spec+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_riscv_isa_spec=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -misa-spec=2.2 -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_riscv_isa_spec=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_isa_spec" >&5
+$as_echo "$gcc_cv_as_riscv_isa_spec" >&6; }
+if test $gcc_cv_as_riscv_isa_spec = yes; then
+
+$as_echo "#define HAVE_AS_MISA_SPEC 1" >>confdefs.h
+
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -march=rv32i_zifencei support" >&5
+$as_echo_n "checking assembler for -march=rv32i_zifencei support... " >&6; }
+if ${gcc_cv_as_riscv_march_zifencei+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_riscv_march_zifencei=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -march=rv32i_zifencei -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_riscv_march_zifencei=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_march_zifencei" >&5
+$as_echo "$gcc_cv_as_riscv_march_zifencei" >&6; }
+if test $gcc_cv_as_riscv_march_zifencei = yes; then
+
+$as_echo "#define HAVE_AS_MARCH_ZIFENCEI 1" >>confdefs.h
+
 fi
 
     ;;
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 08f3034986e..28d96d1cba3 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5111,6 +5111,16 @@ configured with --enable-newlib-nano-formatted-io.])
       [.attribute stack_align,4],,
       [AC_DEFINE(HAVE_AS_RISCV_ATTRIBUTE, 1,
 	  [Define if your assembler supports .attribute.])])
+    gcc_GAS_CHECK_FEATURE([-misa-spec= support],
+      gcc_cv_as_riscv_isa_spec,,
+      [-misa-spec=2.2],,,
+      [AC_DEFINE(HAVE_AS_MISA_SPEC, 1,
+		 [Define if the assembler understands -misa-spec=.])])
+    gcc_GAS_CHECK_FEATURE([-march=rv32i_zifencei support],
+      gcc_cv_as_riscv_march_zifencei,,
+      [-march=rv32i_zifencei],,,
+      [AC_DEFINE(HAVE_AS_MARCH_ZIFENCEI, 1,
+		 [Define if the assembler understands -march=rv*_zifencei.])])
     ;;
     s390*-*-*)
     gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
diff --git a/gcc/testsuite/gcc.target/riscv/arch-10.c b/gcc/testsuite/gcc.target/riscv/arch-10.c
new file mode 100644
index 00000000000..47dbda333c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-10.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32gf2 -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-error "Extension `f' appear more than one time." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-11.c b/gcc/testsuite/gcc.target/riscv/arch-11.c
new file mode 100644
index 00000000000..129d8f72804
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-11.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32g_zicsr2 -mabi=ilp32" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-9.c b/gcc/testsuite/gcc.target/riscv/arch-9.c
new file mode 100644
index 00000000000..74e64103563
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-9.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32g2 -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-warning "version of `g` will be omitted, please specify version for individual extension." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-11.c b/gcc/testsuite/gcc.target/riscv/attribute-11.c
index a8649508b2f..98bd8d4da42 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-11.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-11.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32id -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32id -mabi=ilp32 -misa-spec=2.2" } */
 int foo()
 {
 }
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-12.c b/gcc/testsuite/gcc.target/riscv/attribute-12.c
index df27fc3234d..44fccad3b29 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-12.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-12.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32ifd -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32ifd -mabi=ilp32 -misa-spec=2.2" } */
 int foo()
 {
 }
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-13.c b/gcc/testsuite/gcc.target/riscv/attribute-13.c
index 1e860013293..1b8f93ceaaf 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-13.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-13.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32if3d -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32if3d -mabi=ilp32 -misa-spec=2.2" } */
 int foo()
 {
 }
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-14.c b/gcc/testsuite/gcc.target/riscv/attribute-14.c
index 48456277152..2591c1f92f6 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-14.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-14.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32if -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32if -mabi=ilp32 -misa-spec=20190608" } */
 int foo()
 {
 }
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_f2p0_zicsr2p0\"" } } */
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_f2p2_zicsr2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-15.c b/gcc/testsuite/gcc.target/riscv/attribute-15.c
new file mode 100644
index 00000000000..9cae1a27a6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-15.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=2.2" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_m2p0_a2p0_f2p0_d2p0_c2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-16.c b/gcc/testsuite/gcc.target/riscv/attribute-16.c
new file mode 100644
index 00000000000..f090363b979
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-16.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=20190608" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_m2p0_a2p0_f2p2_d2p2_c2p0_zicsr2p0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-17.c b/gcc/testsuite/gcc.target/riscv/attribute-17.c
new file mode 100644
index 00000000000..19ef540b5b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-17.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=20191213" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-6.c b/gcc/testsuite/gcc.target/riscv/attribute-6.c
deleted file mode 100644
index c75b0d62200..00000000000
--- a/gcc/testsuite/gcc.target/riscv/attribute-6.c
+++ /dev/null
@@ -1,6 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32g2p0 -mabi=ilp32" } */
-int foo()
-{
-}
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_m2p0_a2p0_f2p0_d2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-8.c b/gcc/testsuite/gcc.target/riscv/attribute-8.c
index 1d161763805..90f5a4022a0 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-8.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-8.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xv5_xabc -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xabc_xv5 -mabi=ilp32" } */
 int foo()
 {
 }
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xv5p0_xabc2p0\"" } } */
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xabc_xv5p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-9.c b/gcc/testsuite/gcc.target/riscv/attribute-9.c
index bc4db0eb647..4598872f0a6 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-9.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-9.c
@@ -3,4 +3,4 @@
 int foo()
 {
 }
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_sabc2p0_xbar2p0\"" } } */
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_sabc_xbar\"" } } */
-- 
2.29.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions
  2020-11-13  7:29 ` [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions Kito Cheng
@ 2020-11-13  7:34   ` Kito Cheng
  2020-12-15  8:08   ` Gerald Pfeifer
  1 sibling, 0 replies; 12+ messages in thread
From: Kito Cheng @ 2020-11-13  7:34 UTC (permalink / raw)
  To: Kito Cheng; +Cc: GCC Patches

Oh I was dry-run but cc to gcc patches accidentally, but the patch set
is right, it just sent twice the same patch set.



On Fri, Nov 13, 2020 at 3:29 PM Kito Cheng <kito.cheng@sifive.com> wrote:
>
>  - New option -misa-spec support: -misa-spec=[2.2|20190608|20191213] and
>    corresponding configuration option --with-isa-spec.
>
>  - Current default ISA spec set to 2.2, but we intend to bump this to
>    20191213 or later in next release.
>
> gcc/ChangeLog:
>
>         * common/config/riscv/riscv-common.c (riscv_ext_version): New.
>         (riscv_ext_version_table): Ditto.
>         (get_default_version): Ditto.
>         (riscv_subset_t::implied_p): New field.
>         (riscv_subset_t::riscv_subset_t): Init implied_p.
>         (riscv_subset_list::add): New.
>         (riscv_subset_list::handle_implied_ext): Pass riscv_subset_t
>         instead of separated argument.
>         (riscv_subset_list::to_string): Handle zifencei and zicsr, and
>         omit version if version is unknown.
>         (riscv_subset_list::parsing_subset_version): New argument `ext`,
>         remove default_major_version and default_minor_version, get
>         default version info via get_default_version.
>         (riscv_subset_list::parse_std_ext): Update argument for
>         parsing_subset_version calls.
>         Handle 2.2 ISA spec, always enable zicsr and zifencei, they are
>         included in baseline ISA in that time.
>         (riscv_subset_list::parse_multiletter_ext): Update argument for
>         `parsing_subset_version` and `add` calls.
>         (riscv_subset_list::parse): Adjust argument for
>         riscv_subset_list::handle_implied_ext call.
>         * config.gcc (riscv*-*-*): Handle --with-isa-spec=.
>         * config.in (HAVE_AS_MISA_SPEC): New.
>         (HAVE_AS_MARCH_ZIFENCEI): Ditto.
>         * config/riscv/riscv-opts.h (riscv_isa_spec_class): New.
>         (riscv_isa_spec): Ditto.
>         * config/riscv/riscv.h (HAVE_AS_MISA_SPEC): New.
>         (ASM_SPEC): Pass -misa-spec if gas supported.
>         * config/riscv/riscv.opt (riscv_isa_spec_class) New.
>         * configure.ac (HAVE_AS_MARCH_ZIFENCEI): New test.
>         (HAVE_AS_MISA_SPEC): Ditto.
>         * configure: Regen.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/riscv/arch-9.c: New.
>         * gcc.target/riscv/arch-10.c: Ditto.
>         * gcc.target/riscv/arch-11.c: Ditto.
>         * gcc.target/riscv/attribute-6.c: Remove, we don't support G
>         with version anymore.
>         * gcc.target/riscv/attribute-8.c: Reorder arch string to fit canonical
>         ordering.
>         * gcc.target/riscv/attribute-9.c: We don't emit version for
>         unknown extensions now.
>         * gcc.target/riscv/attribute-11.c: Add -misa-spec=2.2 flags.
>         * gcc.target/riscv/attribute-12.c: Ditto.
>         * gcc.target/riscv/attribute-13.c: Ditto.
>         * gcc.target/riscv/attribute-14.c: Ditto.
>         * gcc.target/riscv/attribute-15.c: New.
>         * gcc.target/riscv/attribute-16.c: Ditto.
>         * gcc.target/riscv/attribute-17.c: Ditto.
> ---
>  gcc/common/config/riscv/riscv-common.c        | 288 +++++++++++++-----
>  gcc/config.gcc                                |  17 +-
>  gcc/config.in                                 |  12 +
>  gcc/config/riscv/riscv-opts.h                 |  10 +
>  gcc/config/riscv/riscv.h                      |   9 +-
>  gcc/config/riscv/riscv.opt                    |  17 ++
>  gcc/configure                                 |  62 ++++
>  gcc/configure.ac                              |  10 +
>  gcc/testsuite/gcc.target/riscv/arch-10.c      |   6 +
>  gcc/testsuite/gcc.target/riscv/arch-11.c      |   5 +
>  gcc/testsuite/gcc.target/riscv/arch-9.c       |   6 +
>  gcc/testsuite/gcc.target/riscv/attribute-11.c |   2 +-
>  gcc/testsuite/gcc.target/riscv/attribute-12.c |   2 +-
>  gcc/testsuite/gcc.target/riscv/attribute-13.c |   2 +-
>  gcc/testsuite/gcc.target/riscv/attribute-14.c |   4 +-
>  gcc/testsuite/gcc.target/riscv/attribute-15.c |   6 +
>  gcc/testsuite/gcc.target/riscv/attribute-16.c |   6 +
>  gcc/testsuite/gcc.target/riscv/attribute-17.c |   6 +
>  gcc/testsuite/gcc.target/riscv/attribute-6.c  |   6 -
>  gcc/testsuite/gcc.target/riscv/attribute-8.c  |   4 +-
>  gcc/testsuite/gcc.target/riscv/attribute-9.c  |   2 +-
>  21 files changed, 394 insertions(+), 88 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/arch-10.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/arch-11.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/arch-9.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-15.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-16.c
>  create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-17.c
>  delete mode 100644 gcc/testsuite/gcc.target/riscv/attribute-6.c
>
> diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
> index ca88ca1dacd..ea2d516bb36 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.  */
> @@ -62,6 +63,58 @@ static const riscv_implied_info_t riscv_implied_info[] =
>    {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) \
> @@ -91,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,
> @@ -124,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)
>  {
>  }
>
> @@ -274,8 +329,31 @@ subset_cmp (const std::string &a, const std::string &b)
>
>  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;
>
> @@ -286,6 +364,7 @@ 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)
> @@ -330,6 +409,43 @@ riscv_subset_list::add (const char *subset, int major_version,
>    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.  */
>
> @@ -340,10 +456,38 @@ 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 don't recognize zicsr.  */
> +  skip_zicsr = true;
> +#endif
> +#ifndef HAVE_AS_MARCH_ZIFENCE
> +  /* Skip since older binutils don't recognize zifencei,
> +     we mad a mistake that is binutils 2.35 support zicsr but not support
> +     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 &&
> @@ -355,12 +499,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 ();
> @@ -408,23 +552,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)
>  {
> @@ -475,11 +617,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;
> @@ -513,23 +651,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)
>         {
> @@ -541,18 +673,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:
> @@ -595,44 +735,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;
>
> -      add (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, 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);
>      }
>  }
>
> @@ -670,16 +813,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';
>
> @@ -691,7 +839,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;
>
> @@ -770,11 +918,7 @@ riscv_subset_list::parse (const char *arch, location_t loc)
>
>    for (itr = subset_list->m_head; itr != NULL; itr = itr->next)
>      {
> -      subset_list->handle_implied_ext (
> -       itr->name.c_str (),
> -       itr->major_version,
> -       itr->minor_version,
> -       itr->explicit_version_p);
> +      subset_list->handle_implied_ext (itr);
>      }
>
>    return subset_list;
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 15318b20ce0..556d138f06e 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -4524,7 +4524,7 @@ case "${target}" in
>                 ;;
>
>         riscv*-*-*)
> -               supported_defaults="abi arch tune riscv_attribute"
> +               supported_defaults="abi arch tune riscv_attribute isa_spec"
>
>                 case "${target}" in
>                 riscv-* | riscv32*) xlen=32 ;;
> @@ -4532,6 +4532,21 @@ case "${target}" in
>                 *) echo "Unsupported RISC-V target ${target}" 1>&2; exit 1 ;;
>                 esac
>
> +               case "${with_isa_spec}" in
> +               ""|default|2.2)
> +                       tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_2P2"
> +                       ;;
> +               20191213 | 201912)
> +                       tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20191213"
> +                       ;;
> +               20190608 | 201906)
> +                       tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20190608"
> +                       ;;
> +               *)
> +                       echo "--with-isa-spec only accept 2.2, 20191213, 201912, 20190608 or 201906" 1>&2
> +                       exit 1
> +               esac
> +
>                 case "${with_riscv_attribute}" in
>                 yes)
>                         tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=1"
> diff --git a/gcc/config.in b/gcc/config.in
> index b7c3107bfe3..6fae7b769b8 100644
> --- a/gcc/config.in
> +++ b/gcc/config.in
> @@ -643,6 +643,18 @@
>  #endif
>
>
> +/* Define if your assembler supports -misa-spec=. */
> +#ifndef USED_FOR_TARGET
> +#undef HAVE_AS_MISA_SPEC
> +#endif
> +
> +
> +/* Define if your assembler supports -march=rv*_zifencei. */
> +#ifndef USED_FOR_TARGET
> +#undef HAVE_AS_MARCH_ZIFENCEI
> +#endif
> +
> +
>  /* Define if your assembler supports relocs needed by -fpic. */
>  #ifndef USED_FOR_TARGET
>  #undef HAVE_AS_SMALL_PIC_RELOCS
> diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
> index de8ac0e038d..0b83f17b78f 100644
> --- a/gcc/config/riscv/riscv-opts.h
> +++ b/gcc/config/riscv/riscv-opts.h
> @@ -39,6 +39,16 @@ enum riscv_code_model {
>  };
>  extern enum riscv_code_model riscv_cmodel;
>
> +enum riscv_isa_spec_class {
> +  ISA_SPEC_CLASS_NONE,
> +
> +  ISA_SPEC_CLASS_2P2,
> +  ISA_SPEC_CLASS_20190608,
> +  ISA_SPEC_CLASS_20191213
> +};
> +
> +extern enum riscv_isa_spec_class riscv_isa_spec;
> +
>  /* Keep this list in sync with define_attr "tune" in riscv.md.  */
>  enum riscv_microarchitecture_type {
>    generic,
> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
> index 172c7ca7c98..9dec5415eab 100644
> --- a/gcc/config/riscv/riscv.h
> +++ b/gcc/config/riscv/riscv.h
> @@ -70,13 +70,20 @@ extern const char *riscv_default_mtune (int argc, const char **argv);
>  #define TARGET_64BIT           (__riscv_xlen == 64)
>  #endif /* IN_LIBGCC2 */
>
> +#ifdef HAVE_AS_MISA_SPEC
> +#define ASM_MISA_SPEC ""
> +#else
> +#define ASM_MISA_SPEC "%{misa-spec=*}"
> +#endif
> +
>  #undef ASM_SPEC
>  #define ASM_SPEC "\
>  %(subtarget_asm_debugging_spec) \
>  %{" FPIE_OR_FPIC_SPEC ":-fpic} \
>  %{march=*} \
>  %{mabi=*} \
> -%(subtarget_asm_spec)"
> +%(subtarget_asm_spec)" \
> +ASM_MISA_SPEC
>
>  #undef DRIVER_SELF_SPECS
>  #define DRIVER_SELF_SPECS                                      \
> diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
> index ca2fc7c8021..9cf14bb1bae 100644
> --- a/gcc/config/riscv/riscv.opt
> +++ b/gcc/config/riscv/riscv.opt
> @@ -186,3 +186,20 @@ long riscv_stack_protector_guard_offset = 0
>
>  TargetVariable
>  int riscv_zi_subext
> +
> +Enum
> +Name(isa_spec_class) Type(enum riscv_isa_spec_class)
> +Supported ISA specs (for use with the -misa-spec= option):
> +
> +EnumValue
> +Enum(isa_spec_class) String(2.2) Value(ISA_SPEC_CLASS_2P2)
> +
> +EnumValue
> +Enum(isa_spec_class) String(20190608) Value(ISA_SPEC_CLASS_20190608)
> +
> +EnumValue
> +Enum(isa_spec_class) String(20191213) Value(ISA_SPEC_CLASS_20191213)
> +
> +misa-spec=
> +Target Report RejectNegative Joined Enum(isa_spec_class) Var(riscv_isa_spec) Init(TARGET_DEFAULT_ISA_SPEC)
> +Set the version of RISC-V ISA spec.
> diff --git a/gcc/configure b/gcc/configure
> index dbda4415a17..ba69f73ed9c 100755
> --- a/gcc/configure
> +++ b/gcc/configure
> @@ -28136,6 +28136,68 @@ if test $gcc_cv_as_riscv_attribute = yes; then
>
>  $as_echo "#define HAVE_AS_RISCV_ATTRIBUTE 1" >>confdefs.h
>
> +fi
> +
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -misa-spec= support" >&5
> +$as_echo_n "checking assembler for -misa-spec= support... " >&6; }
> +if ${gcc_cv_as_riscv_isa_spec+:} false; then :
> +  $as_echo_n "(cached) " >&6
> +else
> +  gcc_cv_as_riscv_isa_spec=no
> +  if test x$gcc_cv_as != x; then
> +    $as_echo '' > conftest.s
> +    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -misa-spec=2.2 -o conftest.o conftest.s >&5'
> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> +  (eval $ac_try) 2>&5
> +  ac_status=$?
> +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; }
> +    then
> +       gcc_cv_as_riscv_isa_spec=yes
> +    else
> +      echo "configure: failed program was" >&5
> +      cat conftest.s >&5
> +    fi
> +    rm -f conftest.o conftest.s
> +  fi
> +fi
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_isa_spec" >&5
> +$as_echo "$gcc_cv_as_riscv_isa_spec" >&6; }
> +if test $gcc_cv_as_riscv_isa_spec = yes; then
> +
> +$as_echo "#define HAVE_AS_MISA_SPEC 1" >>confdefs.h
> +
> +fi
> +
> +    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -march=rv32i_zifencei support" >&5
> +$as_echo_n "checking assembler for -march=rv32i_zifencei support... " >&6; }
> +if ${gcc_cv_as_riscv_march_zifencei+:} false; then :
> +  $as_echo_n "(cached) " >&6
> +else
> +  gcc_cv_as_riscv_march_zifencei=no
> +  if test x$gcc_cv_as != x; then
> +    $as_echo '' > conftest.s
> +    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -march=rv32i_zifencei -o conftest.o conftest.s >&5'
> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> +  (eval $ac_try) 2>&5
> +  ac_status=$?
> +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; }
> +    then
> +       gcc_cv_as_riscv_march_zifencei=yes
> +    else
> +      echo "configure: failed program was" >&5
> +      cat conftest.s >&5
> +    fi
> +    rm -f conftest.o conftest.s
> +  fi
> +fi
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_march_zifencei" >&5
> +$as_echo "$gcc_cv_as_riscv_march_zifencei" >&6; }
> +if test $gcc_cv_as_riscv_march_zifencei = yes; then
> +
> +$as_echo "#define HAVE_AS_MARCH_ZIFENCEI 1" >>confdefs.h
> +
>  fi
>
>      ;;
> diff --git a/gcc/configure.ac b/gcc/configure.ac
> index 08f3034986e..28d96d1cba3 100644
> --- a/gcc/configure.ac
> +++ b/gcc/configure.ac
> @@ -5111,6 +5111,16 @@ configured with --enable-newlib-nano-formatted-io.])
>        [.attribute stack_align,4],,
>        [AC_DEFINE(HAVE_AS_RISCV_ATTRIBUTE, 1,
>           [Define if your assembler supports .attribute.])])
> +    gcc_GAS_CHECK_FEATURE([-misa-spec= support],
> +      gcc_cv_as_riscv_isa_spec,,
> +      [-misa-spec=2.2],,,
> +      [AC_DEFINE(HAVE_AS_MISA_SPEC, 1,
> +                [Define if the assembler understands -misa-spec=.])])
> +    gcc_GAS_CHECK_FEATURE([-march=rv32i_zifencei support],
> +      gcc_cv_as_riscv_march_zifencei,,
> +      [-march=rv32i_zifencei],,,
> +      [AC_DEFINE(HAVE_AS_MARCH_ZIFENCEI, 1,
> +                [Define if the assembler understands -march=rv*_zifencei.])])
>      ;;
>      s390*-*-*)
>      gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
> diff --git a/gcc/testsuite/gcc.target/riscv/arch-10.c b/gcc/testsuite/gcc.target/riscv/arch-10.c
> new file mode 100644
> index 00000000000..47dbda333c9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/arch-10.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -march=rv32gf2 -mabi=ilp32" } */
> +int foo()
> +{
> +}
> +/* { dg-error "Extension `f' appear more than one time." "" { target *-*-* } 0 } */
> diff --git a/gcc/testsuite/gcc.target/riscv/arch-11.c b/gcc/testsuite/gcc.target/riscv/arch-11.c
> new file mode 100644
> index 00000000000..129d8f72804
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/arch-11.c
> @@ -0,0 +1,5 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -march=rv32g_zicsr2 -mabi=ilp32" } */
> +int foo()
> +{
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/arch-9.c b/gcc/testsuite/gcc.target/riscv/arch-9.c
> new file mode 100644
> index 00000000000..74e64103563
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/arch-9.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -march=rv32g2 -mabi=ilp32" } */
> +int foo()
> +{
> +}
> +/* { dg-warning "version of `g` will be omitted, please specify version for individual extension." "" { target *-*-* } 0 } */
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-11.c b/gcc/testsuite/gcc.target/riscv/attribute-11.c
> index a8649508b2f..98bd8d4da42 100644
> --- a/gcc/testsuite/gcc.target/riscv/attribute-11.c
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-11.c
> @@ -1,5 +1,5 @@
>  /* { dg-do compile } */
> -/* { dg-options "-O -mriscv-attribute -march=rv32id -mabi=ilp32" } */
> +/* { dg-options "-O -mriscv-attribute -march=rv32id -mabi=ilp32 -misa-spec=2.2" } */
>  int foo()
>  {
>  }
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-12.c b/gcc/testsuite/gcc.target/riscv/attribute-12.c
> index df27fc3234d..44fccad3b29 100644
> --- a/gcc/testsuite/gcc.target/riscv/attribute-12.c
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-12.c
> @@ -1,5 +1,5 @@
>  /* { dg-do compile } */
> -/* { dg-options "-O -mriscv-attribute -march=rv32ifd -mabi=ilp32" } */
> +/* { dg-options "-O -mriscv-attribute -march=rv32ifd -mabi=ilp32 -misa-spec=2.2" } */
>  int foo()
>  {
>  }
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-13.c b/gcc/testsuite/gcc.target/riscv/attribute-13.c
> index 1e860013293..1b8f93ceaaf 100644
> --- a/gcc/testsuite/gcc.target/riscv/attribute-13.c
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-13.c
> @@ -1,5 +1,5 @@
>  /* { dg-do compile } */
> -/* { dg-options "-O -mriscv-attribute -march=rv32if3d -mabi=ilp32" } */
> +/* { dg-options "-O -mriscv-attribute -march=rv32if3d -mabi=ilp32 -misa-spec=2.2" } */
>  int foo()
>  {
>  }
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-14.c b/gcc/testsuite/gcc.target/riscv/attribute-14.c
> index 48456277152..2591c1f92f6 100644
> --- a/gcc/testsuite/gcc.target/riscv/attribute-14.c
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-14.c
> @@ -1,6 +1,6 @@
>  /* { dg-do compile } */
> -/* { dg-options "-O -mriscv-attribute -march=rv32if -mabi=ilp32" } */
> +/* { dg-options "-O -mriscv-attribute -march=rv32if -mabi=ilp32 -misa-spec=20190608" } */
>  int foo()
>  {
>  }
> -/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_f2p0_zicsr2p0\"" } } */
> +/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_f2p2_zicsr2p0\"" } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-15.c b/gcc/testsuite/gcc.target/riscv/attribute-15.c
> new file mode 100644
> index 00000000000..9cae1a27a6f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-15.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=2.2" } */
> +int foo()
> +{
> +}
> +/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_m2p0_a2p0_f2p0_d2p0_c2p0\"" } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-16.c b/gcc/testsuite/gcc.target/riscv/attribute-16.c
> new file mode 100644
> index 00000000000..f090363b979
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-16.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=20190608" } */
> +int foo()
> +{
> +}
> +/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_m2p0_a2p0_f2p2_d2p2_c2p0_zicsr2p0" } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-17.c b/gcc/testsuite/gcc.target/riscv/attribute-17.c
> new file mode 100644
> index 00000000000..19ef540b5b9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-17.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=20191213" } */
> +int foo()
> +{
> +}
> +/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0" } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-6.c b/gcc/testsuite/gcc.target/riscv/attribute-6.c
> deleted file mode 100644
> index c75b0d62200..00000000000
> --- a/gcc/testsuite/gcc.target/riscv/attribute-6.c
> +++ /dev/null
> @@ -1,6 +0,0 @@
> -/* { dg-do compile } */
> -/* { dg-options "-O -mriscv-attribute -march=rv32g2p0 -mabi=ilp32" } */
> -int foo()
> -{
> -}
> -/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_m2p0_a2p0_f2p0_d2p0\"" } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-8.c b/gcc/testsuite/gcc.target/riscv/attribute-8.c
> index 1d161763805..90f5a4022a0 100644
> --- a/gcc/testsuite/gcc.target/riscv/attribute-8.c
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-8.c
> @@ -1,6 +1,6 @@
>  /* { dg-do compile } */
> -/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xv5_xabc -mabi=ilp32" } */
> +/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xabc_xv5 -mabi=ilp32" } */
>  int foo()
>  {
>  }
> -/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xv5p0_xabc2p0\"" } } */
> +/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xabc_xv5p0\"" } } */
> diff --git a/gcc/testsuite/gcc.target/riscv/attribute-9.c b/gcc/testsuite/gcc.target/riscv/attribute-9.c
> index bc4db0eb647..4598872f0a6 100644
> --- a/gcc/testsuite/gcc.target/riscv/attribute-9.c
> +++ b/gcc/testsuite/gcc.target/riscv/attribute-9.c
> @@ -3,4 +3,4 @@
>  int foo()
>  {
>  }
> -/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_sabc2p0_xbar2p0\"" } } */
> +/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_sabc_xbar\"" } } */
> --
> 2.29.2
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/3] RISC-V: Support zicsr and zifencei extension for -march.
  2020-11-13  7:29 ` [PATCH 2/3] RISC-V: Support zicsr and zifencei extension for -march Kito Cheng
@ 2020-11-17 21:23   ` Jim Wilson
  2020-11-18  5:44     ` Kito Cheng
  0 siblings, 1 reply; 12+ messages in thread
From: Jim Wilson @ 2020-11-17 21:23 UTC (permalink / raw)
  To: Kito Cheng; +Cc: GCC Patches, Kito Cheng

On Thu, Nov 12, 2020 at 11:29 PM Kito Cheng <kito.cheng@sifive.com> wrote:

>  - CSR related instructions and fence instructions has to be splitted from
>    baseline ISA, zicsr and zifencei are corresponding sub-extension.
>

It is actually only fence.i that is split off.  fence is still part of the
base ISA.  This is why it is called zifencei.

diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
> index 738556539f6..2aaa8e96451 100644
> --- a/gcc/config/riscv/riscv.c
> +++ b/gcc/config/riscv/riscv.c
> @@ -3337,6 +3337,9 @@ riscv_memmodel_needs_amo_acquire (enum memmodel
> model)
>  static bool
>  riscv_memmodel_needs_release_fence (enum memmodel model)
>  {
> +  if (!TARGET_ZIFENCEI)
> +    return false;
> +
>    switch (model)
>      {
>        case MEMMODEL_ACQ_REL:
>

This part looks wrong, as riscv_memmodel_needs_release_fence is only used
for fence instructions, not for fence.i.

> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index f15bad3b29e..756b35fb8c0 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -1543,19 +1543,20 @@
>                      LCT_NORMAL, VOIDmode, operands[0], Pmode,
>                      operands[1], Pmode, const0_rtx, Pmode);
>  #else
> -  emit_insn (gen_fence_i ());
> +  if (TARGET_ZIFENCEI)
> +    emit_insn (gen_fence_i ());
>  #endif
>    DONE;
>  })
>
>  (define_insn "fence"
>    [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
> -  ""
> +  "TARGET_ZIFENCEI"
>    "%|fence%-")
>
>  (define_insn "fence_i"
>    [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
> -  ""
> +  "TARGET_ZIFENCEI"
>    "fence.i")
>
>  ;;
>

The fence_i and clear_cache patterns are OK.  The fence pattern change is
wrong.

You didn't change sync.md, but it only uses fence, so it needs no change.

Jim

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/3] RISC-V: Support zicsr and zifencei extension for -march.
  2020-11-17 21:23   ` Jim Wilson
@ 2020-11-18  5:44     ` Kito Cheng
  0 siblings, 0 replies; 12+ messages in thread
From: Kito Cheng @ 2020-11-18  5:44 UTC (permalink / raw)
  To: Jim Wilson; +Cc: Kito Cheng, GCC Patches

>>  - CSR related instructions and fence instructions has to be splitted from
>>    baseline ISA, zicsr and zifencei are corresponding sub-extension.
>
>
> It is actually only fence.i that is split off.  fence is still part of the base ISA.  This is why it is called zifencei.

Oh...I didn't notice that, thanks for the review.


>> diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
>> index 738556539f6..2aaa8e96451 100644
>> --- a/gcc/config/riscv/riscv.c
>> +++ b/gcc/config/riscv/riscv.c
>> @@ -3337,6 +3337,9 @@ riscv_memmodel_needs_amo_acquire (enum memmodel model)
>>  static bool
>>  riscv_memmodel_needs_release_fence (enum memmodel model)
>>  {
>> +  if (!TARGET_ZIFENCEI)
>> +    return false;
>> +
>>    switch (model)
>>      {
>>        case MEMMODEL_ACQ_REL:
>
>
> This part looks wrong, as riscv_memmodel_needs_release_fence is only used for fence instructions, not for fence.i.
>>
>> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
>> index f15bad3b29e..756b35fb8c0 100644
>> --- a/gcc/config/riscv/riscv.md
>> +++ b/gcc/config/riscv/riscv.md
>> @@ -1543,19 +1543,20 @@
>>                      LCT_NORMAL, VOIDmode, operands[0], Pmode,
>>                      operands[1], Pmode, const0_rtx, Pmode);
>>  #else
>> -  emit_insn (gen_fence_i ());
>> +  if (TARGET_ZIFENCEI)
>> +    emit_insn (gen_fence_i ());
>>  #endif
>>    DONE;
>>  })
>>
>>  (define_insn "fence"
>>    [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
>> -  ""
>> +  "TARGET_ZIFENCEI"
>>    "%|fence%-")
>>
>>  (define_insn "fence_i"
>>    [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
>> -  ""
>> +  "TARGET_ZIFENCEI"
>>    "fence.i")
>>
>>  ;;
>
>
> The fence_i and clear_cache patterns are OK.  The fence pattern change is wrong.
>
> You didn't change sync.md, but it only uses fence, so it needs no change.
>
> Jim
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions
  2020-11-13  7:29 ` [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions Kito Cheng
  2020-11-13  7:34   ` Kito Cheng
@ 2020-12-15  8:08   ` Gerald Pfeifer
  2020-12-17  3:44     ` Kito Cheng
  1 sibling, 1 reply; 12+ messages in thread
From: Gerald Pfeifer @ 2020-12-15  8:08 UTC (permalink / raw)
  To: Kito Cheng; +Cc: gcc-patches, kito.cheng

On Fri, 13 Nov 2020, Kito Cheng wrote:
>  - New option -misa-spec support: -misa-spec=[2.2|20190608|20191213] and
>    corresponding configuration option --with-isa-spec.

I noticed https://gcc.gnu.org/gcc-11/changes.html is currently empty.

Are you planning to add updates for the GCC 11 release?  (It may be
useful to add them as they happen, so they we won't miss them and
also for the benefit of users tracking development.)

Gerald

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions
  2020-12-15  8:08   ` Gerald Pfeifer
@ 2020-12-17  3:44     ` Kito Cheng
  0 siblings, 0 replies; 12+ messages in thread
From: Kito Cheng @ 2020-12-17  3:44 UTC (permalink / raw)
  To: Gerald Pfeifer; +Cc: Kito Cheng, GCC Patches

Hi Gerald:

Thanks for notifying me, we'll update that page soon :)

On Tue, Dec 15, 2020 at 4:08 PM Gerald Pfeifer <gerald@pfeifer.com> wrote:
>
> On Fri, 13 Nov 2020, Kito Cheng wrote:
> >  - New option -misa-spec support: -misa-spec=[2.2|20190608|20191213] and
> >    corresponding configuration option --with-isa-spec.
>
> I noticed https://gcc.gnu.org/gcc-11/changes.html is currently empty.
>
> Are you planning to add updates for the GCC 11 release?  (It may be
> useful to add them as they happen, so they we won't miss them and
> also for the benefit of users tracking development.)
>
> Gerald

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions
  2020-11-17 21:29     ` Jim Wilson
@ 2020-11-18  5:44       ` Kito Cheng
  0 siblings, 0 replies; 12+ messages in thread
From: Kito Cheng @ 2020-11-18  5:44 UTC (permalink / raw)
  To: Jim Wilson; +Cc: Kito Cheng, GCC Patches

On Wed, Nov 18, 2020 at 5:29 AM Jim Wilson <jimw@sifive.com> wrote:
>
> On Thu, Nov 12, 2020 at 11:28 PM Kito Cheng <kito.cheng@sifive.com> wrote:
>>
>> +#ifndef HAVE_AS_MARCH_ZIFENCE
>> +  /* Skip since older binutils don't recognize zifencei,
>> +     we mad a mistake that is binutils 2.35 support zicsr but not support
>> +     zifencei.  */
>> +  skip_zifencei = true;
>> +#endif
>
>
> I'd suggest something like "Skip since older binutils doesn't recognize zifencei, we made a mistake in that binutils 2.35 supports zicsr but not zifencei."

Thanks for suggestions :)

>>
>> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
>> index 172c7ca7c98..9dec5415eab 100644
>> --- a/gcc/config/riscv/riscv.h
>> +++ b/gcc/config/riscv/riscv.h
>> @@ -70,13 +70,20 @@ extern const char *riscv_default_mtune (int argc, const char **argv);
>>  #define TARGET_64BIT           (__riscv_xlen == 64)
>>  #endif /* IN_LIBGCC2 */
>>
>> +#ifdef HAVE_AS_MISA_SPEC
>> +#define ASM_MISA_SPEC ""
>> +#else
>> +#define ASM_MISA_SPEC "%{misa-spec=*}"
>> +#endif
>
>
> This is backwards.  We do want to pass -misa-spec to the assembler if it supports it.  Or maybe you meant ifndef?

Oh, it should be ifndef here.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions
  2020-11-13  7:27   ` [PATCH 3/3] " Kito Cheng
@ 2020-11-17 21:29     ` Jim Wilson
  2020-11-18  5:44       ` Kito Cheng
  0 siblings, 1 reply; 12+ messages in thread
From: Jim Wilson @ 2020-11-17 21:29 UTC (permalink / raw)
  To: Kito Cheng; +Cc: GCC Patches, Kito Cheng

On Thu, Nov 12, 2020 at 11:28 PM Kito Cheng <kito.cheng@sifive.com> wrote:

> +#ifndef HAVE_AS_MARCH_ZIFENCE
> +  /* Skip since older binutils don't recognize zifencei,
> +     we mad a mistake that is binutils 2.35 support zicsr but not support
> +     zifencei.  */
> +  skip_zifencei = true;
> +#endif
>

I'd suggest something like "Skip since older binutils doesn't recognize
zifencei, we made a mistake in that binutils 2.35 supports zicsr but not
zifencei."

> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
> index 172c7ca7c98..9dec5415eab 100644
> --- a/gcc/config/riscv/riscv.h
> +++ b/gcc/config/riscv/riscv.h
> @@ -70,13 +70,20 @@ extern const char *riscv_default_mtune (int argc,
> const char **argv);
>  #define TARGET_64BIT           (__riscv_xlen == 64)
>  #endif /* IN_LIBGCC2 */
>
> +#ifdef HAVE_AS_MISA_SPEC
> +#define ASM_MISA_SPEC ""
> +#else
> +#define ASM_MISA_SPEC "%{misa-spec=*}"
> +#endif
>

This is backwards.  We do want to pass -misa-spec to the assembler if it
supports it.  Or maybe you meant ifndef?

Jim

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions
  2020-11-13  7:27 ` Kito Cheng
@ 2020-11-13  7:27   ` Kito Cheng
  2020-11-17 21:29     ` Jim Wilson
  0 siblings, 1 reply; 12+ messages in thread
From: Kito Cheng @ 2020-11-13  7:27 UTC (permalink / raw)
  To: gcc-patches, kito.cheng; +Cc: Kito Cheng

 - New option -misa-spec support: -misa-spec=[2.2|20190608|20191213] and
   corresponding configuration option --with-isa-spec.

 - Current default ISA spec set to 2.2, but we intend to bump this to
   20191213 or later in next release.

gcc/ChangeLog:

	* common/config/riscv/riscv-common.c (riscv_ext_version): New.
	(riscv_ext_version_table): Ditto.
	(get_default_version): Ditto.
	(riscv_subset_t::implied_p): New field.
	(riscv_subset_t::riscv_subset_t): Init implied_p.
	(riscv_subset_list::add): New.
	(riscv_subset_list::handle_implied_ext): Pass riscv_subset_t
	instead of separated argument.
	(riscv_subset_list::to_string): Handle zifencei and zicsr, and
	omit version if version is unknown.
	(riscv_subset_list::parsing_subset_version): New argument `ext`,
	remove default_major_version and default_minor_version, get
	default version info via get_default_version.
	(riscv_subset_list::parse_std_ext): Update argument for
	parsing_subset_version calls.
	Handle 2.2 ISA spec, always enable zicsr and zifencei, they are
	included in baseline ISA in that time.
	(riscv_subset_list::parse_multiletter_ext): Update argument for
	`parsing_subset_version` and `add` calls.
	(riscv_subset_list::parse): Adjust argument for
	riscv_subset_list::handle_implied_ext call.
	* config.gcc (riscv*-*-*): Handle --with-isa-spec=.
	* config.in (HAVE_AS_MISA_SPEC): New.
	(HAVE_AS_MARCH_ZIFENCEI): Ditto.
	* config/riscv/riscv-opts.h (riscv_isa_spec_class): New.
	(riscv_isa_spec): Ditto.
	* config/riscv/riscv.h (HAVE_AS_MISA_SPEC): New.
	(ASM_SPEC): Pass -misa-spec if gas supported.
	* config/riscv/riscv.opt (riscv_isa_spec_class) New.
	* configure.ac (HAVE_AS_MARCH_ZIFENCEI): New test.
	(HAVE_AS_MISA_SPEC): Ditto.
	* configure: Regen.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/arch-9.c: New.
	* gcc.target/riscv/arch-10.c: Ditto.
	* gcc.target/riscv/arch-11.c: Ditto.
	* gcc.target/riscv/attribute-6.c: Remove, we don't support G
	with version anymore.
	* gcc.target/riscv/attribute-8.c: Reorder arch string to fit canonical
	ordering.
	* gcc.target/riscv/attribute-9.c: We don't emit version for
	unknown extensions now.
	* gcc.target/riscv/attribute-11.c: Add -misa-spec=2.2 flags.
	* gcc.target/riscv/attribute-12.c: Ditto.
	* gcc.target/riscv/attribute-13.c: Ditto.
	* gcc.target/riscv/attribute-14.c: Ditto.
	* gcc.target/riscv/attribute-15.c: New.
	* gcc.target/riscv/attribute-16.c: Ditto.
	* gcc.target/riscv/attribute-17.c: Ditto.
---
 gcc/common/config/riscv/riscv-common.c        | 288 +++++++++++++-----
 gcc/config.gcc                                |  17 +-
 gcc/config.in                                 |  12 +
 gcc/config/riscv/riscv-opts.h                 |  10 +
 gcc/config/riscv/riscv.h                      |   9 +-
 gcc/config/riscv/riscv.opt                    |  17 ++
 gcc/configure                                 |  62 ++++
 gcc/configure.ac                              |  10 +
 gcc/testsuite/gcc.target/riscv/arch-10.c      |   6 +
 gcc/testsuite/gcc.target/riscv/arch-11.c      |   5 +
 gcc/testsuite/gcc.target/riscv/arch-9.c       |   6 +
 gcc/testsuite/gcc.target/riscv/attribute-11.c |   2 +-
 gcc/testsuite/gcc.target/riscv/attribute-12.c |   2 +-
 gcc/testsuite/gcc.target/riscv/attribute-13.c |   2 +-
 gcc/testsuite/gcc.target/riscv/attribute-14.c |   4 +-
 gcc/testsuite/gcc.target/riscv/attribute-15.c |   6 +
 gcc/testsuite/gcc.target/riscv/attribute-16.c |   6 +
 gcc/testsuite/gcc.target/riscv/attribute-17.c |   6 +
 gcc/testsuite/gcc.target/riscv/attribute-6.c  |   6 -
 gcc/testsuite/gcc.target/riscv/attribute-8.c  |   4 +-
 gcc/testsuite/gcc.target/riscv/attribute-9.c  |   2 +-
 21 files changed, 394 insertions(+), 88 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-11.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-9.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-15.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-16.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-17.c
 delete mode 100644 gcc/testsuite/gcc.target/riscv/attribute-6.c

diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c
index ca88ca1dacd..ea2d516bb36 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.  */
@@ -62,6 +63,58 @@ static const riscv_implied_info_t riscv_implied_info[] =
   {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) \
@@ -91,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,
@@ -124,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)
 {
 }
 
@@ -274,8 +329,31 @@ subset_cmp (const std::string &a, const std::string &b)
 
 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;
 
@@ -286,6 +364,7 @@ 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)
@@ -330,6 +409,43 @@ riscv_subset_list::add (const char *subset, int major_version,
   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.  */
 
@@ -340,10 +456,38 @@ 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 don't recognize zicsr.  */
+  skip_zicsr = true;
+#endif
+#ifndef HAVE_AS_MARCH_ZIFENCE
+  /* Skip since older binutils don't recognize zifencei,
+     we mad a mistake that is binutils 2.35 support zicsr but not support
+     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 &&
@@ -355,12 +499,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 ();
@@ -408,23 +552,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)
 {
@@ -475,11 +617,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;
@@ -513,23 +651,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)
 	{
@@ -541,18 +673,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:
@@ -595,44 +735,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;
 
-      add (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, 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);
     }
 }
 
@@ -670,16 +813,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';
 
@@ -691,7 +839,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;
 
@@ -770,11 +918,7 @@ riscv_subset_list::parse (const char *arch, location_t loc)
 
   for (itr = subset_list->m_head; itr != NULL; itr = itr->next)
     {
-      subset_list->handle_implied_ext (
-	itr->name.c_str (),
-	itr->major_version,
-	itr->minor_version,
-	itr->explicit_version_p);
+      subset_list->handle_implied_ext (itr);
     }
 
   return subset_list;
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 15318b20ce0..556d138f06e 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4524,7 +4524,7 @@ case "${target}" in
 		;;
 
 	riscv*-*-*)
-		supported_defaults="abi arch tune riscv_attribute"
+		supported_defaults="abi arch tune riscv_attribute isa_spec"
 
 		case "${target}" in
 		riscv-* | riscv32*) xlen=32 ;;
@@ -4532,6 +4532,21 @@ case "${target}" in
 		*) echo "Unsupported RISC-V target ${target}" 1>&2; exit 1 ;;
 		esac
 
+		case "${with_isa_spec}" in
+		""|default|2.2)
+			tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_2P2"
+			;;
+		20191213 | 201912)
+			tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20191213"
+			;;
+		20190608 | 201906)
+			tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20190608"
+			;;
+		*)
+			echo "--with-isa-spec only accept 2.2, 20191213, 201912, 20190608 or 201906" 1>&2
+			exit 1
+		esac
+
 		case "${with_riscv_attribute}" in
 		yes)
 			tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=1"
diff --git a/gcc/config.in b/gcc/config.in
index b7c3107bfe3..6fae7b769b8 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -643,6 +643,18 @@
 #endif
 
 
+/* Define if your assembler supports -misa-spec=. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MISA_SPEC
+#endif
+
+
+/* Define if your assembler supports -march=rv*_zifencei. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MARCH_ZIFENCEI
+#endif
+
+
 /* Define if your assembler supports relocs needed by -fpic. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_SMALL_PIC_RELOCS
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index de8ac0e038d..0b83f17b78f 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -39,6 +39,16 @@ enum riscv_code_model {
 };
 extern enum riscv_code_model riscv_cmodel;
 
+enum riscv_isa_spec_class {
+  ISA_SPEC_CLASS_NONE,
+
+  ISA_SPEC_CLASS_2P2,
+  ISA_SPEC_CLASS_20190608,
+  ISA_SPEC_CLASS_20191213
+};
+
+extern enum riscv_isa_spec_class riscv_isa_spec;
+
 /* Keep this list in sync with define_attr "tune" in riscv.md.  */
 enum riscv_microarchitecture_type {
   generic,
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 172c7ca7c98..9dec5415eab 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -70,13 +70,20 @@ extern const char *riscv_default_mtune (int argc, const char **argv);
 #define TARGET_64BIT           (__riscv_xlen == 64)
 #endif /* IN_LIBGCC2 */
 
+#ifdef HAVE_AS_MISA_SPEC
+#define ASM_MISA_SPEC ""
+#else
+#define ASM_MISA_SPEC "%{misa-spec=*}"
+#endif
+
 #undef ASM_SPEC
 #define ASM_SPEC "\
 %(subtarget_asm_debugging_spec) \
 %{" FPIE_OR_FPIC_SPEC ":-fpic} \
 %{march=*} \
 %{mabi=*} \
-%(subtarget_asm_spec)"
+%(subtarget_asm_spec)" \
+ASM_MISA_SPEC
 
 #undef DRIVER_SELF_SPECS
 #define DRIVER_SELF_SPECS					\
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index ca2fc7c8021..9cf14bb1bae 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -186,3 +186,20 @@ long riscv_stack_protector_guard_offset = 0
 
 TargetVariable
 int riscv_zi_subext
+
+Enum
+Name(isa_spec_class) Type(enum riscv_isa_spec_class)
+Supported ISA specs (for use with the -misa-spec= option):
+
+EnumValue
+Enum(isa_spec_class) String(2.2) Value(ISA_SPEC_CLASS_2P2)
+
+EnumValue
+Enum(isa_spec_class) String(20190608) Value(ISA_SPEC_CLASS_20190608)
+
+EnumValue
+Enum(isa_spec_class) String(20191213) Value(ISA_SPEC_CLASS_20191213)
+
+misa-spec=
+Target Report RejectNegative Joined Enum(isa_spec_class) Var(riscv_isa_spec) Init(TARGET_DEFAULT_ISA_SPEC)
+Set the version of RISC-V ISA spec.
diff --git a/gcc/configure b/gcc/configure
index dbda4415a17..ba69f73ed9c 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -28136,6 +28136,68 @@ if test $gcc_cv_as_riscv_attribute = yes; then
 
 $as_echo "#define HAVE_AS_RISCV_ATTRIBUTE 1" >>confdefs.h
 
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -misa-spec= support" >&5
+$as_echo_n "checking assembler for -misa-spec= support... " >&6; }
+if ${gcc_cv_as_riscv_isa_spec+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_riscv_isa_spec=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -misa-spec=2.2 -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_riscv_isa_spec=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_isa_spec" >&5
+$as_echo "$gcc_cv_as_riscv_isa_spec" >&6; }
+if test $gcc_cv_as_riscv_isa_spec = yes; then
+
+$as_echo "#define HAVE_AS_MISA_SPEC 1" >>confdefs.h
+
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -march=rv32i_zifencei support" >&5
+$as_echo_n "checking assembler for -march=rv32i_zifencei support... " >&6; }
+if ${gcc_cv_as_riscv_march_zifencei+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_riscv_march_zifencei=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -march=rv32i_zifencei -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_riscv_march_zifencei=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_march_zifencei" >&5
+$as_echo "$gcc_cv_as_riscv_march_zifencei" >&6; }
+if test $gcc_cv_as_riscv_march_zifencei = yes; then
+
+$as_echo "#define HAVE_AS_MARCH_ZIFENCEI 1" >>confdefs.h
+
 fi
 
     ;;
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 08f3034986e..28d96d1cba3 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5111,6 +5111,16 @@ configured with --enable-newlib-nano-formatted-io.])
       [.attribute stack_align,4],,
       [AC_DEFINE(HAVE_AS_RISCV_ATTRIBUTE, 1,
 	  [Define if your assembler supports .attribute.])])
+    gcc_GAS_CHECK_FEATURE([-misa-spec= support],
+      gcc_cv_as_riscv_isa_spec,,
+      [-misa-spec=2.2],,,
+      [AC_DEFINE(HAVE_AS_MISA_SPEC, 1,
+		 [Define if the assembler understands -misa-spec=.])])
+    gcc_GAS_CHECK_FEATURE([-march=rv32i_zifencei support],
+      gcc_cv_as_riscv_march_zifencei,,
+      [-march=rv32i_zifencei],,,
+      [AC_DEFINE(HAVE_AS_MARCH_ZIFENCEI, 1,
+		 [Define if the assembler understands -march=rv*_zifencei.])])
     ;;
     s390*-*-*)
     gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
diff --git a/gcc/testsuite/gcc.target/riscv/arch-10.c b/gcc/testsuite/gcc.target/riscv/arch-10.c
new file mode 100644
index 00000000000..47dbda333c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-10.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32gf2 -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-error "Extension `f' appear more than one time." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-11.c b/gcc/testsuite/gcc.target/riscv/arch-11.c
new file mode 100644
index 00000000000..129d8f72804
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-11.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32g_zicsr2 -mabi=ilp32" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-9.c b/gcc/testsuite/gcc.target/riscv/arch-9.c
new file mode 100644
index 00000000000..74e64103563
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-9.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32g2 -mabi=ilp32" } */
+int foo()
+{
+}
+/* { dg-warning "version of `g` will be omitted, please specify version for individual extension." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-11.c b/gcc/testsuite/gcc.target/riscv/attribute-11.c
index a8649508b2f..98bd8d4da42 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-11.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-11.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32id -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32id -mabi=ilp32 -misa-spec=2.2" } */
 int foo()
 {
 }
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-12.c b/gcc/testsuite/gcc.target/riscv/attribute-12.c
index df27fc3234d..44fccad3b29 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-12.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-12.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32ifd -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32ifd -mabi=ilp32 -misa-spec=2.2" } */
 int foo()
 {
 }
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-13.c b/gcc/testsuite/gcc.target/riscv/attribute-13.c
index 1e860013293..1b8f93ceaaf 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-13.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-13.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32if3d -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32if3d -mabi=ilp32 -misa-spec=2.2" } */
 int foo()
 {
 }
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-14.c b/gcc/testsuite/gcc.target/riscv/attribute-14.c
index 48456277152..2591c1f92f6 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-14.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-14.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32if -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32if -mabi=ilp32 -misa-spec=20190608" } */
 int foo()
 {
 }
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_f2p0_zicsr2p0\"" } } */
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_f2p2_zicsr2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-15.c b/gcc/testsuite/gcc.target/riscv/attribute-15.c
new file mode 100644
index 00000000000..9cae1a27a6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-15.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=2.2" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_m2p0_a2p0_f2p0_d2p0_c2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-16.c b/gcc/testsuite/gcc.target/riscv/attribute-16.c
new file mode 100644
index 00000000000..f090363b979
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-16.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=20190608" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_m2p0_a2p0_f2p2_d2p2_c2p0_zicsr2p0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-17.c b/gcc/testsuite/gcc.target/riscv/attribute-17.c
new file mode 100644
index 00000000000..19ef540b5b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-17.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mriscv-attribute -march=rv32gc -mabi=ilp32 -misa-spec=20191213" } */
+int foo()
+{
+}
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-6.c b/gcc/testsuite/gcc.target/riscv/attribute-6.c
deleted file mode 100644
index c75b0d62200..00000000000
--- a/gcc/testsuite/gcc.target/riscv/attribute-6.c
+++ /dev/null
@@ -1,6 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32g2p0 -mabi=ilp32" } */
-int foo()
-{
-}
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_m2p0_a2p0_f2p0_d2p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-8.c b/gcc/testsuite/gcc.target/riscv/attribute-8.c
index 1d161763805..90f5a4022a0 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-8.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-8.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
-/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xv5_xabc -mabi=ilp32" } */
+/* { dg-options "-O -mriscv-attribute -march=rv32i2p0xabc_xv5 -mabi=ilp32" } */
 int foo()
 {
 }
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xv5p0_xabc2p0\"" } } */
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_xabc_xv5p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-9.c b/gcc/testsuite/gcc.target/riscv/attribute-9.c
index bc4db0eb647..4598872f0a6 100644
--- a/gcc/testsuite/gcc.target/riscv/attribute-9.c
+++ b/gcc/testsuite/gcc.target/riscv/attribute-9.c
@@ -3,4 +3,4 @@
 int foo()
 {
 }
-/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_sabc2p0_xbar2p0\"" } } */
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p0_sabc_xbar\"" } } */
-- 
2.29.2


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-12-17  3:44 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-13  7:29 [PATCH 0/3] RISC-V: Support version controling for ISA standard extensions Kito Cheng
2020-11-13  7:29 ` [PATCH 1/3] RISC-V: Handle implied extension in canonical ordering Kito Cheng
2020-11-13  7:29 ` [PATCH 2/3] RISC-V: Support zicsr and zifencei extension for -march Kito Cheng
2020-11-17 21:23   ` Jim Wilson
2020-11-18  5:44     ` Kito Cheng
2020-11-13  7:29 ` [PATCH 3/3] RISC-V: Support version controling for ISA standard extensions Kito Cheng
2020-11-13  7:34   ` Kito Cheng
2020-12-15  8:08   ` Gerald Pfeifer
2020-12-17  3:44     ` Kito Cheng
     [not found] <Kito Cheng <kito.cheng@sifive.com>
2020-11-13  7:27 ` Kito Cheng
2020-11-13  7:27   ` [PATCH 3/3] " Kito Cheng
2020-11-17 21:29     ` Jim Wilson
2020-11-18  5:44       ` Kito Cheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).