aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/target/riscv/riscv-013.c24
-rw-r--r--src/target/riscv/riscv.c10
-rw-r--r--src/target/riscv/riscv.h1
-rw-r--r--src/target/target_type.h6
4 files changed, 37 insertions, 4 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index a673265..417cb9f 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -1727,6 +1727,29 @@ static int riscv013_hart_count(struct target *target)
return dm->hart_count;
}
+static unsigned riscv013_data_bits(struct target *target)
+{
+ RISCV013_INFO(info);
+ /* TODO: Once there is a spec for discovering abstract commands, we can
+ * take those into account as well. For now we assume abstract commands
+ * support XLEN-wide accesses. */
+ if (info->progbufsize >= 2 && !riscv_prefer_sba)
+ return riscv_xlen(target);
+
+ if (get_field(info->sbcs, DMI_SBCS_SBACCESS128))
+ return 128;
+ if (get_field(info->sbcs, DMI_SBCS_SBACCESS64))
+ return 64;
+ if (get_field(info->sbcs, DMI_SBCS_SBACCESS32))
+ return 32;
+ if (get_field(info->sbcs, DMI_SBCS_SBACCESS16))
+ return 16;
+ if (get_field(info->sbcs, DMI_SBCS_SBACCESS8))
+ return 8;
+
+ return riscv_xlen(target);
+}
+
static int init_target(struct command_context *cmd_ctx,
struct target *target)
{
@@ -1759,6 +1782,7 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->test_sba_config_reg = &riscv013_test_sba_config_reg;
generic_info->test_compliance = &riscv013_test_compliance;
generic_info->hart_count = &riscv013_hart_count;
+ generic_info->data_bits = &riscv013_data_bits;
generic_info->version_specific = calloc(1, sizeof(riscv013_info_t));
if (!generic_info->version_specific)
return ERROR_FAIL;
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 41ac87c..ec00d9f 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -2462,6 +2462,14 @@ static unsigned riscv_xlen_nonconst(struct target *target)
return riscv_xlen(target);
}
+static unsigned riscv_data_bits(struct target *target)
+{
+ RISCV_INFO(r);
+ if (r->data_bits)
+ return r->data_bits(target);
+ return riscv_xlen(target);
+}
+
struct target_type riscv_target = {
.name = "riscv",
@@ -2501,7 +2509,7 @@ struct target_type riscv_target = {
.commands = riscv_command_handlers,
.address_bits = riscv_xlen_nonconst,
- .data_bits = riscv_xlen_nonconst
+ .data_bits = riscv_data_bits
};
/*** RISC-V Interface ***/
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index 3dfb4e5..855116a 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -146,6 +146,7 @@ typedef struct {
/* How many harts are attached to the DM that this target is attached to? */
int (*hart_count)(struct target *target);
+ unsigned (*data_bits)(struct target *target);
} riscv_info_t;
typedef struct {
diff --git a/src/target/target_type.h b/src/target/target_type.h
index b94be12..87ef829 100644
--- a/src/target/target_type.h
+++ b/src/target/target_type.h
@@ -297,9 +297,9 @@ struct target_type {
* implemented, it's assumed to be 32. */
unsigned (*address_bits)(struct target *target);
- /* Return the number of data bits this target supports. This will
- * typically be 32 for 32-bit targets, and 64 for 64-bit targets. If not
- * implemented, it's assumed to be 32. */
+ /* Return the number of system bus data bits this target supports. This
+ * will typically be 32 for 32-bit targets, and 64 for 64-bit targets. If
+ * not implemented, it's assumed to be 32. */
unsigned (*data_bits)(struct target *target);
};