Add target_data_bits().
This is used to compute memory block read alignment, and specifically allows 64-bit targets to ensure that memory block reads are only requested on 64-bit boundaries. Signed-off-by: Tim Newsome <tim@sifive.com> Change-Id: Idb1a27b9fc02c46245556bb0f3d6d94b368c4817 Reviewed-on: http://openocd.zylin.com/6249 Reviewed-by: Marc Schink <dev@zapb.de> Tested-by: jenkins Reviewed-by: Jan Matyas <matyas@codasip.com> Reviewed-by: Xiang W <wxjstz@126.com> Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
parent
6ae38ef7f7
commit
358ab3483d
|
@ -2813,6 +2813,14 @@ static unsigned riscv_xlen_nonconst(struct target *target)
|
|||
return riscv_xlen(target);
|
||||
}
|
||||
|
||||
static unsigned int 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",
|
||||
|
||||
|
@ -2857,6 +2865,7 @@ struct target_type riscv_target = {
|
|||
.commands = riscv_command_handlers,
|
||||
|
||||
.address_bits = riscv_xlen_nonconst,
|
||||
.data_bits = riscv_data_bits
|
||||
};
|
||||
|
||||
/*** RISC-V Interface ***/
|
||||
|
|
|
@ -1506,6 +1506,13 @@ unsigned target_address_bits(struct target *target)
|
|||
return 32;
|
||||
}
|
||||
|
||||
unsigned int target_data_bits(struct target *target)
|
||||
{
|
||||
if (target->type->data_bits)
|
||||
return target->type->data_bits(target);
|
||||
return 32;
|
||||
}
|
||||
|
||||
static int target_profiling(struct target *target, uint32_t *samples,
|
||||
uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
|
||||
{
|
||||
|
@ -2402,10 +2409,13 @@ static int target_write_buffer_default(struct target *target,
|
|||
target_addr_t address, uint32_t count, const uint8_t *buffer)
|
||||
{
|
||||
uint32_t size;
|
||||
unsigned int data_bytes = target_data_bits(target) / 8;
|
||||
|
||||
/* Align up to maximum 4 bytes. The loop condition makes sure the next pass
|
||||
/* Align up to maximum bytes. The loop condition makes sure the next pass
|
||||
* will have something to do with the size we leave to it. */
|
||||
for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
|
||||
for (size = 1;
|
||||
size < data_bytes && count >= size * 2 + (address & size);
|
||||
size *= 2) {
|
||||
if (address & size) {
|
||||
int retval = target_write_memory(target, address, size, 1, buffer);
|
||||
if (retval != ERROR_OK)
|
||||
|
@ -2463,10 +2473,13 @@ int target_read_buffer(struct target *target, target_addr_t address, uint32_t si
|
|||
static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer)
|
||||
{
|
||||
uint32_t size;
|
||||
unsigned int data_bytes = target_data_bits(target) / 8;
|
||||
|
||||
/* Align up to maximum 4 bytes. The loop condition makes sure the next pass
|
||||
/* Align up to maximum bytes. The loop condition makes sure the next pass
|
||||
* will have something to do with the size we leave to it. */
|
||||
for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
|
||||
for (size = 1;
|
||||
size < data_bytes && count >= size * 2 + (address & size);
|
||||
size *= 2) {
|
||||
if (address & size) {
|
||||
int retval = target_read_memory(target, address, size, 1, buffer);
|
||||
if (retval != ERROR_OK)
|
||||
|
|
|
@ -684,6 +684,13 @@ target_addr_t target_address_max(struct target *target);
|
|||
*/
|
||||
unsigned target_address_bits(struct target *target);
|
||||
|
||||
/**
|
||||
* Return the number of data bits this target supports.
|
||||
*
|
||||
* This routine is a wrapper for target->type->data_bits.
|
||||
*/
|
||||
unsigned int target_data_bits(struct target *target);
|
||||
|
||||
/** Return the *name* of this targets current state */
|
||||
const char *target_state_name(struct target *target);
|
||||
|
||||
|
|
|
@ -295,6 +295,11 @@ struct target_type {
|
|||
* typically be 32 for 32-bit targets, and 64 for 64-bit targets. If not
|
||||
* implemented, it's assumed to be 32. */
|
||||
unsigned (*address_bits)(struct target *target);
|
||||
|
||||
/* 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 int (*data_bits)(struct target *target);
|
||||
};
|
||||
|
||||
#endif /* OPENOCD_TARGET_TARGET_TYPE_H */
|
||||
|
|
Loading…
Reference in New Issue