Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

Commit 2bccf4e

Browse files
committed
riscv32: Refactor progbuf-based memory I/O to fit into 1 slot and use GPR
1 parent db5265b commit 2bccf4e

2 files changed

Lines changed: 91 additions & 68 deletions

File tree

src/target/riscv32.c

Lines changed: 89 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -569,34 +569,26 @@ static void riscv32_sysbus_mem_write(
569569

570570
#define RV_DM_PROGBUF_BASE 0x20U
571571

572+
#define RV_GPR_A0 0x100aU
573+
574+
#define RV_EBREAK 0x00100073U
575+
572576
static void riscv32_progbuf_mem_read(
573577
riscv_hart_s *const hart, void *const dest, const target_addr_t src, const size_t len)
574578
{
575579
/* Figure out the maximal width of access to perform, up to the bitness of the target */
576580
const uint8_t access_width = riscv_mem_access_width(hart, src, len);
577581
const uint8_t access_length = 1U << access_width;
578582

579-
/* RV32I opcodes: extract ptr32 from data1, load word/half/byte, store back to data0 */
580-
static const uint32_t progbuf_read32[5] = {
581-
0x38000513U, // li a0, 0x380
582-
0x00452583U, // lw a1, 4(a0)
583-
0x0005a583U, // lw a1, 0(a1)
584-
0x00b52023U, // sw a1, 0(a0)
585-
0x00100073U
583+
/* RV32I opcodes: load word/half/byte from address A0 into A0 (clobber) */
584+
static const uint32_t progbuf_read32[1] = {
585+
0x00052503U, // lw a0, 0(a0)
586586
};
587-
static const uint32_t progbuf_read16[5] = {
588-
0x38000513U, // li a0, 0x380
589-
0x00452583U, // lw a1, 4(a0)
590-
0x00059583U, // lh a1, 0(a1)
591-
0x00b51023U, // sh a1, 0(a0)
592-
0x00100073U
587+
static const uint32_t progbuf_read16[1] = {
588+
0x00051503U, // lh a0, 0(a0)
593589
};
594-
static const uint32_t progbuf_read8[5] = {
595-
0x38000513U, // li a0, 0x380
596-
0x00452583U, // lw a1, 4(a0)
597-
0x00058583U, // lb a1, 0(a1)
598-
0x00b50023U, // sb a1, 0(a0)
599-
0x00100073U
590+
static const uint32_t progbuf_read8[1] = {
591+
0x00050503U, // lb a0, 0(a0)
600592
};
601593
const uint32_t *progbuf_read = progbuf_read32;
602594
switch (access_width) {
@@ -612,35 +604,62 @@ static void riscv32_progbuf_mem_read(
612604
default:
613605
return;
614606
}
607+
#if 0
608+
/* assume ptr is in A0, load word/half/byte to A1 (clobber), postincrement A0 */
609+
static const uint32_t progbuf_read32_autoexec[2] = {
610+
0x00052583U, // lw a1, 0(a0)
611+
0x00450513U, // addi a0, a0, 4
612+
}
613+
DEBUG_TARGET("%s: 0x%08x+%lu width %u\n", __func__, src, len, access_width);
614+
#endif
615615
/* Fill the program buffer */
616-
for (int i = 0; i < 5; i++) {
617-
if (!riscv_dm_write(hart->dbg_module, RV_DM_PROGBUF_BASE + i, progbuf_read[i]))
616+
if (!riscv_dm_write(hart->dbg_module, RV_DM_PROGBUF_BASE, progbuf_read[0]))
617+
return;
618+
/* Append literal ebreak (if impebreak is not reached) */
619+
if (hart->progbuf_size > 1) {
620+
if (!riscv_dm_write(hart->dbg_module, RV_DM_PROGBUF_BASE + 1, RV_EBREAK))
618621
return;
619622
}
620623

621624
uint32_t a0_save = 0;
622-
uint32_t a1_save = 0;
623-
riscv_csr_read(hart, RV_GPR_BASE + 10, &a0_save);
624-
riscv_csr_read(hart, RV_GPR_BASE + 11, &a1_save);
625+
//uint32_t a1_save = 0;
626+
riscv_csr_read(hart, RV_GPR_A0, &a0_save);
627+
//riscv_csr_read(hart, RV_GPR_A0 + 11, &a1_save);
625628

626629
uint8_t *const data = (uint8_t *)dest;
627630
for (size_t offset = 0; offset < len; offset += access_length) {
628-
/* Write the address to read to arg1 */
629-
if (!riscv_dm_write(hart->dbg_module, RV_DM_DATA1, src + offset))
631+
/* Write the source address to DATA0 */
632+
if (!riscv_dm_write(hart->dbg_module, RV_DM_DATA0, src + offset))
630633
return;
631-
/* Execute progbuf: postexec only, no reg transfer */
632-
if (!riscv_dm_write(hart->dbg_module, RV_DM_ABST_COMMAND, RV_ABST_POSTEXEC) ||
633-
!riscv_command_wait_complete(hart))
634+
/* Copy the source address from DATA0 to GPR A0 and launch the progbuf postexec */
635+
const uint32_t abstract_command1 = RV_DM_ABST_CMD_ACCESS_REG | RV_ABST_WRITE | RV_REG_XFER | RV_ABST_POSTEXEC |
636+
RV_REG_ACCESS_32_BIT | RV_GPR_A0;
637+
bool result = riscv_dm_write(hart->dbg_module, RV_DM_ABST_COMMAND, abstract_command1);
638+
/* Wait for both the register write and progbuf execution to complete */
639+
result &= riscv_command_wait_complete(hart);
640+
if (!result)
634641
return;
635-
/* Extract back the data from arg0 */
642+
#if 1
643+
/* Copy the read value from GPR A0 to DATA0 */
644+
const uint32_t abstract_command2 =
645+
RV_DM_ABST_CMD_ACCESS_REG | RV_ABST_READ | RV_REG_XFER | RV_REG_ACCESS_32_BIT | RV_GPR_A0;
646+
result = riscv_dm_write(hart->dbg_module, RV_DM_ABST_COMMAND, abstract_command2);
647+
result &= riscv_command_wait_complete(hart);
648+
if (!result)
649+
return;
650+
/* Extract the read value from DATA0 */
636651
uint32_t value = 0;
637652
if (!riscv_dm_read(hart->dbg_module, RV_DM_DATA0, &value))
638653
return;
654+
#else
655+
uint32_t value = 0;
656+
riscv_csr_read(hart, RV_GPR_A0, &value);
657+
#endif
639658
riscv32_unpack_data(data + offset, value, access_width);
640659
}
641660

642-
riscv_csr_write(hart, RV_GPR_BASE + 10, &a0_save);
643-
riscv_csr_write(hart, RV_GPR_BASE + 11, &a1_save);
661+
riscv_csr_write(hart, RV_GPR_A0, &a0_save);
662+
//riscv_csr_write(hart, RV_GPR_A0 + 1, &a1_save);
644663
}
645664

646665
static void riscv32_progbuf_mem_write(
@@ -649,27 +668,18 @@ static void riscv32_progbuf_mem_write(
649668
/* Figure out the maxmial width of access to perform, up to the bitness of the target */
650669
const uint8_t access_width = riscv_mem_access_width(hart, dest, len);
651670
const uint8_t access_length = 1U << access_width;
652-
/* RV32I opcodes: extract ptr32 from data1 and val from data0, store word/half/byte */
653-
static const uint32_t progbuf_write32[5] = {
654-
0x38000513U, // li a0, 0x380
655-
0x00452583U, // lw a1, 4(a0)
656-
0x00052603U, // lw a2, 0(a0)
657-
0x00c5a023U, // sw a2, 0(a1)
658-
0x00100073U
671+
/* RV32I opcodes: store word/half/byte in a1 into address pointed-by a0 */
672+
static const uint32_t progbuf_write32[] = {
673+
0x00b52023U, // sw a1, 0(a0)
674+
0x00450513U, // addi a0, a0, 4
659675
};
660-
static const uint32_t progbuf_write16[5] = {
661-
0x38000513U, // li a0, 0x380
662-
0x00452583U, // lw a1, 4(a0)
663-
0x00051603U, // lh a2, 0(a0)
664-
0x00c59023U, // sh a2, 0(a1)
665-
0x00100073U
676+
static const uint32_t progbuf_write16[] = {
677+
0x00b51023U, // sh a1, 0(a0)
678+
0x00450513U, // addi a0, a0, 4
666679
};
667-
static const uint32_t progbuf_write8[5] = {
668-
0x38000513U, // li a0, 0x380
669-
0x00452583U, // lw a1, 4(a0)
670-
0x00050603U, // lb a2, 0(a0)
671-
0x00c58023U, // sb a2, 0(a1)
672-
0x00100073U
680+
static const uint32_t progbuf_write8[] = {
681+
0x00b50023U, // sb a1, 0(a0)
682+
0x00450513U, // addi a0, a0, 4
673683
};
674684
const uint32_t *progbuf_write = progbuf_write32;
675685
switch (access_width) {
@@ -686,36 +696,49 @@ static void riscv32_progbuf_mem_write(
686696
return;
687697
}
688698
/* Fill the program buffer */
689-
for (int i = 0; i < 5; i++) {
690-
if (!riscv_dm_write(hart->dbg_module, RV_DM_PROGBUF_BASE + i, progbuf_write[i]))
699+
if (!riscv_dm_write(hart->dbg_module, RV_DM_PROGBUF_BASE, progbuf_write[0]))
700+
return;
701+
/* Append literal ebreak (if impebreak is not reached) */
702+
if (hart->progbuf_size > 1) {
703+
if (!riscv_dm_write(hart->dbg_module, RV_DM_PROGBUF_BASE + 1, RV_EBREAK))
691704
return;
692705
}
693706

694707
uint32_t a0_save = 0;
695708
uint32_t a1_save = 0;
696-
uint32_t a2_save = 0;
697-
riscv_csr_read(hart, RV_GPR_BASE + 10, &a0_save);
698-
riscv_csr_read(hart, RV_GPR_BASE + 11, &a1_save);
699-
riscv_csr_read(hart, RV_GPR_BASE + 12, &a2_save);
709+
riscv_csr_read(hart, RV_GPR_A0, &a0_save);
710+
riscv_csr_read(hart, RV_GPR_A0 + 1, &a1_save);
700711

701712
const uint8_t *const data = (const uint8_t *)src;
702713
for (size_t offset = 0; offset < len; offset += access_length) {
703-
/* Write the address to write to arg1 */
704-
if (!riscv_dm_write(hart->dbg_module, RV_DM_DATA1, dest + offset))
714+
/* Copy the destination address from DATA0 to GPR A0 */
715+
if (!riscv_dm_write(hart->dbg_module, RV_DM_DATA0, dest + offset))
705716
return;
706-
/* Pack the data to write into arg0 */
717+
/* Copy the source address from DATA0 to GPR A0 */
718+
const uint32_t abstract_command1 =
719+
RV_DM_ABST_CMD_ACCESS_REG | RV_ABST_WRITE | RV_REG_XFER | RV_REG_ACCESS_32_BIT | RV_GPR_A0;
720+
bool result = riscv_dm_write(hart->dbg_module, RV_DM_ABST_COMMAND, abstract_command1);
721+
result &= riscv_command_wait_complete(hart);
722+
if (!result)
723+
return;
724+
//riscv_csr_write(hart, RV_GPR_A0, dest + offset);
725+
726+
/* Pack the data to write into GPR A1 */
707727
uint32_t value = riscv32_pack_data(data + offset, access_width);
708728
if (!riscv_dm_write(hart->dbg_module, RV_DM_DATA0, value))
709729
return;
710-
/* Execute progbuf: postexec only, no reg transfer */
711-
if (!riscv_dm_write(hart->dbg_module, RV_DM_ABST_COMMAND, RV_ABST_POSTEXEC) ||
712-
!riscv_command_wait_complete(hart))
730+
/* Copy the write value from DATA0 to GPR A1 and launch the progbuf postexec */
731+
const uint32_t abstract_command2 = RV_DM_ABST_CMD_ACCESS_REG | RV_ABST_WRITE | RV_REG_XFER | RV_ABST_POSTEXEC |
732+
RV_REG_ACCESS_32_BIT | (RV_GPR_A0 + 1);
733+
result = riscv_dm_write(hart->dbg_module, RV_DM_ABST_COMMAND, abstract_command2);
734+
result &= riscv_command_wait_complete(hart);
735+
if (!result)
713736
return;
737+
//riscv_csr_write(hart, RV_GPR_A1, value);
714738
}
715739

716-
riscv_csr_write(hart, RV_GPR_BASE + 10, &a0_save);
717-
riscv_csr_write(hart, RV_GPR_BASE + 11, &a1_save);
718-
riscv_csr_write(hart, RV_GPR_BASE + 12, &a2_save);
740+
riscv_csr_write(hart, RV_GPR_A0, &a0_save);
741+
riscv_csr_write(hart, RV_GPR_A0 + 1, &a1_save);
719742
}
720743

721744
void riscv32_mem_read(target_s *const target, void *const dest, const target_addr64_t src, const size_t len)

src/target/riscv_debug.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,8 @@ static uint32_t riscv_hart_discover_isa(riscv_hart_s *const hart)
674674
/* Now use the data count bits to divine an initial guess on the platform width */
675675
data_registers &= RV_DM_ABST_STATUS_DATA_COUNT;
676676
DEBUG_INFO("Hart has %" PRIu32 " data registers and %u progbuf registers\n", data_registers, hart->progbuf_size);
677-
/* Memory access using less than 8 progbuf slots is not supported yet */
678-
if (hart->progbuf_size >= 8)
677+
/* Memory access using less than 2 progbuf slots is not supported yet */
678+
if (hart->progbuf_size >= 2)
679679
hart->flags |= RV_HART_FLAG_MEMORY_PROGBUF;
680680
/* Check we have at least enough data registers for arg0 */
681681
if (data_registers >= 4)

0 commit comments

Comments
 (0)