From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-il1-x141.google.com (mail-il1-x141.google.com [IPv6:2607:f8b0:4864:20::141]) by sourceware.org (Postfix) with ESMTPS id D386B396ECCD for ; Tue, 19 May 2020 09:08:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org D386B396ECCD Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nelson.chu@sifive.com Received: by mail-il1-x141.google.com with SMTP id l20so12665254ilj.10 for ; Tue, 19 May 2020 02:08:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=zgt+0rCtdjd5COsKbOR5304rCvAgL9Kk+cbCRDAkrjk=; b=X98eqBv3tYrWTvLbaKWtr8ml/jswB5/9Ce6RyylvANjx3hG0ylBpooKasvy0z5+pqQ HjtW6syYq8MypZVzGZj2etUs+zrRXJCjtYlKI9BnvdhVZPiALyMEL1u5PtV/QU1A1Jjs Ya693BeqnSmJEc4aTRvvJC+9HolURE/+3wfIxtIR4c80e03huk8hI9J7lGXvIY4CTisk XdL/oBLID7FyXLH9AQwMTQbzVfCYeKAZepBtqDVX6KBgkyGM4e/HdYhSpvmM7gindDPt L3cwcDKNHyjtO/QcwAvxgvClwcJRjOs112dCa3AwIszOH0cCr1UWajShRbP8741WjFjl jCYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=zgt+0rCtdjd5COsKbOR5304rCvAgL9Kk+cbCRDAkrjk=; b=YZH3nKHp8znUba2FyUeBkE+8je6txl+MB65mJzjpu4cnEMCEwVDBo3kAzZRGrkGCcp VLOLjTd90HCQLaW4yacdOKcnD9bRQl2tcB8JJ0c0Hc1+OBSPXFA+uwpOkmQvWk6sor9W MZg4sfyAeItuYg4Fg3y96K7ZjZvOrzbYnskq1PRGjq6Zb1VWt+hkSeEXBvze58fECKgL jUxzXGD8I3FOgnoeAyMsEVNTdLUV/6khXwuAdmNXMf3v8fZDkGOvE6Lp4GjHs24LDvXV v13pYD+NIdkEgDG+dh5r9S43ZPpFlngVTppfC6bZXCuPzkDaCUGadbPpJ9iRDiWqpILK jTyQ== X-Gm-Message-State: AOAM530FHxQHi6UHRsQ6YIhei7jDiCeRrlUMDm4qLZz6jf36DIY6e3P9 mnpMWfUq69iyuE1tD8/8CBqx7OBkJo+PbKeyBOBHAQ== X-Google-Smtp-Source: ABdhPJyKHwzLP2arPuletbshRLD2Q8/+uLmTYt2rL5LJpT6s15NsiSG04kna2phDAjxq1ACyAtEqECn6uvXuaYcjPD0= X-Received: by 2002:a92:6411:: with SMTP id y17mr17080187ilb.161.1589879279902; Tue, 19 May 2020 02:07:59 -0700 (PDT) MIME-Version: 1.0 References: <1588733747-18787-1-git-send-email-nelson.chu@sifive.com> <1588733747-18787-4-git-send-email-nelson.chu@sifive.com> In-Reply-To: <1588733747-18787-4-git-send-email-nelson.chu@sifive.com> From: Nelson Chu Date: Tue, 19 May 2020 17:07:48 +0800 Message-ID: Subject: Re: [PATCH v2 3/9] RISC-V: Support GAS option -misa-spec to set ISA versions. To: Binutils , gdb-patches@sourceware.org Cc: Palmer Dabbelt , Kito Cheng , Jim Wilson , Andrew Waterman , Andrew Burgess , Alex Bradbury , Maxim Blinov Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, 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: Tue, 19 May 2020 09:08:04 -0000 PING :) On Wed, May 6, 2020 at 10:55 AM Nelson Chu 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 option to make it easiler. > > * -misa-spec = [2.2|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 do not set in > the ELF arch attributes or -march option. > > The default ISA spec is set to 2.2 rather than the lastest version, if > the -misa-spec is not set. The reason is that compiler generates the ISA > string with fixed 2p0 verisons only for the RISCV ELF architecture attributes, > but not for the -march option. We should resolve this in the future patches. > > gas/ > * config/tc-riscv.c (default_arch_with_ext, default_isa_spec): > Static variables which are used to set the ISA extensions. You can > use -march (or ELF build attributes) and -misa-spec to set them, > respectively. > > (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): Set the callback function. > > (enum options, struct option md_longopts): Add new option -misa-spec. > (md_parse_option): Do not call riscv_set_arch for -march. We will > call it later in riscv_after_parse_args. Call riscv_get_isa_spec_class > to set default_isa_spec class. > (riscv_after_parse_args): Call init_ext_version_hash to initialize the > ext_version_hash, and then call riscv_set_arch to set the architecture > with versions according to default_arch_with_ext. > > * testsuite/gas/riscv/attribute-02.d: Set 0p0 as default version for > x extensions. > * testsuite/gas/riscv/attribute-03.d: Likewise. > * testsuite/gas/riscv/attribute-09.d: New testcase. For i-ext, we > already set it's version to 2p1 by march, so no need to use the default > 2p2 version. For m-ext, we do not set the version by -march and ELF arch > attribute, so set the default 2p0 to it. For zicsr, it is not defined in > ISA spec 2p2, so set 0p0 to it. > * testsuite/gas/riscv/attribute-10.d: New testcase. The version of > zicsr is 2p0 according to ISA spec 20191213. > > bfd/ > * elfxx-riscv.h (riscv_parse_subset_t): Add new callback function > get_default_version. It is used to find the default version for > the specific extension. > > * 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_parse_std_ext): 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): Likewise. > (riscv_std_z_ext_strtab): Support Zicsr extensions. > > * elfnn-riscv.c (riscv_merge_std_ext): Use strcasecmp to compare the > strings rather than characters. > riscv_merge_arch_attr_info): The callback function get_default_version > is only needed for assembler, so set it to NULL int the linker. > > include/ > * opcode/riscv.h: Include "bfd.h" to support bfd_boolean. > (enum riscv_isa_spec_class): New enum class. All supported ISA spec > belong to one of the class > (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. > (struct isa_spec_t, isa_specs): List for all supported ISA spec > classes and the corresponding strings. > (riscv_get_isa_spec_class): New function. Get the corresponding ISA > spec class by giving a ISA spec string. > --- > bfd/elfnn-riscv.c | 6 +- > bfd/elfxx-riscv.c | 203 +++++++++++++++++++-------------- > bfd/elfxx-riscv.h | 3 + > gas/config/tc-riscv.c | 100 +++++++++++++++- > gas/testsuite/gas/riscv/attribute-02.d | 2 +- > gas/testsuite/gas/riscv/attribute-03.d | 2 +- > gas/testsuite/gas/riscv/attribute-09.d | 6 + > gas/testsuite/gas/riscv/attribute-10.d | 6 + > include/opcode/riscv.h | 26 +++++ > opcodes/riscv-opc.c | 93 +++++++++++++++ > 10 files changed, 355 insertions(+), 92 deletions(-) > create mode 100644 gas/testsuite/gas/riscv/attribute-09.d > create mode 100644 gas/testsuite/gas/riscv/attribute-10.d > > diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c > index 473bf50..2b5e713 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 > @@ -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; > diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c > index b15fdee..e025689 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; > } > > @@ -1122,38 +1113,58 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps, > { > 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); > + > + /* Find the default version if needed. */ > + if (use_default_version > + && rps->get_default_version != NULL) > + rps->get_default_version ("i", > + &major_version, > + &minor_version); > + riscv_add_subset (rps->subset_list, "i", > + major_version, minor_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); > + > + /* Find the default version if needed. */ > + if (use_default_version > + && rps->get_default_version != NULL) > + rps->get_default_version ("e", > + &major_version, > + &minor_version); > + riscv_add_subset (rps->subset_list, "e", > + major_version, minor_version); > + > + /* i-ext must be enabled. */ > + if (rps->get_default_version != NULL) > + rps->get_default_version ("i", > + &major_version, > + &minor_version); > + riscv_add_subset (rps->subset_list, "i", > + major_version, minor_version); > > if (*rps->xlen > 32) > { > @@ -1161,25 +1172,36 @@ 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); > + > + /* i-ext must be enabled. */ > + if (rps->get_default_version != NULL) > + rps->get_default_version ("i", > + &major_version, > + &minor_version); > + riscv_add_subset (rps->subset_list, "i", > + major_version, minor_version); > > for ( ; *std_exts != 'q'; std_exts++) > { > const char subset[] = {*std_exts, '\0'}; > - riscv_add_subset ( > - rps->subset_list, subset, major_version, minor_version); > + if (rps->get_default_version != NULL) > + rps->get_default_version (subset, > + &major_version, > + &minor_version); > + riscv_add_subset (rps->subset_list, subset, > + major_version, minor_version); > } > break; > > @@ -1189,7 +1211,9 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps, > 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 +1242,26 @@ 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; > - > - riscv_add_subset (rps->subset_list, subset, major_version, minor_version); > + p = riscv_parsing_subset_version (rps, > + march, > + ++p, > + &major_version, > + &minor_version, > + TRUE, > + &use_default_version); > + > + /* Find the default version if needed. */ > + if (use_default_version > + && rps->get_default_version != NULL) > + rps->get_default_version (subset, > + &major_version, > + &minor_version); > + riscv_add_subset (rps->subset_list, subset, > + major_version, minor_version); > } > return p; > } > @@ -1272,9 +1301,10 @@ 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, > + `rps`: Hooks and status for parsing subset. > + `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. */ > > static const char * > @@ -1287,6 +1317,7 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps, > unsigned minor_version = 0; > const char *last_name; > riscv_isa_ext_class_t class; > + bfd_boolean use_default_version; > > while (*p) > { > @@ -1309,15 +1340,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. > @@ -1337,7 +1364,6 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps, > > /* Check that the last item is not the same as this. */ > last_name = rps->subset_list->tail->name; > - > if (!strcasecmp (last_name, subset)) > { > rps->error_handler ("-march=%s: Duplicate %s ISA extension: \'%s\'", > @@ -1357,7 +1383,15 @@ riscv_parse_prefixed_ext (riscv_parse_subset_t *rps, > return NULL; > } > > - 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 != NULL) > + rps->get_default_version (subset, > + &major_version, > + &minor_version); > + riscv_add_subset (rps->subset_list, subset, > + major_version, minor_version); > + > free (subset); > p += end_of_version - subset; > > @@ -1384,7 +1418,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. */ > @@ -1490,7 +1524,6 @@ riscv_parse_subset (riscv_parse_subset_t *rps, > return FALSE; > > /* 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]); > > diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h > index 76ee274..cbafd28 100644 > --- a/bfd/elfxx-riscv.h > +++ b/bfd/elfxx-riscv.h > @@ -72,6 +72,9 @@ typedef struct { > void (*error_handler) (const char *, > ...) ATTRIBUTE_PRINTF_1; > unsigned *xlen; > + void (*get_default_version) (const char *, > + unsigned int *, > + unsigned int *); > } riscv_parse_subset_t; > > extern bfd_boolean > diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c > index 168561e..5ef257e 100644 > --- a/gas/config/tc-riscv.c > +++ b/gas/config/tc-riscv.c > @@ -64,6 +64,8 @@ struct riscv_cl_insn > #endif > > static const char default_arch[] = DEFAULT_ARCH; > +static const char *default_arch_with_ext = NULL; > +static enum riscv_isa_spec_class default_isa_spec = ISA_SPEC_CLASS_NONE; > > static unsigned xlen = 0; /* width of an x-register */ > static unsigned abi_xlen = 0; /* width of a pointer in the ABI */ > @@ -147,6 +149,67 @@ 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, > + unsigned int *major_version, > + unsigned int *minor_version) > +{ > + struct riscv_ext_version *ext; > + > + *major_version = 0; > + *minor_version = 0; > + > + if (name == NULL || default_isa_spec == ISA_SPEC_CLASS_NONE) > + return; > + > + ext = (struct riscv_ext_version *) hash_find (ext_version_hash, name); > + while (ext > + && ext->name > + && strcmp (ext->name, name) == 0) > + { > + if (ext->isa_spec_class == default_isa_spec) > + { > + *major_version = ext->major_version; > + *minor_version = ext->minor_version; > + return; > + } > + ext++; > + } > +} > + > /* Set which ISA and extensions are available. */ > > static void > @@ -156,6 +219,10 @@ riscv_set_arch (const char *s) > rps.subset_list = &riscv_subsets; > rps.error_handler = as_fatal; > rps.xlen = &xlen; > + rps.get_default_version = riscv_get_default_ext_version; > + > + if (s == NULL) > + return; > > riscv_release_subset_list (&riscv_subsets); > riscv_parse_subset (&rps, s); > @@ -2348,6 +2415,7 @@ enum options > OPTION_NO_ARCH_ATTR, > OPTION_CSR_CHECK, > OPTION_NO_CSR_CHECK, > + OPTION_MISA_SPEC, > OPTION_END_OF_ENUM > }; > > @@ -2364,6 +2432,7 @@ 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}, > > {NULL, no_argument, NULL, 0} > }; > @@ -2392,7 +2461,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 +2521,14 @@ md_parse_option (int c, const char *arg) > riscv_opts.csr_check = FALSE; > break; > > + case OPTION_MISA_SPEC: > + if (!riscv_get_isa_spec_class (arg, &default_isa_spec)) > + { > + as_bad ("Unknown default ISA spec `%s' set by -misa-spec", arg); > + return 0; > + } > + break; > + > default: > return 0; > } > @@ -2469,9 +2548,22 @@ riscv_after_parse_args (void) > else > as_bad ("unknown default architecture `%s'", default_arch); > } > - > - if (riscv_subsets.head == NULL) > - riscv_set_arch (xlen == 64 ? "rv64g" : "rv32g"); > + if (default_arch_with_ext == NULL) > + default_arch_with_ext = xlen == 64 ? "rv64g" : "rv32g"; > + > + /* Initialize the hash table for extensions with default version. */ > + ext_version_hash = init_ext_version_hash (riscv_ext_version_table); > + > + /* The default ISA spec is set to 2.2 rather than the lastest version. > + The reason is that compiler generates the ISA string with fixed 2p0 > + verisons only for the RISCV ELF architecture attributes, but not for > + the -march option. Therefore, we should update the compiler or linker > + to resolve this problem. */ > + if (default_isa_spec == ISA_SPEC_CLASS_NONE) > + default_isa_spec = ISA_SPEC_CLASS_2P2; > + > + /* Set the architecture according to -march. */ > + riscv_set_arch (default_arch_with_ext); > > /* Add the RVC extension, regardless of -march, to support .option rvc. */ > riscv_set_rvc (FALSE); > diff --git a/gas/testsuite/gas/riscv/attribute-02.d b/gas/testsuite/gas/riscv/attribute-02.d > index bc3295b..e1e8ce3 100644 > --- a/gas/testsuite/gas/riscv/attribute-02.d > +++ b/gas/testsuite/gas/riscv/attribute-02.d > @@ -3,4 +3,4 @@ > #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..fa38bf3 100644 > --- a/gas/testsuite/gas/riscv/attribute-03.d > +++ b/gas/testsuite/gas/riscv/attribute-03.d > @@ -3,4 +3,4 @@ > #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-09.d b/gas/testsuite/gas/riscv/attribute-09.d > new file mode 100644 > index 0000000..cad1713 > --- /dev/null > +++ b/gas/testsuite/gas/riscv/attribute-09.d > @@ -0,0 +1,6 @@ > +#as: -march-attr -march=rv32i2p1m_zicsr -misa-spec=2.2 > +#readelf: -A > +#source: empty.s > +Attribute Section: riscv > +File Attributes > + Tag_RISCV_arch: "rv32i2p1_m2p0_zicsr0p0" > diff --git a/gas/testsuite/gas/riscv/attribute-10.d b/gas/testsuite/gas/riscv/attribute-10.d > new file mode 100644 > index 0000000..ba903d1 > --- /dev/null > +++ b/gas/testsuite/gas/riscv/attribute-10.d > @@ -0,0 +1,6 @@ > +#as: -march-attr -march=rv32gc_zicsr -misa-spec=20191213 > +#readelf: -A > +#source: empty.s > +Attribute Section: riscv > +File Attributes > + Tag_RISCV_arch: "rv32i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0" > diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h > index ac6e861..d83e9ca 100644 > --- a/include/opcode/riscv.h > +++ b/include/opcode/riscv.h > @@ -24,6 +24,7 @@ > #include "riscv-opc.h" > #include > #include > +#include "bfd.h" > > typedef uint64_t insn_t; > > @@ -343,6 +344,27 @@ struct riscv_opcode > unsigned long pinfo; > }; > > +/* The current supported ISA spec versions. */ > + > +enum riscv_isa_spec_class > +{ > + ISA_SPEC_CLASS_NONE, > + > + ISA_SPEC_CLASS_2P2, > + ISA_SPEC_CLASS_20190608, > + ISA_SPEC_CLASS_20191213 > +}; > + > +/* This structure holds version information for specific ISA. */ > + > +struct riscv_ext_version > +{ > + const char *name; > + enum riscv_isa_spec_class isa_spec_class; > + unsigned int major_version; > + unsigned int minor_version; > +}; > + > /* Instruction is a simple alias (e.g. "mv" for "addi"). */ > #define INSN_ALIAS 0x00000001 > > @@ -420,5 +442,9 @@ 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[]; > + > +extern bfd_boolean > +riscv_get_isa_spec_class (const char *, enum riscv_isa_spec_class *); > > #endif /* _RISCV_H_ */ > diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c > index ceedcaf..f08b15e 100644 > --- a/opcodes/riscv-opc.c > +++ b/opcodes/riscv-opc.c > @@ -884,3 +884,96 @@ const struct riscv_opcode riscv_insn_types[] = > /* Terminate the list. */ > {0, 0, INSN_CLASS_NONE, 0, 0, 0, 0, 0} > }; > + > +/* All standard extensions defined in all supported ISA spec. */ > +const struct riscv_ext_version riscv_ext_version_table[] = > +{ > +/* name, ISA spec, major version, minor_version. */ > +{"e", ISA_SPEC_CLASS_20191213, 1, 9}, > +{"e", ISA_SPEC_CLASS_20190608, 1, 9}, > +{"e", ISA_SPEC_CLASS_2P2, 1, 9}, > + > +{"i", ISA_SPEC_CLASS_20191213, 2, 1}, > +{"i", ISA_SPEC_CLASS_20190608, 2, 1}, > +{"i", ISA_SPEC_CLASS_2P2, 2, 0}, > + > +{"m", ISA_SPEC_CLASS_20191213, 2, 0}, > +{"m", ISA_SPEC_CLASS_20190608, 2, 0}, > +{"m", ISA_SPEC_CLASS_2P2, 2, 0}, > + > +{"a", ISA_SPEC_CLASS_20191213, 2, 1}, > +{"a", ISA_SPEC_CLASS_20190608, 2, 0}, > +{"a", ISA_SPEC_CLASS_2P2, 2, 0}, > + > +{"f", ISA_SPEC_CLASS_20191213, 2, 2}, > +{"f", ISA_SPEC_CLASS_20190608, 2, 2}, > +{"f", ISA_SPEC_CLASS_2P2, 2, 0}, > + > +{"d", ISA_SPEC_CLASS_20191213, 2, 2}, > +{"d", ISA_SPEC_CLASS_20190608, 2, 2}, > +{"d", ISA_SPEC_CLASS_2P2, 2, 0}, > + > +{"q", ISA_SPEC_CLASS_20191213, 2, 2}, > +{"q", ISA_SPEC_CLASS_20190608, 2, 2}, > +{"q", ISA_SPEC_CLASS_2P2, 2, 0}, > + > +{"c", ISA_SPEC_CLASS_20191213, 2, 0}, > +{"c", ISA_SPEC_CLASS_20190608, 2, 0}, > +{"c", ISA_SPEC_CLASS_2P2, 2, 0}, > + > +{"p", ISA_SPEC_CLASS_20191213, 0, 2}, > +{"p", ISA_SPEC_CLASS_20190608, 0, 2}, > +{"p", ISA_SPEC_CLASS_2P2, 0, 1}, > + > +{"v", ISA_SPEC_CLASS_20191213, 0, 7}, > +{"v", ISA_SPEC_CLASS_20190608, 0, 7}, > +{"v", ISA_SPEC_CLASS_2P2, 0, 7}, > + > +{"n", ISA_SPEC_CLASS_20190608, 1, 1}, > +{"n", ISA_SPEC_CLASS_2P2, 1, 1}, > + > +{"zicsr", ISA_SPEC_CLASS_20191213, 2, 0}, > +{"zicsr", ISA_SPEC_CLASS_20190608, 2, 0}, > + > +/* Terminate the list. */ > +{NULL, 0, 0, 0} > +}; > + > +struct isa_spec_t > +{ > + const char *name; > + enum riscv_isa_spec_class class; > +}; > + > +/* List for all supported ISA spec versions. */ > +static const struct isa_spec_t isa_specs[] = > +{ > + {"2.2", ISA_SPEC_CLASS_2P2}, > + {"20190608", ISA_SPEC_CLASS_20190608}, > + {"20191213", ISA_SPEC_CLASS_20191213}, > + > +/* Terminate the list. */ > + {NULL, 0} > +}; > + > +/* Get the corresponding ISA spec class by giving a ISA spec string. */ > + > +bfd_boolean > +riscv_get_isa_spec_class (const char *s, > + enum riscv_isa_spec_class *class) > +{ > + const struct isa_spec_t *version; > + > + if (s == NULL) > + return FALSE; > + > + for (version = &isa_specs[0]; version->name != NULL; ++version) > + if (strcmp (version->name, s) == 0) > + { > + *class = version->class; > + return TRUE; > + } > + > + /* Can not find the supported ISA spec. */ > + return FALSE; > +} > -- > 2.7.4 >