From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x444.google.com (mail-pf1-x444.google.com [IPv6:2607:f8b0:4864:20::444]) by sourceware.org (Postfix) with ESMTPS id 3E8F33957483 for ; Thu, 23 Apr 2020 22:59:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 3E8F33957483 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=dabbelt.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=palmer@dabbelt.com Received: by mail-pf1-x444.google.com with SMTP id x77so3805986pfc.0 for ; Thu, 23 Apr 2020 15:59:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dabbelt-com.20150623.gappssmtp.com; s=20150623; h=date:subject:in-reply-to:cc:from:to:message-id:mime-version :content-transfer-encoding; bh=Q0W5zesUzHDhrzWRzP/qWROglk2PhJbxS51OfYUBNIE=; b=wjoFU8nZFtsicuekB09F4gQLLZJZOPzcGnis9F6PydYYxt4SLl5ubseHHwxKPTlZ/b AoLU8eMoCZjW5YhC5Z9KcA4IPcCw4+rX/2824q/HXZx/yWc5QVxRZjP3r+dU6YCbkIL3 TauD2ZfCo8w9LKFWW/kjEHJFgEMfIrEXBVa6VuafxYTouoPK6eoE2JGPa7FQxugPSy0r wZfx/Zqmz32lPBNEBhqY7udDg14/yGBJyIjIlLPXNkjHoWX/NpU8510BF5vo+yQJqAeG YYQOBWHqzMBXCAO5skarySn69c0DkUX77/IihgzyEmJYAqxLN76RK7UyJbJabPWkRLvD gxDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:subject:in-reply-to:cc:from:to:message-id :mime-version:content-transfer-encoding; bh=Q0W5zesUzHDhrzWRzP/qWROglk2PhJbxS51OfYUBNIE=; b=rek9Qrnwn9p59hob7zCsS5jzPpqrQ6JkTzILjq7gea9AvUqtlG/rifPlrHfmZHwUTA gAWu5oXCjcgyt8MT/HFOMb+fboehXxmyGtxKkcJGL0YeaeBQPWPzNONc8SQo9whX1JE2 +TdHoBMX9e8ZeLq/QX2u9FV6X3eKJQUVB+/Cs9GUBaa2dxoMGum85wpon3Z2vKuEVqlr L2y2L3O0jN3KPv/Lfrzl8CtI3R5Lz6GD7Vxej6InbfehO3MboaUyTFqswi0/+1DMLBbr bXcgD+QjV3y8BfQXWBdK0UcNO6WlHNHIiJAKy5V3sL1mvEuYOjxVsDvOreBMPlu0IWKv 3ciw== X-Gm-Message-State: AGi0PuYIU6OO8EYmpeQN/RsemOhCFy8/n2P0YBOXq+AuFOB3gm/Wi0D+ 86OIQcQYf8rTSuR1tTpBMdWMOA== X-Google-Smtp-Source: APiQypIYqRZEXppvGPEh0x7+2JCRICfYU2Mcl3nK3uISOxv6qfvpDMk4WWFIBAXBxY4VZUWQfB6odA== X-Received: by 2002:a62:6106:: with SMTP id v6mr6472843pfb.199.1587682740199; Thu, 23 Apr 2020 15:59:00 -0700 (PDT) Received: from localhost (76-210-143-223.lightspeed.sntcca.sbcglobal.net. [76.210.143.223]) by smtp.gmail.com with ESMTPSA id b15sm3709933pfd.139.2020.04.23.15.58.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Apr 2020 15:58:59 -0700 (PDT) Date: Thu, 23 Apr 2020 15:58:59 -0700 (PDT) X-Google-Original-Date: Thu, 23 Apr 2020 15:58:53 PDT (-0700) Subject: Re: [PATCH 3/7] RISC-V: Support new GAS options and configure options to set ISA versions. In-Reply-To: <1587208075-2462-4-git-send-email-nelson.chu@sifive.com> CC: binutils@sourceware.org, gdb-patches@sourceware.org, Andrew Waterman , asb@lowrisc.org, maxim.blinov@embecosm.com, kito.cheng@sifive.com From: Palmer Dabbelt To: nelson.chu@sifive.com Message-ID: Mime-Version: 1.0 (MHng) Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-24.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Apr 2020 22:59:07 -0000 On Sat, 18 Apr 2020 04:07:51 PDT (-0700), 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. This makes sense. > * -mriscv-isa-version = > The syntax of 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. I don't buy the argument for this. The V extension stuff isn't relevant: those are all draft versions, and this is a perfect reason why we don't want to take drafts upstream. When we have a defined V ISA it'll be part of a versioned RISC-V specification and any users that want it can just use at least that ISA spec. For the second argument, why not just provide those via -march? I can buy that it's a pain to build up valid -march strings in build scripts, but this just fixes a specific instance of that problem (and that's not going to be that common, as most users just want a single ISA version). I haven't really looked at the code, as dropping this will change the patches pretty drasticly. > New Default Configure Options, > > * --with-arch = > The syntax of is same as -march option. Assembler will check this > if -march option and ELF arch attributes aren’t set. Ya, we should have had that a while ago :) > * --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 = > The syntax of 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=. The syntax of 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=. The syntax of 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=. The syntax of 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=. The syntax of 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} > +};