Skip to content

Commit 856f70f

Browse files
committed
Try abstract register writes as well.
1 parent f37e93b commit 856f70f

File tree

1 file changed

+133
-55
lines changed

1 file changed

+133
-55
lines changed

src/target/riscv/riscv-013.c

Lines changed: 133 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -578,45 +578,6 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
578578
}
579579
}
580580

581-
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number);
582-
583-
static int register_write_direct(struct target *target, unsigned number,
584-
uint64_t value)
585-
{
586-
struct riscv_program program;
587-
588-
LOG_DEBUG("[%d] reg[0x%x] <- 0x%" PRIx64, riscv_current_hartid(target),
589-
number, value);
590-
591-
riscv_program_init(&program, target);
592-
593-
riscv_addr_t input = riscv_program_alloc_d(&program);
594-
riscv_program_write_ram(&program, input + 4, value >> 32);
595-
riscv_program_write_ram(&program, input, value);
596-
597-
assert(GDB_REGNO_XPR0 == 0);
598-
if (number <= GDB_REGNO_XPR31) {
599-
riscv_program_lx(&program, number, input);
600-
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
601-
riscv_program_fld(&program, number, input);
602-
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
603-
enum gdb_regno temp = riscv_program_gettemp(&program);
604-
riscv_program_lx(&program, temp, input);
605-
riscv_program_csrw(&program, temp, number);
606-
} else {
607-
LOG_ERROR("Unsupported register (enum gdb_regno)(%d)", number);
608-
abort();
609-
}
610-
611-
int exec_out = riscv_program_exec(&program, target);
612-
if (exec_out != ERROR_OK) {
613-
riscv013_clear_abstract_error(target);
614-
return ERROR_FAIL;
615-
}
616-
617-
return ERROR_OK;
618-
}
619-
620581
static int execute_abstract_command(struct target *target, uint32_t command)
621582
{
622583
LOG_DEBUG("command=0x%x", command);
@@ -640,9 +601,9 @@ static int execute_abstract_command(struct target *target, uint32_t command)
640601
return ERROR_OK;
641602
}
642603

