aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2017-11-17 15:34:18 -0800
committerTim Newsome <tim@sifive.com>2017-12-19 10:41:48 -0800
commita5cb0b22704c25fa2cbadd2b3b2024a662362c87 (patch)
tree95460703c26d51acc2ebe61b22bce1acbdc930ea /src
parente648856a412b8d0aca6efe100e83c44cd8a60bef (diff)
downloadriscv-openocd-a5cb0b22704c25fa2cbadd2b3b2024a662362c87.zip
riscv-openocd-a5cb0b22704c25fa2cbadd2b3b2024a662362c87.tar.gz
riscv-openocd-a5cb0b22704c25fa2cbadd2b3b2024a662362c87.tar.bz2
WIP. Hide FPRs if the hart doesn't support F/D.
Change-Id: I988c0c36f2de8157d76874a697b3c054773b787d
Diffstat (limited to 'src')
-rw-r--r--src/target/riscv/riscv-013.c33
-rw-r--r--src/target/riscv/riscv.c21
2 files changed, 31 insertions, 23 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index ba55379..9e57a22 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -1149,40 +1149,47 @@ static int init_registers(struct target *target)
.id = "ieee_double"
};
- for (unsigned int i = 0; i < GDB_REGNO_COUNT; i++) {
- struct reg *r = &target->reg_cache->reg_list[i];
- r->number = i;
+ // 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
+ // 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 < GDB_REGNO_COUNT; number++) {
+ struct reg *r = &target->reg_cache->reg_list[number];
r->caller_save = true;
r->dirty = false;
r->valid = false;
r->exist = true;
r->type = &riscv_reg_arch_type;
r->arch_info = target;
+ r->number = number;
// 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 (i <= GDB_REGNO_XPR31) {
- sprintf(reg_name, "x%d", i);
+ if (number <= GDB_REGNO_XPR31) {
+ sprintf(reg_name, "x%d", number);
r->group = "general";
r->feature = &feature_cpu;
- } else if (i == GDB_REGNO_PC) {
+ } else if (number == GDB_REGNO_PC) {
sprintf(reg_name, "pc");
r->group = "general";
r->feature = &feature_cpu;
- } else if (i >= GDB_REGNO_FPR0 && i <= GDB_REGNO_FPR31) {
- sprintf(reg_name, "f%d", i - GDB_REGNO_FPR0);
- r->group = "float";
- r->feature = &feature_fpu;
+ } else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
if (riscv_supports_extension(target, 'D')) {
r->reg_data_type = &type_ieee_double;
} else if (riscv_supports_extension(target, 'F')) {
r->reg_data_type = &type_ieee_single;
+ } else {
+ r->exist = false;
}
- } else if (i >= GDB_REGNO_CSR0 && i <= GDB_REGNO_CSR4095) {
- sprintf(reg_name, "csr%d", i - GDB_REGNO_CSR0);
+ sprintf(reg_name, "f%d", number - GDB_REGNO_FPR0);
+ r->group = "float";
+ r->feature = &feature_fpu;
+ } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
+ sprintf(reg_name, "csr%d", number - GDB_REGNO_CSR0);
r->group = "csr";
r->feature = &feature_csr;
- } else if (i == GDB_REGNO_PRIV) {
+ } else if (number == GDB_REGNO_PRIV) {
sprintf(reg_name, "priv");
r->group = "general";
r->feature = &feature_virtual;
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 9f00a52..431e06f 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -760,6 +760,11 @@ static int riscv_get_gdb_reg_list(struct target *target,
LOG_DEBUG("reg_class=%d", reg_class);
LOG_DEBUG("rtos_hartid=%d current_hartid=%d", r->rtos_hartid, r->current_hartid);
+ if (!target->reg_cache) {
+ LOG_ERROR("Target not initialized. Return ERROR_FAIL.");
+ return ERROR_FAIL;
+ }
+
if (r->rtos_hartid != -1 && riscv_rtos_enabled(target))
riscv_set_current_hartid(target, r->rtos_hartid);
else
@@ -770,7 +775,7 @@ static int riscv_get_gdb_reg_list(struct target *target,
*reg_list_size = 32;
break;
case REG_CLASS_ALL:
- *reg_list_size = REG_COUNT;
+ *reg_list_size = GDB_REGNO_COUNT;
break;
default:
LOG_ERROR("Unsupported reg_class: %d", reg_class);
@@ -781,14 +786,10 @@ static int riscv_get_gdb_reg_list(struct target *target,
if (!*reg_list) {
return ERROR_FAIL;
}
-
- if (!target->reg_cache) {
- LOG_ERROR("Target not initialized. Return ERROR_FAIL.");
- return ERROR_FAIL;
- }
-
+
for (int i = 0; i < *reg_list_size; i++) {
- assert(target->reg_cache->reg_list[i].size > 0);
+ assert(!target->reg_cache->reg_list[i].valid ||
+ target->reg_cache->reg_list[i].size > 0);
(*reg_list)[i] = &target->reg_cache->reg_list[i];
}
@@ -1424,9 +1425,9 @@ void riscv_invalidate_register_cache(struct target *target)
reg->value = &r->reg_cache_values[i];
reg->valid = false;
- if (i == GDB_REGNO_PRIV) {
+ if (reg->number == GDB_REGNO_PRIV) {
reg->size = 8;
- } else if (i >= GDB_REGNO_FPR0 && i <= GDB_REGNO_FPR31) {
+ } else if (reg->number >= GDB_REGNO_FPR0 && reg->number <= GDB_REGNO_FPR31) {
if (riscv_supports_extension(target, 'D')) {
reg->size = 64;
} else if (riscv_supports_extension(target, 'F')) {