aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-riscv.c
diff options
context:
space:
mode:
authorNelson Chu <nelson.chu@sifive.com>2021-01-28 10:45:56 +0800
committerNelson Chu <nelson.chu@sifive.com>2021-02-18 15:09:16 +0800
commit3d73d29e4eff8701ae6251347d03dd6057911178 (patch)
treece9f9774e088fdf2760261983841664b13dc1e4a /gas/config/tc-riscv.c
parent6a780b6766378e3dc9610cba7e12d7eaba196f52 (diff)
downloadgdb-3d73d29e4eff8701ae6251347d03dd6057911178.zip
gdb-3d73d29e4eff8701ae6251347d03dd6057911178.tar.gz
gdb-3d73d29e4eff8701ae6251347d03dd6057911178.tar.bz2
RISC-V: Add bfd/cpu-riscv.h to support all spec versions controlling.
Make the opcode/riscv-opc.c and include/opcode/riscv.h tidy, move the spec versions stuff to bfd/cpu-riscv.h. Also move the csr stuff and ext_version_table to gas/config/tc-riscv.c for internal use. To avoid too many repeated code, define general RISCV_GET_SPEC_NAME/SPEC_CLASS macros. Therefore, assembler/dis-assembler/linker/gdb can get all spec versions related stuff from cpu-riscv.h and cpu-riscv.c, since the stuff are defined there uniformly. bfd/ * Makefile.am: Added cpu-riscv.h. * Makefile.in: Regenerated. * po/SRC-POTFILES.in: Regenerated. * cpu-riscv.h: Added to support spec versions controlling. Also added extern arrays and functions for cpu-riscv.c. (enum riscv_spec_class): Define all spec classes here uniformly. (struct riscv_spec): Added for all specs. (RISCV_GET_SPEC_CLASS): Added to reduce repeated code. (RISCV_GET_SPEC_NAME): Likewise. (RISCV_GET_ISA_SPEC_CLASS): Added to get ISA spec class. (RISCV_GET_PRIV_SPEC_CLASS): Added to get privileged spec class. (RISCV_GET_PRIV_SPEC_NAME): Added to get privileged spec name. * cpu-riscv.c (struct priv_spec_t): Replaced with struct riscv_spec. (riscv_get_priv_spec_class): Replaced with RISCV_GET_PRIV_SPEC_CLASS. (riscv_get_priv_spec_name): Replaced with RISCV_GET_PRIV_SPEC_NAME. (riscv_priv_specs): Moved below. (riscv_get_priv_spec_class_from_numbers): Likewise, updated. (riscv_isa_specs): Moved from include/opcode/riscv.h. * elfnn-riscv.c: Included cpu-riscv.h. (riscv_merge_attributes): Initialize in_priv_spec and out_priv_spec. * elfxx-riscv.c: Included cpu-riscv.h and opcode/riscv.h. (RISCV_UNKNOWN_VERSION): Moved from include/opcode/riscv.h. * elfxx-riscv.h: Removed extern functions to cpu-riscv.h. gas/ * config/tc-riscv.c: Included cpu-riscv.h. (enum riscv_csr_clas): Moved from include/opcode/riscv.h. (struct riscv_csr_extra): Likewise. (struct riscv_ext_version): Likewise. (ext_version_table): Moved from opcodes/riscv-opc.c. (default_isa_spec): Updated type to riscv_spec_class. (default_priv_spec): Likewise. (riscv_set_default_isa_spec): Updated. (init_ext_version_hash): Likewise. (riscv_init_csr_hash): Likewise, also fixed indent. include/ * opcode/riscv.h: Moved stuff and make the file tidy. opcodes/ * riscv-dis.c: Included cpu-riscv.h, and removed elfxx-riscv.h. (default_priv_spec): Updated type to riscv_spec_class. (parse_riscv_dis_option): Updated. * riscv-opc.c: Moved stuff and make the file tidy.
Diffstat (limited to 'gas/config/tc-riscv.c')
-rw-r--r--gas/config/tc-riscv.c137
1 files changed, 113 insertions, 24 deletions
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 44d9cb1..44450d7 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -29,6 +29,7 @@
#include "dwarf2dbg.h"
#include "dw2gencfi.h"
+#include "bfd/cpu-riscv.h"
#include "bfd/elfxx-riscv.h"
#include "elf/riscv.h"
#include "opcode/riscv.h"
@@ -55,6 +56,93 @@ struct riscv_cl_insn
fixS *fixp;
};
+/* All RISC-V CSR belong to one of these classes. */
+enum riscv_csr_class
+{
+ CSR_CLASS_NONE,
+
+ CSR_CLASS_I,
+ CSR_CLASS_I_32, /* rv32 only */
+ CSR_CLASS_F, /* f-ext only */
+ CSR_CLASS_DEBUG /* debug CSR */
+};
+
+/* This structure holds all restricted conditions for a CSR. */
+struct riscv_csr_extra
+{
+ /* Class to which this CSR belongs. Used to decide whether or
+ not this CSR is legal in the current -march context. */
+ enum riscv_csr_class csr_class;
+
+ /* CSR may have differnet numbers in the previous priv spec. */
+ unsigned address;
+
+ /* Record the CSR is defined/valid in which versions. */
+ enum riscv_spec_class define_version;
+
+ /* Record the CSR is aborted/invalid from which versions. If it isn't
+ aborted in the current version, then it should be CSR_CLASS_VDRAFT. */
+ enum riscv_spec_class abort_version;
+
+ /* The CSR may have more than one setting. */
+ 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},
+
+ /* Terminate the list. */
+ {NULL, 0, 0, 0}
+};
+
#ifndef DEFAULT_ARCH
#define DEFAULT_ARCH "riscv64"
#endif
@@ -79,8 +167,8 @@ struct riscv_cl_insn
static const char default_arch[] = DEFAULT_ARCH;
static const char *default_arch_with_ext = DEFAULT_RISCV_ARCH_WITH_EXT;
-static enum riscv_isa_spec_class default_isa_spec = ISA_SPEC_CLASS_NONE;
-static enum riscv_priv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE;
+static enum riscv_spec_class default_isa_spec = ISA_SPEC_CLASS_NONE;
+static enum riscv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE;
static unsigned xlen = 0; /* The width of an x-register. */
static unsigned abi_xlen = 0; /* The width of a pointer in the ABI. */
@@ -106,8 +194,9 @@ static unsigned elf_flags = 0;
static int
riscv_set_default_isa_spec (const char *s)
{
- enum riscv_isa_spec_class class;
- if (!riscv_get_isa_spec_class (s, &class))
+ enum riscv_spec_class class = ISA_SPEC_CLASS_NONE;
+ RISCV_GET_ISA_SPEC_CLASS (s, class);
+ if (class == ISA_SPEC_CLASS_NONE)
{
as_bad ("unknown default ISA spec `%s' set by "
"-misa-spec or --with-isa-spec", s);
@@ -125,11 +214,12 @@ riscv_set_default_isa_spec (const char *s)
static int
riscv_set_default_priv_spec (const char *s)
{
- enum riscv_priv_spec_class class;
+ enum riscv_spec_class class = PRIV_SPEC_CLASS_NONE;
unsigned major, minor, revision;
obj_attribute *attr;
- if (riscv_get_priv_spec_class (s, &class))
+ RISCV_GET_PRIV_SPEC_CLASS (s, class);
+ if (class != PRIV_SPEC_CLASS_NONE)
{
default_priv_spec = class;
return 1;
@@ -147,15 +237,13 @@ riscv_set_default_priv_spec (const char *s)
major = (unsigned) attr[Tag_RISCV_priv_spec].i;
minor = (unsigned) attr[Tag_RISCV_priv_spec_minor].i;
revision = (unsigned) attr[Tag_RISCV_priv_spec_revision].i;
- if (riscv_get_priv_spec_class_from_numbers (major,
- minor,
- revision,
- &class))
- {
- /* 0.0.0 is meaningless. */
- if (class == PRIV_SPEC_CLASS_NONE)
- return 1;
+ /* Version 0.0.0 is the default value and meningless. */
+ if (major == 0 && minor == 0 && revision == 0)
+ return 1;
+ riscv_get_priv_spec_class_from_numbers (major, minor, revision, &class);
+ if (class != PRIV_SPEC_CLASS_NONE)
+ {
default_priv_spec = class;
return 1;
}
@@ -252,10 +340,11 @@ riscv_multi_subset_supports (enum riscv_insn_class insn_class)
static htab_t ext_version_hash = NULL;
static htab_t
-init_ext_version_hash (const struct riscv_ext_version *table)
+init_ext_version_hash (void)
{
- int i = 0;
+ const struct riscv_ext_version *table = ext_version_table;
htab_t hash = str_htab_create ();
+ int i = 0;
while (table[i].name)
{
@@ -687,10 +776,10 @@ hash_reg_names (enum reg_class class, const char * const names[], unsigned n)
static void
riscv_init_csr_hash (const char *name,
- unsigned address,
- enum riscv_csr_class class,
- enum riscv_priv_spec_class define_version,
- enum riscv_priv_spec_class abort_version)
+ unsigned address,
+ enum riscv_csr_class class,
+ enum riscv_spec_class define_version,
+ enum riscv_spec_class abort_version)
{
struct riscv_csr_extra *entry, *pre_entry;
bfd_boolean need_enrty = TRUE;
@@ -782,8 +871,8 @@ riscv_csr_address (const char *csr_name,
so use the newly defined value. */
if (riscv_opts.csr_check)
{
- const char *priv_name = riscv_get_priv_spec_name (default_priv_spec);
-
+ const char *priv_name = NULL;
+ RISCV_GET_PRIV_SPEC_NAME (priv_name, default_priv_spec);
if (priv_name != NULL)
as_warn (_("invalid CSR `%s' for the privileged spec `%s'"),
csr_name, priv_name);
@@ -2812,7 +2901,7 @@ riscv_after_parse_args (void)
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);
+ ext_version_hash = init_ext_version_hash ();
/* Set default specs. */
if (default_isa_spec == ISA_SPEC_CLASS_NONE)
@@ -3648,7 +3737,7 @@ riscv_write_out_attrs (void)
if (!explicit_priv_attr)
return;
- priv_str = riscv_get_priv_spec_name (default_priv_spec);
+ RISCV_GET_PRIV_SPEC_NAME (priv_str, default_priv_spec);
p = priv_str;
for (i = 0; *p; ++p)
{