643-
static uint64_t read_abstract_arg(struct target *target, unsigned index)
604+
static riscv_reg_t read_abstract_arg(struct target *target, unsigned index)
644605
{
645-
uint64_t value = 0;
606+
riscv_reg_t value = 0;
646607
unsigned xlen = riscv_xlen(target);
647608
unsigned offset = index * xlen / 32;
648609
switch (xlen) {
@@ -657,6 +618,23 @@ static uint64_t read_abstract_arg(struct target *target, unsigned index)
657618
return value;
658619
}
659620

621+
static int write_abstract_arg(struct target *target, unsigned index,
622+
riscv_reg_t value)
623+
{
624+
unsigned xlen = riscv_xlen(target);
625+
unsigned offset = index * xlen / 32;
626+
switch (xlen) {
627+
default:
628+
LOG_ERROR("Unsupported xlen: %d", xlen);
629+
return ~0;
630+
case 64:
631+
dmi_write(target, DMI_DATA0 + offset + 1, value >> 32);
632+
case 32:
633+
dmi_write(target, DMI_DATA0 + offset, value);
634+
}
635+
return ERROR_OK;
636+
}
637+
660638
static int register_read_abstract(struct target *target, uint64_t *value,
661639
uint32_t number, unsigned size)
662640
{
@@ -712,30 +690,91 @@ static int register_read_abstract(struct target *target, uint64_t *value,
712690
return ERROR_OK;
713691
}
714692

715-
/** Actually read registers from the target right now. */
716-
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number)
693+
static int register_write_abstract(struct target *target, uint32_t number,
694+
uint64_t value, unsigned size)
717695
{
718-
int result = register_read_abstract(target, value, number,
696+
RISCV013_INFO(r);
697+
698+
uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0);
699+
switch (size) {
700+
case 32:
701+
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 2);
702+
break;
703+
case 64:
704+
command = set_field(command, AC_ACCESS_REGISTER_SIZE, 3);
705+
break;
706+
default:
707+
LOG_ERROR("Unsupported abstract register read size: %d", size);
708+
return ERROR_FAIL;
709+
}
710+
command = set_field(command, AC_ACCESS_REGISTER_POSTEXEC, 0);
711+
command = set_field(command, AC_ACCESS_REGISTER_TRANSFER, 1);
712+
command = set_field(command, AC_ACCESS_REGISTER_WRITE, 1);
713+
714+
if (number <= GDB_REGNO_XPR31) {
715+
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
716+
0x1000 + number - GDB_REGNO_XPR0);
717+
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
718+
if (!r->abstract_read_fpr_supported)
719+
return ERROR_FAIL;
720+
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
721+
0x1020 + number - GDB_REGNO_FPR0);
722+
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
723+
if (!r->abstract_read_csr_supported)
724+
return ERROR_FAIL;
725+
command = set_field(command, AC_ACCESS_REGISTER_REGNO,
726+
number - GDB_REGNO_CSR0);
727+
} else {
728+
return ERROR_FAIL;
729+
}
730+
731+
if (write_abstract_arg(target, 0, value) != ERROR_OK) {
732+
return ERROR_FAIL;
733+
}
734+
735+
int result = execute_abstract_command(target, command);
736+
if (result != ERROR_OK) {
737+
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
738+
r->abstract_write_fpr_supported = false;
739+
LOG_INFO("Disabling abstract command writes to FPRs.");
740+
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
741+
r->abstract_write_csr_supported = false;
742+
LOG_INFO("Disabling abstract command writes to CSRs.");
743+
}
744+
return result;
745+
}
746+
747+
return ERROR_OK;
748+
}
749+
750+
static int register_write_direct(struct target *target, unsigned number,
751+
uint64_t value)
752+
{
753+
LOG_DEBUG("[%d] reg[0x%x] <- 0x%" PRIx64, riscv_current_hartid(target),
754+
number, value);
755+
756+
int result = register_write_abstract(target, number, value,
719757
riscv_xlen(target));
720758
if (result == ERROR_OK)
721759
return ERROR_OK;
722760

723761
struct riscv_program program;
762+
724763
riscv_program_init(&program, target);
725-
riscv_addr_t output = riscv_program_alloc_d(&program);
726-
riscv_program_write_ram(&program, output + 4, 0);
727-
riscv_program_write_ram(&program, output, 0);
764+
765+
riscv_addr_t input = riscv_program_alloc_d(&program);
766+
riscv_program_write_ram(&program, input + 4, value >> 32);
767+
riscv_program_write_ram(&program, input, value);
728768

729769
assert(GDB_REGNO_XPR0 == 0);
730770
if (number <= GDB_REGNO_XPR31) {
731-
riscv_program_sx(&program, number, output);
771+
riscv_program_lx(&program, number, input);
732772
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
733-
riscv_program_fsd(&program, number, output);
773+
riscv_program_fld(&program, number, input);
734774
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
735-
LOG_DEBUG("reading CSR index=0x%03x", number - GDB_REGNO_CSR0);
736775
enum gdb_regno temp = riscv_program_gettemp(&program);
737-
riscv_program_csrr(&program, temp, number);
738-
riscv_program_sx(&program, temp, output);
776+
riscv_program_lx(&program, temp, input);
777+
riscv_program_csrw(&program, temp, number);
739778
} else {
740779
LOG_ERROR("Unsupported register (enum gdb_regno)(%d)", number);
741780
abort();
@@ -747,9 +786,48 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
747786
return ERROR_FAIL;
748787
}
749788

750-
*value = 0;
751-
*value |= ((uint64_t)(riscv_program_read_ram(&program, output + 4))) << 32;
752-
*value |= riscv_program_read_ram(&program, output);
789+
return ERROR_OK;
790+
}
791+
792+
/** Actually read registers from the target right now. */
793+
static int register_read_direct(struct target *target, uint64_t *value, uint32_t number)
794+
{
795+
int result = register_read_abstract(target, value, number,
796+
riscv_xlen(target));
797+
798+
if (result != ERROR_OK) {
799+
struct riscv_program program;
800+
riscv_program_init(&program, target);
801+
riscv_addr_t output = riscv_program_alloc_d(&program);
802+
riscv_program_write_ram(&program, output + 4, 0);
803+
riscv_program_write_ram(&program, output, 0);
804+
805+
assert(GDB_REGNO_XPR0 == 0);
806+
if (number <= GDB_REGNO_XPR31) {
807+
riscv_program_sx(&program, number, output);
808+
} else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
809+
riscv_program_fsd(&program, number, output);
810+
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
811+
LOG_DEBUG("reading CSR index=0x%03x", number - GDB_REGNO_CSR0);
812+
enum gdb_regno temp = riscv_program_gettemp(&program);
813+
riscv_program_csrr(&program, temp, number);
814+
riscv_program_sx(&program, temp, output);
815+
} else {
816+
LOG_ERROR("Unsupported register (enum gdb_regno)(%d)", number);
817+
abort();
818+
}
819+
820+
int exec_out = riscv_program_exec(&program, target);
821+
if (exec_out != ERROR_OK) {
822+
riscv013_clear_abstract_error(target);
823+
return ERROR_FAIL;
824+
}
825+
826+
*value = 0;
827+
*value |= ((uint64_t)(riscv_program_read_ram(&program, output + 4))) << 32;
828+
*value |= riscv_program_read_ram(&program, output);
829+
}
830+
753831
LOG_DEBUG("[%d] reg[0x%x] = 0x%" PRIx64, riscv_current_hartid(target),
754832
number, *value);
755833
return ERROR_OK;

0 commit comments

Comments
 (0)