aboutsummaryrefslogtreecommitdiff
path: root/gdb/riscv-tdep.c
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2018-10-16 22:40:09 +0100
committerAndrew Burgess <andrew.burgess@embecosm.com>2018-10-23 10:32:34 +0100
commit0dbfcfffe9abbc5198bce95eb8c66b6bc9b364be (patch)
tree389fd6bdc0b2f58914bfbdf59b28ea798ae5be33 /gdb/riscv-tdep.c
parentba37fe2e8b13194a1ef216f4224d7521e748e1cf (diff)
downloadgdb-0dbfcfffe9abbc5198bce95eb8c66b6bc9b364be.zip
gdb-0dbfcfffe9abbc5198bce95eb8c66b6bc9b364be.tar.gz
gdb-0dbfcfffe9abbc5198bce95eb8c66b6bc9b364be.tar.bz2
gdb/riscv: Fix register access for register aliases
Some confusion over how the register names and aliases are setup in riscv means that we currently can't access registers through their architectural name. This commit fixes this issue, and moves some of the csr register handling out of the alias handling code and deals with it separately. This has the benefit that we can now directly access some arrays rather than having to iterate over them. A new test is added to ensure that register aliases now work correctly. gdb/ChangeLog: * riscv-tdep.c (riscv_gdb_reg_names): Update comment, and all register names. (struct register_alias): Rename to... (struct riscv_register_alias): ...this, and update comment. (riscv_register_aliases): Update type, and alias names. Remove CSR names from this list. (riscv_register_name): Use riscv_gdb_reg_names for int and float register names. Add an extra assertion. (riscv_is_regnum_a_named_csr): New function. (riscv_register_reggroup_p): Use riscv_is_regnum_a_named_csr. gdb/testsuite/ChangeLog: * gdb.arch/riscv-reg-aliases.c: New file. * gdb.arch/riscv-reg-aliases.exp: New file.
Diffstat (limited to 'gdb/riscv-tdep.c')
-rw-r--r--gdb/riscv-tdep.c221
1 files changed, 116 insertions, 105 deletions
diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c
index dd80f95..2fd335a 100644
--- a/gdb/riscv-tdep.c
+++ b/gdb/riscv-tdep.c
@@ -95,24 +95,25 @@ struct riscv_unwind_cache
CORE_ADDR frame_base;
};
-/* Architectural name for core registers. */
+/* The preferred register names for all the general purpose and floating
+ point registers. These are what GDB will use when referencing a
+ register. */
static const char * const riscv_gdb_reg_names[RISCV_LAST_FP_REGNUM + 1] =
{
- "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
- "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
- "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
- "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
- "pc",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "s1",
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4",
+ "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
+ "pc",
+ "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", "fs0", "fs1",
+ "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", "fs2", "fs3",
+ "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", "fs10", "fs11", "ft8", "ft9",
+ "ft10", "ft11",
};
-/* Maps "pretty" register names onto their GDB register number. */
+/* Map alternative register names onto their GDB register number. */
-struct register_alias
+struct riscv_register_alias
{
/* The register alias. Usually more descriptive than the
architectural name of the register. */
@@ -124,77 +125,78 @@ struct register_alias
/* Table of register aliases. */
-static const struct register_alias riscv_register_aliases[] =
-{
- { "zero", 0 },
- { "ra", 1 },
- { "sp", 2 },
- { "gp", 3 },
- { "tp", 4 },
- { "t0", 5 },
- { "t1", 6 },
- { "t2", 7 },
- { "s0", 8 },
- { "fp", 8 },
- { "s1", 9 },
- { "a0", 10 },
- { "a1", 11 },
- { "a2", 12 },
- { "a3", 13 },
- { "a4", 14 },
- { "a5", 15 },
- { "a6", 16 },
- { "a7", 17 },
- { "s2", 18 },
- { "s3", 19 },
- { "s4", 20 },
- { "s5", 21 },
- { "s6", 22 },
- { "s7", 23 },
- { "s8", 24 },
- { "s9", 25 },
- { "s10", 26 },
- { "s11", 27 },
- { "t3", 28 },
- { "t4", 29 },
- { "t5", 30 },
- { "t6", 31 },
- /* pc is 32. */
- { "ft0", 33 },
- { "ft1", 34 },
- { "ft2", 35 },
- { "ft3", 36 },
- { "ft4", 37 },
- { "ft5", 38 },
- { "ft6", 39 },
- { "ft7", 40 },
- { "fs0", 41 },
- { "fs1", 42 },
- { "fa0", 43 },
- { "fa1", 44 },
- { "fa2", 45 },
- { "fa3", 46 },
- { "fa4", 47 },
- { "fa5", 48 },
- { "fa6", 49 },
- { "fa7", 50 },
- { "fs2", 51 },
- { "fs3", 52 },
- { "fs4", 53 },
- { "fs5", 54 },
- { "fs6", 55 },
- { "fs7", 56 },
- { "fs8", 57 },
- { "fs9", 58 },
- { "fs10", 59 },
- { "fs11", 60 },
- { "ft8", 61 },
- { "ft9", 62 },
- { "ft10", 63 },
- { "ft11", 64 },
-#define DECLARE_CSR(name, num) { #name, (num) + 65 },
-#include "opcode/riscv-opc.h"
-#undef DECLARE_CSR
+static const struct riscv_register_alias riscv_register_aliases[] =
+{
+ /* Aliases for general purpose registers. These are the architectural
+ names, as GDB uses the more user friendly names by default. */
+ { "x0", (RISCV_ZERO_REGNUM + 0) },
+ { "x1", (RISCV_ZERO_REGNUM + 1) },
+ { "x2", (RISCV_ZERO_REGNUM + 2) },
+ { "x3", (RISCV_ZERO_REGNUM + 3) },
+ { "x4", (RISCV_ZERO_REGNUM + 4) },
+ { "x5", (RISCV_ZERO_REGNUM + 5) },
+ { "x6", (RISCV_ZERO_REGNUM + 6) },
+ { "x7", (RISCV_ZERO_REGNUM + 7) },
+ { "x8", (RISCV_ZERO_REGNUM + 8) },
+ { "s0", (RISCV_ZERO_REGNUM + 8) }, /* fp, s0, and x8 are all aliases. */
+ { "x9", (RISCV_ZERO_REGNUM + 9) },
+ { "x10", (RISCV_ZERO_REGNUM + 10) },
+ { "x11", (RISCV_ZERO_REGNUM + 11) },
+ { "x12", (RISCV_ZERO_REGNUM + 12) },
+ { "x13", (RISCV_ZERO_REGNUM + 13) },
+ { "x14", (RISCV_ZERO_REGNUM + 14) },
+ { "x15", (RISCV_ZERO_REGNUM + 15) },
+ { "x16", (RISCV_ZERO_REGNUM + 16) },
+ { "x17", (RISCV_ZERO_REGNUM + 17) },
+ { "x18", (RISCV_ZERO_REGNUM + 18) },
+ { "x19", (RISCV_ZERO_REGNUM + 19) },
+ { "x20", (RISCV_ZERO_REGNUM + 20) },
+ { "x21", (RISCV_ZERO_REGNUM + 21) },
+ { "x22", (RISCV_ZERO_REGNUM + 22) },
+ { "x23", (RISCV_ZERO_REGNUM + 23) },
+ { "x24", (RISCV_ZERO_REGNUM + 24) },
+ { "x25", (RISCV_ZERO_REGNUM + 25) },
+ { "x26", (RISCV_ZERO_REGNUM + 26) },
+ { "x27", (RISCV_ZERO_REGNUM + 27) },
+ { "x28", (RISCV_ZERO_REGNUM + 28) },
+ { "x29", (RISCV_ZERO_REGNUM + 29) },
+ { "x30", (RISCV_ZERO_REGNUM + 30) },
+ { "x31", (RISCV_ZERO_REGNUM + 31) },
+
+ /* Aliases for the floating-point registers. These are the architectural
+ names as GDB uses the more user friendly names by default. */
+ { "f0", (RISCV_FIRST_FP_REGNUM + 0) },
+ { "f1", (RISCV_FIRST_FP_REGNUM + 1) },
+ { "f2", (RISCV_FIRST_FP_REGNUM + 2) },
+ { "f3", (RISCV_FIRST_FP_REGNUM + 3) },
+ { "f4", (RISCV_FIRST_FP_REGNUM + 4) },
+ { "f5", (RISCV_FIRST_FP_REGNUM + 5) },
+ { "f6", (RISCV_FIRST_FP_REGNUM + 6) },
+ { "f7", (RISCV_FIRST_FP_REGNUM + 7) },
+ { "f8", (RISCV_FIRST_FP_REGNUM + 8) },
+ { "f9", (RISCV_FIRST_FP_REGNUM + 9) },
+ { "f10", (RISCV_FIRST_FP_REGNUM + 10) },
+ { "f11", (RISCV_FIRST_FP_REGNUM + 11) },
+ { "f12", (RISCV_FIRST_FP_REGNUM + 12) },
+ { "f13", (RISCV_FIRST_FP_REGNUM + 13) },
+ { "f14", (RISCV_FIRST_FP_REGNUM + 14) },
+ { "f15", (RISCV_FIRST_FP_REGNUM + 15) },
+ { "f16", (RISCV_FIRST_FP_REGNUM + 16) },
+ { "f17", (RISCV_FIRST_FP_REGNUM + 17) },
+ { "f18", (RISCV_FIRST_FP_REGNUM + 18) },
+ { "f19", (RISCV_FIRST_FP_REGNUM + 19) },
+ { "f20", (RISCV_FIRST_FP_REGNUM + 20) },
+ { "f21", (RISCV_FIRST_FP_REGNUM + 21) },
+ { "f22", (RISCV_FIRST_FP_REGNUM + 22) },
+ { "f23", (RISCV_FIRST_FP_REGNUM + 23) },
+ { "f24", (RISCV_FIRST_FP_REGNUM + 24) },
+ { "f25", (RISCV_FIRST_FP_REGNUM + 25) },
+ { "f26", (RISCV_FIRST_FP_REGNUM + 26) },
+ { "f27", (RISCV_FIRST_FP_REGNUM + 27) },
+ { "f28", (RISCV_FIRST_FP_REGNUM + 28) },
+ { "f29", (RISCV_FIRST_FP_REGNUM + 29) },
+ { "f30", (RISCV_FIRST_FP_REGNUM + 30) },
+ { "f31", (RISCV_FIRST_FP_REGNUM + 31) },
};
/* Controls whether we place compressed breakpoints or not. When in auto
@@ -468,17 +470,15 @@ static const char *
riscv_register_name (struct gdbarch *gdbarch, int regnum)
{
/* Prefer to use the alias. */
- if (regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_LAST_REGNUM)
+ if (regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_LAST_FP_REGNUM)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE (riscv_register_aliases); ++i)
- if (regnum == riscv_register_aliases[i].regnum)
- return riscv_register_aliases[i].name;
+ gdb_assert (regnum < ARRAY_SIZE (riscv_gdb_reg_names));
+ return riscv_gdb_reg_names[regnum];
}
- if (regnum >= RISCV_ZERO_REGNUM && regnum <= RISCV_LAST_FP_REGNUM)
- return riscv_gdb_reg_names[regnum];
+ /* Check that there's no gap between the set of registers handled above,
+ and the set of registers handled next. */
+ gdb_assert ((RISCV_LAST_FP_REGNUM + 1) == RISCV_FIRST_CSR_REGNUM);
if (regnum >= RISCV_FIRST_CSR_REGNUM && regnum <= RISCV_LAST_CSR_REGNUM)
{
@@ -838,6 +838,27 @@ riscv_print_one_register_info (struct gdbarch *gdbarch,
fprintf_filtered (file, "\n");
}
+/* Return true if REGNUM is a valid CSR register. The CSR register space
+ is sparsely populated, so not every number is a named CSR. */
+
+static bool
+riscv_is_regnum_a_named_csr (int regnum)
+{
+ gdb_assert (regnum >= RISCV_FIRST_CSR_REGNUM
+ && regnum <= RISCV_LAST_CSR_REGNUM);
+
+ switch (regnum)
+ {
+#define DECLARE_CSR(name, num) case RISCV_ ## num ## _REGNUM:
+#include "opcode/riscv-opc.h"
+#undef DECLARE_CSR
+ return true;
+
+ default:
+ return false;
+ }
+}
+
/* Implement the register_reggroup_p gdbarch method. Is REGNUM a member
of REGGROUP? */
@@ -845,8 +866,6 @@ static int
riscv_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
struct reggroup *reggroup)
{
- unsigned int i;
-
/* Used by 'info registers' and 'info registers <groupname>'. */
if (gdbarch_register_name (gdbarch, regnum) == NULL
@@ -857,12 +876,8 @@ riscv_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
{
if (regnum < RISCV_FIRST_CSR_REGNUM || regnum == RISCV_PRIV_REGNUM)
return 1;
- /* Only include CSRs that have aliases. */
- for (i = 0; i < ARRAY_SIZE (riscv_register_aliases); ++i)
- {
- if (regnum == riscv_register_aliases[i].regnum)
- return 1;
- }
+ if (riscv_is_regnum_a_named_csr (regnum))
+ return 1;
return 0;
}
else if (reggroup == float_reggroup)
@@ -885,12 +900,8 @@ riscv_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
return 1;
if (regnum < RISCV_FIRST_CSR_REGNUM || regnum > RISCV_LAST_CSR_REGNUM)
return 0;
- /* Only include CSRs that have aliases. */
- for (i = 0; i < ARRAY_SIZE (riscv_register_aliases); ++i)
- {
- if (regnum == riscv_register_aliases[i].regnum)
- return 1;
- }
+ if (riscv_is_regnum_a_named_csr (regnum))
+ return 1;
return 0;
}
else if (reggroup == vector_reggroup)