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:
Nelson Chu 2021-09-16 14:36:54 +08:00
parent 648d5dc4e6
commit c9f2799101
4 changed files with 235 additions and 256 deletions

View file

@ -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)

View file

@ -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);

View file

@ -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 *);

View file

@ -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)