diff --git a/src/target/riscv/gdb_regs.h b/src/target/riscv/gdb_regs.h index 2952e10ab..3f60d018d 100644 --- a/src/target/riscv/gdb_regs.h +++ b/src/target/riscv/gdb_regs.h @@ -4,12 +4,41 @@ // gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in // its source tree. We must interpret the numbers the same here. enum gdb_regno { - GDB_REGNO_XPR0 = 0, - GDB_REGNO_X0 = GDB_REGNO_XPR0 + 0, - GDB_REGNO_ZERO = GDB_REGNO_XPR0 + 0, - GDB_REGNO_S0 = GDB_REGNO_XPR0 + 8, - GDB_REGNO_S1 = GDB_REGNO_XPR0 + 9, - GDB_REGNO_XPR31 = GDB_REGNO_XPR0 + 31, + GDB_REGNO_ZERO = 0, /* Read-only register, always 0. */ + GDB_REGNO_RA = 1, /* Return Address. */ + GDB_REGNO_SP = 2, /* Stack Pointer. */ + GDB_REGNO_GP = 3, /* Global Pointer. */ + GDB_REGNO_TP = 4, /* Thread Pointer. */ + GDB_REGNO_T0, + GDB_REGNO_T1, + GDB_REGNO_T2, + GDB_REGNO_S0 = 8, + GDB_REGNO_FP = 8, /* Frame Pointer. */ + GDB_REGNO_S1, + GDB_REGNO_A0 = 10, /* First argument. */ + GDB_REGNO_A1 = 11, /* Second argument. */ + GDB_REGNO_A2, + GDB_REGNO_A3, + GDB_REGNO_A4, + GDB_REGNO_A5, + GDB_REGNO_A6, + GDB_REGNO_A7, + GDB_REGNO_S2, + GDB_REGNO_S3, + GDB_REGNO_S4, + GDB_REGNO_S5, + GDB_REGNO_S6, + GDB_REGNO_S7, + GDB_REGNO_S8, + GDB_REGNO_S9, + GDB_REGNO_S10, + GDB_REGNO_S11, + GDB_REGNO_T3, + GDB_REGNO_T4, + GDB_REGNO_T5, + GDB_REGNO_T6, + GDB_REGNO_XPR31 = GDB_REGNO_T6, + GDB_REGNO_PC = 32, GDB_REGNO_FPR0 = 33, GDB_REGNO_FPR31 = GDB_REGNO_FPR0 + 31, diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c index e7238ddce..0c0dbd8bf 100644 --- a/src/target/riscv/program.c +++ b/src/target/riscv/program.c @@ -45,7 +45,7 @@ int riscv_program_exec(struct riscv_program *p, struct target *t) keep_alive(); riscv_reg_t saved_registers[GDB_REGNO_XPR31 + 1]; - for (size_t i = GDB_REGNO_XPR0 + 1; i <= GDB_REGNO_XPR31; ++i) { + for (size_t i = GDB_REGNO_ZERO + 1; i <= GDB_REGNO_XPR31; ++i) { if (p->writes_xreg[i]) { LOG_DEBUG("Saving register %d as used by program", (int)i); saved_registers[i] = riscv_get_register(t, i); @@ -72,7 +72,7 @@ int riscv_program_exec(struct riscv_program *p, struct target *t) if (i >= riscv_debug_buffer_size(p->target)) p->debug_buffer[i] = riscv_read_debug_buffer(t, i); - for (size_t i = GDB_REGNO_XPR0; i <= GDB_REGNO_XPR31; ++i) + for (size_t i = GDB_REGNO_ZERO; i <= GDB_REGNO_XPR31; ++i) if (p->writes_xreg[i]) riscv_set_register(t, i, saved_registers[i]); @@ -112,13 +112,13 @@ int riscv_program_lbr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno int riscv_program_csrr(struct riscv_program *p, enum gdb_regno d, enum gdb_regno csr) { assert(csr >= GDB_REGNO_CSR0 && csr <= GDB_REGNO_CSR4095); - return riscv_program_insert(p, csrrs(d, GDB_REGNO_X0, csr - GDB_REGNO_CSR0)); + return riscv_program_insert(p, csrrs(d, GDB_REGNO_ZERO, csr - GDB_REGNO_CSR0)); } int riscv_program_csrw(struct riscv_program *p, enum gdb_regno s, enum gdb_regno csr) { assert(csr >= GDB_REGNO_CSR0); - return riscv_program_insert(p, csrrw(GDB_REGNO_X0, s, csr - GDB_REGNO_CSR0)); + return riscv_program_insert(p, csrrw(GDB_REGNO_ZERO, s, csr - GDB_REGNO_CSR0)); } int riscv_program_fence_i(struct riscv_program *p) diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 6e576fef9..1382387d3 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -1344,7 +1344,7 @@ static int register_write(struct target *target, unsigned int number, cache_set_store(target, 1, S0, SLOT_LAST); cache_set_jump(target, 2); } else if (number <= GDB_REGNO_XPR31) { - cache_set_load(target, 0, number - GDB_REGNO_XPR0, SLOT0); + cache_set_load(target, 0, number - GDB_REGNO_ZERO, SLOT0); cache_set_jump(target, 1); } else if (number == GDB_REGNO_PC) { info->dpc = value; diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index a63d168c9..4238273a6 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -647,7 +647,7 @@ static uint32_t access_register_command(uint32_t number, unsigned size, if (number <= GDB_REGNO_XPR31) { command = set_field(command, AC_ACCESS_REGISTER_REGNO, - 0x1000 + number - GDB_REGNO_XPR0); + 0x1000 + number - GDB_REGNO_ZERO); } else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { command = set_field(command, AC_ACCESS_REGISTER_REGNO, 0x1020 + number - GDB_REGNO_FPR0); @@ -1104,6 +1104,16 @@ static struct reg_arch_type riscv_reg_arch_type = { .set = register_set }; +struct csr_info { + unsigned number; + const char *name; +}; + +static int cmp_csr_info(const void *p1, const void *p2) +{ + return (int) (((struct csr_info *)p1)->number) - (int) (((struct csr_info *)p2)->number); +} + static int init_registers(struct target *target) { riscv013_info_t *info = get_info(target); @@ -1148,6 +1158,14 @@ static int init_registers(struct target *target) .type = REG_TYPE_IEEE_DOUBLE, .id = "ieee_double" }; + struct csr_info csr_info[] = { +#define DECLARE_CSR(name, number) { number, #name }, +#include "encoding.h" +#undef DECLARE_CSR + }; + // encoding.h does not contain the registers in sorted order. + qsort(csr_info, DIM(csr_info), sizeof(*csr_info), cmp_csr_info); + unsigned csr_info_index = 0; // When gdb request register N, gdb_get_register_packet() assumes that this // is register at index N in reg_list. So if there are certain registers @@ -1167,7 +1185,40 @@ static int init_registers(struct target *target) // target is in theory allowed to change XLEN on us. But I expect a lot // of other things to break in that case as well. if (number <= GDB_REGNO_XPR31) { - sprintf(reg_name, "x%d", number); + switch (number) { + case GDB_REGNO_ZERO: r->name = "zero"; break; + case GDB_REGNO_RA: r->name = "ra"; break; + case GDB_REGNO_SP: r->name = "sp"; break; + case GDB_REGNO_GP: r->name = "gp"; break; + case GDB_REGNO_TP: r->name = "tp"; break; + case GDB_REGNO_T0: r->name = "t0"; break; + case GDB_REGNO_T1: r->name = "t1"; break; + case GDB_REGNO_T2: r->name = "t2"; break; + case GDB_REGNO_FP: r->name = "fp"; break; + case GDB_REGNO_S1: r->name = "s1"; break; + case GDB_REGNO_A0: r->name = "a0"; break; + case GDB_REGNO_A1: r->name = "a1"; break; + case GDB_REGNO_A2: r->name = "a2"; break; + case GDB_REGNO_A3: r->name = "a3"; break; + case GDB_REGNO_A4: r->name = "a4"; break; + case GDB_REGNO_A5: r->name = "a5"; break; + case GDB_REGNO_A6: r->name = "a6"; break; + case GDB_REGNO_A7: r->name = "a7"; break; + case GDB_REGNO_S2: r->name = "s2"; break; + case GDB_REGNO_S3: r->name = "s3"; break; + case GDB_REGNO_S4: r->name = "s4"; break; + case GDB_REGNO_S5: r->name = "s5"; break; + case GDB_REGNO_S6: r->name = "s6"; break; + case GDB_REGNO_S7: r->name = "s7"; break; + case GDB_REGNO_S8: r->name = "s8"; break; + case GDB_REGNO_S9: r->name = "s9"; break; + case GDB_REGNO_S10: r->name = "s10"; break; + case GDB_REGNO_S11: r->name = "s11"; break; + case GDB_REGNO_T3: r->name = "t3"; break; + case GDB_REGNO_T4: r->name = "t4"; break; + case GDB_REGNO_T5: r->name = "t5"; break; + case GDB_REGNO_T6: r->name = "t6"; break; + } r->group = "general"; r->feature = &feature_cpu; } else if (number == GDB_REGNO_PC) { @@ -1189,36 +1240,33 @@ static int init_registers(struct target *target) r->group = "csr"; r->feature = &feature_csr; r->exist = true; - switch (number) { + unsigned csr_number = number - GDB_REGNO_CSR0; + + while (csr_info[csr_info_index].number < csr_number) { + csr_info_index++; + } + if (csr_info[csr_info_index].number == csr_number) { + r->name = csr_info[csr_info_index].name; + } else { + sprintf(reg_name, "csr%d", csr_number); + } + + switch (csr_number) { case CSR_FFLAGS: - strcpy(reg_name, "fflags"); r->exist = riscv_supports_extension(target, 'F'); r->group = "float"; r->feature = &feature_fpu; break; case CSR_FRM: - strcpy(reg_name, "frm"); r->exist = riscv_supports_extension(target, 'F'); r->group = "float"; r->feature = &feature_fpu; break; case CSR_FCSR: - strcpy(reg_name, "fcsr"); r->exist = riscv_supports_extension(target, 'F'); r->group = "float"; r->feature = &feature_fpu; break; - case CSR_CYCLE: - strcpy(reg_name, "cycle"); - break; - case CSR_TIME: - strcpy(reg_name, "time"); - break; - case CSR_INSTRET: - strcpy(reg_name, "instret"); - break; - default: - sprintf(reg_name, "csr%d", number - GDB_REGNO_CSR0); } } else if (number == GDB_REGNO_PRIV) { sprintf(reg_name, "priv"); diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 431e06f79..a196fdce8 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -151,21 +151,6 @@ typedef enum slot { #define DBUS_ADDRESS_UNKNOWN 0xffff -// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in -// its source tree. We must interpret the numbers the same here. -enum { - REG_XPR0 = 0, - REG_XPR31 = 31, - REG_PC = 32, - REG_FPR0 = 33, - REG_FPR31 = 64, - REG_CSR0 = 65, - REG_MSTATUS = CSR_MSTATUS + REG_CSR0, - REG_CSR4095 = 4160, - REG_PRIV = 4161, - REG_COUNT -}; - #define MAX_HWBPS 16 #define DRAM_CACHE_SIZE 16 @@ -842,7 +827,7 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params, return ERROR_FAIL; } - if (r->number > REG_XPR31) { + if (r->number > GDB_REGNO_XPR31) { LOG_ERROR("Only GPRs can be use as argument registers."); return ERROR_FAIL; } @@ -1404,7 +1389,7 @@ void riscv_set_current_hartid(struct target *target, int hartid) /* Avoid invalidating the register cache all the time. */ if (r->registers_initialized && (!riscv_rtos_enabled(target) || (previous_hartid == hartid)) - && target->reg_cache->reg_list[GDB_REGNO_XPR0].size == (unsigned)riscv_xlen(target) + && target->reg_cache->reg_list[GDB_REGNO_ZERO].size == (unsigned)riscv_xlen(target) && (!riscv_rtos_enabled(target) || (r->rtos_hartid != -1))) { return; } else @@ -1694,7 +1679,7 @@ const char *gdb_regno_name(enum gdb_regno regno) return "priv"; default: if (regno <= GDB_REGNO_XPR31) { - sprintf(buf, "x%d", regno - GDB_REGNO_XPR0); + sprintf(buf, "x%d", regno - GDB_REGNO_ZERO); } else if (regno >= GDB_REGNO_CSR0 && regno <= GDB_REGNO_CSR4095) { sprintf(buf, "csr%d", regno - GDB_REGNO_CSR0); } else if (regno >= GDB_REGNO_FPR0 && regno <= GDB_REGNO_FPR31) {