diff --git a/src/target/riscv32.c b/src/target/riscv32.c index f0d8df02179..bfafec67655 100644 --- a/src/target/riscv32.c +++ b/src/target/riscv32.c @@ -67,6 +67,8 @@ typedef struct riscv32_regs { #define RV32_MATCH_BEFORE 0x00000000U #define RV32_MATCH_AFTER 0x00040000U +static ssize_t riscv32_reg_read(target_s *target, uint32_t c, void *data, size_t max); +static ssize_t riscv32_reg_write(target_s *target, uint32_t c, const void *data, size_t max); static void riscv32_regs_read(target_s *target, void *data); static void riscv32_regs_write(target_s *target, const void *data); static void riscv32_mem_read(target_s *target, void *dest, target_addr_t src, size_t len); @@ -83,6 +85,8 @@ bool riscv32_probe(target_s *const target) target->regs_size = sizeof(riscv32_regs_s); target->regs_read = riscv32_regs_read; target->regs_write = riscv32_regs_write; + target->reg_write = riscv32_reg_write; + target->reg_read = riscv32_reg_read; target->mem_read = riscv32_mem_read; target->mem_write = riscv32_mem_write; @@ -133,6 +137,41 @@ static void riscv32_regs_write(target_s *const target, const void *const data) riscv_csr_write(hart, RV_DPC, ®s->pc); } +static inline ssize_t riscv32_bool_to_4(const bool ret) +{ + return ret ? 4 : -1; +} + +static ssize_t riscv32_reg_read(target_s *target, const uint32_t reg, void *data, const size_t max) +{ + if (max != 4) + return -1; + /* Grab the hart structure */ + riscv_hart_s *const hart = riscv_hart_struct(target); + if (reg < 32) + return riscv32_bool_to_4(riscv_csr_read(hart, RV_GPR_BASE + reg, data)); + if (reg == 32) + return riscv32_bool_to_4(riscv_csr_read(hart, RV_DPC, data)); + if (reg >= RV_CSR_GDB_OFFSET) + return riscv32_bool_to_4(riscv_csr_read(hart, reg - RV_CSR_GDB_OFFSET, data)); + return -1; +} + +static ssize_t riscv32_reg_write(target_s *const target, const uint32_t reg, const void *data, const size_t max) +{ + if (max != 4) + return -1; + /* Grab the hart structure */ + riscv_hart_s *const hart = riscv_hart_struct(target); + if (reg < 32) + return riscv32_bool_to_4(riscv_csr_write(hart, RV_GPR_BASE + reg, data)); + if (reg == 32) + return riscv32_bool_to_4(riscv_csr_write(hart, RV_DPC, data)); + if (reg >= RV_CSR_GDB_OFFSET) + return riscv32_bool_to_4(riscv_csr_write(hart, reg - RV_CSR_GDB_OFFSET, data)); + return -1; +} + /* Takes in data from abstract command arg0 and, based on the access width, unpacks it to dest */ void riscv32_unpack_data(void *const dest, const uint32_t data, const uint8_t access_width) { diff --git a/src/target/riscv_debug.c b/src/target/riscv_debug.c index ca4dffe125c..44ec9e42c8b 100644 --- a/src/target/riscv_debug.c +++ b/src/target/riscv_debug.c @@ -137,6 +137,24 @@ static const char *const riscv_gpr_names[RV_GPRS_COUNT] = { "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", }; + +typedef struct riscv_csr_descriptor { + const char *name; + const uint32_t csr_number; // fits in 16 bits actually (?) +} riscv_csr_descriptor_s; + +static const riscv_csr_descriptor_s riscv_csrs[]={ + {"mstatus",RV_CSR_STATUS}, + {"misa",RV_CSR_MISA}, + {"mie", RV_CSR_MIE}, + {"mtvec", RV_CSR_MTVEC}, + {"tscratch",RV_CSR_MSCRATCH}, + {"mepc", RV_CSR_MEPC}, + {"mcause",RV_CSR_MCAUSE}, + {"mtval", RV_CSR_MTVAL}, + {"mip", RV_CSR_MIP}, +}; + // clang-format on /* General-purpose register types */ @@ -946,6 +964,17 @@ static size_t riscv_build_target_description( /* XXX: TODO - implement generation of the FPU feature and registers */ + /* Add main CSR registers*/ + if (max_length != 0) + print_size = max_length - (size_t)offset; + offset += snprintf(buffer + offset, print_size, ""); + for (size_t i = 0; i < ARRAY_LENGTH(riscv_csrs); i++) { + if (max_length != 0) + print_size = max_length - (size_t)offset; + offset += snprintf(buffer + offset, print_size, " ", + riscv_csrs[i].name, address_width, riscv_csrs[i].csr_number + RV_CSR_GDB_OFFSET, + gdb_reg_save_restore_strings[GDB_SAVE_RESTORE_NO]); + } /* Add the closing tags required */ if (max_length != 0) print_size = max_length - (size_t)offset; diff --git a/src/target/riscv_debug.h b/src/target/riscv_debug.h index c1b71790c78..1b96257ff00 100644 --- a/src/target/riscv_debug.h +++ b/src/target/riscv_debug.h @@ -178,6 +178,20 @@ typedef struct riscv_hart { #define RV_TRIGGER_MODE_MASK 0xffff0000U #define RV_TRIGGER_SUPPORT_BREAKWATCH 0x00000004U +// The CSR id when reported by GDB is shifted by RV_CSR_GDB_OFFSET +// so they cannot collide with GPR registers, so you have to substract +// RV_CSR_GDB_OFFSET from the value received from gdb +#define RV_CSR_GDB_OFFSET 128 +#define RV_CSR_STATUS 0x300 +#define RV_CSR_MISA 0x301 +#define RV_CSR_MIE 0x304 +#define RV_CSR_MTVEC 0x305 +#define RV_CSR_MSCRATCH 0x340 +#define RV_CSR_MEPC 0x341 +#define RV_CSR_MCAUSE 0x342 +#define RV_CSR_MTVAL 0x343 +#define RV_CSR_MIP 0x344 + #define RV_TOPT_INHIBIT_NRST 0x00000001U void riscv_jtag_dtm_handler(uint8_t dev_index);