Allow riscv_semihosting without 16 bit access to memory with instructions (#544)

* Allow riscv_semihosting without 16 bit access to memory with instrustions

Signed-off-by: Samuel Obuch <sobuch@codasip.com>

* rename *_by_any_size to riscv_*_by_any_size
This commit is contained in:
Samuel Obuch 2020-10-16 18:19:53 +02:00 committed by GitHub
parent fb477376da
commit bc1d689e6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 13 deletions

View File

@ -778,7 +778,7 @@ static int read_by_given_size(struct target *target, target_addr_t address,
* Write one memory item using any memory access size that will work.
* Utilize read-modify-write, if needed.
* */
static int write_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
int riscv_write_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
{
assert(size == 1 || size == 2 || size == 4 || size == 8);
@ -810,7 +810,7 @@ static int write_by_any_size(struct target *target, target_addr_t address, uint3
* Read one memory item using any memory access size that will work.
* Read larger section of memory and pick out the required portion, if needed.
* */
static int read_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
int riscv_read_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
{
assert(size == 1 || size == 2 || size == 4 || size == 8);
@ -855,7 +855,7 @@ int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
}
/* Read the original instruction. */
if (read_by_any_size(
if (riscv_read_by_any_size(
target, breakpoint->address, breakpoint->length, breakpoint->orig_instr) != ERROR_OK) {
LOG_ERROR("Failed to read original instruction at 0x%" TARGET_PRIxADDR,
breakpoint->address);
@ -865,7 +865,7 @@ int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
uint8_t buff[4] = { 0 };
buf_set_u32(buff, 0, breakpoint->length * CHAR_BIT, breakpoint->length == 4 ? ebreak() : ebreak_c());
/* Write the ebreak instruction. */
if (write_by_any_size(target, breakpoint->address, breakpoint->length, buff) != ERROR_OK) {
if (riscv_write_by_any_size(target, breakpoint->address, breakpoint->length, buff) != ERROR_OK) {
LOG_ERROR("Failed to write %d-byte breakpoint instruction at 0x%"
TARGET_PRIxADDR, breakpoint->length, breakpoint->address);
return ERROR_FAIL;
@ -937,7 +937,7 @@ int riscv_remove_breakpoint(struct target *target,
{
if (breakpoint->type == BKPT_SOFT) {
/* Write the original instruction. */
if (write_by_any_size(
if (riscv_write_by_any_size(
target, breakpoint->address, breakpoint->length, breakpoint->orig_instr) != ERROR_OK) {
LOG_ERROR("Failed to restore instruction for %d-byte breakpoint at "
"0x%" TARGET_PRIxADDR, breakpoint->length, breakpoint->address);

View File

@ -414,4 +414,7 @@ semihosting_result_t riscv_semihosting(struct target *target, int *retval);
void riscv_add_bscan_tunneled_scan(struct target *target, struct scan_field *field,
riscv_bscan_tunneled_scan_context_t *ctxt);
int riscv_read_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer);
int riscv_write_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer);
#endif

View File

@ -85,12 +85,15 @@ semihosting_result_t riscv_semihosting(struct target *target, int *retval)
if (result != ERROR_OK)
return SEMI_ERROR;
uint8_t tmp[12];
uint8_t tmp_buf[12];
/* Read the current instruction, including the bracketing */
*retval = target_read_memory(target, pc - 4, 2, 6, tmp);
if (*retval != ERROR_OK)
return SEMI_ERROR;
/* Read three uncompressed instructions: The previous, the current one (pointed to by PC) and the next one */
for (int i = 0; i < 3; i++) {
/* Instruction memories may not support arbitrary read size. Use any size that will work. */
*retval = riscv_read_by_any_size(target, (pc - 4) + 4 * i, 4, tmp_buf + 4 * i);
if (*retval != ERROR_OK)
return SEMI_ERROR;
}
/*
* The instructions that trigger a semihosting call,
@ -100,9 +103,9 @@ semihosting_result_t riscv_semihosting(struct target *target, int *retval)
* 00100073 ebreak
* 40705013 srai zero,zero,0x7
*/
uint32_t pre = target_buffer_get_u32(target, tmp);
uint32_t ebreak = target_buffer_get_u32(target, tmp + 4);
uint32_t post = target_buffer_get_u32(target, tmp + 8);
uint32_t pre = target_buffer_get_u32(target, tmp_buf);
uint32_t ebreak = target_buffer_get_u32(target, tmp_buf + 4);
uint32_t post = target_buffer_get_u32(target, tmp_buf + 8);
LOG_DEBUG("check %08x %08x %08x from 0x%" PRIx64 "-4", pre, ebreak, post, pc);
if (pre != 0x01f01013 || ebreak != 0x00100073 || post != 0x40705013) {