Skip to content

Commit 1566256

Browse files
meanesden
authored andcommitted
riscv: add single register access, add csr access with an offset, expose some CSRs register in the xml description
1 parent a7cdaff commit 1566256

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

src/target/riscv32.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ typedef struct riscv32_regs {
6565
#define RV32_MATCH_BEFORE 0x00000000U
6666
#define RV32_MATCH_AFTER 0x00040000U
6767

68+
static ssize_t riscv32_reg_read(target_s *target, uint32_t c, void *data, size_t max);
69+
static ssize_t riscv32_reg_write(target_s *target, uint32_t c, const void *data, size_t max);
6870
static void riscv32_regs_read(target_s *target, void *data);
6971
static void riscv32_regs_write(target_s *target, const void *data);
7072
static void riscv32_mem_read(target_s *target, void *dest, target_addr_t src, size_t len);
@@ -81,6 +83,8 @@ bool riscv32_probe(target_s *const target)
8183
target->regs_size = sizeof(riscv32_regs_s);
8284
target->regs_read = riscv32_regs_read;
8385
target->regs_write = riscv32_regs_write;
86+
target->reg_write = riscv32_reg_write;
87+
target->reg_read = riscv32_reg_read;
8488
target->mem_read = riscv32_mem_read;
8589
target->mem_write = riscv32_mem_write;
8690

@@ -120,6 +124,41 @@ static void riscv32_regs_write(target_s *const target, const void *const data)
120124
riscv_csr_write(hart, RV_DPC, &regs->pc);
121125
}
122126

127+
static inline ssize_t riscv32_bool_to_4(const bool ret)
128+
{
129+
return ret ? 4 : -1;
130+
}
131+
132+
static ssize_t riscv32_reg_read(target_s *target, const uint32_t reg, void *data, const size_t max)
133+
{
134+
if (max != 4)
135+
return -1;
136+
/* Grab the hart structure */
137+
riscv_hart_s *const hart = riscv_hart_struct(target);
138+
if (reg < 32)
139+
return riscv32_bool_to_4(riscv_csr_read(hart, RV_GPR_BASE + reg, data));
140+
if (reg == 32)
141+
return riscv32_bool_to_4(riscv_csr_read(hart, RV_DPC, data));
142+
if (reg >= RV_CSR_GDB_OFFSET)
143+
return riscv32_bool_to_4(riscv_csr_read(hart, reg - RV_CSR_GDB_OFFSET, data));
144+
return -1;
145+
}
146+
147+
static ssize_t riscv32_reg_write(target_s *const target, const uint32_t reg, const void *data, const size_t max)
148+
{
149+
if (max != 4)
150+
return -1;
151+
/* Grab the hart structure */
152+
riscv_hart_s *const hart = riscv_hart_struct(target);
153+
if (reg < 32)
154+
return riscv32_bool_to_4(riscv_csr_write(hart, RV_GPR_BASE + reg, data));
155+
if (reg == 32)
156+
return riscv32_bool_to_4(riscv_csr_write(hart, RV_DPC, data));
157+
if (reg >= RV_CSR_GDB_OFFSET)
158+
return riscv32_bool_to_4(riscv_csr_write(hart, reg - RV_CSR_GDB_OFFSET, data));
159+
return -1;
160+
}
161+
123162
/* Takes in data from abstract command arg0 and, based on the access width, unpacks it to dest */
124163
void riscv32_unpack_data(void *const dest, const uint32_t data, const uint8_t access_width)
125164
{

src/target/riscv_debug.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,24 @@ static const char *const riscv_gpr_names[RV_GPRS_COUNT] = {
137137
"s8", "s9", "s10", "s11",
138138
"t3", "t4", "t5", "t6",
139139
};
140+
141+
typedef struct riscv_csr_descriptor {
142+
const char *name;
143+
const uint32_t csr_number; // fits in 16 bits actually (?)
144+
} riscv_csr_descriptor_s;
145+
146+
static const riscv_csr_descriptor_s riscv_csrs[]={
147+
{"mstatus",RV_CSR_STATUS},
148+
{"misa",RV_CSR_MISA},
149+
{"mie", RV_CSR_MIE},
150+
{"mtvec", RV_CSR_MTVEC},
151+
{"tscratch",RV_CSR_MSCRATCH},
152+
{"mepc", RV_CSR_MEPC},
153+
{"mcause",RV_CSR_MCAUSE},
154+
{"mtval", RV_CSR_MTVAL},
155+
{"mip", RV_CSR_MIP},
156+
};
157+
140158
// clang-format on
141159

142160
/* General-purpose register types */
@@ -945,6 +963,17 @@ static size_t riscv_build_target_description(
945963

946964
/* XXX: TODO - implement generation of the FPU feature and registers */
947965

966+
/* Add main CSR registers*/
967+
if (max_length != 0)
968+
print_size = max_length - (size_t)offset;
969+
offset += snprintf(buffer + offset, print_size, "</feature><feature name=\"org.gnu.gdb.riscv.csr\">");
970+
for (size_t i = 0; i < ARRAY_LENGTH(riscv_csrs); i++) {
971+
if (max_length != 0)
972+
print_size = max_length - (size_t)offset;
973+
offset += snprintf(buffer + offset, print_size, " <reg name=\"%s\" bitsize=\"%u\" regnum=\"%" PRIu32 "\" %s/>",
974+
riscv_csrs[i].name, address_width, riscv_csrs[i].csr_number + RV_CSR_GDB_OFFSET,
975+
gdb_reg_save_restore_strings[GDB_SAVE_RESTORE_NO]);
976+
}
948977
/* Add the closing tags required */
949978
if (max_length != 0)
950979
print_size = max_length - (size_t)offset;

src/target/riscv_debug.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,20 @@ typedef struct riscv_hart {
178178
#define RV_TRIGGER_MODE_MASK 0xffff0000U
179179
#define RV_TRIGGER_SUPPORT_BREAKWATCH 0x00000004U
180180

181+
// The CSR id when reported by GDB is shifted by RV_CSR_GDB_OFFSET
182+
// so they cannot collide with GPR registers, so you have to substract
183+
// RV_CSR_GDB_OFFSET from the value received from gdb
184+
#define RV_CSR_GDB_OFFSET 128
185+
#define RV_CSR_STATUS 0x300
186+
#define RV_CSR_MISA 0x301
187+
#define RV_CSR_MIE 0x304
188+
#define RV_CSR_MTVEC 0x305
189+
#define RV_CSR_MSCRATCH 0x340
190+
#define RV_CSR_MEPC 0x341
191+
#define RV_CSR_MCAUSE 0x342
192+
#define RV_CSR_MTVAL 0x343
193+
#define RV_CSR_MIP 0x344
194+
181195
#define RV_TOPT_INHIBIT_NRST 0x00000001U
182196

183197
void riscv_jtag_dtm_handler(uint8_t dev_index);

0 commit comments

Comments
 (0)