Upstream tons of RISC-V changes.
[fw/openocd] / src / target / riscv / riscv_semihosting.c
index c4b66537298908436a86d9e5eea7ee4b6715c829..99d6c7713e5976134244e6e2bfb0443db8c61781 100644 (file)
@@ -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)