[PATCH 3/7] RISC-V: Support new GAS options and configure options to set ISA versions.

Nelson Chu nelson.chu@sifive.com
Sat Apr 18 11:18:15 GMT 2020


CC Palmer.

Thanks
Nelson

On Sat, Apr 18, 2020 at 7:08 PM Nelson Chu <nelson.chu@sifive.com> wrote:
>
> For now, we can only use the GAS option -march and ELF arch attribute to set
> the versions for ISA extensions.  It seems not so friendly for user.
> Therefore, we support new GAS options and configure options to make it easiler
> for user.
>
> New Assembler Options,
>
> * -misa-spec = [2p0|2p1|2p2|20190608|20191213]
> You can simply choose the ISA spec by this option, and then assembler will set
> the version for the standard extensions if you don’t set in the ELF arch
> attributes or -march option.
>
> * -mriscv-isa-version = <ISA-string>
> The syntax of <ISA-string> is same as -march option, but without rv32 or rv64
> prefix.  There are two reasons that you may need this option,
>
> 1. Some versions of extensions defined in the ISA spec are not matched to the
> toolchain’s implementation.  For example, V-ext is defined to version 0.7 in
> ISA spec, but we only have implementations for 0.8 and 0.9.  Therefore, you
> have to use this option to choose the correct version for V-ext.
>
> 2. You want to update the version for the specific standard extensions if the
> version are not set in the ELF arch attributes and -march option.
>
> New Default Configure Options,
>
> * --with-arch = <ISA-string>
> The syntax of <ISA-string> is same as -march option.  Assembler will check this
> if -march option and ELF arch attributes aren’t set.
>
> * --with-isa-spec = [2p0|2p1|2p2|20190608|20191213]
> The syntax is same as -misa-spec option.  Assembler will check this if
> -misa-spec option isn’t set.
>
> * --with-riscv-isa-version = <ISA-string>
> The syntax of <ISA-string> is same as -mriscv-isa-version option.  Assembler
> will check this if -mriscv-isa-version option isn’t set.
>
> The Priority of these options,
>
> * ELF arch attributes > Assembler options > Default configure options
> * For GAS options, -march > -mriscv-isa-version > -misa-spec
> * For configure options, --with-arch > --with-riscv-isa-version > --with-isa-spec
>
>         gas/
>         * config/tc-riscv.c (DEFAULT_ARCH_WITH_EXT, DEFAULT_ISA_SPEC,
>         DEFAULT_RISCV_ISA_VERSION): Default configure option settings.
>         You can set them by new configure options --with-arch,
>         --with-isa-spec and --with-riscv-isa-version.
>
>         (default_arch_with_ext, default_isa_spec, default_riscv_isa_version):
>         const char strings which are used to set the ISA extensions. You can
>         use gas options -march (or ELF build attributes), and new gas options
>         -misa-spec and -mriscv-isa-version to set them, respectively.  If the
>         gas options and attributes are not set, then assembler will check the
>         default configure option settings.
>
>         (ext_version_hash): The hash table used to handle the extensions
>         with versions.
>         (init_ext_version_hash): Initialize the ext_version_hash according
>         to riscv_ext_version_table.
>
>         (riscv_get_default_ext_version): The callback function of
>         riscv_parse_subset_t.  According to the choosed ISA spec,
>         get the default version for the specific extension.
>
>         (riscv_set_arch): Add new bfd_boolean parameter update_version.
>         The update_version is TRUE means we just want to update the version
>         according to default_riscv_isa_version, so don't call the
>         riscv_release_subset_list to reset the subset list.  Pass two new
>         arguments to riscv_parse_subset, one is update_version mentioned above,
>         the other is the default_isa_spec.  We use the default_isa_spec to
>         choose the default version for the extensions.
>
>         (enum options, struct option md_longopts): Add new gas options,
>         -misa-spec and -mriscv-isa-version.
>         (md_parse_option): Handle the above new gas options.
>         (riscv_after_parse_args): Call init_ext_version_hash to initialize the
>         ext_version_hash, and then always call riscv_set_arch twice to set and
>         update the architecture with versions according to default_arch_with_ext
>         and default_riscv_isa_version.
>         (s_riscv_attribute): Same as riscv_after_parse_args, we need to call
>         riscv_set_arch twice.
>
>         * testsuite/gas/riscv/attribute-01.d: Add -misa-spec=2p2.  Set 0p0
>         as default version for x extensions.
>         * testsuite/gas/riscv/attribute-02.d: Likewise.
>         * testsuite/gas/riscv/attribute-03.d: Likewise.
>         * testsuite/gas/riscv/attribute-04.d: Likewise.
>         * testsuite/gas/riscv/attribute-05.d: Likewise.
>         * testsuite/gas/riscv/attribute-06.d: Likewise.
>         * testsuite/gas/riscv/attribute-07.d: Likewise.
>         * testsuite/gas/riscv/attribute-08.d: Likewise.
>         * testsuite/gas/riscv/attribute-09.d: New testcase.  For i-ext, we
>         already set the version 1p9 in elf attribute, so -misa-spec and
>         -mriscv-isa-version don't update the version to 2p0 and 2p1.
>         For f-ext, we don't set the version to it, so use the default version
>         2p0 according to the ISA spec 2p2.  For v-ext, the default version is
>         0p7 according to ISA spec 2p2, but we use -mriscv-isa-version to update
>         it to 0p9.  For a-ext, it isn't enabled by -march or elf attribute, so
>         we don't update it's version even if -mriscv-isa-version is set.
>         As for the zicsr extension, it is defined in the lastest ISA spec
>         rather than 2p2, so set it's version to 0p0.
>         * testsuite/gas/riscv/attribute-09.s: Likewise.
>         * testsuite/gas/riscv/attribute-10.d: New testcase.  The version of
>         zicsr is 2p0 according to ISA spec 20191213.
>         * testsuite/gas/riscv/attribute-11.d: New testcase.  We can also update
>         the z* extension by -mriscv-isa-version.
>
>         * configure.ac: Add new configure options, --with-arch, --with-isa-spec
>         and --with-riscv-isa-version.
>         * configure: Regenerated.
>         * config.in: Regenerated.
>
>         bfd/
>         * elfxx-riscv.h (struct riscv_subset_t): Add new bfd_boolean field
>         use_default_version, which is used to record whether the default
>         version is used for the extension.
>         (struct riscv_parse_subset_t): Add new callback function
>         get_default_version.  It is used to find the default version for
>         the specific extension.
>         (riscv_add_subset, riscv_parse_subset): Update function declaration.
>
>         * elfxx-riscv.c (riscv_parsing_subset_version): Remove the parameters
>         default_major_version and default_minor_version.  Add new bfd_boolean
>         parameter *use_default_version.  Set it to TRUE if we need to call
>         the callback rps->get_default_version to find the default version.
>
>         (riscv_update_subset_version): Only update the version of existin
>         standard extensions and their Z* sub extensions, if -mriscv-isa-version
>         or --with-riscv-isa-version are set, and the default version are used.
>
>         (riscv_add_subset): New parameter use_default_version.  Record whether
>         the default version is used.  riscv_update_subset_version only update
>         the version of extensions if the default versions are used.
>
>         (riscv_parse_subset): Add two parameters isa_spec_name and
>         update_version.  Pass them to riscv_parse_std_ext and
>         riscv_parse_prefixed_ext.  The string set by -mriscv-isa-version or
>         --with-riscv-isa-version doesn't have to start with rv32/rv64, so
>         skip the checking if update_version is TRUE.
>         (riscv_parse_std_ext): If update_version is TRUE, then we just call
>         riscv_update_subset_version to update the default version.  Otherwise,
>         Call rps->get_default_version if we fail to find the default version
>         in riscv_parsing_subset_version, and then call riscv_add_subset to add
>         the subset into subset list.
>         (riscv_parse_prefixed_ext): Same as the riscv_parse_std_ext.
>         (riscv_std_z_ext_strtab): Support Zicsr extensions.
>
>         * elfnn-riscv.c (riscv_merge_std_ext, riscv_merge_multi_letter_ext):
>         Updated.  Pass update_version as FALSE to riscv_add_subset, the
>         update_version is only needed for assembler, not linker.
>         (riscv_merge_arch_attr_info): The callback function get_default_version
>         is only needed for assembler, so set it to NULL in linker.  Also, Pass
>         isa_spec_name as NULL and update_version as FALSE to riscv_parse_subset.
>
>         include/
>         * opcode/riscv.h (struct riscv_ext_version): New structure holds
>         version information for the specific ISA.
>
>         opcodes/
>         * riscv-opc.c (riscv_ext_version_table): The table used to store
>         all information about the supported spec and the corresponding ISA
>         versions.  Currently, only Zicsr is supported to verify the
>         correctness of Z sub extension settings.  Others will be supported
>         in the future patches.
> ---
>  bfd/elfnn-riscv.c                      |  24 ++-
>  bfd/elfxx-riscv.c                      | 350 ++++++++++++++++++++++++---------
>  bfd/elfxx-riscv.h                      |  12 +-
>  gas/config.in                          |   9 +
>  gas/config/tc-riscv.c                  | 128 +++++++++++-
>  gas/configure                          |  53 ++++-
>  gas/configure.ac                       |  35 +++-
>  gas/testsuite/gas/riscv/attribute-01.d |   2 +-
>  gas/testsuite/gas/riscv/attribute-02.d |   4 +-
>  gas/testsuite/gas/riscv/attribute-03.d |   4 +-
>  gas/testsuite/gas/riscv/attribute-04.d |   2 +-
>  gas/testsuite/gas/riscv/attribute-05.d |   2 +-
>  gas/testsuite/gas/riscv/attribute-06.d |   2 +-
>  gas/testsuite/gas/riscv/attribute-07.d |   2 +-
>  gas/testsuite/gas/riscv/attribute-08.d |   2 +-
>  gas/testsuite/gas/riscv/attribute-09.d |   6 +
>  gas/testsuite/gas/riscv/attribute-09.s |   1 +
>  gas/testsuite/gas/riscv/attribute-10.d |   6 +
>  gas/testsuite/gas/riscv/attribute-11.d |   6 +
>  include/opcode/riscv.h                 |  11 ++
>  opcodes/riscv-opc.c                    |  53 +++++
>  21 files changed, 585 insertions(+), 129 deletions(-)
>  create mode 100644 gas/testsuite/gas/riscv/attribute-09.d
>  create mode 100644 gas/testsuite/gas/riscv/attribute-09.s
>  create mode 100644 gas/testsuite/gas/riscv/attribute-10.d
>  create mode 100644 gas/testsuite/gas/riscv/attribute-11.d
>
> diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
> index 8fcb106..4ca49e0 100644
> --- a/bfd/elfnn-riscv.c
> +++ b/bfd/elfnn-riscv.c
> @@ -2802,7 +2802,7 @@ riscv_merge_std_ext (bfd *ibfd,
>    if (!riscv_i_or_e_p (ibfd, out_arch, out))
>      return FALSE;
>
> -  if (in->name[0] != out->name[0])
> +  if (strcasecmp (in->name, out->name) != 0)
>      {
>        /* TODO: We might allow merge 'i' with 'e'.  */
>        _bfd_error_handler
> @@ -2818,8 +2818,8 @@ riscv_merge_std_ext (bfd *ibfd,
>        return FALSE;
>      }
>    else
> -    riscv_add_subset (&merged_subsets,
> -                     in->name, in->major_version, in->minor_version);
> +    riscv_add_subset (&merged_subsets, in->name, in->major_version,
> +                     in->minor_version, FALSE);
>
>    in = in->next;
>    out = out->next;
> @@ -2848,7 +2848,7 @@ riscv_merge_std_ext (bfd *ibfd,
>
>        struct riscv_subset_t *merged = find_in ? find_in : find_out;
>        riscv_add_subset (&merged_subsets, merged->name,
> -                       merged->major_version, merged->minor_version);
> +                       merged->major_version, merged->minor_version, FALSE);
>      }
>
>    /* Skip all standard extensions.  */
> @@ -2917,14 +2917,14 @@ riscv_merge_multi_letter_ext (bfd *ibfd,
>         {
>           /* `in' comes before `out', append `in' and increment.  */
>           riscv_add_subset (&merged_subsets, in->name, in->major_version,
> -                           in->minor_version);
> +                           in->minor_version, FALSE);
>           in = in->next;
>         }
>        else if (cmp > 0)
>         {
>           /* `out' comes before `in', append `out' and increment.  */
>           riscv_add_subset (&merged_subsets, out->name, out->major_version,
> -                           out->minor_version);
> +                           out->minor_version, FALSE);
>           out = out->next;
>         }
>        else
> @@ -2938,7 +2938,7 @@ riscv_merge_multi_letter_ext (bfd *ibfd,
>             }
>
>           riscv_add_subset (&merged_subsets, out->name, out->major_version,
> -                           out->minor_version);
> +                           out->minor_version, FALSE);
>           out = out->next;
>           in = in->next;
>         }
> @@ -2952,7 +2952,7 @@ riscv_merge_multi_letter_ext (bfd *ibfd,
>      while (tail)
>        {
>         riscv_add_subset (&merged_subsets, tail->name, tail->major_version,
> -                         tail->minor_version);
> +                         tail->minor_version, FALSE);
>         tail = tail->next;
>        }
>    }
> @@ -2975,13 +2975,17 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
>    riscv_parse_subset_t rpe_in;
>    riscv_parse_subset_t rpe_out;
>
> +  /* Only assembler needs to check the default version of ISA, so just set
> +     the rpe_in.get_default_version and rpe_out.get_default_version to NULL.  */
>    rpe_in.subset_list = &in_subsets;
>    rpe_in.error_handler = _bfd_error_handler;
>    rpe_in.xlen = &xlen_in;
> +  rpe_in.get_default_version = NULL;
>
>    rpe_out.subset_list = &out_subsets;
>    rpe_out.error_handler = _bfd_error_handler;
>    rpe_out.xlen = &xlen_out;
> +  rpe_out.get_default_version = NULL;
>
>    if (in_arch == NULL && out_arch == NULL)
>      return NULL;
> @@ -2993,10 +2997,10 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
>      return in_arch;
>
>    /* Parse subset from arch string.  */
> -  if (!riscv_parse_subset (&rpe_in, in_arch))
> +  if (!riscv_parse_subset (&rpe_in, in_arch, NULL, FALSE))
>      return NULL;
>
> -  if (!riscv_parse_subset (&rpe_out, out_arch))
> +  if (!riscv_parse_subset (&rpe_out, out_arch, NULL, FALSE))
>      return NULL;
>
>    /* Checking XLEN.  */
> diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
> index b15fdee..3a6aaf3 100644
> --- a/bfd/elfxx-riscv.c
> +++ b/bfd/elfxx-riscv.c
> @@ -1025,9 +1025,8 @@ riscv_elf_add_sub_reloc (bfd *abfd,
>       `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.  */
> +     `std_ext_p`: True if parsing std extension.
> +     `use_default_version`: Set it to True if we need the default version.  */
>
>  static const char *
>  riscv_parsing_subset_version (riscv_parse_subset_t *rps,
> @@ -1035,17 +1034,16 @@ riscv_parsing_subset_version (riscv_parse_subset_t *rps,
>                               const char *p,
>                               unsigned *major_version,
>                               unsigned *minor_version,
> -                             unsigned default_major_version,
> -                             unsigned default_minor_version,
> -                             bfd_boolean std_ext_p)
> +                             bfd_boolean std_ext_p,
> +                             bfd_boolean *use_default_version)
>  {
>    bfd_boolean major_p = TRUE;
>    unsigned version = 0;
> -  unsigned major = 0;
> -  unsigned minor = 0;
>    char np;
>
> -  for (;*p; ++p)
> +  *major_version = 0;
> +  *minor_version = 0;
> +  for (; *p; ++p)
>      {
>        if (*p == 'p')
>         {
> @@ -1057,7 +1055,6 @@ riscv_parsing_subset_version (riscv_parse_subset_t *rps,
>               if (std_ext_p)
>                 {
>                   *major_version = version;
> -                 *minor_version = 0;
>                   return p;
>                 }
>               else
> @@ -1068,7 +1065,7 @@ riscv_parsing_subset_version (riscv_parse_subset_t *rps,
>                 }
>             }
>
> -         major = version;
> +         *major_version = version;
>           major_p = FALSE;
>           version = 0;
>         }
> @@ -1079,21 +1076,15 @@ riscv_parsing_subset_version (riscv_parse_subset_t *rps,
>      }
>
>    if (major_p)
> -    major = version;
> +    *major_version = version;
>    else
> -    minor = version;
> +    *minor_version = version;
>
> -  if (major == 0 && minor == 0)
> -    {
> -      /* We don't found any version string, use default version.  */
> -      *major_version = default_major_version;
> -      *minor_version = default_minor_version;
> -    }
> -  else
> -    {
> -      *major_version = major;
> -      *minor_version = minor;
> -    }
> +  /* We can not find any version in string, need to parse default version.  */
> +  if (use_default_version != NULL
> +      && *major_version == 0
> +      && *minor_version == 0)
> +    *use_default_version = TRUE;
>    return p;
>  }
>
> @@ -1106,6 +1097,41 @@ riscv_supported_std_ext (void)
>    return "mafdqlcbjtpvn";
>  }
>
> +/* Update the version of standard extensions and their Z* sub extensions
> +   if -mriscv-isa-version is set.  */
> +
> +static bfd_boolean
> +riscv_update_subset_version (riscv_parse_subset_t *rps,
> +                            const char *ext_with_version,
> +                            char *ext,
> +                             unsigned major_version,
> +                            unsigned minor_version,
> +                            bfd_boolean use_default_version)
> +{
> +  riscv_subset_t *subset = riscv_lookup_subset (rps->subset_list, ext);;
> +
> +  /* The extension doesn't exist, so just return.  */
> +  if (subset == NULL)
> +    return TRUE;
> +
> +  /* This means we can not find the version in the string.  */
> +  if (use_default_version)
> +    {
> +      rps->error_handler ("-mriscv-isa-version=%s: unexpected version "
> +                         "setting for subset `%s'", ext_with_version, ext);
> +      return FALSE;
> +    }
> +
> +  /* We only update the extension which use the default version.  */
> +  if (subset->use_default_version)
> +    {
> +      subset->major_version = major_version;
> +      subset->minor_version = minor_version;
> +    }
> +
> +  return TRUE;
> +}
> +
>  /* Parsing function for standard extensions.
>
>     Return Value:
> @@ -1114,46 +1140,95 @@ riscv_supported_std_ext (void)
>     Arguments:
>       `rps`: Hooks and status for parsing subset.
>       `march`: Full arch string.
> -     `p`: Curent parsing position.  */
> +     `p`: Curent parsing position.
> +     `isa_spec_name`: The ISA spec name.  We set the default ISA versions
> +     according to it.
> +     `update_version`: True if the -mriscv-isa-version is set, and we need
> +     to update the version for the existing extensions.  */
>
>  static const char *
>  riscv_parse_std_ext (riscv_parse_subset_t *rps,
> -                    const char *march, const char *p)
> +                    const char *march,
> +                    const char *p,
> +                    const char *isa_spec_name,
> +                    bfd_boolean update_version)
>  {
>    const char *all_std_exts = riscv_supported_std_ext ();
>    const char *std_exts = all_std_exts;
> -
>    unsigned major_version = 0;
>    unsigned minor_version = 0;
>    char std_ext = '\0';
> +  bfd_boolean use_default_version = FALSE;
>
>    /* First letter must start with i, e or g.  */
>    switch (*p)
>      {
>        case 'i':
> -       p++;
> -       p = riscv_parsing_subset_version (
> -             rps,
> -             march,
> -             p, &major_version, &minor_version,
> -             /* default_major_version= */ 2,
> -             /* default_minor_version= */ 0,
> -             /* std_ext_p= */TRUE);
> -       riscv_add_subset (rps->subset_list, "i", major_version, minor_version);
> +       p = riscv_parsing_subset_version (rps,
> +                                         march,
> +                                         ++p,
> +                                         &major_version,
> +                                         &minor_version,
> +                                         /* std_ext_p= */TRUE,
> +                                         &use_default_version);
> +
> +       /* Update the version for exsiting extension.  */
> +       if (update_version)
> +         {
> +           if (!riscv_update_subset_version (rps, march, "i",
> +                                             major_version,
> +                                             minor_version,
> +                                             use_default_version))
> +             return NULL;
> +           break;
> +         }
> +
> +       /* Find the default version if needed.  */
> +       if (use_default_version)
> +         rps->get_default_version ("i",
> +                                   isa_spec_name,
> +                                   &major_version,
> +                                   &minor_version);
> +       riscv_add_subset (rps->subset_list, "i", major_version, minor_version,
> +                         use_default_version);
>         break;
>
>        case 'e':
> -       p++;
> -       p = riscv_parsing_subset_version (
> -             rps,
> -             march,
> -             p, &major_version, &minor_version,
> -             /* default_major_version= */ 1,
> -             /* default_minor_version= */ 9,
> -             /* std_ext_p= */TRUE);
> -
> -       riscv_add_subset (rps->subset_list, "e", major_version, minor_version);
> -       riscv_add_subset (rps->subset_list, "i", 2, 0);
> +       p = riscv_parsing_subset_version (rps,
> +                                         march,
> +                                         ++p,
> +                                         &major_version,
> +                                         &minor_version,
> +                                         /* std_ext_p= */TRUE,
> +                                         &use_default_version);
> +
> +       /* Update the version for exsiting extension.  */
> +       if (update_version)
> +         {
> +           if (!riscv_update_subset_version (rps, march, "e",
> +                                             major_version,
> +                                             minor_version,
> +                                             use_default_version))
> +             return NULL;
> +           break;
> +         }
> +
> +       /* Find the default version if needed.  */
> +       if (use_default_version)
> +         rps->get_default_version ("e",
> +                                   isa_spec_name,
> +                                   &major_version,
> +                                   &minor_version);
> +       riscv_add_subset (rps->subset_list, "e", major_version, minor_version,
> +                         use_default_version);
> +
> +       /* i-ext must be enabled.  */
> +       rps->get_default_version ("i",
> +                                 isa_spec_name,
> +                                 &major_version,
> +                                 &minor_version);
> +       riscv_add_subset (rps->subset_list, "i", major_version, minor_version,
> +                         TRUE);
>
>         if (*rps->xlen > 32)
>           {
> @@ -1161,35 +1236,58 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
>                                 march, *rps->xlen);
>             return NULL;
>           }
> -
>         break;
>
>        case 'g':
> -       p++;
> -       p = riscv_parsing_subset_version (
> -             rps,
> -             march,
> -             p, &major_version, &minor_version,
> -             /* default_major_version= */ 2,
> -             /* default_minor_version= */ 0,
> -             /* std_ext_p= */TRUE);
> -       riscv_add_subset (rps->subset_list, "i", major_version, minor_version);
> +       /* The g-ext shouldn't has the version, so we just skip the setting if
> +          user set a version to it.  */
> +       p = riscv_parsing_subset_version (rps,
> +                                         march,
> +                                         ++p,
> +                                         &major_version,
> +                                         &minor_version,
> +                                         TRUE,
> +                                         &use_default_version);
> +
> +       /* Set the version of g in -mriscv-isa-version is meaningless,
> +          so just skip it.  */
> +       if (update_version)
> +         break;
> +
> +       /* i-ext must be enabled.  */
> +       rps->get_default_version ("i",
> +                                 isa_spec_name,
> +                                 &major_version,
> +                                 &minor_version);
> +       riscv_add_subset (rps->subset_list, "i", major_version, minor_version,
> +                         TRUE);
>
>         for ( ; *std_exts != 'q'; std_exts++)
>           {
>             const char subset[] = {*std_exts, '\0'};
> -           riscv_add_subset (
> -             rps->subset_list, subset, major_version, minor_version);
> +           rps->get_default_version (subset,
> +                                     isa_spec_name,
> +                                     &major_version,
> +                                     &minor_version);
> +           riscv_add_subset (rps->subset_list, subset, major_version,
> +                             minor_version, TRUE);
>           }
>         break;
>
>        default:
> -       rps->error_handler (
> -         "-march=%s: first ISA subset must be `e', `i' or `g'", march);
> -       return NULL;
> +       /* The first ISA subset of -mriscv-isa-version will not necessarily
> +          be e/i/g.  */
> +       if (!update_version)
> +         {
> +           rps->error_handler (
> +           "-march=%s: first ISA subset must be `e', `i' or `g'", march);
> +           return NULL;
> +         }
>      }
>
> -  while (*p)
> +  /* The riscv_parsing_subset_version may set `p` to NULL, so I think we should
> +     skip parsing the string if `p` is NULL or value of `p` is `\0`.  */
> +  while (p != NULL && *p != '\0')
>      {
>        char subset[2] = {0, 0};
>
> @@ -1218,21 +1316,37 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
>               march, *p);
>           return NULL;
>         }
> -
>        std_exts++;
>
> -      p++;
> -      p = riscv_parsing_subset_version (
> -           rps,
> -           march,
> -           p, &major_version, &minor_version,
> -           /* default_major_version= */ 2,
> -           /* default_minor_version= */ 0,
> -           /* std_ext_p= */TRUE);
> -
> +      use_default_version = FALSE;
>        subset[0] = std_ext;
> +      p = riscv_parsing_subset_version (rps,
> +                                       march,
> +                                       ++p,
> +                                       &major_version,
> +                                       &minor_version,
> +                                       TRUE,
> +                                       &use_default_version);
> +
> +      /* Update the version for exsiting extension.  */
> +      if (update_version)
> +       {
> +         if (!riscv_update_subset_version (rps, march, subset,
> +                                           major_version,
> +                                           minor_version,
> +                                           use_default_version))
> +           return NULL;
> +         continue;
> +       }
>
> -      riscv_add_subset (rps->subset_list, subset, major_version, minor_version);
> +      /* Find the default version if needed.  */
> +      if (use_default_version)
> +       rps->get_default_version (subset,
> +                                 isa_spec_name,
> +                                 &major_version,
> +                                 &minor_version);
> +      riscv_add_subset (rps->subset_list, subset, major_version, minor_version,
> +                       use_default_version);
>      }
>    return p;
>  }
> @@ -1272,21 +1386,28 @@ typedef struct riscv_parse_config
>  } riscv_parse_config_t;
>
>  /* Parse a generic prefixed extension.
> -   march: The full architecture string as passed in by "-march=...".
> -   p: Point from which to start parsing the -march string.
> -   config: What class of extensions to parse, predicate funcs,
> -   and strings to use in error reporting.  */
> +   `march`: The full architecture string as passed in by "-march=...".
> +   `p`: Point from which to start parsing the -march string.
> +   `config`: What class of extensions to parse, predicate funcs,
> +   and strings to use in error reporting.
> +   `isa_spec_name`: ISA spec name.  We set the default ISA versions
> +   according to it.
> +   `update_version`: True if the -mriscv-isa-version is set, and we need
> +   update the version for the existing extensions.  */
>
>  static const char *
>  riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
>                           const char *march,
>                           const char *p,
> -                         const riscv_parse_config_t *config)
> +                         const riscv_parse_config_t *config,
> +                         const char *isa_spec_name,
> +                         bfd_boolean update_version)
>  {
>    unsigned major_version = 0;
>    unsigned minor_version = 0;
>    const char *last_name;
>    riscv_isa_ext_class_t class;
> +  bfd_boolean use_default_version;
>
>    while (*p)
>      {
> @@ -1309,15 +1430,11 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
>        while (*++q != '\0' && *q != '_' && !ISDIGIT (*q))
>         ;
>
> +      use_default_version = FALSE;
>        end_of_version =
> -       riscv_parsing_subset_version (
> -         rps,
> -         march,
> -         q, &major_version, &minor_version,
> -         /* default_major_version= */ 2,
> -         /* default_minor_version= */ 0,
> -         /* std_ext_p= */FALSE);
> -
> +       riscv_parsing_subset_version (rps, march, q, &major_version,
> +                                     &minor_version, FALSE,
> +                                     &use_default_version);
>        *q = '\0';
>
>        /* Check that the name is valid.
> @@ -1335,10 +1452,11 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
>           return NULL;
>         }
>
> -      /* Check that the last item is not the same as this.  */
> +      /* Check that the last item is not the same as this.  Just skip this
> +        check when updating the version.  */
>        last_name = rps->subset_list->tail->name;
> -
> -      if (!strcasecmp (last_name, subset))
> +      if (!update_version
> +         && !strcasecmp (last_name, subset))
>         {
>           rps->error_handler ("-march=%s: Duplicate %s ISA extension: \'%s\'",
>                               march, config->prefix, subset);
> @@ -1357,7 +1475,30 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
>           return NULL;
>         }
>
> -      riscv_add_subset (rps->subset_list, subset, major_version, minor_version);
> +      if (update_version)
> +       {
> +         /* Update the version for exsiting extension.  */
> +         if (!riscv_update_subset_version (rps, march, subset,
> +                                           major_version,
> +                                           minor_version,
> +                                           use_default_version))
> +           {
> +             free (subset);
> +             return NULL;
> +           }
> +       }
> +      else
> +       {
> +         /* Find the default version if needed.  */
> +         if (use_default_version)
> +           rps->get_default_version (subset,
> +                                     isa_spec_name,
> +                                     &major_version,
> +                                     &minor_version);
> +         riscv_add_subset (rps->subset_list, subset, major_version,
> +                           minor_version, use_default_version);
> +       }
> +
>        free (subset);
>        p += end_of_version - subset;
>
> @@ -1384,7 +1525,7 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps,
>
>  static const char * const riscv_std_z_ext_strtab[] =
>    {
> -    NULL
> +    "zicsr", NULL
>    };
>
>  /* Same as `riscv_std_z_ext_strtab', but for S-class extensions.  */
> @@ -1457,11 +1598,17 @@ static const riscv_parse_config_t parse_config[] =
>
>     Arguments:
>       `rps`: Hooks and status for parsing subset.
> -     `arch`: Arch string.  */
> +     `arch`: Arch string.
> +     `isa_spec_name`: The ISA spec name.   We set the default ISA versions
> +     according to it.
> +     `update_version`: True if the -mriscv-isa-version is set, and we need
> +     update the version for the existing extensions.  */
>
>  bfd_boolean
>  riscv_parse_subset (riscv_parse_subset_t *rps,
> -                   const char *arch)
> +                   const char *arch,
> +                   const char *isa_spec_name,
> +                   bfd_boolean update_version)
>  {
>    const char *p = arch;
>    size_t i;
> @@ -1476,15 +1623,17 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
>        *rps->xlen = 64;
>        p += 4;
>      }
> -  else
> +  else if (!update_version)
>      {
> +      /* The string set by -mriscv-isa-version doesn't have to start
> +        with rv32/rv64.  */
>        rps->error_handler ("-march=%s: ISA string must begin with rv32 or rv64",
>                           arch);
>        return FALSE;
>      }
>
>    /* Parsing standard extension.  */
> -  p = riscv_parse_std_ext (rps, arch, p);
> +  p = riscv_parse_std_ext (rps, arch, p, isa_spec_name, update_version);
>
>    if (p == NULL)
>      return FALSE;
> @@ -1492,7 +1641,8 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
>    /* Parse the different classes of extensions in the specified order.  */
>
>    for (i = 0; i < ARRAY_SIZE (parse_config); ++i) {
> -    p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i]);
> +    p = riscv_parse_prefixed_ext (rps, arch, p, &parse_config[i],
> +                                 isa_spec_name, update_version);
>
>      if (p == NULL)
>        return FALSE;
> @@ -1543,7 +1693,8 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
>  void
>  riscv_add_subset (riscv_subset_list_t *subset_list,
>                   const char *subset,
> -                 int major, int minor)
> +                 int major, int minor,
> +                 bfd_boolean use_default_version)
>  {
>    riscv_subset_t *s = xmalloc (sizeof *s);
>
> @@ -1553,6 +1704,9 @@ riscv_add_subset (riscv_subset_list_t *subset_list,
>    s->name = xstrdup (subset);
>    s->major_version = major;
>    s->minor_version = minor;
> +  /* Record whether the default version is used.  The -mriscv-isa-version
> +     only update the ISA which use the default version.  */
> +  s->use_default_version = use_default_version;
>    s->next = NULL;
>
>    if (subset_list->tail != NULL)
> diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h
> index 76ee274..e3d5177 100644
> --- a/bfd/elfxx-riscv.h
> +++ b/bfd/elfxx-riscv.h
> @@ -40,6 +40,7 @@ struct riscv_subset_t
>    const char *name;
>    int major_version;
>    int minor_version;
> +  bfd_boolean use_default_version;
>    struct riscv_subset_t *next;
>  };
>
> @@ -56,7 +57,8 @@ riscv_release_subset_list (riscv_subset_list_t *);
>  extern void
>  riscv_add_subset (riscv_subset_list_t *,
>                   const char *,
> -                 int, int);
> +                 int, int,
> +                 bfd_boolean);
>
>  extern riscv_subset_t *
>  riscv_lookup_subset (const riscv_subset_list_t *,
> @@ -72,11 +74,17 @@ typedef struct {
>    void (*error_handler) (const char *,
>                          ...) ATTRIBUTE_PRINTF_1;
>    unsigned *xlen;
> +  void (*get_default_version) (const char *,
> +                              const char *,
> +                              unsigned int *,
> +                              unsigned int *);
>  } riscv_parse_subset_t;
>
>  extern bfd_boolean
>  riscv_parse_subset (riscv_parse_subset_t *,
> -                   const char *);
> +                   const char *,
> +                   const char *,
> +                   bfd_boolean);
>
>  extern const char *
>  riscv_supported_std_ext (void);
> diff --git a/gas/config.in b/gas/config.in
> index 8724eb1..935bd9b 100644
> --- a/gas/config.in
> +++ b/gas/config.in
> @@ -30,6 +30,9 @@
>  /* Default architecture. */
>  #undef DEFAULT_ARCH
>
> +/* Define default value for -march */
> +#undef DEFAULT_ARCH_WITH_EXT
> +
>  /* Default CRIS architecture. */
>  #undef DEFAULT_CRIS_ARCH
>
> @@ -50,12 +53,18 @@
>  /* Define to 1 if you want to generate x86 relax relocations by default. */
>  #undef DEFAULT_GENERATE_X86_RELAX_RELOCATIONS
>
> +/* Define default value for -misa-spec */
> +#undef DEFAULT_ISA_SPEC
> +
>  /* Define to 1 if you want to fix Loongson3 LLSC Errata by default. */
>  #undef DEFAULT_MIPS_FIX_LOONGSON3_LLSC
>
>  /* Define to 1 if you want to generate RISC-V arch attribute by default. */
>  #undef DEFAULT_RISCV_ATTR
>
> +/* Define default isa version which are not covered by --with-isa-spec */
> +#undef DEFAULT_RISCV_ISA_VERSION
> +
>  /* Define to 1 if you want to generate GNU x86 used ISA and feature properties
>     by default. */
>  #undef DEFAULT_X86_USED_NOTE
> diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
> index 168561e..bfcf2f0 100644
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -63,7 +63,22 @@ struct riscv_cl_insn
>  #define DEFAULT_RISCV_ATTR 0
>  #endif
>
> +#ifndef DEFAULT_ARCH_WITH_EXT
> +#define DEFAULT_ARCH_WITH_EXT NULL
> +#endif
> +
> +#ifndef DEFAULT_ISA_SPEC
> +#define DEFAULT_ISA_SPEC "2p2"
> +#endif
> +
> +#ifndef DEFAULT_RISCV_ISA_VERSION
> +#define DEFAULT_RISCV_ISA_VERSION NULL
> +#endif
> +
>  static const char default_arch[] = DEFAULT_ARCH;
> +static const char *default_arch_with_ext = DEFAULT_ARCH_WITH_EXT;
> +static const char *default_isa_spec = DEFAULT_ISA_SPEC;
> +static const char *default_riscv_isa_version = DEFAULT_RISCV_ISA_VERSION;
>
>  static unsigned xlen = 0; /* width of an x-register */
>  static unsigned abi_xlen = 0; /* width of a pointer in the ABI */
> @@ -147,18 +162,87 @@ riscv_multi_subset_supports (enum riscv_insn_class insn_class)
>      }
>  }
>
> +/* Handle of the extension with version hash table.  */
> +static struct hash_control *ext_version_hash = NULL;
> +
> +static struct hash_control *
> +init_ext_version_hash (const struct riscv_ext_version *table)
> +{
> +  int i = 0;
> +  struct hash_control *hash = hash_new ();
> +
> +  while (table[i].name)
> +    {
> +      const char *name = table[i].name;
> +      const char *hash_error =
> +       hash_insert (hash, name, (void *) &table[i]);
> +
> +      if (hash_error != NULL)
> +       {
> +         fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
> +                  table[i].name, hash_error);
> +         /* Probably a memory allocation problem?  Give up now.  */
> +         as_fatal (_("Broken assembler.  No assembly attempted."));
> +         return NULL;
> +       }
> +
> +      i++;
> +      while (table[i].name
> +            && strcmp (table[i].name, name) == 0)
> +       i++;
> +    }
> +
> +  return hash;
> +}
> +
> +static void
> +riscv_get_default_ext_version (const char *name,
> +                              const char *spec_name,
> +                              unsigned int *major_version,
> +                              unsigned int *minor_version)
> +{
> +  struct riscv_ext_version *ext;
> +
> +  *major_version = 0;
> +  *minor_version = 0;
> +
> +  if (name == NULL
> +      || spec_name == NULL)
> +    return;
> +
> +  ext = (struct riscv_ext_version *) hash_find (ext_version_hash, name);
> +  while (ext
> +        && ext->name
> +        && strcmp (ext->name, name) == 0)
> +    {
> +      if (ext->spec_name
> +         && strcmp (ext->spec_name, spec_name) == 0)
> +       {
> +         *major_version = ext->major_version;
> +         *minor_version = ext->minor_version;
> +         return;
> +       }
> +      ext++;
> +    }
> +}
> +
>  /* Set which ISA and extensions are available.  */
>
>  static void
> -riscv_set_arch (const char *s)
> +riscv_set_arch (const char *s, bfd_boolean update_version)
>  {
>    riscv_parse_subset_t rps;
>    rps.subset_list = &riscv_subsets;
>    rps.error_handler = as_fatal;
>    rps.xlen = &xlen;
> +  rps.get_default_version = riscv_get_default_ext_version;
>
> -  riscv_release_subset_list (&riscv_subsets);
> -  riscv_parse_subset (&rps, s);
> +  if (s == NULL)
> +    return;
> +
> +  if (!update_version)
> +    riscv_release_subset_list (&riscv_subsets);
> +  riscv_parse_subset (&rps, s, default_isa_spec, update_version);
>  }
>
>  /* Handle of the OPCODE hash table.  */
> @@ -2348,6 +2432,8 @@ enum options
>    OPTION_NO_ARCH_ATTR,
>    OPTION_CSR_CHECK,
>    OPTION_NO_CSR_CHECK,
> +  OPTION_MISA_SPEC,
> +  OPTION_MRISCV_ISA_VERSION,
>    OPTION_END_OF_ENUM
>  };
>
> @@ -2364,6 +2450,8 @@ struct option md_longopts[] =
>    {"mno-arch-attr", no_argument, NULL, OPTION_NO_ARCH_ATTR},
>    {"mcsr-check", no_argument, NULL, OPTION_CSR_CHECK},
>    {"mno-csr-check", no_argument, NULL, OPTION_NO_CSR_CHECK},
> +  {"misa-spec", required_argument, NULL, OPTION_MISA_SPEC},
> +  {"mriscv-isa-version", required_argument, NULL, OPTION_MRISCV_ISA_VERSION},
>
>    {NULL, no_argument, NULL, 0}
>  };
> @@ -2392,7 +2480,9 @@ md_parse_option (int c, const char *arg)
>    switch (c)
>      {
>      case OPTION_MARCH:
> -      riscv_set_arch (arg);
> +      /* riscv_after_parse_args will call riscv_set_arch to parse
> +        the architecture.  */
> +      default_arch_with_ext = arg;
>        break;
>
>      case OPTION_NO_PIC:
> @@ -2450,6 +2540,14 @@ md_parse_option (int c, const char *arg)
>        riscv_opts.csr_check = FALSE;
>        break;
>
> +    case OPTION_MISA_SPEC:
> +      default_isa_spec = arg;
> +      break;
> +
> +    case OPTION_MRISCV_ISA_VERSION:
> +      default_riscv_isa_version = arg;
> +      break;
> +
>      default:
>        return 0;
>      }
> @@ -2460,6 +2558,13 @@ md_parse_option (int c, const char *arg)
>  void
>  riscv_after_parse_args (void)
>  {
> +  /* Initialize the hash table for extensions with default version.  */
> +  ext_version_hash = init_ext_version_hash (riscv_ext_version_table);
> +
> +  /* The --with-arch is optional for now, so we have to set the xlen
> +     according to the default_arch, which is set by the --targte, first.
> +     Then, we use the xlen to set the default_arch_with_ext if the
> +     -march and --with-arch are not set.  */
>    if (xlen == 0)
>      {
>        if (strcmp (default_arch, "riscv32") == 0)
> @@ -2469,9 +2574,15 @@ riscv_after_parse_args (void)
>        else
>         as_bad ("unknown default architecture `%s'", default_arch);
>      }
> +  if (default_arch_with_ext == NULL)
> +    default_arch_with_ext = xlen == 64 ? "rv64g" : "rv32g";
> +
> +  /* Set the architecture according to -march or --with-arch.  */
> +  riscv_set_arch (default_arch_with_ext, FALSE);
>
> -  if (riscv_subsets.head == NULL)
> -    riscv_set_arch (xlen == 64 ? "rv64g" : "rv32g");
> +  /* Update the version info according to -mriscv-isa-spec or
> +     --with-riscv-isa-spec.  */
> +  riscv_set_arch (default_riscv_isa_version, TRUE);
>
>    /* Add the RVC extension, regardless of -march, to support .option rvc.  */
>    riscv_set_rvc (FALSE);
> @@ -3366,7 +3477,7 @@ s_riscv_attribute (int ignored ATTRIBUTE_UNUSED)
>        obj_attribute *attr;
>        attr = elf_known_obj_attributes_proc (stdoutput);
>        if (!start_assemble)
> -       riscv_set_arch (attr[Tag_RISCV_arch].s);
> +       riscv_set_arch (attr[Tag_RISCV_arch].s, FALSE);
>        else
>         as_fatal (_(".attribute arch must set before any instructions"));
>
> @@ -3379,6 +3490,9 @@ s_riscv_attribute (int ignored ATTRIBUTE_UNUSED)
>           if (! bfd_set_arch_mach (stdoutput, bfd_arch_riscv, mach))
>             as_warn (_("Could not set architecture and machine"));
>         }
> +
> +      /* We also need to update the version of ISA here.  */
> +      riscv_set_arch (default_riscv_isa_version, TRUE);
>      }
>  }
>
> diff --git a/gas/configure b/gas/configure
> index 1515787..bce847a 100755
> --- a/gas/configure
> +++ b/gas/configure
> @@ -13009,7 +13009,7 @@ $as_echo "#define NDS32_DEFAULT_ZOL_EXT 1" >>confdefs.h
>  $as_echo "$enable_zol_ext" >&6; }
>         ;;
>
> -      aarch64 | i386 | riscv | s390 | sparc)
> +      aarch64 | i386 | s390 | sparc)
>         if test $this_target = $target ; then
>
>  cat >>confdefs.h <<_ACEOF
> @@ -13019,6 +13019,57 @@ _ACEOF
>         fi
>         ;;
>
> +      riscv)
> +       # --target=riscv[32|64]-*-*.  */
> +       if test $this_target = $target ; then
> +
> +cat >>confdefs.h <<_ACEOF
> +#define DEFAULT_ARCH "${arch}"
> +_ACEOF
> +
> +       fi
> +
> +       # --with-arch=<value>.  The syntax of <value> is same as Gas option -march.
> +       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --with-arch" >&5
> +$as_echo_n "checking for default configuration of --with-arch... " >&6; }
> +       if test "x${with_arch}" != x; then
> +
> +cat >>confdefs.h <<_ACEOF
> +#define DEFAULT_ARCH_WITH_EXT "$with_arch"
> +_ACEOF
> +
> +       fi
> +       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_arch" >&5
> +$as_echo "$with_arch" >&6; }
> +
> +       # --with-isa-spec=[2p0|2p1|2p2|20190608|20191213].
> +       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --with-isa-spec" >&5
> +$as_echo_n "checking for default configuration of --with-isa-spec... " >&6; }
> +       if test "x${with_isa_spec}" != x; then
> +
> +cat >>confdefs.h <<_ACEOF
> +#define DEFAULT_ISA_SPEC "$with_isa_spec"
> +_ACEOF
> +
> +       fi
> +       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_isa_spec" >&5
> +$as_echo "$with_isa_spec" >&6; }
> +
> +       # --with-riscv-isa-version=<value>.  The syntax of <value> is same as Gas
> +       # -march, but without the rv[32|64] prefix.
> +       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration of --with-riscv-isa-version" >&5
> +$as_echo_n "checking for default configuration of --with-riscv-isa-version... " >&6; }
> +       if test "x${with_riscv_isa_version}" != x; then
> +
> +cat >>confdefs.h <<_ACEOF
> +#define DEFAULT_RISCV_ISA_VERSION "$with_riscv_isa_version"
> +_ACEOF
> +
> +       fi
> +       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_riscv_isa_version" >&5
> +$as_echo "$with_riscv_isa_version" >&6; }
> +       ;;
> +
>        rl78)
>         f=rl78-parse.o
>         case " $extra_objects " in
> diff --git a/gas/configure.ac b/gas/configure.ac
> index 6f32e55..be4ba20 100644
> --- a/gas/configure.ac
> +++ b/gas/configure.ac
> @@ -569,12 +569,45 @@ changequote([,])dnl
>         AC_MSG_RESULT($enable_zol_ext)
>         ;;
>
> -      aarch64 | i386 | riscv | s390 | sparc)
> +      aarch64 | i386 | s390 | sparc)
>         if test $this_target = $target ; then
>           AC_DEFINE_UNQUOTED(DEFAULT_ARCH, "${arch}", [Default architecture.])
>         fi
>         ;;
>
> +      riscv)
> +       # --target=riscv[32|64]-*-*.  */
> +       if test $this_target = $target ; then
> +         AC_DEFINE_UNQUOTED(DEFAULT_ARCH, "${arch}", [Default architecture.])
> +       fi
> +
> +       # --with-arch=<value>.  The syntax of <value> is same as Gas option -march.
> +       AC_MSG_CHECKING(for default configuration of --with-arch)
> +       if test "x${with_arch}" != x; then
> +         AC_DEFINE_UNQUOTED(DEFAULT_ARCH_WITH_EXT, "$with_arch",
> +                            [Define default value for -march])
> +       fi
> +       AC_MSG_RESULT($with_arch)
> +
> +       # --with-isa-spec=[2p0|2p1|2p2|20190608|20191213].
> +       AC_MSG_CHECKING(for default configuration of --with-isa-spec)
> +       if test "x${with_isa_spec}" != x; then
> +         AC_DEFINE_UNQUOTED(DEFAULT_ISA_SPEC, "$with_isa_spec",
> +                            [Define default value for -misa-spec])
> +       fi
> +       AC_MSG_RESULT($with_isa_spec)
> +
> +       # --with-riscv-isa-version=<value>.  The syntax of <value> is same as Gas
> +       # -march, but without the rv[32|64] prefix.
> +       AC_MSG_CHECKING(for default configuration of --with-riscv-isa-version)
> +       if test "x${with_riscv_isa_version}" != x; then
> +         AC_DEFINE_UNQUOTED(DEFAULT_RISCV_ISA_VERSION, "$with_riscv_isa_version",
> +                            [Define default isa version which are not
> +                             covered by --with-isa-spec])
> +       fi
> +       AC_MSG_RESULT($with_riscv_isa_version)
> +       ;;
> +
>        rl78)
>         f=rl78-parse.o
>         case " $extra_objects " in
> diff --git a/gas/testsuite/gas/riscv/attribute-01.d b/gas/testsuite/gas/riscv/attribute-01.d
> index e22773e..3f9e841 100644
> --- a/gas/testsuite/gas/riscv/attribute-01.d
> +++ b/gas/testsuite/gas/riscv/attribute-01.d
> @@ -1,4 +1,4 @@
> -#as: -march=rv32g -march-attr
> +#as: -march=rv32g -march-attr -misa-spec=2p2
>  #readelf: -A
>  #source: empty.s
>  Attribute Section: riscv
> diff --git a/gas/testsuite/gas/riscv/attribute-02.d b/gas/testsuite/gas/riscv/attribute-02.d
> index bc3295b..a58248e 100644
> --- a/gas/testsuite/gas/riscv/attribute-02.d
> +++ b/gas/testsuite/gas/riscv/attribute-02.d
> @@ -1,6 +1,6 @@
> -#as: -march=rv32gxargle -march-attr
> +#as: -march=rv32gxargle -march-attr -misa-spec=2p2
>  #readelf: -A
>  #source: empty.s
>  Attribute Section: riscv
>  File Attributes
> -  Tag_RISCV_arch: "rv32i2p0_m2p0_a2p0_f2p0_d2p0_xargle2p0"
> +  Tag_RISCV_arch: "rv32i2p0_m2p0_a2p0_f2p0_d2p0_xargle0p0"
> diff --git a/gas/testsuite/gas/riscv/attribute-03.d b/gas/testsuite/gas/riscv/attribute-03.d
> index 78b706a..04b9ab5 100644
> --- a/gas/testsuite/gas/riscv/attribute-03.d
> +++ b/gas/testsuite/gas/riscv/attribute-03.d
> @@ -1,6 +1,6 @@
> -#as: -march=rv32gxargle_xfoo -march-attr
> +#as: -march=rv32gxargle_xfoo -march-attr -misa-spec=2p2
>  #readelf: -A
>  #source: empty.s
>  Attribute Section: riscv
>  File Attributes
> -  Tag_RISCV_arch: "rv32i2p0_m2p0_a2p0_f2p0_d2p0_xargle2p0_xfoo2p0"
> +  Tag_RISCV_arch: "rv32i2p0_m2p0_a2p0_f2p0_d2p0_xargle0p0_xfoo0p0"
> diff --git a/gas/testsuite/gas/riscv/attribute-04.d b/gas/testsuite/gas/riscv/attribute-04.d
> index c97bf03..8a3f51b 100644
> --- a/gas/testsuite/gas/riscv/attribute-04.d
> +++ b/gas/testsuite/gas/riscv/attribute-04.d
> @@ -1,4 +1,4 @@
> -#as: -march-attr
> +#as: -march-attr -misa-spec=2p2
>  #readelf: -A
>  #source: attribute-04.s
>  Attribute Section: riscv
> diff --git a/gas/testsuite/gas/riscv/attribute-05.d b/gas/testsuite/gas/riscv/attribute-05.d
> index f9b65f2..3309ff3 100644
> --- a/gas/testsuite/gas/riscv/attribute-05.d
> +++ b/gas/testsuite/gas/riscv/attribute-05.d
> @@ -1,4 +1,4 @@
> -#as: -march-attr
> +#as: -march-attr -misa-spec=2p2
>  #readelf: -A
>  #source: attribute-05.s
>  Attribute Section: riscv
> diff --git a/gas/testsuite/gas/riscv/attribute-06.d b/gas/testsuite/gas/riscv/attribute-06.d
> index 1abeb47..5c8a5c6 100644
> --- a/gas/testsuite/gas/riscv/attribute-06.d
> +++ b/gas/testsuite/gas/riscv/attribute-06.d
> @@ -1,4 +1,4 @@
> -#as: -march=rv32g2p0 -march-attr
> +#as: -march=rv32g2p1 -march-attr -misa-spec=2p2
>  #readelf: -A
>  #source: attribute-06.s
>  Attribute Section: riscv
> diff --git a/gas/testsuite/gas/riscv/attribute-07.d b/gas/testsuite/gas/riscv/attribute-07.d
> index dfd7e6b..20ac9be 100644
> --- a/gas/testsuite/gas/riscv/attribute-07.d
> +++ b/gas/testsuite/gas/riscv/attribute-07.d
> @@ -1,4 +1,4 @@
> -#as: -march=rv64g2p0 -march-attr
> +#as: -march=rv64g2p1 -march-attr -misa-spec=2p2
>  #readelf: -A
>  #source: attribute-07.s
>  Attribute Section: riscv
> diff --git a/gas/testsuite/gas/riscv/attribute-08.d b/gas/testsuite/gas/riscv/attribute-08.d
> index c10ac0c..7f580d3 100644
> --- a/gas/testsuite/gas/riscv/attribute-08.d
> +++ b/gas/testsuite/gas/riscv/attribute-08.d
> @@ -1,4 +1,4 @@
> -#as: -march-attr
> +#as: -march-attr -misa-spec=2p2
>  #readelf: -A
>  #source: attribute-08.s
>  Attribute Section: riscv
> diff --git a/gas/testsuite/gas/riscv/attribute-09.d b/gas/testsuite/gas/riscv/attribute-09.d
> new file mode 100644
> index 0000000..77c7ef3
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/attribute-09.d
> @@ -0,0 +1,6 @@
> +#as: -march-attr -misa-spec=2p2 -mriscv-isa-version=i2p1a2p1v0p9
> +#readelf: -A
> +#source: attribute-09.s
> +Attribute Section: riscv
> +File Attributes
> +  Tag_RISCV_arch: "rv32i1p9_f2p0_v0p9_zicsr0p0"
> diff --git a/gas/testsuite/gas/riscv/attribute-09.s b/gas/testsuite/gas/riscv/attribute-09.s
> new file mode 100644
> index 0000000..0b1b16c
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/attribute-09.s
> @@ -0,0 +1 @@
> +       .attribute arch, "rv32i1p9fv_zicsr"
> diff --git a/gas/testsuite/gas/riscv/attribute-10.d b/gas/testsuite/gas/riscv/attribute-10.d
> new file mode 100644
> index 0000000..9c72035
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/attribute-10.d
> @@ -0,0 +1,6 @@
> +#as: -march-attr -march=rv32i_zicsr -misa-spec=20191213
> +#readelf: -A
> +#source: empty.s
> +Attribute Section: riscv
> +File Attributes
> +  Tag_RISCV_arch: "rv32i2p1_zicsr2p0"
> diff --git a/gas/testsuite/gas/riscv/attribute-11.d b/gas/testsuite/gas/riscv/attribute-11.d
> new file mode 100644
> index 0000000..bc7f986
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/attribute-11.d
> @@ -0,0 +1,6 @@
> +#as: -march-attr -march=rv32i_zicsr -misa-spec=20191213 -mriscv-isa-version=zicsr2p1
> +#readelf: -A
> +#source: empty.s
> +Attribute Section: riscv
> +File Attributes
> +  Tag_RISCV_arch: "rv32i2p1_zicsr2p1"
> diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
> index ac6e861..f8b0de3 100644
> --- a/include/opcode/riscv.h
> +++ b/include/opcode/riscv.h
> @@ -343,6 +343,16 @@ struct riscv_opcode
>    unsigned long pinfo;
>  };
>
> +/* This structure holds version information for specific ISA.  */
> +
> +struct riscv_ext_version
> +{
> +  const char *name;
> +  const char *spec_name;
> +  unsigned int major_version;
> +  unsigned int minor_version;
> +};
> +
>  /* Instruction is a simple alias (e.g. "mv" for "addi").  */
>  #define        INSN_ALIAS              0x00000001
>
> @@ -420,5 +430,6 @@ extern const char * const riscv_fpr_names_abi[NFPR];
>
>  extern const struct riscv_opcode riscv_opcodes[];
>  extern const struct riscv_opcode riscv_insn_types[];
> +extern const struct riscv_ext_version riscv_ext_version_table[];
>
>  #endif /* _RISCV_H_ */
> diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
> index ceedcaf..7b885bf 100644
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -884,3 +884,56 @@ const struct riscv_opcode riscv_insn_types[] =
>  /* Terminate the list.  */
>  {0, 0, INSN_CLASS_NONE, 0, 0, 0, 0, 0}
>  };
> +
> +const struct riscv_ext_version riscv_ext_version_table[] =
> +{
> +/* name, spec name,  major,  minor.  */
> +{"e",    "20191213",      1,     9},
> +{"e",    "20190608",      1,     9},
> +{"e",    "2p2",           1,     9},
> +
> +{"i",    "20191213",      2,     1},
> +{"i",    "20190608",      2,     1},
> +{"i",    "2p2",           2,     0},
> +
> +{"m",    "20191213",      2,     0},
> +{"m",    "20190608",      2,     0},
> +{"m",    "2p2",           2,     0},
> +
> +{"a",    "20191213",      2,     1},
> +{"a",    "20190608",      2,     0},
> +{"a",    "2p2",           2,     0},
> +
> +{"f",    "20191213",      2,     2},
> +{"f",    "20190608",      2,     2},
> +{"f",    "2p2",           2,     0},
> +
> +{"d",    "20191213",      2,     2},
> +{"d",    "20190608",      2,     2},
> +{"d",    "2p2",           2,     0},
> +
> +{"q",    "20191213",      2,     2},
> +{"q",    "20190608",      2,     2},
> +{"q",    "2p2",           2,     0},
> +
> +{"c",    "20191213",      2,     0},
> +{"c",    "20190608",      2,     0},
> +{"c",    "2p2",           2,     0},
> +
> +{"p",    "20191213",      0,     2},
> +{"p",    "20190608",      0,     2},
> +{"p",    "2p2",           0,     1},
> +
> +{"v",    "20191213",      0,     7},
> +{"v",    "20190608",      0,     7},
> +{"v",    "2p2",           0,     7},
> +
> +{"n",    "20190608",      1,     1},
> +{"n",    "2p2",           1,     1},
> +
> +{"zicsr","20191213",      2,     0},
> +{"zicsr","20190608",      2,     0},
> +
> +/* Terminate the list.  */
> +{NULL, NULL, 0, 0}
> +};
> --
> 2.7.4
>


More information about the Binutils mailing list