From dcbc29942524bcd8ad1decb09574078c5b2e6233 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Mon, 15 Jan 2024 17:46:23 +0000 Subject: [PATCH 1/8] buffer_utils: add write_char util write_char writes a single char into a char buffer at the provided offset, returns the offset incremented by 1 Memory safety safeguards are in place, if no buffer is provided, a buffer size of 0 is given, or the offset is out of bounds of the buffer, the buffer is not accessed, but the offset is still incremented Target use case is using in special print functions behaving similar to snprintf --- src/include/buffer_utils.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/include/buffer_utils.h b/src/include/buffer_utils.h index 0f05a25e4f3..0340699a12e 100644 --- a/src/include/buffer_utils.h +++ b/src/include/buffer_utils.h @@ -84,4 +84,11 @@ static inline uint64_t read_be8(const uint8_t *const buffer, const size_t offset ((uint64_t)buffer[offset + 6] << 8U) | buffer[offset + 7]; } +static inline size_t write_char(char *const buffer, const size_t buffer_size, const size_t offset, const char c) +{ + if (buffer && offset < buffer_size) + buffer[offset] = c; + return offset + 1U; +} + #endif /*INCLUDE_BUFFER_UTILS_H*/ From 280d3e6da5268b54c289a49dfa4a3776c6bd3403 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Mon, 15 Jan 2024 17:50:22 +0000 Subject: [PATCH 2/8] riscv_debug: formally parse the ISA subset --- src/target/riscv_debug.c | 96 ++++++++++++++++++++++++++++++---------- src/target/riscv_debug.h | 41 ++++++++++++++--- 2 files changed, 109 insertions(+), 28 deletions(-) diff --git a/src/target/riscv_debug.c b/src/target/riscv_debug.c index 2c917b33709..b127ac1935d 100644 --- a/src/target/riscv_debug.c +++ b/src/target/riscv_debug.c @@ -36,6 +36,7 @@ #include "target_internal.h" #include "gdb_reg.h" #include "riscv_debug.h" +#include "buffer_utils.h" #include @@ -421,6 +422,58 @@ static void riscv_hart_read_ids(riscv_hart_s *const hart) /* rv128 is unimpl. */ } +static size_t riscv_snprint_isa_subset( + char *const string_buffer, const size_t buffer_size, const uint32_t access_width, const uint32_t extensions) +{ + size_t offset = snprintf(string_buffer, buffer_size, "rv%" PRIu8, access_width); + + const bool is_embedded = extensions & RV_ISA_EXT_EMBEDDED; + + offset = write_char(string_buffer, buffer_size, offset, is_embedded ? 'e' : 'i'); + + const bool is_general_purpose_isa = + !is_embedded && (extensions & RV_ISA_EXT_GENERAL_PURPOSE) == RV_ISA_EXT_GENERAL_PURPOSE; + + if (is_general_purpose_isa) { + offset = write_char(string_buffer, buffer_size, offset, 'g'); + if (extensions & RV_ISA_EXT_QUAD_FLOAT) + offset = write_char(string_buffer, buffer_size, offset, 'q'); + } else { + if (extensions & RV_ISA_EXT_MUL_DIV_INT) + offset = write_char(string_buffer, buffer_size, offset, 'm'); + if (extensions & RV_ISA_EXT_ATOMIC) + offset = write_char(string_buffer, buffer_size, offset, 'a'); + if (extensions & RV_ISA_EXT_QUAD_FLOAT) + offset = write_char(string_buffer, buffer_size, offset, 'q'); /* Implies d */ + else if (extensions & RV_ISA_EXT_DOUBLE_FLOAT) + offset = write_char(string_buffer, buffer_size, offset, 'd'); /* Implies f */ + else if (extensions & RV_ISA_EXT_SINGLE_FLOAT) + offset = write_char(string_buffer, buffer_size, offset, 'f'); + } + if (extensions & RV_ISA_EXT_DECIMAL_FLOAT) + offset = write_char(string_buffer, buffer_size, offset, 'l'); + if (extensions & RV_ISA_EXT_COMPRESSED) + offset = write_char(string_buffer, buffer_size, offset, 'c'); + if (extensions & RV_ISA_EXT_BIT_MANIP) + offset = write_char(string_buffer, buffer_size, offset, 'b'); + if (extensions & RV_ISA_EXT_DYNAMIC_LANG) + offset = write_char(string_buffer, buffer_size, offset, 'j'); + if (extensions & RV_ISA_EXT_TRANSACT_MEM) + offset = write_char(string_buffer, buffer_size, offset, 't'); + if (extensions & RV_ISA_EXT_PACKED_SIMD) + offset = write_char(string_buffer, buffer_size, offset, 'p'); + if (extensions & RV_ISA_EXT_VECTOR) + offset = write_char(string_buffer, buffer_size, offset, 'v'); + if (extensions & RV_ISA_EXT_USER_INTERRUPTS) + offset = write_char(string_buffer, buffer_size, offset, 'n'); + + /* null-terminate the string */ + if (string_buffer && buffer_size > 0) + string_buffer[offset < buffer_size ? offset : buffer_size - 1U] = '\0'; + + return offset; +} + static bool riscv_hart_init(riscv_hart_s *const hart) { /* Allocate a new target */ @@ -444,9 +497,12 @@ static bool riscv_hart_init(riscv_hart_s *const hart) /* Then read out the ID registers */ riscv_hart_read_ids(hart); - DEBUG_INFO("Hart %" PRIx32 ": %u-bit RISC-V (arch = %08" PRIx32 "), vendor = %" PRIx32 ", impl = %" PRIx32 - ", exts = %08" PRIx32 "\n", - hart->hartid, hart->access_width, hart->archid, hart->vendorid, hart->implid, hart->extensions); + /* Build the ISA subset string from the Hart */ + riscv_snprint_isa_subset(hart->isa_name, sizeof(hart->isa_name), hart->access_width, hart->extensions); + + DEBUG_INFO("Hart %" PRIx32 ": %u-bit RISC-V (arch = %08" PRIx32 "), %s ISA (exts = %08" PRIx32 + "), vendor = %" PRIx32 ", impl = %" PRIx32 "\n", + hart->hartid, hart->access_width, hart->archid, hart->isa_name, hart->extensions, hart->vendorid, hart->implid); /* We don't support rv128, so tell the user and fast-quit on this target. */ if (hart->access_width == 128U) { @@ -1091,17 +1147,6 @@ static void riscv_reset(target_s *const target) target_check_error(target); } -static const char *riscv_fpu_ext_string(const uint32_t extensions) -{ - if (extensions & RV_ISA_EXT_QUAD_FLOAT) - return "q"; - if (extensions & RV_ISA_EXT_DOUBLE_FLOAT) - return "d"; - if (extensions & RV_ISA_EXT_SINGLE_FLOAT) - return "f"; - return ""; -} - /* * Generate the FPU section of the description. * fpu_size = 32 -> single precision float @@ -1220,19 +1265,24 @@ static size_t riscv_build_target_fpu_description(char *const buffer, size_t max_ * */ static size_t riscv_build_target_description( - char *const buffer, size_t max_length, const uint8_t address_width, const uint32_t extensions) + char *const buffer, const size_t max_length, const uint8_t address_width, const uint32_t extensions) { - const bool embedded = extensions & RV_ISA_EXT_EMBEDDED; - const uint32_t fpu = extensions & RV_ISA_EXT_ANY_FLOAT; - size_t print_size = max_length; /* Start with the "preamble" chunks, which are mostly common across targets save for 2 words. */ - size_t offset = - (size_t)snprintf(buffer, print_size, "%s target %sriscv:rv%u%c%s%s ", - gdb_xml_preamble_first, gdb_xml_preamble_second, address_width, embedded ? 'e' : 'i', - riscv_fpu_ext_string(fpu), gdb_xml_preamble_third); + int offset = snprintf(buffer, print_size, "%s target %sriscv:", gdb_xml_preamble_first, gdb_xml_preamble_second); + if (max_length != 0) + print_size = max_length - (size_t)offset; + /* Write the architecture string, which is the ISA subset */ + offset += riscv_snprint_isa_subset(buffer + offset, print_size, address_width, extensions); + if (max_length != 0) + print_size = max_length - (size_t)offset; + /* Finally finish the rest of the preamble */ + offset += + snprintf(buffer + offset, print_size, "%s ", gdb_xml_preamble_third); + if (max_length != 0) + print_size = max_length - (size_t)offset; - const uint8_t gprs = embedded ? 16U : 32U; + const uint8_t gprs = extensions & RV_ISA_EXT_EMBEDDED ? 16U : 32U; /* Then build the general purpose register descriptions using the arrays at top of file */ /* Note that in a device using the embedded (E) extension, we only generate the first 16. */ for (uint8_t i = 0; i < gprs; ++i) { diff --git a/src/target/riscv_debug.h b/src/target/riscv_debug.h index aa4a305aa02..f94e0fed22a 100644 --- a/src/target/riscv_debug.h +++ b/src/target/riscv_debug.h @@ -150,6 +150,8 @@ typedef struct riscv_hart { uint32_t implid; uint32_t hartid; + char isa_name[32U]; + uint32_t triggers; uint32_t trigger_uses[RV_TRIGGERS_MAX]; } riscv_hart_s; @@ -201,11 +203,40 @@ typedef struct riscv_hart { /* The FP base defines the starting register space address for the floating point registers */ #define RV_FP_BASE 0x1020U -#define RV_ISA_EXT_EMBEDDED 0x00000010U -#define RV_ISA_EXT_ANY_FLOAT 0x00010028U -#define RV_ISA_EXT_SINGLE_FLOAT 0x00000020U -#define RV_ISA_EXT_DOUBLE_FLOAT 0x00000008U -#define RV_ISA_EXT_QUAD_FLOAT 0x00010000U +/* + * The Extensions field encodes the presence of standard extensions, with a single bit per alphabet letter + * (bit 0 encodes presence of extension “A” through to bit 25 which encodes “Z”) + * + * This list is taken from the RISC-V Instruction Set Manual v2.2 + * + * The list order is the canonical representation order in the ISA subset string + */ + +/* Base ISA */ +#define RV_ISA_EXT_INTEGER (1U << 8U) /* 'I': RV32I/64I/128I integer base ISA */ +#define RV_ISA_EXT_EMBEDDED (1U << 4U) /* 'E': RV32E reduced integer base ISA (Embedded) */ + +/* Standard general-purpose ISA */ +#define RV_ISA_EXT_MUL_DIV_INT (1U << 12U) /* 'M': Integer multiplication and division */ +#define RV_ISA_EXT_ATOMIC (1U << 0U) /* 'A': Atomic instructions */ +#define RV_ISA_EXT_SINGLE_FLOAT (1U << 5U) /* 'F': Single-precision floating-point */ +#define RV_ISA_EXT_DOUBLE_FLOAT (1U << 3U) /* 'D': Double-precision floating-point */ + +/* 'G' standard general-purpose ISA abbreviation, representing 'IMAFD' */ +#define RV_ISA_EXT_GENERAL_PURPOSE \ + (RV_ISA_EXT_INTEGER | RV_ISA_EXT_MUL_DIV_INT | RV_ISA_EXT_ATOMIC | RV_ISA_EXT_SINGLE_FLOAT | \ + RV_ISA_EXT_DOUBLE_FLOAT) + +/* Standard Unprivileged Extensions */ +#define RV_ISA_EXT_QUAD_FLOAT (1U << 16U) /* 'Q': Quad-precision floating-point */ +#define RV_ISA_EXT_DECIMAL_FLOAT (1U << 11U) /* 'L': Decimal floating-point */ +#define RV_ISA_EXT_COMPRESSED (1U << 2U) /* 'C': 16-bit compressed instructions */ +#define RV_ISA_EXT_BIT_MANIP (1U << 1U) /* 'B': Bit manipulation */ +#define RV_ISA_EXT_DYNAMIC_LANG (1U << 9U) /* 'J': Dynamic languages */ +#define RV_ISA_EXT_TRANSACT_MEM (1U << 19U) /* 'T': Transactional memory */ +#define RV_ISA_EXT_PACKED_SIMD (1U << 15U) /* 'P': Packed-SIMD */ +#define RV_ISA_EXT_VECTOR (1U << 21U) /* 'V': Vector extensions */ +#define RV_ISA_EXT_USER_INTERRUPTS (1U << 13U) /* 'N': User-level interrupts */ #define RV_TRIGGER_SUPPORT_MASK 0x0000fffeU #define RV_TRIGGER_MODE_MASK 0xffff0000U From 3d2cc4ad47048c95341192ddcdbb7b33e5dd1391 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Mon, 15 Jan 2024 17:52:15 +0000 Subject: [PATCH 3/8] riscv_debug: use the ISA subset as the target core name --- src/target/riscv32.c | 4 +--- src/target/riscv64.c | 4 +--- src/target/riscv_debug.c | 2 +- src/target/target_internal.h | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/target/riscv32.c b/src/target/riscv32.c index 57e9472c844..233880991a3 100644 --- a/src/target/riscv32.c +++ b/src/target/riscv32.c @@ -79,9 +79,7 @@ static int riscv32_breakwatch_clear(target_s *target, breakwatch_s *breakwatch); bool riscv32_probe(target_s *const target) { /* Finish setting up the target structure with generic rv32 functions */ - target->core = "rv32"; - /* Provide the length of a suitable registers structure */ - target->regs_size = sizeof(riscv32_regs_s); + target->regs_size = sizeof(riscv32_regs_s); /* Provide the length of a suitable registers structure */ target->regs_read = riscv32_regs_read; target->regs_write = riscv32_regs_write; target->reg_write = riscv32_reg_write; diff --git a/src/target/riscv64.c b/src/target/riscv64.c index b2fe72051e2..37a8aae774c 100644 --- a/src/target/riscv64.c +++ b/src/target/riscv64.c @@ -49,9 +49,7 @@ static void riscv64_mem_read(target_s *target, void *dest, target_addr64_t src, bool riscv64_probe(target_s *const target) { /* Finish setting up the target structure with generic rv64 functions */ - target->core = "rv64"; - /* Provide the length of a suitable registers structure */ - target->regs_size = sizeof(riscv64_regs_s); + target->regs_size = sizeof(riscv64_regs_s); /* Provide the length of a suitable registers structure */ target->regs_read = riscv64_regs_read; target->regs_write = riscv64_regs_write; target->mem_read = riscv64_mem_read; diff --git a/src/target/riscv_debug.c b/src/target/riscv_debug.c index b127ac1935d..8714ab2e9c7 100644 --- a/src/target/riscv_debug.c +++ b/src/target/riscv_debug.c @@ -499,6 +499,7 @@ static bool riscv_hart_init(riscv_hart_s *const hart) /* Build the ISA subset string from the Hart */ riscv_snprint_isa_subset(hart->isa_name, sizeof(hart->isa_name), hart->access_width, hart->extensions); + target->core = hart->isa_name; DEBUG_INFO("Hart %" PRIx32 ": %u-bit RISC-V (arch = %08" PRIx32 "), %s ISA (exts = %08" PRIx32 "), vendor = %" PRIx32 ", impl = %" PRIx32 "\n", @@ -506,7 +507,6 @@ static bool riscv_hart_init(riscv_hart_s *const hart) /* We don't support rv128, so tell the user and fast-quit on this target. */ if (hart->access_width == 128U) { - target->core = "(unsup) rv128"; DEBUG_WARN("rv128 is unsupported, ignoring this hart\n"); return true; } diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 3eec221b8b1..f93238e2a75 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -179,7 +179,7 @@ struct target { /* Other stuff */ const char *driver; uint32_t cpuid; - char *core; + const char *core; char cmdline[MAX_CMDLINE]; target_addr_t heapinfo[4]; target_command_s *commands; From c070433729f3e6fde818a23c882c2afb3d272890 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Mon, 15 Jan 2024 17:55:11 +0000 Subject: [PATCH 4/8] riscv_debug: fix typo --- src/target/riscv_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/riscv_debug.c b/src/target/riscv_debug.c index 8714ab2e9c7..3862ecb253b 100644 --- a/src/target/riscv_debug.c +++ b/src/target/riscv_debug.c @@ -481,7 +481,7 @@ static bool riscv_hart_init(riscv_hart_s *const hart) if (!target) return false; - /* Grab a reference to the DMI and DM structurues and do preliminary setup of the target structure */ + /* Grab a reference to the DMI and DM structures and do preliminary setup of the target structure */ riscv_dm_ref(hart->dbg_module); target->driver = "RISC-V"; target->priv = hart; From 5e38fb7a15add6d0665e2fb80e218d7ae8c83067 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Mon, 15 Jan 2024 17:55:25 +0000 Subject: [PATCH 5/8] riscv64: fix typo --- src/target/riscv64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/riscv64.c b/src/target/riscv64.c index 37a8aae774c..4dc4b6b11be 100644 --- a/src/target/riscv64.c +++ b/src/target/riscv64.c @@ -114,7 +114,7 @@ static void riscv64_mem_read(target_s *const target, void *const dest, const tar if (!len) return; riscv_hart_s *const hart = riscv_hart_struct(target); - /* Figure out the maxmial width of access to perform, up to the bitness of the target */ + /* Figure out the maximal width of access to perform, up to the bitness of the target */ const uint8_t access_width = riscv_mem_access_width(hart, src, len); const uint8_t access_length = 1U << access_width; /* Build the access command */ From d14bdce8f3ef4ec80270a9cd3bac459123a2bd1d Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Mon, 15 Jan 2024 20:04:11 +0000 Subject: [PATCH 6/8] riscv_debug: update RV_CSR macros --- src/target/riscv_debug.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/target/riscv_debug.h b/src/target/riscv_debug.h index f94e0fed22a..305c357216b 100644 --- a/src/target/riscv_debug.h +++ b/src/target/riscv_debug.h @@ -246,16 +246,16 @@ typedef struct riscv_hart { * The CSR number when requested by GDB is shifted by RV_CSR_GDB_OFFSET so they cannot collide with * the GPRs. As a result, we have to subtract 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_CSR_GDB_OFFSET 128U +#define RV_CSR_STATUS 0x300U +#define RV_CSR_MISA 0x301U +#define RV_CSR_MIE 0x304U +#define RV_CSR_MTVEC 0x305U +#define RV_CSR_MSCRATCH 0x340U +#define RV_CSR_MEPC 0x341U +#define RV_CSR_MCAUSE 0x342U +#define RV_CSR_MTVAL 0x343U +#define RV_CSR_MIP 0x344U /* * These two lines are about allowing GDB to access FPU registers through fake registers offset by From 530120392ef11a1ccd22ffc6fa7a00376846e8d0 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Thu, 19 Dec 2024 12:14:06 +0000 Subject: [PATCH 7/8] riscv_debug: document the misa mxl field --- src/target/riscv_debug.c | 17 +++++++---------- src/target/riscv_debug.h | 13 +++++++++++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/target/riscv_debug.c b/src/target/riscv_debug.c index 3862ecb253b..97a55590428 100644 --- a/src/target/riscv_debug.c +++ b/src/target/riscv_debug.c @@ -124,8 +124,6 @@ #define RV_CSRW_A0 0x00051073U #define RV_EBREAK 0x00100073U -#define RV_ISA_EXTENSIONS_MASK 0x03ffffffU - #define RV_VENDOR_JEP106_CONT_MASK 0x7fffff80U #define RV_VENDOR_JEP106_CODE_MASK 0x7fU @@ -383,18 +381,17 @@ static void riscv_dm_init(riscv_dm_s *const dbg_module) static uint8_t riscv_isa_address_width(const uint32_t isa) { - switch (isa >> 30U) { - case 1: + switch ((isa & RV_ISA_MXL_MASK) >> RV_ISA_MXL_SHIFT) { + case RV_ISA_MXL_32: return 32U; - case 2: + case RV_ISA_MXL_64: return 64U; - case 3: + case RV_ISA_MXL_128: return 128U; default: - break; + DEBUG_INFO("Unknown address width, defaulting to 32\n"); + return 32U; } - DEBUG_INFO("Unknown address width, defaulting to 32\n"); - return 32U; } static void riscv_hart_read_ids(riscv_hart_s *const hart) @@ -423,7 +420,7 @@ static void riscv_hart_read_ids(riscv_hart_s *const hart) } static size_t riscv_snprint_isa_subset( - char *const string_buffer, const size_t buffer_size, const uint32_t access_width, const uint32_t extensions) + char *const string_buffer, const size_t buffer_size, const uint8_t access_width, const uint32_t extensions) { size_t offset = snprintf(string_buffer, buffer_size, "rv%" PRIu8, access_width); diff --git a/src/target/riscv_debug.h b/src/target/riscv_debug.h index 305c357216b..9db24a4993e 100644 --- a/src/target/riscv_debug.h +++ b/src/target/riscv_debug.h @@ -203,6 +203,18 @@ typedef struct riscv_hart { /* The FP base defines the starting register space address for the floating point registers */ #define RV_FP_BASE 0x1020U +/** + * The MXL (Machine XLEN) field encodes the native base integer ISA width + * + * The RISC-V Machine ISA register is MXLEN bits wide so the MXL offset is not fixed + * To work around this we convert the register to it's canonical 32-bit form internally + */ +#define RV_ISA_MXL_SHIFT 30U /* misa Machine XLEN field shift (for 32-bit misa) */ +#define RV_ISA_MXL_MASK (0x3U << RV_ISA_MXL_SHIFT) /* misa Machine XLEN field mask (for 32-bit misa) */ +#define RV_ISA_MXL_32 0x1U /* misa Machine XLEN field value for 32-bit ISA */ +#define RV_ISA_MXL_64 0x2U /* misa Machine XLEN field value for 64-bit ISA */ +#define RV_ISA_MXL_128 0x3U /* misa Machine XLEN field value for 128-bit ISA */ + /* * The Extensions field encodes the presence of standard extensions, with a single bit per alphabet letter * (bit 0 encodes presence of extension “A” through to bit 25 which encodes “Z”) @@ -211,6 +223,7 @@ typedef struct riscv_hart { * * The list order is the canonical representation order in the ISA subset string */ +#define RV_ISA_EXTENSIONS_MASK 0x03ffffffU /* misa extensions field mask */ /* Base ISA */ #define RV_ISA_EXT_INTEGER (1U << 8U) /* 'I': RV32I/64I/128I integer base ISA */ From 1109a64e22a6d8e075b83bd3042b217f5a8bfffa Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Thu, 19 Dec 2024 14:12:57 +0000 Subject: [PATCH 8/8] riscv32: fix RV32E register count and respective size RV32E base ISA devices have 16 GPRs while RV32I base ISA devices have 32, this is correctly reported to gdb in the target description xml, but when reading or writing all registers 32 registers were considered to be present --- src/target/riscv32.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/target/riscv32.c b/src/target/riscv32.c index 233880991a3..0d98a1b1596 100644 --- a/src/target/riscv32.c +++ b/src/target/riscv32.c @@ -40,11 +40,6 @@ #include "gdb_packet.h" #include "adiv5.h" -typedef struct riscv32_regs { - uint32_t gprs[32]; - uint32_t pc; -} riscv32_regs_s; - /* This defines a match trigger that's for an address or data location */ #define RV32_MATCH_ADDR_DATA_TRIGGER 0x20000000U /* A dmode of 1 restricts the writability of the trigger to debug mode only */ @@ -78,8 +73,11 @@ static int riscv32_breakwatch_clear(target_s *target, breakwatch_s *breakwatch); bool riscv32_probe(target_s *const target) { + /* 'E' base ISA has 16 GPRs + PC, 'I' base ISA has 32 GPRs + PC */ + riscv_hart_s *const hart = riscv_hart_struct(target); + target->regs_size = ((hart->extensions & RV_ISA_EXT_EMBEDDED ? 16U : 32U) + 1U) * sizeof(uint32_t); + /* Finish setting up the target structure with generic rv32 functions */ - target->regs_size = sizeof(riscv32_regs_s); /* Provide the length of a suitable registers structure */ target->regs_read = riscv32_regs_read; target->regs_write = riscv32_regs_write; target->reg_write = riscv32_reg_write; @@ -113,30 +111,30 @@ static void riscv32_regs_read(target_s *const target, void *const data) { /* Grab the hart structure and figure out how many registers need reading out */ riscv_hart_s *const hart = riscv_hart_struct(target); - riscv32_regs_s *const regs = (riscv32_regs_s *)data; + uint32_t *const regs = (uint32_t *)data; const size_t gprs_count = hart->extensions & RV_ISA_EXT_EMBEDDED ? 16U : 32U; /* Loop through reading out the GPRs */ for (size_t gpr = 0; gpr < gprs_count; ++gpr) { // TODO: handle when this fails.. - riscv_csr_read(hart, RV_GPR_BASE + gpr, ®s->gprs[gpr]); + riscv_csr_read(hart, RV_GPR_BASE + gpr, ®s[gpr]); } /* Special access to grab the program counter that would be executed on resuming the hart */ - riscv_csr_read(hart, RV_DPC, ®s->pc); + riscv_csr_read(hart, RV_DPC, ®s[gprs_count]); } static void riscv32_regs_write(target_s *const target, const void *const data) { /* Grab the hart structure and figure out how many registers need reading out */ riscv_hart_s *const hart = riscv_hart_struct(target); - const riscv32_regs_s *const regs = (const riscv32_regs_s *)data; + const uint32_t *const regs = (const uint32_t *)data; const size_t gprs_count = hart->extensions & RV_ISA_EXT_EMBEDDED ? 16U : 32U; /* Loop through writing out the GPRs, except for the first which is always 0 */ for (size_t gpr = 1; gpr < gprs_count; ++gpr) { // TODO: handle when this fails.. - riscv_csr_write(hart, RV_GPR_BASE + gpr, ®s->gprs[gpr]); + riscv_csr_write(hart, RV_GPR_BASE + gpr, ®s[gpr]); } /* Special access to poke in the program counter that will be executed on resuming the hart */ - riscv_csr_write(hart, RV_DPC, ®s->pc); + riscv_csr_write(hart, RV_DPC, ®s[gprs_count]); } static inline size_t riscv32_bool_to_4(const bool ret)