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. */
/* 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
static unsigned int riscv_debug_unwinder = 0;
-/* Read the MISA register from the target. The register will only be read
- once, and the value read will be cached. If the register can't be read
- from the target then a default value (0) will be returned. If the
- pointer READ_P is not null, then the bool pointed to is updated to
- indicate if the value returned was read from the target (true) or is the
- default (false). */
+/* Read the MISA register from the target. There are a couple of locations
+ that the register might be found, these are all tried. If the MISA
+ register can't be found at all then the default value of 0 is returned,
+ this is inline with the RISC-V specification. */
static uint32_t
-riscv_read_misa_reg (bool *read_p)
+riscv_read_misa_reg ()
{
uint32_t value = 0;
if (target_has_registers)
{
+ /* Old cores might have MISA located at a different offset. */
+ static int misa_regs[] =
+ { RISCV_CSR_MISA_REGNUM, RISCV_CSR_LEGACY_MISA_REGNUM };
+
struct frame_info *frame = get_current_frame ();
- TRY
+ for (int i = 0; i < ARRAY_SIZE (misa_regs); ++i)
{
- value = get_frame_register_unsigned (frame,
- RISCV_CSR_MISA_REGNUM);
- }
- CATCH (ex, RETURN_MASK_ERROR)
- {
- /* Old cores might have MISA located at a different offset. */
- value = get_frame_register_unsigned (frame,
- RISCV_CSR_LEGACY_MISA_REGNUM);
+ bool success = false;
+
+ TRY
+ {
+ value = get_frame_register_unsigned (frame, misa_regs[i]);
+ success = true;
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ /* Ignore errors, it is acceptable for a target to not
+ provide a MISA register, in which case the default value
+ of 0 should be used. */
+ }
+ END_CATCH
+
+ if (success)
+ break;
}
- END_CATCH
}
return value;
static bool
riscv_has_feature (struct gdbarch *gdbarch, char feature)
{
- bool have_read_misa = false;
- uint32_t misa;
-
gdb_assert (feature >= 'A' && feature <= 'Z');
- misa = riscv_read_misa_reg (&have_read_misa);
- if (!have_read_misa || misa == 0)
+ uint32_t misa = riscv_read_misa_reg ();
+ if (misa == 0)
misa = gdbarch_tdep (gdbarch)->core_features;
return (misa & (1 << (feature - 'A'))) != 0;
}
-/* Return the width in bytes of the general purpose registers for GDBARCH.
- Possible return values are 4, 8, or 16 for RiscV variants RV32, RV64, or
- RV128. */
+/* See riscv-tdep.h. */
int
riscv_isa_xlen (struct gdbarch *gdbarch)
}
}
-/* Return the width in bytes of the floating point registers for GDBARCH.
- If this architecture has no floating point registers, then return 0.
- Possible values are 4, 8, or 16 for depending on which of single, double
- or quad floating point support is available. */
+/* See riscv-tdep.h. */
-static int
+int
riscv_isa_flen (struct gdbarch *gdbarch)
{
if (riscv_has_feature (gdbarch, 'Q'))
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)
{
- static char buf[20];
+#define DECLARE_CSR(NAME,VALUE) \
+ case RISCV_ ## VALUE ## _REGNUM: return # NAME;
+
+ switch (regnum)
+ {
+ #include "opcode/riscv-opc.h"
+ default:
+ {
+ static char buf[20];
- xsnprintf (buf, sizeof (buf), "csr%d",
- regnum - RISCV_FIRST_CSR_REGNUM);
- return buf;
+ xsnprintf (buf, sizeof (buf), "csr%d",
+ regnum - RISCV_FIRST_CSR_REGNUM);
+ return buf;
+ }
+ }
+#undef DECLARE_CSR
}
if (regnum == RISCV_PRIV_REGNUM)
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? */
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
{
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)
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)
set_gdbarch_return_value (gdbarch, riscv_return_value);
set_gdbarch_breakpoint_kind_from_pc (gdbarch, riscv_breakpoint_kind_from_pc);
set_gdbarch_sw_breakpoint_from_kind (gdbarch, riscv_sw_breakpoint_from_kind);
+ set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
/* Register architecture. */
set_gdbarch_num_regs (gdbarch, RISCV_LAST_REGNUM + 1);