Try abstract register writes as well.
parent
f37e93bbc0
commit
856f70fe44
|
@ -578,45 +578,6 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number);
|
|
||||||
|
|
||||||
static int register_write_direct(struct target *target, unsigned number,
|
|
||||||
uint64_t value)
|
|
||||||
{
|
|
||||||
struct riscv_program program;
|
|
||||||
|
|
||||||
LOG_DEBUG("[%d] reg[0x%x] <- 0x%" PRIx64, riscv_current_hartid(target),
|
|
||||||
number, value);
|
|
||||||
|
|
||||||
riscv_program_init(&program, target);
|
|
||||||
|
|
||||||
riscv_addr_t input = riscv_program_alloc_d(&program);
|
|
||||||
riscv_program_write_ram(&program, input + 4, value >> 32);
|
|
||||||
riscv_program_write_ram(&program, input, value);
|
|
||||||
|
|
||||||
assert(GDB_REGNO_XPR0 == 0);
|
|
||||||
if (number <= GDB_REGNO_XPR31) {
|
|
||||||
riscv_program_lx(&program, number, input);
|
|
||||||
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
|
||||||
riscv_program_fld(&program, number, input);
|
|
||||||
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
|
||||||
enum gdb_regno temp = riscv_program_gettemp(&program);
|
|
||||||
riscv_program_lx(&program, temp, input);
|
|
||||||
riscv_program_csrw(&program, temp, number);
|
|
||||||
} else {
|
|
||||||
LOG_ERROR("Unsupported register (enum gdb_regno)(%d)", number);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
int exec_out = riscv_program_exec(&program, target);
|
|
||||||
if (exec_out != ERROR_OK) {
|
|
||||||
riscv013_clear_abstract_error(target);
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ERROR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int execute_abstract_command(struct target *target, uint32_t command)
|
static int execute_abstract_command(struct target *target, uint32_t command)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("command=0x%x", command);
|
LOG_DEBUG("command=0x%x", command);
|
||||||
|
@ -640,9 +601,9 @@ static int execute_abstract_command(struct target *target, uint32_t command)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t read_abstract_arg(struct target *target, unsigned index)
|
static riscv_reg_t read_abstract_arg(struct target *target, unsigned index)
|
||||||
{
|
{
|
||||||
uint64_t value = 0;
|
riscv_reg_t value = 0;
|
||||||
unsigned xlen = riscv_xlen(target);
|
unsigned xlen = riscv_xlen(target);
|
||||||
unsigned offset = index * xlen / 32;
|
unsigned offset = index * xlen / 32;
|
||||||
switch (xlen) {
|
switch (xlen) {
|
||||||
|
@ -657,6 +618,23 @@ static uint64_t read_abstract_arg(struct target *target, unsigned index)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int write_abstract_arg(struct target *target, unsigned index,
|
||||||
|
riscv_reg_t value)
|
||||||
|
{
|
||||||
|
unsigned xlen = riscv_xlen(target);
|
||||||
|
unsigned offset = index * xlen / 32;
|
||||||
|
switch (xlen) {
|
||||||
|
default:
|
||||||
|
LOG_ERROR("Unsupported xlen: %d", xlen);
|
||||||
|
return ~0;
|
||||||
|
case 64:
|
||||||
|
dmi_write(target, DMI_DATA0 + offset + 1, value >> 32);
|
||||||
|
case 32:
|
||||||
|
dmi_write(target, DMI_DATA0 + offset, value);
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int register_read_abstract(struct target *target, uint64_t *value,
|
static int register_read_abstract(struct target *target, uint64_t *value,
|
||||||
uint32_t number, unsigned size)
|
uint32_t number, unsigned size)
|
||||||
{
|
{
|
||||||
|
@ -712,14 +690,112 @@ static int register_read_abstract(struct target *target, uint64_t *value,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int register_write_abstract(struct target *target, uint32_t number,
|
||||||
|
uint64_t value, unsigned size)
|
||||||
|
{
|
||||||
|
RISCV013_INFO(r);
|
||||||
|
|
||||||
|
uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0);
|
||||||
|
switch (size) {
|
||||||
|
case 32:
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 2);
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 3);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR("Unsupported abstract register read size: %d", size);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_POSTEXEC, 0);
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_TRANSFER, 1);
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_WRITE, 1);
|
||||||
|
|
||||||
|
if (number <= GDB_REGNO_XPR31) {
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
|
||||||
|
0x1000 + number - GDB_REGNO_XPR0);
|
||||||
|
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
||||||
|
if (!r->abstract_read_fpr_supported)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
|
||||||
|
0x1020 + number - GDB_REGNO_FPR0);
|
||||||
|
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
||||||
|
if (!r->abstract_read_csr_supported)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
|
||||||
|
number - GDB_REGNO_CSR0);
|
||||||
|
} else {
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_abstract_arg(target, 0, value) != ERROR_OK) {
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = execute_abstract_command(target, command);
|
||||||
|
if (result != ERROR_OK) {
|
||||||
|
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
||||||
|
r->abstract_write_fpr_supported = false;
|
||||||
|
LOG_INFO("Disabling abstract command writes to FPRs.");
|
||||||
|
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
||||||
|
r->abstract_write_csr_supported = false;
|
||||||
|
LOG_INFO("Disabling abstract command writes to CSRs.");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int register_write_direct(struct target *target, unsigned number,
|
||||||
|
uint64_t value)
|
||||||
|
{
|
||||||
|
LOG_DEBUG("[%d] reg[0x%x] <- 0x%" PRIx64, riscv_current_hartid(target),
|
||||||
|
number, value);
|
||||||
|
|
||||||
|
int result = register_write_abstract(target, number, value,
|
||||||
|
riscv_xlen(target));
|
||||||
|
if (result == ERROR_OK)
|
||||||
|
return ERROR_OK;
|
||||||
|
|
||||||
|
struct riscv_program program;
|
||||||
|
|
||||||
|
riscv_program_init(&program, target);
|
||||||
|
|
||||||
|
riscv_addr_t input = riscv_program_alloc_d(&program);
|
||||||
|
riscv_program_write_ram(&program, input + 4, value >> 32);
|
||||||
|
riscv_program_write_ram(&program, input, value);
|
||||||
|
|
||||||
|
assert(GDB_REGNO_XPR0 == 0);
|
||||||
|
if (number <= GDB_REGNO_XPR31) {
|
||||||
|
riscv_program_lx(&program, number, input);
|
||||||
|
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
|
||||||
|
riscv_program_fld(&program, number, input);
|
||||||
|
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
||||||
|
enum gdb_regno temp = riscv_program_gettemp(&program);
|
||||||
|
riscv_program_lx(&program, temp, input);
|
||||||
|
riscv_program_csrw(&program, temp, number);
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Unsupported register (enum gdb_regno)(%d)", number);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
int exec_out = riscv_program_exec(&program, target);
|
||||||
|
if (exec_out != ERROR_OK) {
|
||||||
|
riscv013_clear_abstract_error(target);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/** Actually read registers from the target right now. */
|
/** Actually read registers from the target right now. */
|
||||||
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number)
|
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number)
|
||||||
{
|
{
|
||||||
int result = register_read_abstract(target, value, number,
|
int result = register_read_abstract(target, value, number,
|
||||||
riscv_xlen(target));
|
riscv_xlen(target));
|
||||||
if (result == ERROR_OK)
|
|
||||||
return ERROR_OK;
|
|
||||||
|
|
||||||
|
if (result != ERROR_OK) {
|
||||||
struct riscv_program program;
|
struct riscv_program program;
|
||||||
riscv_program_init(&program, target);
|
riscv_program_init(&program, target);
|
||||||
riscv_addr_t output = riscv_program_alloc_d(&program);
|
riscv_addr_t output = riscv_program_alloc_d(&program);
|
||||||
|
@ -750,6 +826,8 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
|
||||||
*value = 0;
|
*value = 0;
|
||||||
*value |= ((uint64_t)(riscv_program_read_ram(&program, output + 4))) << 32;
|
*value |= ((uint64_t)(riscv_program_read_ram(&program, output + 4))) << 32;
|
||||||
*value |= riscv_program_read_ram(&program, output);
|
*value |= riscv_program_read_ram(&program, output);
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DEBUG("[%d] reg[0x%x] = 0x%" PRIx64, riscv_current_hartid(target),
|
LOG_DEBUG("[%d] reg[0x%x] = 0x%" PRIx64, riscv_current_hartid(target),
|
||||||
number, *value);
|
number, *value);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
|
Loading…
Reference in New Issue