RISC-V: Merged extension string tables and their version tables into one.
There are two main reasons for this patch, * In the past we had two extension tables, one is used to record all supported extensions in bfd/elfxx-riscv.c, another is used to get the default extension versions in gas/config/tc-riscv.c. It is hard to maintain lots of tables in different files, but in fact we can merge them into just one table. Therefore, we now define many riscv_supported_std* tables, which record names and versions for all supported extensions. We not only use these tables to initialize the riscv_ext_order, but also use them to get the default versions of extensions, and decide if the extensions should be enbaled by default. * We add a new filed `default_enable' for the riscv_supported_std* tables, to decide if the extension should be enabled by default. For now if the `default_enable' field of the extension is set to EXT_DEFAULT, then we should enable the extension when the -march and elf architecture attributes are not set. In the future, I suppose the `default_enable' can be set to lots of EXT_<VENDOR>, each vendor can decide to open which extensions, when the target triple of vendor is chosen. The elf/linux regression tests of riscv-gnu-toolchain are passed. bfd/ * elfnn-riscv.c (cpu-riscv.h): Removed sine it is included in bfd/elfxx-riscv.h. (riscv_merge_std_ext): Updated since the field of rpe is changed. * elfxx-riscv.c (cpu-riscv.h): Removed. (riscv_implicit_subsets): Added implicit extensions for g. (struct riscv_supported_ext): Used to be riscv_ext_version. Moved from gas/config/tc-riscv.c, and added new field `default_enable' to decide if the extension should be enabled by default. (EXT_DEFAULT): Defined for `default_enable' field. (riscv_supported_std_ext): It used to return the supported standard architecture string, but now we move ext_version_table from gas/config/tc-riscv.c to here, and rename it to riscv_supported_std_ext. Currently we not only use the table to initialize riscv_ext_order, but also get the default versions of extensions, and decide if the extensions should be enbaled by default. (riscv_supported_std_z_ext): Likewise, but is used for z* extensions. (riscv_supported_std_s_ext): Likewise, but is used for s* extensions. (riscv_supported_std_h_ext): Likewise, but is used for h* extensions. (riscv_supported_std_zxm_ext): Likewise, but is used for zxm* extensions. (riscv_all_supported_ext): Includes all supported extension tables. (riscv_known_prefixed_ext): Updated. (riscv_valid_prefixed_ext): Updated. (riscv_init_ext_order): Init the riscv_ext_order table according to riscv_supported_std_ext. (riscv_get_default_ext_version): Moved from gas/config/tc-riscv.c. Get the versions of extensions from riscv_supported_std* tables. (riscv_parse_add_subset): Updated. (riscv_parse_std_ext): Updated. (riscv_set_default_arch): Set the default subset list according to the default_enable field of riscv_supported_*ext tables. (riscv_parse_subset): If the input ARCH is NULL, then we call riscv_set_default_arch to set the default subset list. * elfxx-riscv.h (cpu-riscv.h): Included. (riscv_parse_subset_t): Removed get_default_version field, and added isa_spec field to replace it. (extern riscv_supported_std_ext): Removed. gas/ * (bfd/cpu-riscv.h): Removed. (struct riscv_ext_version): Renamed and moved to bfd/elfxx-riscv.c. (ext_version_table): Likewise. (riscv_get_default_ext_version): Likewise. (ext_version_hash): Removed. (init_ext_version_hash): Removed. (riscv_set_arch): Updated since the field of rps is changed. Besides, report error when the architecture string is empty. (riscv_after_parse_args): Updated.
This commit is contained in:
parent
648d5dc4e6
commit
c9f2799101
4 changed files with 235 additions and 256 deletions
|
@ -32,7 +32,6 @@
|
|||
#include "elf/riscv.h"
|
||||
#include "opcode/riscv.h"
|
||||
#include "objalloc.h"
|
||||
#include "cpu-riscv.h"
|
||||
|
||||
#include <limits.h>
|
||||
#ifndef CHAR_BIT
|
||||
|
@ -3443,7 +3442,7 @@ riscv_merge_std_ext (bfd *ibfd,
|
|||
struct riscv_subset_t **pin,
|
||||
struct riscv_subset_t **pout)
|
||||
{
|
||||
const char *standard_exts = riscv_supported_std_ext ();
|
||||
const char *standard_exts = "mafdqlcbjtpvn";
|
||||
const char *p;
|
||||
struct riscv_subset_t *in = *pin;
|
||||
struct riscv_subset_t *out = *pout;
|
||||
|
@ -3587,13 +3586,13 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch)
|
|||
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_in.isa_spec = ISA_SPEC_CLASS_NONE;
|
||||
rpe_in.check_unknown_prefixed_ext = false;
|
||||
|
||||
rpe_out.subset_list = &out_subsets;
|
||||
rpe_out.error_handler = _bfd_error_handler;
|
||||
rpe_out.xlen = &xlen_out;
|
||||
rpe_out.get_default_version = NULL;
|
||||
rpe_out.isa_spec = ISA_SPEC_CLASS_NONE;
|
||||
rpe_out.check_unknown_prefixed_ext = false;
|
||||
|
||||
if (in_arch == NULL && out_arch == NULL)
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "libiberty.h"
|
||||
#include "elfxx-riscv.h"
|
||||
#include "safe-ctype.h"
|
||||
#include "cpu-riscv.h"
|
||||
|
||||
#define MINUS_ONE ((bfd_vma)0 - 1)
|
||||
|
||||
|
@ -1066,6 +1065,11 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
|
|||
{"e", "i", check_implicit_always},
|
||||
{"i", "zicsr", check_implicit_for_i},
|
||||
{"i", "zifencei", check_implicit_for_i},
|
||||
{"g", "i", check_implicit_always},
|
||||
{"g", "m", check_implicit_always},
|
||||
{"g", "a", check_implicit_always},
|
||||
{"g", "f", check_implicit_always},
|
||||
{"g", "d", check_implicit_always},
|
||||
{"g", "zicsr", check_implicit_always},
|
||||
{"g", "zifencei", check_implicit_always},
|
||||
{"q", "d", check_implicit_always},
|
||||
|
@ -1074,31 +1078,98 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
|
|||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* Lists of prefixed class extensions that binutils should know about.
|
||||
Whether or not a particular entry is in these lists will dictate if
|
||||
gas/ld will accept its presence in the architecture string.
|
||||
/* For default_enable field, decide if the extension should
|
||||
be enbaled by default. */
|
||||
|
||||
Please add the extensions to the lists in lower case. However, keep
|
||||
these subsets in alphabetical order in these tables is recommended,
|
||||
although there is no impact on the current implementation. */
|
||||
#define EXT_DEFAULT 0x1
|
||||
|
||||
static const char * const riscv_std_z_ext_strtab[] =
|
||||
/* List all extensions that binutils should know about. */
|
||||
|
||||
struct riscv_supported_ext
|
||||
{
|
||||
"zba", "zbb", "zbc", "zicsr", "zifencei", "zihintpause", NULL
|
||||
const char *name;
|
||||
enum riscv_spec_class isa_spec_class;
|
||||
int major_version;
|
||||
int minor_version;
|
||||
unsigned long default_enable;
|
||||
};
|
||||
|
||||
static const char * const riscv_std_s_ext_strtab[] =
|
||||
/* The standard extensions must be added in canonical order. */
|
||||
|
||||
static struct riscv_supported_ext riscv_supported_std_ext[] =
|
||||
{
|
||||
NULL
|
||||
{"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 },
|
||||
{"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 },
|
||||
{"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 },
|
||||
{"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
|
||||
{"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 },
|
||||
{"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
|
||||
/* The g is a special case which we don't want to output it,
|
||||
but still need it when adding implicit extensions. */
|
||||
{"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT },
|
||||
{"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
|
||||
{"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
|
||||
{"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
|
||||
{"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 },
|
||||
{"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
|
||||
{"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
|
||||
{"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
|
||||
{"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
|
||||
{"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
|
||||
{"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
|
||||
{"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
|
||||
{"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
|
||||
{"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 },
|
||||
{"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 },
|
||||
{"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
|
||||
{"l", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
|
||||
{"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
|
||||
{"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
|
||||
{"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 },
|
||||
{"b", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
|
||||
{"j", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
|
||||
{"t", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
|
||||
{"p", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
|
||||
{"v", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
|
||||
{"n", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, 0 },
|
||||
{NULL, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static const char * const riscv_std_h_ext_strtab[] =
|
||||
static struct riscv_supported_ext riscv_supported_std_z_ext[] =
|
||||
{
|
||||
NULL
|
||||
{"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
|
||||
{"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
|
||||
{"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 },
|
||||
{"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 },
|
||||
{"zihintpause", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
|
||||
{"zbb", ISA_SPEC_CLASS_DRAFT, 0, 93, 0 },
|
||||
{"zba", ISA_SPEC_CLASS_DRAFT, 0, 93, 0 },
|
||||
{"zbc", ISA_SPEC_CLASS_DRAFT, 0, 93, 0 },
|
||||
{NULL, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static const char * const riscv_std_zxm_ext_strtab[] =
|
||||
static struct riscv_supported_ext riscv_supported_std_s_ext[] =
|
||||
{
|
||||
{NULL, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static struct riscv_supported_ext riscv_supported_std_h_ext[] =
|
||||
{
|
||||
{NULL, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
|
||||
{
|
||||
{NULL, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
const struct riscv_supported_ext *riscv_all_supported_ext[] =
|
||||
{
|
||||
riscv_supported_std_ext,
|
||||
riscv_supported_std_z_ext,
|
||||
riscv_supported_std_s_ext,
|
||||
riscv_supported_std_h_ext,
|
||||
riscv_supported_std_zxm_ext,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -1156,11 +1227,11 @@ riscv_get_prefix_class (const char *arch)
|
|||
|
||||
static bool
|
||||
riscv_known_prefixed_ext (const char *ext,
|
||||
const char *const *known_exts)
|
||||
struct riscv_supported_ext *known_exts)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; known_exts[i]; ++i)
|
||||
if (strcmp (ext, known_exts[i]) == 0)
|
||||
for (i = 0; known_exts[i].name != NULL; ++i)
|
||||
if (strcmp (ext, known_exts[i].name) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -1175,13 +1246,13 @@ riscv_valid_prefixed_ext (const char *ext)
|
|||
switch (class)
|
||||
{
|
||||
case RV_ISA_CLASS_Z:
|
||||
return riscv_known_prefixed_ext (ext, riscv_std_z_ext_strtab);
|
||||
return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext);
|
||||
case RV_ISA_CLASS_ZXM:
|
||||
return riscv_known_prefixed_ext (ext, riscv_std_zxm_ext_strtab);
|
||||
return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext);
|
||||
case RV_ISA_CLASS_S:
|
||||
return riscv_known_prefixed_ext (ext, riscv_std_s_ext_strtab);
|
||||
return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext);
|
||||
case RV_ISA_CLASS_H:
|
||||
return riscv_known_prefixed_ext (ext, riscv_std_h_ext_strtab);
|
||||
return riscv_known_prefixed_ext (ext, riscv_supported_std_h_ext);
|
||||
case RV_ISA_CLASS_X:
|
||||
/* Only the single x is invalid. */
|
||||
if (strcmp (ext, "x") != 0)
|
||||
|
@ -1201,24 +1272,22 @@ static void
|
|||
riscv_init_ext_order (void)
|
||||
{
|
||||
static bool inited = false;
|
||||
const char *std_base_exts = "eig";
|
||||
const char *std_remain_exts = riscv_supported_std_ext ();
|
||||
const char *ext;
|
||||
int order;
|
||||
|
||||
if (inited)
|
||||
return;
|
||||
|
||||
/* The orders of all standard extensions are positive. */
|
||||
order = 1;
|
||||
int order = 1;
|
||||
|
||||
/* Init the standard base extensions first. */
|
||||
for (ext = std_base_exts; *ext; ext++)
|
||||
riscv_ext_order[(*ext - 'a')] = order++;
|
||||
|
||||
/* Init the standard remaining extensions. */
|
||||
for (ext = std_remain_exts; *ext; ext++)
|
||||
riscv_ext_order[(*ext - 'a')] = order++;
|
||||
int i = 0;
|
||||
while (riscv_supported_std_ext[i].name != NULL)
|
||||
{
|
||||
const char *ext = riscv_supported_std_ext[i].name;
|
||||
riscv_ext_order[(*ext - 'a')] = order++;
|
||||
i++;
|
||||
while (riscv_supported_std_ext[i].name
|
||||
&& strcmp (ext, riscv_supported_std_ext[i].name) == 0)
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Some of the prefixed keyword are not single letter, so we set
|
||||
their prefixed orders in the riscv_compare_subsets directly,
|
||||
|
@ -1345,6 +1414,46 @@ riscv_add_subset (riscv_subset_list_t *subset_list,
|
|||
subset_list->tail = new;
|
||||
}
|
||||
|
||||
/* Get the default versions from the riscv_supported_*ext tables. */
|
||||
|
||||
static void
|
||||
riscv_get_default_ext_version (enum riscv_spec_class default_isa_spec,
|
||||
const char *name,
|
||||
int *major_version,
|
||||
int *minor_version)
|
||||
{
|
||||
if (name == NULL || default_isa_spec == ISA_SPEC_CLASS_NONE)
|
||||
return;
|
||||
|
||||
struct riscv_supported_ext *table = NULL;
|
||||
enum riscv_prefix_ext_class class = riscv_get_prefix_class (name);
|
||||
switch (class)
|
||||
{
|
||||
case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break;
|
||||
case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break;
|
||||
case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break;
|
||||
case RV_ISA_CLASS_H: table = riscv_supported_std_h_ext; break;
|
||||
case RV_ISA_CLASS_X:
|
||||
break;
|
||||
default:
|
||||
table = riscv_supported_std_ext;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (table != NULL && table[i].name != NULL)
|
||||
{
|
||||
if (strcmp (table[i].name, name) == 0
|
||||
&& (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT
|
||||
|| table[i].isa_spec_class == default_isa_spec))
|
||||
{
|
||||
*major_version = table[i].major_version;
|
||||
*minor_version = table[i].minor_version;
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the default versions for the extension before adding them to
|
||||
the subset list, if their versions are RISCV_UNKNOWN_VERSION.
|
||||
Afterwards, report errors if we can not find their default versions. */
|
||||
|
@ -1359,10 +1468,10 @@ riscv_parse_add_subset (riscv_parse_subset_t *rps,
|
|||
int major_version = major;
|
||||
int minor_version = minor;
|
||||
|
||||
if ((major_version == RISCV_UNKNOWN_VERSION
|
||||
if (major_version == RISCV_UNKNOWN_VERSION
|
||||
|| minor_version == RISCV_UNKNOWN_VERSION)
|
||||
&& rps->get_default_version != NULL)
|
||||
rps->get_default_version (subset, &major_version, &minor_version);
|
||||
riscv_get_default_ext_version (rps->isa_spec, subset,
|
||||
&major_version, &minor_version);
|
||||
|
||||
/* We don't care the versions of the implicit extensions. */
|
||||
if (!implicit
|
||||
|
@ -1476,15 +1585,6 @@ riscv_parsing_subset_version (riscv_parse_subset_t *rps,
|
|||
return p;
|
||||
}
|
||||
|
||||
/* Return string which contain all supported standard extensions in
|
||||
canonical order. */
|
||||
|
||||
const char *
|
||||
riscv_supported_std_ext (void)
|
||||
{
|
||||
return "mafdqlcbjtpvn";
|
||||
}
|
||||
|
||||
/* Parsing function for standard extensions.
|
||||
|
||||
Return Value:
|
||||
|
@ -1500,59 +1600,13 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
|||
const char *arch,
|
||||
const char *p)
|
||||
{
|
||||
const char *all_std_exts = riscv_supported_std_ext ();
|
||||
const char *std_exts = all_std_exts;
|
||||
int major_version;
|
||||
int minor_version;
|
||||
char subset[2] = {0, 0};
|
||||
|
||||
/* First letter must start with i, e or g. */
|
||||
switch (*p)
|
||||
if (*p != 'e' && *p != 'i' && *p != 'g')
|
||||
{
|
||||
case 'i':
|
||||
p = riscv_parsing_subset_version (rps, arch, ++p,
|
||||
&major_version,
|
||||
&minor_version, true);
|
||||
riscv_parse_add_subset (rps, "i",
|
||||
major_version,
|
||||
minor_version, false);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
p = riscv_parsing_subset_version (rps, arch, ++p,
|
||||
&major_version,
|
||||
&minor_version, true);
|
||||
riscv_parse_add_subset (rps, "e",
|
||||
major_version,
|
||||
minor_version, false);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
p = riscv_parsing_subset_version (rps, arch, ++p,
|
||||
&major_version,
|
||||
&minor_version, true);
|
||||
/* Expand g to imafd. */
|
||||
riscv_parse_add_subset (rps, "i",
|
||||
RISCV_UNKNOWN_VERSION,
|
||||
RISCV_UNKNOWN_VERSION, false);
|
||||
for ( ; *std_exts != 'q'; std_exts++)
|
||||
{
|
||||
subset[0] = *std_exts;
|
||||
riscv_parse_add_subset (rps, subset,
|
||||
RISCV_UNKNOWN_VERSION,
|
||||
RISCV_UNKNOWN_VERSION, false);
|
||||
}
|
||||
/* Add g as an implicit extension. */
|
||||
riscv_parse_add_subset (rps, "g",
|
||||
RISCV_UNKNOWN_VERSION,
|
||||
RISCV_UNKNOWN_VERSION, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
rps->error_handler
|
||||
(_("%s: first ISA extension must be `e', `i' or `g'"),
|
||||
arch);
|
||||
return NULL;
|
||||
rps->error_handler
|
||||
(_("%s: first ISA extension must be `e', `i' or `g'"),
|
||||
arch);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (p != NULL && *p != '\0')
|
||||
|
@ -1568,32 +1622,41 @@ riscv_parse_std_ext (riscv_parse_subset_t *rps,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Checking canonical order. */
|
||||
char std_ext = *p;
|
||||
while (*std_exts && std_ext != *std_exts)
|
||||
std_exts++;
|
||||
bool implicit = false;
|
||||
int major = RISCV_UNKNOWN_VERSION;
|
||||
int minor = RISCV_UNKNOWN_VERSION;
|
||||
char subset[2] = {0, 0};
|
||||
|
||||
if (std_ext != *std_exts)
|
||||
subset[0] = *p;
|
||||
|
||||
/* Check if the standard extension is supported. */
|
||||
if (riscv_ext_order[(subset[0] - 'a')] == 0)
|
||||
{
|
||||
if (riscv_ext_order[(std_ext - 'a')] == 0)
|
||||
rps->error_handler
|
||||
(_("%s: unknown standard ISA extension `%c'"),
|
||||
arch, std_ext);
|
||||
else
|
||||
rps->error_handler
|
||||
(_("%s: standard ISA extension `%c' is not "
|
||||
"in canonical order"), arch, std_ext);
|
||||
rps->error_handler
|
||||
(_("%s: unknown standard ISA extension `%c'"),
|
||||
arch, subset[0]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std_exts++;
|
||||
subset[0] = std_ext;
|
||||
p = riscv_parsing_subset_version (rps, arch, ++p,
|
||||
&major_version,
|
||||
&minor_version, true);
|
||||
riscv_parse_add_subset (rps, subset,
|
||||
major_version,
|
||||
minor_version, false);
|
||||
/* Checking canonical order. */
|
||||
if (rps->subset_list->tail != NULL
|
||||
&& riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0)
|
||||
{
|
||||
rps->error_handler
|
||||
(_("%s: standard ISA extension `%c' is not "
|
||||
"in canonical order"), arch, subset[0]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = riscv_parsing_subset_version (rps, arch, ++p, &major, &minor, true);
|
||||
/* Added g as an implicit extension. */
|
||||
if (subset[0] == 'g')
|
||||
{
|
||||
implicit = true;
|
||||
major = RISCV_UNKNOWN_VERSION;
|
||||
minor = RISCV_UNKNOWN_VERSION;
|
||||
}
|
||||
riscv_parse_add_subset (rps, subset, major, minor, implicit);
|
||||
}
|
||||
|
||||
return p;
|
||||
|
@ -1761,6 +1824,30 @@ riscv_parse_check_conflicts (riscv_parse_subset_t *rps)
|
|||
return no_conflict;
|
||||
}
|
||||
|
||||
/* Set the default subset list according to the default_enable field
|
||||
of riscv_supported_*ext tables. */
|
||||
|
||||
static void
|
||||
riscv_set_default_arch (riscv_parse_subset_t *rps)
|
||||
{
|
||||
unsigned long enable = EXT_DEFAULT;
|
||||
int i, j;
|
||||
for (i = 0; riscv_all_supported_ext[i] != NULL; i++)
|
||||
{
|
||||
const struct riscv_supported_ext *table = riscv_all_supported_ext[i];
|
||||
for (j = 0; table[j].name != NULL; j++)
|
||||
{
|
||||
bool implicit = false;
|
||||
if (strcmp (table[j].name, "g") == 0)
|
||||
implicit = true;
|
||||
if (table[j].default_enable & enable)
|
||||
riscv_parse_add_subset (rps, table[j].name,
|
||||
RISCV_UNKNOWN_VERSION,
|
||||
RISCV_UNKNOWN_VERSION, implicit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Function for parsing ISA string.
|
||||
|
||||
Return Value:
|
||||
|
@ -1776,6 +1863,17 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
|
|||
{
|
||||
const char *p;
|
||||
|
||||
/* Init the riscv_ext_order array to compare the order of extensions
|
||||
quickly. */
|
||||
riscv_init_ext_order ();
|
||||
|
||||
if (arch == NULL)
|
||||
{
|
||||
riscv_set_default_arch (rps);
|
||||
riscv_parse_add_implicit_subsets (rps);
|
||||
return riscv_parse_check_conflicts (rps);
|
||||
}
|
||||
|
||||
for (p = arch; *p != '\0'; p++)
|
||||
{
|
||||
if (ISUPPER (*p))
|
||||
|
@ -1800,11 +1898,13 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* ISA string shouldn't be NULL or empty here. However,
|
||||
it might be empty only when we failed to merge the ISA
|
||||
string in the riscv_merge_attributes. We have already
|
||||
issued the correct error message in another side, so do
|
||||
not issue this error when the ISA string is empty. */
|
||||
/* ISA string shouldn't be NULL or empty here. For linker,
|
||||
it might be empty when we failed to merge the ISA string
|
||||
in the riscv_merge_attributes. For assembler, we might
|
||||
give an empty string by .attribute arch, "" or -march=.
|
||||
However, We have already issued the correct error message
|
||||
in another side, so do not issue this error when the ISA
|
||||
string is empty. */
|
||||
if (strlen (arch))
|
||||
rps->error_handler (
|
||||
_("%s: ISA string must begin with rv32 or rv64"),
|
||||
|
@ -1812,10 +1912,6 @@ riscv_parse_subset (riscv_parse_subset_t *rps,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Init the riscv_ext_order array to compare the order of extensions
|
||||
quickly. */
|
||||
riscv_init_ext_order ();
|
||||
|
||||
/* Parsing standard extension. */
|
||||
p = riscv_parse_std_ext (rps, arch, p);
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "elf/common.h"
|
||||
#include "elf/internal.h"
|
||||
#include "opcode/riscv.h"
|
||||
#include "cpu-riscv.h"
|
||||
|
||||
#define RISCV_UNKNOWN_VERSION -1
|
||||
|
||||
|
@ -71,9 +72,7 @@ typedef struct
|
|||
void (*error_handler) (const char *,
|
||||
...) ATTRIBUTE_PRINTF_1;
|
||||
unsigned *xlen;
|
||||
void (*get_default_version) (const char *,
|
||||
int *,
|
||||
int *);
|
||||
enum riscv_spec_class isa_spec;
|
||||
bool check_unknown_prefixed_ext;
|
||||
} riscv_parse_subset_t;
|
||||
|
||||
|
@ -81,9 +80,6 @@ extern bool
|
|||
riscv_parse_subset (riscv_parse_subset_t *,
|
||||
const char *);
|
||||
|
||||
extern const char *
|
||||
riscv_supported_std_ext (void);
|
||||
|
||||
extern void
|
||||
riscv_release_subset_list (riscv_subset_list_t *);
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "dwarf2dbg.h"
|
||||
#include "dw2gencfi.h"
|
||||
|
||||
#include "bfd/cpu-riscv.h"
|
||||
#include "bfd/elfxx-riscv.h"
|
||||
#include "elf/riscv.h"
|
||||
#include "opcode/riscv.h"
|
||||
|
@ -88,65 +87,6 @@ struct riscv_csr_extra
|
|||
struct riscv_csr_extra *next;
|
||||
};
|
||||
|
||||
/* All standard/Z* extensions defined in all supported ISA spec. */
|
||||
struct riscv_ext_version
|
||||
{
|
||||
const char *name;
|
||||
enum riscv_spec_class isa_spec_class;
|
||||
int major_version;
|
||||
int minor_version;
|
||||
};
|
||||
|
||||
static const struct riscv_ext_version ext_version_table[] =
|
||||
{
|
||||
{"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},
|
||||
|
||||
{"zicsr", ISA_SPEC_CLASS_20191213, 2, 0},
|
||||
{"zicsr", ISA_SPEC_CLASS_20190608, 2, 0},
|
||||
|
||||
{"zifencei", ISA_SPEC_CLASS_20191213, 2, 0},
|
||||
{"zifencei", ISA_SPEC_CLASS_20190608, 2, 0},
|
||||
|
||||
{"zihintpause", ISA_SPEC_CLASS_DRAFT, 1, 0},
|
||||
|
||||
{"zbb", ISA_SPEC_CLASS_DRAFT, 0, 93},
|
||||
{"zba", ISA_SPEC_CLASS_DRAFT, 0, 93},
|
||||
{"zbc", ISA_SPEC_CLASS_DRAFT, 0, 93},
|
||||
|
||||
/* Terminate the list. */
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
#ifndef DEFAULT_ARCH
|
||||
#define DEFAULT_ARCH "riscv64"
|
||||
#endif
|
||||
|
@ -349,57 +289,6 @@ riscv_multi_subset_supports (enum riscv_insn_class insn_class)
|
|||
}
|
||||
}
|
||||
|
||||
/* Handle of the extension with version hash table. */
|
||||
static htab_t ext_version_hash = NULL;
|
||||
|
||||
static htab_t
|
||||
init_ext_version_hash (void)
|
||||
{
|
||||
const struct riscv_ext_version *table = ext_version_table;
|
||||
htab_t hash = str_htab_create ();
|
||||
int i = 0;
|
||||
|
||||
while (table[i].name)
|
||||
{
|
||||
const char *name = table[i].name;
|
||||
if (str_hash_insert (hash, name, &table[i], 0) != NULL)
|
||||
as_fatal (_("internal: duplicate %s"), name);
|
||||
|
||||
i++;
|
||||
while (table[i].name
|
||||
&& strcmp (table[i].name, name) == 0)
|
||||
i++;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static void
|
||||
riscv_get_default_ext_version (const char *name,
|
||||
int *major_version,
|
||||
int *minor_version)
|
||||
{
|
||||
struct riscv_ext_version *ext;
|
||||
|
||||
if (name == NULL || default_isa_spec == ISA_SPEC_CLASS_NONE)
|
||||
return;
|
||||
|
||||
ext = (struct riscv_ext_version *) str_hash_find (ext_version_hash, name);
|
||||
while (ext
|
||||
&& ext->name
|
||||
&& strcmp (ext->name, name) == 0)
|
||||
{
|
||||
if (ext->isa_spec_class == ISA_SPEC_CLASS_DRAFT
|
||||
|| 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
|
||||
|
@ -409,11 +298,15 @@ riscv_set_arch (const char *s)
|
|||
rps.subset_list = &riscv_subsets;
|
||||
rps.error_handler = as_bad;
|
||||
rps.xlen = &xlen;
|
||||
rps.get_default_version = riscv_get_default_ext_version;
|
||||
rps.isa_spec = default_isa_spec;
|
||||
rps.check_unknown_prefixed_ext = true;
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
if (s != NULL && strcmp (s, "") == 0)
|
||||
{
|
||||
as_bad (_("the architecture string of -march and elf architecture "
|
||||
"attributes cannot be empty"));
|
||||
return;
|
||||
}
|
||||
|
||||
riscv_release_subset_list (&riscv_subsets);
|
||||
riscv_parse_subset (&rps, s);
|
||||
|
@ -3137,11 +3030,6 @@ 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";
|
||||
|
||||
/* Initialize the hash table for extensions with default version. */
|
||||
ext_version_hash = init_ext_version_hash ();
|
||||
|
||||
/* Set default specs. */
|
||||
if (default_isa_spec == ISA_SPEC_CLASS_NONE)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue