1 /***************************************************************************
2 * Copyright (C) 2018 by Liviu Ionescu *
5 * Copyright (C) 2009 by Marvell Technology Group Ltd. *
6 * Written by Nicolas Pitre <nico@marvell.com> *
8 * Copyright (C) 2010 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
11 * Copyright (C) 2016 by Square, Inc. *
12 * Steven Stallion <stallion@squareup.com> *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
26 ***************************************************************************/
30 * Hold RISC-V semihosting support.
32 * The RISC-V code is inspired from ARM semihosting.
34 * Details can be found in chapter 8 of DUI0203I_rvct_developer_guide.pdf
44 #include "target/target.h"
45 #include "target/semihosting_common.h"
48 static int riscv_semihosting_setup(struct target *target, int enable);
49 static int riscv_semihosting_post_result(struct target *target);
52 * Initialize RISC-V semihosting. Use common ARM code.
54 void riscv_semihosting_init(struct target *target)
56 semihosting_common_init(target, riscv_semihosting_setup,
57 riscv_semihosting_post_result);
61 * Check for and process a semihosting request using the ARM protocol). This
62 * is meant to be called when the target is stopped due to a debug mode entry.
63 * If the value 0 is returned then there was nothing to process. A non-zero
64 * return value signifies that a request was processed and the target resumed,
65 * or an error was encountered, in which case the caller must return
68 * @param target Pointer to the target to process.
69 * @param retval Pointer to a location where the return code will be stored
70 * @return non-zero value if a request was processed or an error encountered
72 int riscv_semihosting(struct target *target, int *retval)
74 struct semihosting *semihosting = target->semihosting;
78 if (!semihosting->is_active)
82 int result = riscv_get_register(target, &dpc, GDB_REGNO_DPC);
83 if (result != ERROR_OK)
88 /* Read the current instruction, including the bracketing */
89 *retval = target_read_memory(target, dpc - 4, 2, 6, tmp);
90 if (*retval != ERROR_OK)
94 * The instructions that trigger a semihosting call,
95 * always uncompressed, should look like:
97 * 01f01013 slli zero,zero,0x1f
99 * 40705013 srai zero,zero,0x7
101 uint32_t pre = target_buffer_get_u32(target, tmp);
102 uint32_t ebreak = target_buffer_get_u32(target, tmp + 4);
103 uint32_t post = target_buffer_get_u32(target, tmp + 8);
104 LOG_DEBUG("check %08x %08x %08x from 0x%" PRIx64 "-4", pre, ebreak, post, dpc);
106 if (pre != 0x01f01013 || ebreak != 0x00100073 || post != 0x40705013) {
108 /* Not the magic sequence defining semihosting. */
113 * Perform semihosting call if we are not waiting on a fileio
114 * operation to complete.
116 if (!semihosting->hit_fileio) {
118 /* RISC-V uses A0 and A1 to pass function arguments */
122 result = riscv_get_register(target, &r0, GDB_REGNO_A0);
123 if (result != ERROR_OK)
126 result = riscv_get_register(target, &r1, GDB_REGNO_A1);
127 if (result != ERROR_OK)
130 semihosting->op = r0;
131 semihosting->param = r1;
132 semihosting->word_size_bytes = riscv_xlen(target) / 8;
134 /* Check for ARM operation numbers. */
135 if (0 <= semihosting->op && semihosting->op <= 0x31) {
136 *retval = semihosting_common(target);
137 if (*retval != ERROR_OK) {
138 LOG_ERROR("Failed semihosting operation");
142 /* Unknown operation number, not a semihosting call. */
148 * Resume target if we are not waiting on a fileio
149 * operation to complete.
151 if (semihosting->is_resumable && !semihosting->hit_fileio) {
152 /* Resume right after the EBREAK 4 bytes instruction. */
153 *retval = target_resume(target, 0, dpc+4, 0, 0);
154 if (*retval != ERROR_OK) {
155 LOG_ERROR("Failed to resume target");
165 /* -------------------------------------------------------------------------
166 * Local functions. */
169 * Called via semihosting->setup() later, after the target is known,
170 * usually on the first semihosting command.
172 static int riscv_semihosting_setup(struct target *target, int enable)
174 LOG_DEBUG("enable=%d", enable);
176 struct semihosting *semihosting = target->semihosting;
178 semihosting->setup_time = clock();
183 static int riscv_semihosting_post_result(struct target *target)
185 struct semihosting *semihosting = target->semihosting;
187 /* If not enabled, silently ignored. */
191 LOG_DEBUG("0x%" PRIx64, semihosting->result);
192 riscv_set_register(target, GDB_REGNO_A0, semihosting->result);