This is an automated email from Gerrit. "Erhan Kurubas <erhan.kuru...@espressif.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7760
-- gerrit commit f992457db0ef6c46ea7d4f35192107914c187404 Author: Erhan Kurubas <erhan.kuru...@espressif.com> Date: Tue Jul 4 05:23:46 2023 +0200 target/xtensa: add arch level algorithm support to execute code on target Also includes Xtensa flasher stub jumper binary. Signed-off-by: Erhan Kurubas <erhan.kuru...@espressif.com> Change-Id: Ie67993e4100cca7264ffa7a868ee2b2f1268c723 diff --git a/src/target/espressif/esp.c b/src/target/espressif/esp.c index e7257a7bf4..6c43f544d3 100644 --- a/src/target/espressif/esp.c +++ b/src/target/espressif/esp.c @@ -14,6 +14,13 @@ #include "target/target.h" #include "esp.h" +int esp_common_init(struct esp_common *esp, const struct algorithm_hw *algo_hw) +{ + esp->algo_hw = algo_hw; + + return ERROR_OK; +} + int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs) { uint32_t table_size, table_start_id, desc_entry_id, gcov_entry_id; diff --git a/src/target/espressif/esp.h b/src/target/espressif/esp.h index 3ba2b8bcfa..d629f031b5 100644 --- a/src/target/espressif/esp.h +++ b/src/target/espressif/esp.h @@ -77,9 +77,11 @@ struct esp_dbg_stubs { }; struct esp_common { + const struct algorithm_hw *algo_hw; struct esp_dbg_stubs dbg_stubs; }; +int esp_common_init(struct esp_common *esp, const struct algorithm_hw *algo_hw); int esp_dbgstubs_table_read(struct target *target, struct esp_dbg_stubs *dbg_stubs); #endif /* OPENOCD_TARGET_ESP_H */ diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c index 5cc236c36f..d11857d176 100644 --- a/src/target/espressif/esp32.c +++ b/src/target/espressif/esp32.c @@ -496,6 +496,10 @@ struct target_type esp32_target = { .get_gdb_arch = xtensa_get_gdb_arch, .get_gdb_reg_list = xtensa_get_gdb_reg_list, + .run_algorithm = xtensa_run_algorithm, + .start_algorithm = xtensa_start_algorithm, + .wait_algorithm = xtensa_wait_algorithm, + .add_breakpoint = esp_xtensa_breakpoint_add, .remove_breakpoint = esp_xtensa_breakpoint_remove, diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c index 3628cc0931..35ed8190fd 100644 --- a/src/target/espressif/esp32s2.c +++ b/src/target/espressif/esp32s2.c @@ -542,6 +542,10 @@ struct target_type esp32s2_target = { .get_gdb_arch = xtensa_get_gdb_arch, .get_gdb_reg_list = xtensa_get_gdb_reg_list, + .run_algorithm = xtensa_run_algorithm, + .start_algorithm = xtensa_start_algorithm, + .wait_algorithm = xtensa_wait_algorithm, + .add_breakpoint = esp_xtensa_breakpoint_add, .remove_breakpoint = esp_xtensa_breakpoint_remove, diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c index 074155f6a6..f150a91a68 100644 --- a/src/target/espressif/esp32s3.c +++ b/src/target/espressif/esp32s3.c @@ -415,6 +415,10 @@ struct target_type esp32s3_target = { .get_gdb_arch = xtensa_get_gdb_arch, .get_gdb_reg_list = xtensa_get_gdb_reg_list, + .run_algorithm = xtensa_run_algorithm, + .start_algorithm = xtensa_start_algorithm, + .wait_algorithm = xtensa_wait_algorithm, + .add_breakpoint = esp_xtensa_breakpoint_add, .remove_breakpoint = esp_xtensa_breakpoint_remove, diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c index 72d6c202f6..44671b6303 100644 --- a/src/target/espressif/esp_xtensa.c +++ b/src/target/espressif/esp_xtensa.c @@ -12,6 +12,8 @@ #include <stdbool.h> #include <stdint.h> #include <target/smp.h> +#include <target/xtensa/xtensa_algorithm.h> +#include "esp.h" #include "esp_xtensa_apptrace.h" #include <target/register.h> #include "esp_xtensa.h" @@ -64,6 +66,9 @@ int esp_xtensa_init_arch_info(struct target *target, const struct esp_semihost_ops *semihost_ops) { int ret = xtensa_init_arch_info(target, &esp_xtensa->xtensa, dm_cfg); + if (ret != ERROR_OK) + return ret; + ret = esp_common_init(&esp_xtensa->esp, &xtensa_algo_hw); if (ret != ERROR_OK) return ret; esp_xtensa->semihost.ops = (struct esp_semihost_ops *)semihost_ops; diff --git a/src/target/espressif/esp_xtensa_smp.h b/src/target/espressif/esp_xtensa_smp.h index 6bfc713ffd..79bc35d2d8 100644 --- a/src/target/espressif/esp_xtensa_smp.h +++ b/src/target/espressif/esp_xtensa_smp.h @@ -8,8 +8,8 @@ #ifndef OPENOCD_TARGET_XTENSA_ESP_SMP_H #define OPENOCD_TARGET_XTENSA_ESP_SMP_H -#include "esp_xtensa.h" #include "esp_algorithm.h" +#include "esp_xtensa.h" struct esp_xtensa_smp_chip_ops { int (*poll)(struct target *target); diff --git a/src/target/xtensa/Makefile.am b/src/target/xtensa/Makefile.am index 22504e78b2..486b434ce6 100644 --- a/src/target/xtensa/Makefile.am +++ b/src/target/xtensa/Makefile.am @@ -6,6 +6,8 @@ noinst_LTLIBRARIES += %D%/libxtensa.la %D%/xtensa.h \ %D%/xtensa_chip.c \ %D%/xtensa_chip.h \ + %D%/xtensa_algorithm.c \ + %D%/xtensa_algorithm.h \ %D%/xtensa_debug_module.c \ %D%/xtensa_debug_module.h \ %D%/xtensa_fileio.c \ diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 431c36a249..a7cd508d62 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -16,9 +16,11 @@ #include <helper/time_support.h> #include <helper/align.h> #include <target/register.h> +#include <target/algorithm.h> #include "xtensa_chip.h" #include "xtensa.h" +#include "xtensa_algorithm.h" /* Swap 4-bit Xtensa opcodes and fields */ #define XT_NIBSWAP8(V) \ @@ -2635,6 +2637,210 @@ int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoin return ERROR_OK; } +int xtensa_start_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t entry_point, target_addr_t exit_point, + void *arch_info) +{ + struct xtensa *xtensa = target_to_xtensa(target); + struct xtensa_algorithm *algorithm_info = arch_info; + int retval = ERROR_OK; + bool usr_ps = false; + + /* NOTE: xtensa_run_algorithm requires that each algorithm uses a software breakpoint + * at the exit point */ + + if (target->state != TARGET_HALTED) { + LOG_WARNING("Target not halted!"); + return ERROR_TARGET_NOT_HALTED; + } + + for (unsigned int i = 0; i < xtensa->core_cache->num_regs; i++) { + struct reg *reg = &xtensa->core_cache->reg_list[i]; + buf_cpy(reg->value, xtensa->algo_context_backup[i], reg->size); + } + /* save debug reason, it will be changed */ + algorithm_info->ctx_debug_reason = target->debug_reason; + /* write mem params */ + for (int i = 0; i < num_mem_params; i++) { + if (mem_params[i].direction != PARAM_IN) { + retval = target_write_buffer(target, mem_params[i].address, + mem_params[i].size, + mem_params[i].value); + if (retval != ERROR_OK) + return retval; + } + } + /* write reg params */ + for (int i = 0; i < num_reg_params; i++) { + assert(reg_params[i].size <= 32); + struct reg *reg = register_get_by_name(xtensa->core_cache, reg_params[i].reg_name, 0); + if (!reg) { + LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + return ERROR_COMMAND_SYNTAX_ERROR; + } + if (reg->size != reg_params[i].size) { + LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); + return ERROR_COMMAND_SYNTAX_ERROR; + } + if (memcmp(reg_params[i].reg_name, "ps", 3)) { + usr_ps = true; + } else { + unsigned int reg_id = xtensa->eps_dbglevel_idx; + assert(reg_id < xtensa->core_cache->num_regs && "Attempt to access non-existing reg!"); + reg = &xtensa->core_cache->reg_list[reg_id]; + } + xtensa_reg_set_value(reg, buf_get_u32(reg_params[i].value, 0, reg->size)); + reg->valid = 1; + } + /* ignore custom core mode if custom PS value is specified */ + if (!usr_ps) { + unsigned int eps_reg_idx = xtensa->eps_dbglevel_idx; + xtensa_reg_val_t ps = xtensa_reg_get(target, eps_reg_idx); + enum xtensa_mode core_mode = XT_PS_RING_GET(ps); + if (algorithm_info->core_mode != XT_MODE_ANY && algorithm_info->core_mode != core_mode) { + LOG_DEBUG("setting core_mode: 0x%x", algorithm_info->core_mode); + xtensa_reg_val_t new_ps = (ps & ~XT_PS_RING_MSK) | XT_PS_RING(algorithm_info->core_mode); + /* save previous core mode */ + algorithm_info->core_mode = core_mode; + xtensa_reg_set(target, eps_reg_idx, new_ps); + xtensa->core_cache->reg_list[eps_reg_idx].valid = 1; + } + } + + return xtensa_resume(target, 0, entry_point, 1, 1); +} + +/** Waits for an algorithm in the target. */ +int xtensa_wait_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t exit_point, unsigned int timeout_ms, + void *arch_info) +{ + struct xtensa *xtensa = target_to_xtensa(target); + struct xtensa_algorithm *algorithm_info = arch_info; + int retval = ERROR_OK; + xtensa_reg_val_t pc; + + /* NOTE: xtensa_run_algorithm requires that each algorithm uses a software breakpoint + * at the exit point */ + + retval = target_wait_state(target, TARGET_HALTED, timeout_ms); + /* If the target fails to halt due to the breakpoint, force a halt */ + if (retval != ERROR_OK || target->state != TARGET_HALTED) { + retval = target_halt(target); + if (retval != ERROR_OK) + return retval; + retval = target_wait_state(target, TARGET_HALTED, 500); + if (retval != ERROR_OK) + return retval; + LOG_TARGET_ERROR(target, "not halted %d, pc 0x%x, ps 0x%x", retval, + xtensa_reg_get(target, XT_REG_IDX_PC), + xtensa_reg_get(target, xtensa->eps_dbglevel_idx)); + return ERROR_TARGET_TIMEOUT; + } + pc = xtensa_reg_get(target, XT_REG_IDX_PC); + if (exit_point && pc != exit_point) { + LOG_ERROR("failed algorithm halted at 0x%" PRIx32 ", expected " TARGET_ADDR_FMT, pc, exit_point); + return ERROR_TARGET_TIMEOUT; + } + /* Copy core register values to reg_params[] */ + for (int i = 0; i < num_reg_params; i++) { + if (reg_params[i].direction != PARAM_OUT) { + struct reg *reg = register_get_by_name(xtensa->core_cache, reg_params[i].reg_name, 0); + if (!reg) { + LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name); + return ERROR_COMMAND_SYNTAX_ERROR; + } + if (reg->size != reg_params[i].size) { + LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name); + return ERROR_COMMAND_SYNTAX_ERROR; + } + buf_set_u32(reg_params[i].value, 0, 32, xtensa_reg_get_value(reg)); + } + } + /* Read memory values to mem_params */ + LOG_DEBUG("Read mem params"); + for (int i = 0; i < num_mem_params; i++) { + LOG_DEBUG("Check mem param @ " TARGET_ADDR_FMT, mem_params[i].address); + if (mem_params[i].direction != PARAM_OUT) { + LOG_DEBUG("Read mem param @ " TARGET_ADDR_FMT, mem_params[i].address); + retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value); + if (retval != ERROR_OK) + return retval; + } + } + + /* avoid gdb keep_alive warning */ + keep_alive(); + + for (int i = xtensa->core_cache->num_regs - 1; i >= 0; i--) { + struct reg *reg = &xtensa->core_cache->reg_list[i]; + if (i == XT_REG_IDX_PS) { + continue; /* restore mapped reg number of PS depends on NDEBUGLEVEL */ + } else if (i == XT_REG_IDX_DEBUGCAUSE) { + /*FIXME: restoring DEBUGCAUSE causes exception when executing corresponding + * instruction in DIR */ + LOG_DEBUG("Skip restoring register %s: 0x%8.8" PRIx32 " -> 0x%8.8" PRIx32, + xtensa->core_cache->reg_list[i].name, + buf_get_u32(reg->value, 0, 32), + buf_get_u32(xtensa->algo_context_backup[i], 0, 32)); + buf_cpy(xtensa->algo_context_backup[i], reg->value, reg->size); + xtensa->core_cache->reg_list[i].dirty = 0; + xtensa->core_cache->reg_list[i].valid = 0; + } else if (memcmp(xtensa->algo_context_backup[i], reg->value, reg->size / 8)) { + if (reg->size <= 32) { + LOG_DEBUG("restoring register %s: 0x%8.8" PRIx32 " -> 0x%8.8" PRIx32, + xtensa->core_cache->reg_list[i].name, + buf_get_u32(reg->value, 0, reg->size), + buf_get_u32(xtensa->algo_context_backup[i], 0, reg->size)); + } else if (reg->size <= 64) { + LOG_DEBUG("restoring register %s: 0x%8.8" PRIx64 " -> 0x%8.8" PRIx64, + xtensa->core_cache->reg_list[i].name, + buf_get_u64(reg->value, 0, reg->size), + buf_get_u64(xtensa->algo_context_backup[i], 0, reg->size)); + } else { + LOG_DEBUG("restoring register %s %u-bits", xtensa->core_cache->reg_list[i].name, reg->size); + } + buf_cpy(xtensa->algo_context_backup[i], reg->value, reg->size); + xtensa->core_cache->reg_list[i].dirty = 1; + xtensa->core_cache->reg_list[i].valid = 1; + } + } + target->debug_reason = algorithm_info->ctx_debug_reason; + + retval = xtensa_write_dirty_registers(target); + if (retval != ERROR_OK) + LOG_ERROR("Failed to write dirty regs (%d)!", retval); + + return retval; +} + +int xtensa_run_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t entry_point, target_addr_t exit_point, + unsigned int timeout_ms, void *arch_info) +{ + int retval = xtensa_start_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + entry_point, exit_point, + arch_info); + + if (retval == ERROR_OK) { + retval = xtensa_wait_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + exit_point, timeout_ms, + arch_info); + } + + return retval; +} + static int xtensa_build_reg_cache(struct target *target) { struct xtensa *xtensa = target_to_xtensa(target); diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 4216ae24f6..24a649b74b 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -395,6 +395,21 @@ int xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint); int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint); int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint); int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoint); +int xtensa_start_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t entry_point, target_addr_t exit_point, + void *arch_info); +int xtensa_wait_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t exit_point, unsigned int timeout_ms, + void *arch_info); +int xtensa_run_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + target_addr_t entry_point, target_addr_t exit_point, + unsigned int timeout_ms, void *arch_info); void xtensa_set_permissive_mode(struct target *target, bool state); const char *xtensa_get_gdb_arch(struct target *target); int xtensa_gdb_query_custom(struct target *target, const char *packet, char **response_p); diff --git a/src/target/xtensa/xtensa_algorithm.c b/src/target/xtensa/xtensa_algorithm.c new file mode 100644 index 0000000000..7c5ac0bcc7 --- /dev/null +++ b/src/target/xtensa/xtensa_algorithm.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/*************************************************************************** + * Module to run arbitrary code on Xtensa using OpenOCD * + * Copyright (C) 2019 Espressif Systems Ltd. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "xtensa.h" +#include "xtensa_algorithm.h" + +static int xtensa_algo_init(struct target *target, struct algorithm_run_data *run, + uint32_t num_args, va_list ap); +static int xtensa_algo_cleanup(struct target *target, struct algorithm_run_data *run); +static const uint8_t *xtensa_stub_tramp_get(struct target *target, size_t *size); + +const struct algorithm_hw xtensa_algo_hw = { + .algo_init = xtensa_algo_init, + .algo_cleanup = xtensa_algo_cleanup, + .stub_tramp_get = xtensa_stub_tramp_get, +}; + +static const uint8_t xtensa_stub_tramp_win[] = { +#include "src/target/xtensa/xtensa_stub_tramp_win.inc" +}; + +static const uint8_t *xtensa_stub_tramp_get(struct target *target, size_t *size) +{ + struct xtensa *xtensa = target_to_xtensa(target); + + if (!xtensa->core_config->windowed) { + LOG_ERROR("Running stubs is not supported for cores without windowed registers option!"); + return NULL; + } + *size = sizeof(xtensa_stub_tramp_win); + return xtensa_stub_tramp_win; +} + +static int xtensa_algo_regs_init_start(struct target *target, struct algorithm_run_data *run) +{ + uint32_t stack_addr = run->stub.stack_addr; + + LOG_DEBUG("Check stack addr 0x%x", stack_addr); + if (stack_addr & 0xFUL) { + stack_addr &= ~0xFUL; + LOG_DEBUG("Adjust stack addr to 0x%x", stack_addr); + } + stack_addr -= 16; + struct reg_param *params = run->reg_args.params; + init_reg_param(¶ms[0], "a0", 32, PARAM_OUT); /*TODO: move to tramp */ + init_reg_param(¶ms[1], "a1", 32, PARAM_OUT); + init_reg_param(¶ms[2], "a8", 32, PARAM_OUT); + init_reg_param(¶ms[3], "windowbase", 32, PARAM_OUT); /*TODO: move to tramp */ + init_reg_param(¶ms[4], "windowstart", 32, PARAM_OUT); /*TODO: move to tramp */ + init_reg_param(¶ms[5], "ps", 32, PARAM_OUT); + buf_set_u32(params[0].value, 0, 32, 0); /* a0 TODO: move to tramp */ + buf_set_u32(params[1].value, 0, 32, stack_addr); /* a1 */ + buf_set_u32(params[2].value, 0, 32, run->stub.entry); /* a8 */ + buf_set_u32(params[3].value, 0, 32, 0x0); /* initial window base TODO: move to tramp */ + buf_set_u32(params[4].value, 0, 32, 0x1); /* initial window start TODO: move to tramp */ + buf_set_u32(params[5].value, 0, 32, 0x60025); /* enable WOE, UM and debug interrupts level (6) */ + return ERROR_OK; +} + +static int xtensa_algo_init(struct target *target, struct algorithm_run_data *run, + uint32_t num_args, va_list ap) +{ + enum xtensa_mode core_mode = XT_MODE_ANY; + static const char *const arg_regs[] = { "a2", "a3", "a4", "a5", "a6" }; + + if (num_args > ARRAY_SIZE(arg_regs)) { + LOG_ERROR("Too many algo user args %u! Max %zu args are supported.", num_args, ARRAY_SIZE(arg_regs)); + return ERROR_FAIL; + } + + if (run->arch_info) { + struct xtensa_algorithm *xtensa_algo = run->arch_info; + core_mode = xtensa_algo->core_mode; + } + + run->reg_args.first_user_param = XTENSA_STUB_ARGS_FUNC_START; + run->reg_args.count = run->reg_args.first_user_param + num_args; + if (num_args == 0) + run->reg_args.count++; /*a2 reg is used as the 1st arg and return code*/ + LOG_DEBUG("reg params count %d (%d/%d).", + run->reg_args.count, + run->reg_args.first_user_param, + num_args); + run->reg_args.params = calloc(run->reg_args.count, sizeof(struct reg_param)); + assert(run->reg_args.params); + + xtensa_algo_regs_init_start(target, run); + + init_reg_param(&run->reg_args.params[run->reg_args.first_user_param + 0], "a2", 32, PARAM_IN_OUT); + + if (num_args > 0) { + uint32_t arg = va_arg(ap, uint32_t); + algorithm_user_arg_set_uint(run, 0, arg); + LOG_DEBUG("Set arg[0] = %d (%s)", arg, run->reg_args.params[run->reg_args.first_user_param + 0].reg_name); + } else { + algorithm_user_arg_set_uint(run, 0, 0); + } + + for (unsigned int i = 1; i < num_args; i++) { + uint32_t arg = va_arg(ap, uint32_t); + init_reg_param(&run->reg_args.params[run->reg_args.first_user_param + i], (char *)arg_regs[i], 32, PARAM_OUT); + algorithm_user_arg_set_uint(run, i, arg); + LOG_DEBUG("Set arg[%d] = %d (%s)", i, arg, + run->reg_args.params[run->reg_args.first_user_param + i].reg_name); + } + struct xtensa_algorithm *ainfo = calloc(1, sizeof(struct xtensa_algorithm)); + assert(ainfo); + ainfo->core_mode = core_mode; + run->stub.ainfo = ainfo; + return ERROR_OK; +} + +static int xtensa_algo_cleanup(struct target *target, struct algorithm_run_data *run) +{ + free(run->stub.ainfo); + for (uint32_t i = 0; i < run->reg_args.count; i++) + destroy_reg_param(&run->reg_args.params[i]); + free(run->reg_args.params); + return ERROR_OK; +} diff --git a/src/target/xtensa/xtensa_algorithm.h b/src/target/xtensa/xtensa_algorithm.h new file mode 100644 index 0000000000..d4b44b5a75 --- /dev/null +++ b/src/target/xtensa/xtensa_algorithm.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/*************************************************************************** + * Module to run arbitrary code on Xtensa using OpenOCD * + * Copyright (C) 2019 Espressif Systems Ltd. * + ***************************************************************************/ + +#ifndef OPENOCD_TARGET_XTENSA_ALGO_H +#define OPENOCD_TARGET_XTENSA_ALGO_H + +#include "xtensa.h" +#include <target/espressif/esp_algorithm.h> + +/** Index of the first user-defined algo arg. @see algorithm_stub */ +#define XTENSA_STUB_ARGS_FUNC_START 6 + +/** + * Xtensa algorithm data. + */ +struct xtensa_algorithm { + /** User can set this to specify which core mode algorithm should be run in. */ + enum xtensa_mode core_mode; + /** Used internally to backup and restore debug_reason. */ + enum target_debug_reason ctx_debug_reason; +}; + +extern const struct algorithm_hw xtensa_algo_hw; + +#endif /* OPENOCD_TARGET_XTENSA_ALGO_H */ diff --git a/src/target/xtensa/xtensa_stub_tramp_win.S b/src/target/xtensa/xtensa_stub_tramp_win.S new file mode 100644 index 0000000000..18d0ed49f0 --- /dev/null +++ b/src/target/xtensa/xtensa_stub_tramp_win.S @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/*************************************************************************** + * Xtensa flasher stub wrapper * + * Copyright (C) 2017 Espressif Systems Ltd. * + ***************************************************************************/ + +/* To assemble: + * xtensa-esp32-elf-gcc -c xtensa_stub_tramp_win.S -o xtensa_stub_tramp_win.o + * + * To disassemble: + * xtensa-esp32-elf-objdump -d xtensa_stub_tramp_win.o + * + * To generate binary file: + * xtensa-esp32-elf-objcopy -O binary xtensa_stub_tramp_win.o xtensa_stub_tramp_win.bin + * + * To generate include file: + * ../../../src/helper/bin2char.sh < xtensa_stub_tramp_win.bin > xtensa_stub_tramp_win.inc + */ + +/* + * Expects : + * a0 = zero + * a1 = stack_base + stack_size - 16, 16 bytes aligned + * a8 = address of the function to call + * Params : + * a2 = command arg0, result (out) + * a3 = command arg1 + * a4 = command arg2 + * a5 = command arg3 + * a6 = command arg4 + * Maximum 5 user args + */ + .text + + .align 4 +_stub_enter: + /* initialize initial stack frame for callx8 */ + addi a9, sp, 32 /* point 16 past extra save area */ + s32e a9, sp, -12 /* access to extra save area */ + /* prepare args */ + mov a10, a2 + mov a11, a3 + mov a12, a4 + mov a13, a5 + mov a14, a6 + /* call stub */ + callx8 a8 + /* prepare return value */ + mov a2, a10 + break 0,0 + +_idle_loop: + j _idle_loop diff --git a/src/target/xtensa/xtensa_stub_tramp_win.inc b/src/target/xtensa/xtensa_stub_tramp_win.inc new file mode 100644 index 0000000000..a82d0c76ab --- /dev/null +++ b/src/target/xtensa/xtensa_stub_tramp_win.inc @@ -0,0 +1,4 @@ +/* Autogenerated with ../../../src/helper/bin2char.sh */ +0x92,0xc1,0x20,0x90,0xd1,0x49,0xad,0x02,0xbd,0x03,0xcd,0x04,0xdd,0x05,0x60,0xe6, +0x20,0xe0,0x08,0x00,0x2d,0x0a,0x00,0x40,0x00,0x06,0xff,0xff, + --