target/riscv: Adding register tables to make register names consistent
Added the ability to enter dimensionless registers Change-Id: I1b781959ce4690ec65304142bd9a7c6f540b3e86 Signed-off-by: Anastasiya Chernikova <anastasiya.chernikova@syntacore.com>
This commit is contained in:
parent
aad90d8989
commit
805d394ff8
|
@ -120,6 +120,6 @@ enum gdb_regno {
|
|||
GDB_REGNO_COUNT
|
||||
};
|
||||
|
||||
const char *gdb_regno_name(enum gdb_regno regno);
|
||||
const char *gdb_regno_name(struct target *target, enum gdb_regno regno);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1045,7 +1045,7 @@ static int read_remote_csr(struct target *target, uint64_t *value, uint32_t csr)
|
|||
uint32_t exception = cache_get32(target, info->dramsize-1);
|
||||
if (exception) {
|
||||
LOG_WARNING("Got exception 0x%x when reading %s", exception,
|
||||
gdb_regno_name(GDB_REGNO_CSR0 + csr));
|
||||
gdb_regno_name(target, GDB_REGNO_CSR0 + csr));
|
||||
*value = ~0;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -1247,7 +1247,7 @@ static int register_read(struct target *target, riscv_reg_t *value, int regnum)
|
|||
|
||||
uint32_t exception = cache_get32(target, info->dramsize-1);
|
||||
if (exception) {
|
||||
LOG_WARNING("Got exception 0x%x when reading %s", exception, gdb_regno_name(regnum));
|
||||
LOG_WARNING("Got exception 0x%x when reading %s", exception, gdb_regno_name(target, regnum));
|
||||
*value = ~0;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -1322,7 +1322,7 @@ static int register_write(struct target *target, unsigned int number,
|
|||
uint32_t exception = cache_get32(target, info->dramsize-1);
|
||||
if (exception) {
|
||||
LOG_WARNING("Got exception 0x%x when writing %s", exception,
|
||||
gdb_regno_name(number));
|
||||
gdb_regno_name(target, number));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
|
|
@ -937,7 +937,7 @@ static uint32_t access_register_command(struct target *target, uint32_t number,
|
|||
break;
|
||||
default:
|
||||
LOG_TARGET_ERROR(target, "%d-bit register %s not supported.",
|
||||
size, gdb_regno_name(number));
|
||||
size, gdb_regno_name(target, number));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
@ -1173,7 +1173,7 @@ static int prep_for_register_access(struct target *target,
|
|||
return ERROR_OK;
|
||||
|
||||
LOG_TARGET_DEBUG(target, "Preparing mstatus to access %s",
|
||||
gdb_regno_name(regno));
|
||||
gdb_regno_name(target, regno));
|
||||
|
||||
assert(target->state == TARGET_HALTED &&
|
||||
"The target must be halted to modify and then restore mstatus");
|
||||
|
@ -1193,7 +1193,7 @@ static int prep_for_register_access(struct target *target,
|
|||
return ERROR_FAIL;
|
||||
|
||||
LOG_TARGET_DEBUG(target, "Prepared to access %s (mstatus=0x%" PRIx64 ")",
|
||||
gdb_regno_name(regno), new_mstatus);
|
||||
gdb_regno_name(target, regno), new_mstatus);
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -1482,7 +1482,7 @@ static int register_read_progbuf(struct target *target, uint64_t *value,
|
|||
return csr_read_progbuf(target, value, number);
|
||||
|
||||
LOG_TARGET_ERROR(target, "Unexpected read of %s via program buffer.",
|
||||
gdb_regno_name(number));
|
||||
gdb_regno_name(target, number));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -1628,7 +1628,7 @@ static int register_write_progbuf(struct target *target, enum gdb_regno number,
|
|||
return csr_write_progbuf(target, number, value);
|
||||
|
||||
LOG_TARGET_ERROR(target, "Unexpected write to %s via program buffer.",
|
||||
gdb_regno_name(number));
|
||||
gdb_regno_name(target, number));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -1640,7 +1640,7 @@ static int register_write_direct(struct target *target, enum gdb_regno number,
|
|||
riscv_reg_t value)
|
||||
{
|
||||
LOG_TARGET_DEBUG(target, "Writing 0x%" PRIx64 " to %s", value,
|
||||
gdb_regno_name(number));
|
||||
gdb_regno_name(target, number));
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
return register_write_abstract(target, number, value);
|
||||
|
@ -1658,7 +1658,7 @@ static int register_write_direct(struct target *target, enum gdb_regno number,
|
|||
return ERROR_FAIL;
|
||||
|
||||
if (result == ERROR_OK)
|
||||
LOG_TARGET_DEBUG(target, "%s <- 0x%" PRIx64, gdb_regno_name(number),
|
||||
LOG_TARGET_DEBUG(target, "%s <- 0x%" PRIx64, gdb_regno_name(target, number),
|
||||
value);
|
||||
|
||||
return result;
|
||||
|
@ -1668,7 +1668,7 @@ static int register_write_direct(struct target *target, enum gdb_regno number,
|
|||
static int register_read_direct(struct target *target, riscv_reg_t *value,
|
||||
enum gdb_regno number)
|
||||
{
|
||||
LOG_TARGET_DEBUG(target, "Reading %s", gdb_regno_name(number));
|
||||
LOG_TARGET_DEBUG(target, "Reading %s", gdb_regno_name(target, number));
|
||||
|
||||
if (target->state != TARGET_HALTED)
|
||||
return register_read_abstract(target, value, number);
|
||||
|
@ -1687,7 +1687,7 @@ static int register_read_direct(struct target *target, riscv_reg_t *value,
|
|||
return ERROR_FAIL;
|
||||
|
||||
if (result == ERROR_OK)
|
||||
LOG_TARGET_DEBUG(target, "%s = 0x%" PRIx64, gdb_regno_name(number),
|
||||
LOG_TARGET_DEBUG(target, "%s = 0x%" PRIx64, gdb_regno_name(target, number),
|
||||
*value);
|
||||
|
||||
return result;
|
||||
|
@ -2367,7 +2367,7 @@ static int riscv013_get_register_buf(struct target *target,
|
|||
} else {
|
||||
LOG_TARGET_ERROR(target,
|
||||
"Failed to execute vmv/vslide1down while reading %s",
|
||||
gdb_regno_name(regno));
|
||||
gdb_regno_name(target, regno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4666,7 +4666,7 @@ struct target_type riscv013_target = {
|
|||
static int riscv013_get_register(struct target *target,
|
||||
riscv_reg_t *value, enum gdb_regno rid)
|
||||
{
|
||||
LOG_TARGET_DEBUG(target, "reading register %s", gdb_regno_name(rid));
|
||||
LOG_TARGET_DEBUG(target, "reading register %s", gdb_regno_name(target, rid));
|
||||
|
||||
if (dm013_select_target(target) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
@ -4683,7 +4683,7 @@ static int riscv013_set_register(struct target *target, enum gdb_regno rid,
|
|||
riscv_reg_t value)
|
||||
{
|
||||
LOG_TARGET_DEBUG(target, "writing 0x%" PRIx64 " to register %s",
|
||||
value, gdb_regno_name(rid));
|
||||
value, gdb_regno_name(target, rid));
|
||||
|
||||
if (dm013_select_target(target) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
|
|
@ -488,6 +488,21 @@ static void riscv_free_registers(struct target *target)
|
|||
}
|
||||
}
|
||||
|
||||
static void free_reg_names(struct target *target);
|
||||
|
||||
static void free_custom_register_names(struct target *target)
|
||||
{
|
||||
RISCV_INFO(info);
|
||||
|
||||
if (!info->custom_register_names.reg_names)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < info->custom_register_names.num_entries; i++)
|
||||
free(info->custom_register_names.reg_names[i]);
|
||||
free(info->custom_register_names.reg_names);
|
||||
info->custom_register_names.reg_names = NULL;
|
||||
}
|
||||
|
||||
static void riscv_deinit_target(struct target *target)
|
||||
{
|
||||
LOG_TARGET_DEBUG(target, "riscv_deinit_target()");
|
||||
|
@ -524,7 +539,7 @@ static void riscv_deinit_target(struct target *target)
|
|||
free(entry);
|
||||
}
|
||||
|
||||
free(info->reg_names);
|
||||
free_reg_names(target);
|
||||
free(target->arch_info);
|
||||
|
||||
target->arch_info = NULL;
|
||||
|
@ -2670,7 +2685,8 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
|
|||
riscv_reg_t reg_value;
|
||||
if (riscv_get_register(target, ®_value, regno) != ERROR_OK)
|
||||
break;
|
||||
LOG_TARGET_ERROR(target, "%s = 0x%" PRIx64, gdb_regno_name(regno), reg_value);
|
||||
|
||||
LOG_TARGET_ERROR(target, "%s = 0x%" PRIx64, gdb_regno_name(target, regno), reg_value);
|
||||
}
|
||||
return ERROR_TARGET_TIMEOUT;
|
||||
}
|
||||
|
@ -5011,7 +5027,7 @@ static int riscv_set_or_write_register(struct target *target,
|
|||
assert(!target_was_examined(target));
|
||||
LOG_TARGET_DEBUG(target,
|
||||
"No cache, writing to target: %s <- 0x%" PRIx64,
|
||||
gdb_regno_name(regid), value);
|
||||
gdb_regno_name(target, regid), value);
|
||||
return r->set_register(target, regid, value);
|
||||
}
|
||||
|
||||
|
@ -5106,7 +5122,7 @@ int riscv_get_register(struct target *target, riscv_reg_t *value,
|
|||
if (!target->reg_cache) {
|
||||
assert(!target_was_examined(target));
|
||||
LOG_TARGET_DEBUG(target, "No cache, reading %s from target",
|
||||
gdb_regno_name(regid));
|
||||
gdb_regno_name(target, regid));
|
||||
return r->get_register(target, value, regid);
|
||||
}
|
||||
|
||||
|
@ -5143,7 +5159,7 @@ int riscv_save_register(struct target *target, enum gdb_regno regid)
|
|||
{
|
||||
if (target->state != TARGET_HALTED) {
|
||||
LOG_TARGET_ERROR(target, "Can't save register %s on a hart that is not halted.",
|
||||
gdb_regno_name(regid));
|
||||
gdb_regno_name(target, regid));
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
assert(gdb_regno_cacheable(regid, /* is write? */ false) &&
|
||||
|
@ -5322,7 +5338,7 @@ static int disable_trigger_if_dmode(struct target *target, riscv_reg_t tdata1)
|
|||
* something.
|
||||
* Disable any hardware triggers that have dmode set. We can't have set them
|
||||
* ourselves. Maybe they're left over from some killed debug session.
|
||||
* */
|
||||
*/
|
||||
int riscv_enumerate_triggers(struct target *target)
|
||||
{
|
||||
RISCV_INFO(r);
|
||||
|
@ -5381,188 +5397,174 @@ int riscv_enumerate_triggers(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
const char *gdb_regno_name(enum gdb_regno regno)
|
||||
static char *init_reg_name(const char *name)
|
||||
{
|
||||
static char buf[32];
|
||||
const int size_buf = strlen(name) + 1;
|
||||
|
||||
switch (regno) {
|
||||
case GDB_REGNO_ZERO:
|
||||
return "zero";
|
||||
case GDB_REGNO_RA:
|
||||
return "ra";
|
||||
case GDB_REGNO_SP:
|
||||
return "sp";
|
||||
case GDB_REGNO_GP:
|
||||
return "gp";
|
||||
case GDB_REGNO_TP:
|
||||
return "tp";
|
||||
case GDB_REGNO_T0:
|
||||
return "t0";
|
||||
case GDB_REGNO_T1:
|
||||
return "t1";
|
||||
case GDB_REGNO_T2:
|
||||
return "t2";
|
||||
case GDB_REGNO_S0:
|
||||
return "s0";
|
||||
case GDB_REGNO_S1:
|
||||
return "s1";
|
||||
case GDB_REGNO_A0:
|
||||
return "a0";
|
||||
case GDB_REGNO_A1:
|
||||
return "a1";
|
||||
case GDB_REGNO_A2:
|
||||
return "a2";
|
||||
case GDB_REGNO_A3:
|
||||
return "a3";
|
||||
case GDB_REGNO_A4:
|
||||
return "a4";
|
||||
case GDB_REGNO_A5:
|
||||
return "a5";
|
||||
case GDB_REGNO_A6:
|
||||
return "a6";
|
||||
case GDB_REGNO_A7:
|
||||
return "a7";
|
||||
case GDB_REGNO_S2:
|
||||
return "s2";
|
||||
case GDB_REGNO_S3:
|
||||
return "s3";
|
||||
case GDB_REGNO_S4:
|
||||
return "s4";
|
||||
case GDB_REGNO_S5:
|
||||
return "s5";
|
||||
case GDB_REGNO_S6:
|
||||
return "s6";
|
||||
case GDB_REGNO_S7:
|
||||
return "s7";
|
||||
case GDB_REGNO_S8:
|
||||
return "s8";
|
||||
case GDB_REGNO_S9:
|
||||
return "s9";
|
||||
case GDB_REGNO_S10:
|
||||
return "s10";
|
||||
case GDB_REGNO_S11:
|
||||
return "s11";
|
||||
case GDB_REGNO_T3:
|
||||
return "t3";
|
||||
case GDB_REGNO_T4:
|
||||
return "t4";
|
||||
case GDB_REGNO_T5:
|
||||
return "t5";
|
||||
case GDB_REGNO_T6:
|
||||
return "t6";
|
||||
case GDB_REGNO_PC:
|
||||
return "pc";
|
||||
case GDB_REGNO_FPR0:
|
||||
return "fpr0";
|
||||
case GDB_REGNO_FPR31:
|
||||
return "fpr31";
|
||||
case GDB_REGNO_CSR0:
|
||||
return "csr0";
|
||||
case GDB_REGNO_TSELECT:
|
||||
return "tselect";
|
||||
case GDB_REGNO_TDATA1:
|
||||
return "tdata1";
|
||||
case GDB_REGNO_TDATA2:
|
||||
return "tdata2";
|
||||
case GDB_REGNO_MISA:
|
||||
return "misa";
|
||||
case GDB_REGNO_DPC:
|
||||
return "dpc";
|
||||
case GDB_REGNO_DCSR:
|
||||
return "dcsr";
|
||||
case GDB_REGNO_DSCRATCH0:
|
||||
return "dscratch0";
|
||||
case GDB_REGNO_MSTATUS:
|
||||
return "mstatus";
|
||||
case GDB_REGNO_MEPC:
|
||||
return "mepc";
|
||||
case GDB_REGNO_MCAUSE:
|
||||
return "mcause";
|
||||
case GDB_REGNO_PRIV:
|
||||
return "priv";
|
||||
case GDB_REGNO_SATP:
|
||||
return "satp";
|
||||
case GDB_REGNO_VTYPE:
|
||||
return "vtype";
|
||||
case GDB_REGNO_VL:
|
||||
return "vl";
|
||||
case GDB_REGNO_V0:
|
||||
return "v0";
|
||||
case GDB_REGNO_V1:
|
||||
return "v1";
|
||||
case GDB_REGNO_V2:
|
||||
return "v2";
|
||||
case GDB_REGNO_V3:
|
||||
return "v3";
|
||||
case GDB_REGNO_V4:
|
||||
return "v4";
|
||||
case GDB_REGNO_V5:
|
||||
return "v5";
|
||||
case GDB_REGNO_V6:
|
||||
return "v6";
|
||||
case GDB_REGNO_V7:
|
||||
return "v7";
|
||||
case GDB_REGNO_V8:
|
||||
return "v8";
|
||||
case GDB_REGNO_V9:
|
||||
return "v9";
|
||||
case GDB_REGNO_V10:
|
||||
return "v10";
|
||||
case GDB_REGNO_V11:
|
||||
return "v11";
|
||||
case GDB_REGNO_V12:
|
||||
return "v12";
|
||||
case GDB_REGNO_V13:
|
||||
return "v13";
|
||||
case GDB_REGNO_V14:
|
||||
return "v14";
|
||||
case GDB_REGNO_V15:
|
||||
return "v15";
|
||||
case GDB_REGNO_V16:
|
||||
return "v16";
|
||||
case GDB_REGNO_V17:
|
||||
return "v17";
|
||||
case GDB_REGNO_V18:
|
||||
return "v18";
|
||||
case GDB_REGNO_V19:
|
||||
return "v19";
|
||||
case GDB_REGNO_V20:
|
||||
return "v20";
|
||||
case GDB_REGNO_V21:
|
||||
return "v21";
|
||||
case GDB_REGNO_V22:
|
||||
return "v22";
|
||||
case GDB_REGNO_V23:
|
||||
return "v23";
|
||||
case GDB_REGNO_V24:
|
||||
return "v24";
|
||||
case GDB_REGNO_V25:
|
||||
return "v25";
|
||||
case GDB_REGNO_V26:
|
||||
return "v26";
|
||||
case GDB_REGNO_V27:
|
||||
return "v27";
|
||||
case GDB_REGNO_V28:
|
||||
return "v28";
|
||||
case GDB_REGNO_V29:
|
||||
return "v29";
|
||||
case GDB_REGNO_V30:
|
||||
return "v30";
|
||||
case GDB_REGNO_V31:
|
||||
return "v31";
|
||||
default:
|
||||
if (regno <= GDB_REGNO_XPR31)
|
||||
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)
|
||||
sprintf(buf, "f%d", regno - GDB_REGNO_FPR0);
|
||||
else
|
||||
sprintf(buf, "gdb_regno_%d", regno);
|
||||
return buf;
|
||||
char * const buf = calloc(size_buf, sizeof(char));
|
||||
if (!buf) {
|
||||
LOG_ERROR("Failed to allocate memory for a register name.");
|
||||
return NULL;
|
||||
}
|
||||
strcpy(buf, name);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *init_reg_name_with_prefix(const char *name_prefix,
|
||||
unsigned int num)
|
||||
{
|
||||
const int size_buf = snprintf(NULL, 0, "%s%d", name_prefix, num) + 1;
|
||||
|
||||
char * const buf = calloc(size_buf, sizeof(char));
|
||||
if (!buf) {
|
||||
LOG_ERROR("Failed to allocate memory for a register name.");
|
||||
return NULL;
|
||||
}
|
||||
int result = snprintf(buf, size_buf, "%s%d", name_prefix, num);
|
||||
assert(result > 0 && result <= (size_buf - 1));
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char * const default_reg_names[GDB_REGNO_COUNT] = {
|
||||
[GDB_REGNO_ZERO] = "zero",
|
||||
[GDB_REGNO_RA] = "ra",
|
||||
[GDB_REGNO_SP] = "sp",
|
||||
[GDB_REGNO_GP] = "gp",
|
||||
[GDB_REGNO_TP] = "tp",
|
||||
[GDB_REGNO_T0] = "t0",
|
||||
[GDB_REGNO_T1] = "t1",
|
||||
[GDB_REGNO_T2] = "t2",
|
||||
[GDB_REGNO_FP] = "fp",
|
||||
[GDB_REGNO_S1] = "s1",
|
||||
[GDB_REGNO_A0] = "a0",
|
||||
[GDB_REGNO_A1] = "a1",
|
||||
[GDB_REGNO_A2] = "a2",
|
||||
[GDB_REGNO_A3] = "a3",
|
||||
[GDB_REGNO_A4] = "a4",
|
||||
[GDB_REGNO_A5] = "a5",
|
||||
[GDB_REGNO_A6] = "a6",
|
||||
[GDB_REGNO_A7] = "a7",
|
||||
[GDB_REGNO_S2] = "s2",
|
||||
[GDB_REGNO_S3] = "s3",
|
||||
[GDB_REGNO_S4] = "s4",
|
||||
[GDB_REGNO_S5] = "s5",
|
||||
[GDB_REGNO_S6] = "s6",
|
||||
[GDB_REGNO_S7] = "s7",
|
||||
[GDB_REGNO_S8] = "s8",
|
||||
[GDB_REGNO_S9] = "s9",
|
||||
[GDB_REGNO_S10] = "s10",
|
||||
[GDB_REGNO_S11] = "s11",
|
||||
[GDB_REGNO_T3] = "t3",
|
||||
[GDB_REGNO_T4] = "t4",
|
||||
[GDB_REGNO_T5] = "t5",
|
||||
[GDB_REGNO_T6] = "t6",
|
||||
[GDB_REGNO_PC] = "pc",
|
||||
[GDB_REGNO_CSR0] = "csr0",
|
||||
[GDB_REGNO_PRIV] = "priv",
|
||||
[GDB_REGNO_FT0] = "ft0",
|
||||
[GDB_REGNO_FT1] = "ft1",
|
||||
[GDB_REGNO_FT2] = "ft2",
|
||||
[GDB_REGNO_FT3] = "ft3",
|
||||
[GDB_REGNO_FT4] = "ft4",
|
||||
[GDB_REGNO_FT5] = "ft5",
|
||||
[GDB_REGNO_FT6] = "ft6",
|
||||
[GDB_REGNO_FT7] = "ft7",
|
||||
[GDB_REGNO_FS0] = "fs0",
|
||||
[GDB_REGNO_FS1] = "fs1",
|
||||
[GDB_REGNO_FA0] = "fa0",
|
||||
[GDB_REGNO_FA1] = "fa1",
|
||||
[GDB_REGNO_FA2] = "fa2",
|
||||
[GDB_REGNO_FA3] = "fa3",
|
||||
[GDB_REGNO_FA4] = "fa4",
|
||||
[GDB_REGNO_FA5] = "fa5",
|
||||
[GDB_REGNO_FA6] = "fa6",
|
||||
[GDB_REGNO_FA7] = "fa7",
|
||||
[GDB_REGNO_FS2] = "fs2",
|
||||
[GDB_REGNO_FS3] = "fs3",
|
||||
[GDB_REGNO_FS4] = "fs4",
|
||||
[GDB_REGNO_FS5] = "fs5",
|
||||
[GDB_REGNO_FS6] = "fs6",
|
||||
[GDB_REGNO_FS7] = "fs7",
|
||||
[GDB_REGNO_FS8] = "fs8",
|
||||
[GDB_REGNO_FS9] = "fs9",
|
||||
[GDB_REGNO_FS10] = "fs10",
|
||||
[GDB_REGNO_FS11] = "fs11",
|
||||
[GDB_REGNO_FT8] = "ft8",
|
||||
[GDB_REGNO_FT9] = "ft9",
|
||||
[GDB_REGNO_FT10] = "ft10",
|
||||
[GDB_REGNO_FT11] = "ft11",
|
||||
|
||||
#define DECLARE_CSR(csr_name, number)[(number) + GDB_REGNO_CSR0] = #csr_name,
|
||||
#include "encoding.h"
|
||||
#undef DECLARE_CSR
|
||||
};
|
||||
|
||||
static void free_reg_names(struct target *target)
|
||||
{
|
||||
RISCV_INFO(info);
|
||||
|
||||
if (!info->reg_names)
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < GDB_REGNO_COUNT; ++i)
|
||||
free(info->reg_names[i]);
|
||||
free(info->reg_names);
|
||||
info->reg_names = NULL;
|
||||
|
||||
free_custom_register_names(target);
|
||||
}
|
||||
|
||||
static void init_custom_csr_names(struct target *target)
|
||||
{
|
||||
RISCV_INFO(info);
|
||||
range_list_t *entry;
|
||||
|
||||
list_for_each_entry(entry, &info->expose_csr, list) {
|
||||
if (!entry->name)
|
||||
continue;
|
||||
assert(entry->low == entry->high);
|
||||
const unsigned int regno = entry->low + GDB_REGNO_CSR0;
|
||||
assert(regno <= GDB_REGNO_CSR4095);
|
||||
if (info->reg_names[regno])
|
||||
return;
|
||||
info->reg_names[regno] = init_reg_name(entry->name);
|
||||
}
|
||||
}
|
||||
|
||||
const char *gdb_regno_name(struct target *target, unsigned int regno)
|
||||
{
|
||||
RISCV_INFO(info);
|
||||
|
||||
if (regno >= GDB_REGNO_COUNT) {
|
||||
assert(info->custom_register_names.reg_names);
|
||||
assert(regno - GDB_REGNO_COUNT <= info->custom_register_names.num_entries);
|
||||
return info->custom_register_names.reg_names[regno - GDB_REGNO_COUNT];
|
||||
}
|
||||
|
||||
if (!info->reg_names)
|
||||
info->reg_names = calloc(GDB_REGNO_COUNT, sizeof(char *));
|
||||
|
||||
if (info->reg_names[regno])
|
||||
return info->reg_names[regno];
|
||||
if (default_reg_names[regno])
|
||||
return default_reg_names[regno];
|
||||
if (regno <= GDB_REGNO_XPR31) {
|
||||
info->reg_names[regno] = init_reg_name_with_prefix("x", regno - GDB_REGNO_ZERO);
|
||||
return info->reg_names[regno];
|
||||
}
|
||||
if (regno <= GDB_REGNO_V31 && regno >= GDB_REGNO_V0) {
|
||||
info->reg_names[regno] = init_reg_name_with_prefix("v", regno - GDB_REGNO_V0);
|
||||
return info->reg_names[regno];
|
||||
}
|
||||
if (regno >= GDB_REGNO_CSR0 && regno <= GDB_REGNO_CSR4095) {
|
||||
init_custom_csr_names(target);
|
||||
info->reg_names[regno] = init_reg_name_with_prefix("csr", regno - GDB_REGNO_CSR0);
|
||||
return info->reg_names[regno];
|
||||
}
|
||||
assert(!"Encountered uninitialized entry in reg_names table");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is the handler of user's request to read a register.
|
||||
|
@ -5662,14 +5664,54 @@ 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)
|
||||
static int init_custom_register_names(struct list_head *expose_custom,
|
||||
struct reg_name_table *custom_register_names)
|
||||
{
|
||||
return (int) (((struct csr_info *)p1)->number) - (int) (((struct csr_info *)p2)->number);
|
||||
unsigned int custom_regs_num = 0;
|
||||
if (!list_empty(expose_custom)) {
|
||||
range_list_t *entry;
|
||||
list_for_each_entry(entry, expose_custom, list)
|
||||
custom_regs_num += entry->high - entry->low + 1;
|
||||
}
|
||||
|
||||
if (!custom_regs_num)
|
||||
return ERROR_OK;
|
||||
|
||||
custom_register_names->reg_names = calloc(custom_regs_num, sizeof(char *));
|
||||
if (!custom_register_names->reg_names) {
|
||||
LOG_ERROR("Failed to allocate memory for custom_register_names->reg_names");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
custom_register_names->num_entries = custom_regs_num;
|
||||
char **reg_names = custom_register_names->reg_names;
|
||||
range_list_t *range;
|
||||
unsigned int next_custom_reg_index = 0;
|
||||
list_for_each_entry(range, expose_custom, list) {
|
||||
for (unsigned int custom_number = range->low; custom_number <= range->high; ++custom_number) {
|
||||
if (range->name)
|
||||
reg_names[next_custom_reg_index] = init_reg_name(range->name);
|
||||
else
|
||||
reg_names[next_custom_reg_index] =
|
||||
init_reg_name_with_prefix("custom", custom_number);
|
||||
|
||||
if (!reg_names[next_custom_reg_index])
|
||||
return ERROR_FAIL;
|
||||
++next_custom_reg_index;
|
||||
}
|
||||
}
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static bool is_known_standard_csr(unsigned int csr_num)
|
||||
{
|
||||
static const bool is_csr_in_buf[GDB_REGNO_CSR4095 - GDB_REGNO_CSR0 + 1] = {
|
||||
#define DECLARE_CSR(csr_name, number)[number] = true,
|
||||
#include "encoding.h"
|
||||
#undef DECLARE_CSR
|
||||
};
|
||||
assert(csr_num < ARRAY_SIZE(is_csr_in_buf));
|
||||
|
||||
return is_csr_in_buf[csr_num];
|
||||
}
|
||||
|
||||
int riscv_init_registers(struct target *target)
|
||||
|
@ -5679,32 +5721,27 @@ int riscv_init_registers(struct target *target)
|
|||
riscv_free_registers(target);
|
||||
|
||||
target->reg_cache = calloc(1, sizeof(*target->reg_cache));
|
||||
if (!target->reg_cache)
|
||||
if (!target->reg_cache) {
|
||||
LOG_TARGET_ERROR(target, "Failed to allocate memory for target->reg_cache");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
target->reg_cache->name = "RISC-V Registers";
|
||||
target->reg_cache->num_regs = GDB_REGNO_COUNT;
|
||||
|
||||
if (!list_empty(&info->expose_custom)) {
|
||||
range_list_t *entry;
|
||||
list_for_each_entry(entry, &info->expose_custom, list)
|
||||
target->reg_cache->num_regs += entry->high - entry->low + 1;
|
||||
if (init_custom_register_names(&info->expose_custom, &info->custom_register_names) != ERROR_OK) {
|
||||
LOG_TARGET_ERROR(target, "init_custom_register_names failed");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
target->reg_cache->num_regs = GDB_REGNO_COUNT + info->custom_register_names.num_entries;
|
||||
LOG_TARGET_DEBUG(target, "create register cache for %d registers",
|
||||
target->reg_cache->num_regs);
|
||||
|
||||
target->reg_cache->reg_list =
|
||||
calloc(target->reg_cache->num_regs, sizeof(struct reg));
|
||||
if (!target->reg_cache->reg_list)
|
||||
if (!target->reg_cache->reg_list) {
|
||||
LOG_TARGET_ERROR(target, "Failed to allocate memory for target->reg_cache->reg_list");
|
||||
return ERROR_FAIL;
|
||||
|
||||
const unsigned int max_reg_name_len = 12;
|
||||
free(info->reg_names);
|
||||
info->reg_names =
|
||||
calloc(target->reg_cache->num_regs, max_reg_name_len);
|
||||
if (!info->reg_names)
|
||||
return ERROR_FAIL;
|
||||
char *reg_name = info->reg_names;
|
||||
}
|
||||
|
||||
static struct reg_feature feature_cpu = {
|
||||
.name = "org.gnu.gdb.riscv.cpu"
|
||||
|
@ -5836,152 +5873,45 @@ int riscv_init_registers(struct target *target)
|
|||
info->type_vector.type_class = REG_TYPE_CLASS_UNION;
|
||||
info->type_vector.reg_type_union = &info->vector_union;
|
||||
|
||||
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, ARRAY_SIZE(csr_info), sizeof(*csr_info), cmp_csr_info);
|
||||
unsigned csr_info_index = 0;
|
||||
|
||||
int custom_within_range = 0;
|
||||
|
||||
riscv_reg_info_t *shared_reg_info = calloc(1, sizeof(riscv_reg_info_t));
|
||||
if (!shared_reg_info)
|
||||
return ERROR_FAIL;
|
||||
shared_reg_info->target = target;
|
||||
|
||||
int custom_within_range = 0;
|
||||
|
||||
/* When gdb requests register N, gdb_get_register_packet() assumes that this
|
||||
* is register at index N in reg_list. So if there are certain registers
|
||||
* that don't exist, we need to leave holes in the list (or renumber, but
|
||||
* it would be nice not to have yet another set of numbers to translate
|
||||
* between). */
|
||||
for (uint32_t number = 0; number < target->reg_cache->num_regs; number++) {
|
||||
struct reg *r = &target->reg_cache->reg_list[number];
|
||||
for (uint32_t reg_num = 0; reg_num < target->reg_cache->num_regs; reg_num++) {
|
||||
struct reg *r = &target->reg_cache->reg_list[reg_num];
|
||||
r->dirty = false;
|
||||
r->valid = false;
|
||||
r->exist = true;
|
||||
r->type = &riscv_reg_arch_type;
|
||||
r->arch_info = shared_reg_info;
|
||||
r->number = number;
|
||||
r->number = reg_num;
|
||||
r->size = riscv_xlen(target);
|
||||
/* r->size is set in riscv_invalidate_register_cache, maybe because the
|
||||
* 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) {
|
||||
r->exist = number <= GDB_REGNO_XPR15 ||
|
||||
r->name = gdb_regno_name(target, reg_num);
|
||||
if (reg_num <= GDB_REGNO_XPR31) {
|
||||
r->exist = reg_num <= GDB_REGNO_XPR15 ||
|
||||
!riscv_supports_extension(target, 'E');
|
||||
/* TODO: For now we fake that all GPRs exist because otherwise gdb
|
||||
* doesn't work. */
|
||||
r->exist = true;
|
||||
r->caller_save = true;
|
||||
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) {
|
||||
} else if (reg_num == GDB_REGNO_PC) {
|
||||
r->caller_save = true;
|
||||
sprintf(reg_name, "pc");
|
||||
r->group = "general";
|
||||
r->feature = &feature_cpu;
|
||||
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
||||
} else if (reg_num >= GDB_REGNO_FPR0 && reg_num <= GDB_REGNO_FPR31) {
|
||||
r->caller_save = true;
|
||||
if (riscv_supports_extension(target, 'D')) {
|
||||
r->size = 64;
|
||||
|
@ -5995,119 +5925,14 @@ int riscv_init_registers(struct target *target)
|
|||
} else {
|
||||
r->exist = false;
|
||||
}
|
||||
switch (number) {
|
||||
case GDB_REGNO_FT0:
|
||||
r->name = "ft0";
|
||||
break;
|
||||
case GDB_REGNO_FT1:
|
||||
r->name = "ft1";
|
||||
break;
|
||||
case GDB_REGNO_FT2:
|
||||
r->name = "ft2";
|
||||
break;
|
||||
case GDB_REGNO_FT3:
|
||||
r->name = "ft3";
|
||||
break;
|
||||
case GDB_REGNO_FT4:
|
||||
r->name = "ft4";
|
||||
break;
|
||||
case GDB_REGNO_FT5:
|
||||
r->name = "ft5";
|
||||
break;
|
||||
case GDB_REGNO_FT6:
|
||||
r->name = "ft6";
|
||||
break;
|
||||
case GDB_REGNO_FT7:
|
||||
r->name = "ft7";
|
||||
break;
|
||||
case GDB_REGNO_FS0:
|
||||
r->name = "fs0";
|
||||
break;
|
||||
case GDB_REGNO_FS1:
|
||||
r->name = "fs1";
|
||||
break;
|
||||
case GDB_REGNO_FA0:
|
||||
r->name = "fa0";
|
||||
break;
|
||||
case GDB_REGNO_FA1:
|
||||
r->name = "fa1";
|
||||
break;
|
||||
case GDB_REGNO_FA2:
|
||||
r->name = "fa2";
|
||||
break;
|
||||
case GDB_REGNO_FA3:
|
||||
r->name = "fa3";
|
||||
break;
|
||||
case GDB_REGNO_FA4:
|
||||
r->name = "fa4";
|
||||
break;
|
||||
case GDB_REGNO_FA5:
|
||||
r->name = "fa5";
|
||||
break;
|
||||
case GDB_REGNO_FA6:
|
||||
r->name = "fa6";
|
||||
break;
|
||||
case GDB_REGNO_FA7:
|
||||
r->name = "fa7";
|
||||
break;
|
||||
case GDB_REGNO_FS2:
|
||||
r->name = "fs2";
|
||||
break;
|
||||
case GDB_REGNO_FS3:
|
||||
r->name = "fs3";
|
||||
break;
|
||||
case GDB_REGNO_FS4:
|
||||
r->name = "fs4";
|
||||
break;
|
||||
case GDB_REGNO_FS5:
|
||||
r->name = "fs5";
|
||||
break;
|
||||
case GDB_REGNO_FS6:
|
||||
r->name = "fs6";
|
||||
break;
|
||||
case GDB_REGNO_FS7:
|
||||
r->name = "fs7";
|
||||
break;
|
||||
case GDB_REGNO_FS8:
|
||||
r->name = "fs8";
|
||||
break;
|
||||
case GDB_REGNO_FS9:
|
||||
r->name = "fs9";
|
||||
break;
|
||||
case GDB_REGNO_FS10:
|
||||
r->name = "fs10";
|
||||
break;
|
||||
case GDB_REGNO_FS11:
|
||||
r->name = "fs11";
|
||||
break;
|
||||
case GDB_REGNO_FT8:
|
||||
r->name = "ft8";
|
||||
break;
|
||||
case GDB_REGNO_FT9:
|
||||
r->name = "ft9";
|
||||
break;
|
||||
case GDB_REGNO_FT10:
|
||||
r->name = "ft10";
|
||||
break;
|
||||
case GDB_REGNO_FT11:
|
||||
r->name = "ft11";
|
||||
break;
|
||||
}
|
||||
r->group = "float";
|
||||
r->feature = &feature_fpu;
|
||||
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
||||
} else if (reg_num >= GDB_REGNO_CSR0 && reg_num <= GDB_REGNO_CSR4095) {
|
||||
r->group = "csr";
|
||||
r->feature = &feature_csr;
|
||||
unsigned csr_number = number - GDB_REGNO_CSR0;
|
||||
const unsigned int csr_num = reg_num - GDB_REGNO_CSR0;
|
||||
|
||||
while (csr_info[csr_info_index].number < csr_number &&
|
||||
csr_info_index < ARRAY_SIZE(csr_info) - 1) {
|
||||
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);
|
||||
if (!is_known_standard_csr(csr_num)) {
|
||||
/* Assume unnamed registers don't exist, unless we have some
|
||||
* configuration that tells us otherwise. That's important
|
||||
* because eg. Eclipse crashes if a target has too many
|
||||
|
@ -6116,7 +5941,7 @@ int riscv_init_registers(struct target *target)
|
|||
r->exist = false;
|
||||
}
|
||||
|
||||
switch (csr_number) {
|
||||
switch (csr_num) {
|
||||
case CSR_DCSR:
|
||||
case CSR_MVENDORID:
|
||||
case CSR_MCOUNTINHIBIT:
|
||||
|
@ -6306,67 +6131,60 @@ int riscv_init_registers(struct target *target)
|
|||
if (!r->exist && !list_empty(&info->expose_csr)) {
|
||||
range_list_t *entry;
|
||||
list_for_each_entry(entry, &info->expose_csr, list)
|
||||
if ((entry->low <= csr_number) && (csr_number <= entry->high)) {
|
||||
if (entry->name) {
|
||||
*reg_name = 0;
|
||||
r->name = entry->name;
|
||||
}
|
||||
|
||||
LOG_TARGET_DEBUG(target, "Exposing additional CSR %d (name=%s).",
|
||||
csr_number, entry->name ? entry->name : reg_name);
|
||||
|
||||
if (entry->low <= csr_num && csr_num <= entry->high) {
|
||||
LOG_TARGET_DEBUG(target, "Exposing additional CSR %d (name=%s)",
|
||||
csr_num, r->name);
|
||||
r->exist = true;
|
||||
break;
|
||||
}
|
||||
} else if (r->exist && !list_empty(&info->hide_csr)) {
|
||||
range_list_t *entry;
|
||||
list_for_each_entry(entry, &info->hide_csr, list)
|
||||
if (entry->low <= csr_number && csr_number <= entry->high) {
|
||||
LOG_TARGET_DEBUG(target, "Hiding CSR %d (name=%s).", csr_number, r->name);
|
||||
if (entry->low <= csr_num && csr_num <= entry->high) {
|
||||
LOG_TARGET_DEBUG(target, "Hiding CSR %d (name=%s).", csr_num, r->name);
|
||||
r->hidden = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (number == GDB_REGNO_PRIV) {
|
||||
sprintf(reg_name, "priv");
|
||||
} else if (reg_num == GDB_REGNO_PRIV) {
|
||||
r->group = "general";
|
||||
r->feature = &feature_virtual;
|
||||
r->size = 8;
|
||||
|
||||
} else if (number >= GDB_REGNO_V0 && number <= GDB_REGNO_V31) {
|
||||
} else if (reg_num >= GDB_REGNO_V0 && reg_num <= GDB_REGNO_V31) {
|
||||
r->caller_save = false;
|
||||
r->exist = (info->vlenb > 0);
|
||||
r->size = info->vlenb * 8;
|
||||
sprintf(reg_name, "v%d", number - GDB_REGNO_V0);
|
||||
r->group = "vector";
|
||||
r->feature = &feature_vector;
|
||||
r->reg_data_type = &info->type_vector;
|
||||
|
||||
} else if (number >= GDB_REGNO_COUNT) {
|
||||
} else if (reg_num >= GDB_REGNO_COUNT) {
|
||||
/* Custom registers. */
|
||||
const unsigned int custom_reg_index = reg_num - GDB_REGNO_COUNT;
|
||||
|
||||
assert(!list_empty(&info->expose_custom));
|
||||
assert(custom_reg_index < info->custom_register_names.num_entries);
|
||||
|
||||
range_list_t *range = list_first_entry(&info->expose_custom, range_list_t, list);
|
||||
|
||||
unsigned custom_number = range->low + custom_within_range;
|
||||
const unsigned int custom_number = range->low + custom_within_range;
|
||||
|
||||
r->group = "custom";
|
||||
r->feature = &feature_custom;
|
||||
r->arch_info = calloc(1, sizeof(riscv_reg_info_t));
|
||||
if (!r->arch_info)
|
||||
if (!r->arch_info) {
|
||||
LOG_ERROR("Failed to allocate memory for r->arch_info");
|
||||
return ERROR_FAIL;
|
||||
((riscv_reg_info_t *) r->arch_info)->target = target;
|
||||
((riscv_reg_info_t *) r->arch_info)->custom_number = custom_number;
|
||||
sprintf(reg_name, "custom%d", custom_number);
|
||||
|
||||
if (range->name) {
|
||||
*reg_name = 0;
|
||||
r->name = range->name;
|
||||
}
|
||||
((riscv_reg_info_t *)r->arch_info)->target = target;
|
||||
((riscv_reg_info_t *)r->arch_info)->custom_number = custom_number;
|
||||
|
||||
LOG_TARGET_DEBUG(target, "Exposing additional custom register %d (name=%s).",
|
||||
number, range->name ? range->name : reg_name);
|
||||
char **reg_names = info->custom_register_names.reg_names;
|
||||
r->name = reg_names[custom_reg_index];
|
||||
|
||||
LOG_TARGET_DEBUG(target, "Exposing additional custom register %d (name=%s)", reg_num, r->name);
|
||||
|
||||
custom_within_range++;
|
||||
if (custom_within_range > range->high - range->low) {
|
||||
|
@ -6375,12 +6193,6 @@ int riscv_init_registers(struct target *target)
|
|||
}
|
||||
}
|
||||
|
||||
if (reg_name[0]) {
|
||||
r->name = reg_name;
|
||||
reg_name += strlen(reg_name) + 1;
|
||||
assert(reg_name < info->reg_names + target->reg_cache->num_regs *
|
||||
max_reg_name_len);
|
||||
}
|
||||
r->value = calloc(1, DIV_ROUND_UP(r->size, 8));
|
||||
}
|
||||
|
||||
|
|
|
@ -113,6 +113,11 @@ typedef struct {
|
|||
|
||||
#define DTM_DTMCS_VERSION_UNKNOWN ((unsigned int)-1)
|
||||
|
||||
struct reg_name_table {
|
||||
unsigned int num_entries;
|
||||
char **reg_names;
|
||||
};
|
||||
|
||||
struct riscv_info {
|
||||
unsigned int common_magic;
|
||||
|
||||
|
@ -121,9 +126,8 @@ struct riscv_info {
|
|||
struct command_context *cmd_ctx;
|
||||
void *version_specific;
|
||||
|
||||
/* Single buffer that contains all register names, instead of calling
|
||||
* malloc for each register. Needs to be freed when reg_list is freed. */
|
||||
char *reg_names;
|
||||
struct reg_name_table custom_register_names;
|
||||
char **reg_names;
|
||||
|
||||
/* It's possible that each core has a different supported ISA set. */
|
||||
int xlen;
|
||||
|
|
Loading…
Reference in New Issue