Upstream tons of RISC-V changes.
These are all the changes from https://github.com/riscv/riscv-openocd
(approximately 91dc0c0c) made just to src/target/riscv/*. Some of the
new code is disabled because it requires some other target-independent
changes which I didn't want to include here.
Built like this, OpenOCD passes:
* All single-RV32 tests against spike.
* All single-RV64 tests against spike.
* Enough HiFive1 tests. (I suspect the failures are due to the test
suite rotting.)
* Many dual-RV32 (-rtos hwthread) against spike.
* Many dual-RV64 (-rtos hwthread) against spike.
I suspect this is an overall improvement compared to what's in mainline
right now, and it gets me a lot closer to getting all the riscv-openocd
work upstreamed.
Change-Id: Ide2f80c9397400780ff6780d78a206bc6a6e2f98
Signed-off-by: Tim Newsome <tim@sifive.com>
Reviewed-on: http://openocd.zylin.com/5821
Tested-by: jenkins
Reviewed-by: Jan Matyas <matyas@codasip.com>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Karl Palsson <karlp@tweak.net.au>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2018 by Liviu Ionescu *
|
||||
* ilg@livius.net *
|
||||
@@ -60,35 +62,35 @@ void riscv_semihosting_init(struct target *target)
|
||||
/**
|
||||
* Check for and process a semihosting request using the ARM protocol). This
|
||||
* is meant to be called when the target is stopped due to a debug mode entry.
|
||||
* If the value 0 is returned then there was nothing to process. A non-zero
|
||||
* return value signifies that a request was processed and the target resumed,
|
||||
* or an error was encountered, in which case the caller must return
|
||||
* immediately.
|
||||
*
|
||||
* @param target Pointer to the target to process.
|
||||
* @param retval Pointer to a location where the return code will be stored
|
||||
* @return non-zero value if a request was processed or an error encountered
|
||||
*/
|
||||
int riscv_semihosting(struct target *target, int *retval)
|
||||
semihosting_result_t riscv_semihosting(struct target *target, int *retval)
|
||||
{
|
||||
struct semihosting *semihosting = target->semihosting;
|
||||
if (!semihosting)
|
||||
return 0;
|
||||
if (!semihosting) {
|
||||
LOG_DEBUG(" -> NONE (!semihosting)");
|
||||
return SEMI_NONE;
|
||||
}
|
||||
|
||||
if (!semihosting->is_active)
|
||||
return 0;
|
||||
if (!semihosting->is_active) {
|
||||
LOG_DEBUG(" -> NONE (!semihosting->is_active)");
|
||||
return SEMI_NONE;
|
||||
}
|
||||
|
||||
riscv_reg_t dpc;
|
||||
int result = riscv_get_register(target, &dpc, GDB_REGNO_DPC);
|
||||
riscv_reg_t pc;
|
||||
int result = riscv_get_register(target, &pc, GDB_REGNO_PC);
|
||||
if (result != ERROR_OK)
|
||||
return 0;
|
||||
return SEMI_ERROR;
|
||||
|
||||
uint8_t tmp[12];
|
||||
|
||||
/* Read the current instruction, including the bracketing */
|
||||
*retval = target_read_memory(target, dpc - 4, 2, 6, tmp);
|
||||
*retval = target_read_memory(target, pc - 4, 2, 6, tmp);
|
||||
if (*retval != ERROR_OK)
|
||||
return 0;
|
||||
return SEMI_ERROR;
|
||||
|
||||
/*
|
||||
* The instructions that trigger a semihosting call,
|
||||
@@ -101,12 +103,12 @@ int riscv_semihosting(struct target *target, int *retval)
|
||||
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);
|
||||
LOG_DEBUG("check %08x %08x %08x from 0x%" PRIx64 "-4", pre, ebreak, post, dpc);
|
||||
LOG_DEBUG("check %08x %08x %08x from 0x%" PRIx64 "-4", pre, ebreak, post, pc);
|
||||
|
||||
if (pre != 0x01f01013 || ebreak != 0x00100073 || post != 0x40705013) {
|
||||
|
||||
/* Not the magic sequence defining semihosting. */
|
||||
return 0;
|
||||
LOG_DEBUG(" -> NONE (no magic)");
|
||||
return SEMI_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -114,18 +116,21 @@ int riscv_semihosting(struct target *target, int *retval)
|
||||
* operation to complete.
|
||||
*/
|
||||
if (!semihosting->hit_fileio) {
|
||||
|
||||
/* RISC-V uses A0 and A1 to pass function arguments */
|
||||
riscv_reg_t r0;
|
||||
riscv_reg_t r1;
|
||||
|
||||
result = riscv_get_register(target, &r0, GDB_REGNO_A0);
|
||||
if (result != ERROR_OK)
|
||||
return 0;
|
||||
if (result != ERROR_OK) {
|
||||
LOG_DEBUG(" -> ERROR (couldn't read a0)");
|
||||
return SEMI_ERROR;
|
||||
}
|
||||
|
||||
result = riscv_get_register(target, &r1, GDB_REGNO_A1);
|
||||
if (result != ERROR_OK)
|
||||
return 0;
|
||||
if (result != ERROR_OK) {
|
||||
LOG_DEBUG(" -> ERROR (couldn't read a1)");
|
||||
return SEMI_ERROR;
|
||||
}
|
||||
|
||||
semihosting->op = r0;
|
||||
semihosting->param = r1;
|
||||
@@ -136,11 +141,12 @@ int riscv_semihosting(struct target *target, int *retval)
|
||||
*retval = semihosting_common(target);
|
||||
if (*retval != ERROR_OK) {
|
||||
LOG_ERROR("Failed semihosting operation");
|
||||
return 0;
|
||||
return SEMI_ERROR;
|
||||
}
|
||||
} else {
|
||||
/* Unknown operation number, not a semihosting call. */
|
||||
return 0;
|
||||
LOG_DEBUG(" -> NONE (unknown operation number)");
|
||||
return SEMI_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,16 +156,16 @@ int riscv_semihosting(struct target *target, int *retval)
|
||||
*/
|
||||
if (semihosting->is_resumable && !semihosting->hit_fileio) {
|
||||
/* Resume right after the EBREAK 4 bytes instruction. */
|
||||
*retval = target_resume(target, 0, dpc+4, 0, 0);
|
||||
if (*retval != ERROR_OK) {
|
||||
LOG_ERROR("Failed to resume target");
|
||||
return 0;
|
||||
}
|
||||
*retval = riscv_set_register(target, GDB_REGNO_PC, pc + 4);
|
||||
if (*retval != ERROR_OK)
|
||||
return SEMI_ERROR;
|
||||
|
||||
return 1;
|
||||
LOG_DEBUG(" -> HANDLED");
|
||||
return SEMI_HANDLED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
LOG_DEBUG(" -> WAITING");
|
||||
return SEMI_WAITING;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
@@ -171,7 +177,7 @@ int riscv_semihosting(struct target *target, int *retval)
|
||||
*/
|
||||
static int riscv_semihosting_setup(struct target *target, int enable)
|
||||
{
|
||||
LOG_DEBUG("enable=%d", enable);
|
||||
LOG_DEBUG("[%s] enable=%d", target_name(target), enable);
|
||||
|
||||
struct semihosting *semihosting = target->semihosting;
|
||||
if (semihosting)
|
||||
|
||||
Reference in New Issue
Block a user