+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
/***************************************************************************
* Copyright (C) 2018 by Liviu Ionescu *
* ilg@livius.net *
/**
* 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,
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;
}
/*
* 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;
*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;
}
}
*/
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;
}
/* -------------------------------------------------------------------------
*/
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)