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/+/7074

-- gerrit

commit 6bdf673a0129b949802f362486829d5575bef479
Author: Erhan Kurubas <erhan.kuru...@espressif.com>
Date:   Thu Jun 30 13:14:27 2022 +0300

    target/espressif: add semihosting support
    
    ARM semihosting + some custom syscalls implemented for
    Espressif chips (ESP32, ESP32-S2, ESP32-S3)
    
    Signed-off-by: Erhan Kurubas <erhan.kuru...@espressif.com>
    Change-Id: Ic8174cf1cd344fa16d619b7b8405c9650e869443

diff --git a/src/target/espressif/Makefile.am b/src/target/espressif/Makefile.am
index 2ea31d82c0..e8809f71b8 100644
--- a/src/target/espressif/Makefile.am
+++ b/src/target/espressif/Makefile.am
@@ -4,9 +4,13 @@ noinst_LTLIBRARIES += %D%/libespressif.la
        %D%/esp_xtensa.h \
        %D%/esp_xtensa_smp.c \
        %D%/esp_xtensa_smp.h \
+       %D%/esp_xtensa_semihosting.c \
+       %D%/esp_xtensa_semihosting.h \
        %D%/esp32.c \
        %D%/esp32.h \
        %D%/esp32s2.c \
        %D%/esp32s2.h \
        %D%/esp32s3.c \
-       %D%/esp32s3.h
+       %D%/esp32s3.h \
+       %D%/esp_semihosting.c \
+       %D%/esp_semihosting.h
diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c
index db318df7f8..88b490acb9 100644
--- a/src/target/espressif/esp32.c
+++ b/src/target/espressif/esp32.c
@@ -216,7 +216,8 @@ static int esp32_soc_reset(struct target *target)
                alive_sleep(10);
                xtensa_poll(target);
                if (timeval_ms() >= timeout) {
-                       LOG_TARGET_ERROR(target, "Timed out waiting for CPU to 
be reset, target state=%d", target->state);
+                       LOG_TARGET_ERROR(target, "Timed out waiting for CPU to 
be reset, target state=%d",
+                               target->state);
                        get_timeout = true;
                        break;
                }
@@ -342,6 +343,10 @@ static const struct esp_xtensa_smp_chip_ops esp32_chip_ops 
= {
        .on_halt = esp32_on_halt
 };
 
+static const struct esp_semihost_ops esp32_semihost_ops = {
+       .prepare = esp32_disable_wdts
+};
+
 static int esp32_target_create(struct target *target, Jim_Interp *interp)
 {
        struct xtensa_debug_module_config esp32_dm_cfg = {
@@ -359,7 +364,7 @@ static int esp32_target_create(struct target *target, 
Jim_Interp *interp)
        }
 
        int ret = esp_xtensa_smp_init_arch_info(target, &esp32->esp_xtensa_smp,
-               &esp32_dm_cfg, &esp32_chip_ops);
+               &esp32_dm_cfg, &esp32_chip_ops, &esp32_semihost_ops);
        if (ret != ERROR_OK) {
                LOG_ERROR("Failed to init arch info!");
                free(esp32);
@@ -445,6 +450,7 @@ static const struct command_registration 
esp32_any_command_handlers[] = {
 };
 
 extern const struct command_registration semihosting_common_handlers[];
+
 static const struct command_registration esp32_command_handlers[] = {
        {
                .chain = esp_xtensa_smp_command_handlers,
@@ -459,6 +465,13 @@ static const struct command_registration 
esp32_command_handlers[] = {
                .usage = "",
                .chain = esp32_any_command_handlers,
        },
+       {
+               .name = "arm",
+               .mode = COMMAND_ANY,
+               .help = "ARM Command Group",
+               .usage = "",
+               .chain = semihosting_common_handlers
+       },
        COMMAND_REGISTRATION_DONE
 };
 
diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c
index 87ca5be761..7bc9d1c6ff 100644
--- a/src/target/espressif/esp32s2.c
+++ b/src/target/espressif/esp32s2.c
@@ -26,6 +26,7 @@
 #include <target/target.h>
 #include <target/target_type.h>
 #include "esp_xtensa.h"
+#include "esp_xtensa_semihosting.h"
 #include "esp32s2.h"
 
 /* Overall memory map
@@ -304,7 +305,8 @@ static int esp32s2_soc_reset(struct target *target)
                alive_sleep(10);
                xtensa_poll(target);
                if (timeval_ms() >= timeout) {
-                       LOG_TARGET_ERROR(target, "Timed out waiting for CPU to 
be reset, target state=%d", target->state);
+                       LOG_TARGET_ERROR(target, "Timed out waiting for CPU to 
be reset, target state=%d",
+                               target->state);
                        return ERROR_TARGET_TIMEOUT;
                }
        }
@@ -418,6 +420,19 @@ static int esp32s2_poll(struct target *target)
                if (old_state == TARGET_DEBUG_RUNNING) {
                        target_call_event_callbacks(target, 
TARGET_EVENT_DEBUG_HALTED);
                } else {
+                       if (esp_xtensa_semihosting(target, &ret) != 0) {
+                               struct esp_xtensa_common *esp_xtensa = 
target_to_esp_xtensa(target);
+                               if (ret == ERROR_OK && 
esp_xtensa->semihost.need_resume) {
+                                       esp_xtensa->semihost.need_resume = 
false;
+                                       /* Resume xtensa_resume will handle 
BREAK instruction. */
+                                       ret = target_resume(target, 1, 0, 1, 0);
+                                       if (ret != ERROR_OK) {
+                                               LOG_ERROR("Failed to resume 
target");
+                                               return ret;
+                                       }
+                               }
+                               return ret;
+                       }
                        esp32s2_on_halt(target);
                        target_call_event_callbacks(target, 
TARGET_EVENT_HALTED);
                }
@@ -435,7 +450,11 @@ static int esp32s2_virt2phys(struct target *target,
 
 static int esp32s2_target_init(struct command_context *cmd_ctx, struct target 
*target)
 {
-       return esp_xtensa_target_init(cmd_ctx, target);
+       int ret = esp_xtensa_target_init(cmd_ctx, target);
+       if (ret != ERROR_OK)
+               return ret;
+
+       return esp_xtensa_semihosting_init(target);
 }
 
 static const struct xtensa_debug_ops esp32s2_dbg_ops = {
@@ -449,6 +468,10 @@ static const struct xtensa_power_ops esp32s2_pwr_ops = {
        .queue_reg_write = xtensa_dm_queue_pwr_reg_write
 };
 
+static const struct esp_semihost_ops esp32s2_semihost_ops = {
+       .prepare = esp32s2_disable_wdts
+};
+
 static int esp32s2_target_create(struct target *target, Jim_Interp *interp)
 {
        struct xtensa_debug_module_config esp32s2_dm_cfg = {
@@ -466,7 +489,7 @@ static int esp32s2_target_create(struct target *target, 
Jim_Interp *interp)
                return ERROR_FAIL;
        }
 
-       int ret = esp_xtensa_init_arch_info(target, &esp32->esp_xtensa, 
&esp32s2_dm_cfg);
+       int ret = esp_xtensa_init_arch_info(target, &esp32->esp_xtensa, 
&esp32s2_dm_cfg, &esp32s2_semihost_ops);
        if (ret != ERROR_OK) {
                LOG_ERROR("Failed to init arch info!");
                free(esp32);
@@ -479,12 +502,21 @@ static int esp32s2_target_create(struct target *target, 
Jim_Interp *interp)
        return ERROR_OK;
 }
 
+extern const struct command_registration semihosting_common_handlers[];
+
 static const struct command_registration esp32s2_command_handlers[] = {
        {
                .mode = COMMAND_ANY,
                .help = "Xtensa commands group",
                .chain = xtensa_command_handlers,
        },
+       {
+               .name = "arm",
+               .mode = COMMAND_ANY,
+               .help = "ARM Command Group",
+               .usage = "",
+               .chain = semihosting_common_handlers
+       },
        COMMAND_REGISTRATION_DONE
 };
 
diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c
index 48272ffb3b..4c2e7df826 100644
--- a/src/target/espressif/esp32s3.c
+++ b/src/target/espressif/esp32s3.c
@@ -312,10 +312,9 @@ static int esp32s3_virt2phys(struct target *target,
        return ERROR_FAIL;
 }
 
-
 static int esp32s3_target_init(struct command_context *cmd_ctx, struct target 
*target)
 {
-       return esp_xtensa_target_init(cmd_ctx, target);
+       return esp_xtensa_smp_target_init(cmd_ctx, target);
 }
 
 static const struct xtensa_debug_ops esp32s3_dbg_ops = {
@@ -334,6 +333,10 @@ static const struct esp_xtensa_smp_chip_ops 
esp32s3_chip_ops = {
        .on_halt = esp32s3_on_halt
 };
 
+static const struct esp_semihost_ops esp32s3_semihost_ops = {
+       .prepare = esp32s3_disable_wdts
+};
+
 static int esp32s3_target_create(struct target *target, Jim_Interp *interp)
 {
        struct xtensa_debug_module_config esp32s3_dm_cfg = {
@@ -353,7 +356,8 @@ static int esp32s3_target_create(struct target *target, 
Jim_Interp *interp)
        int ret = esp_xtensa_smp_init_arch_info(target,
                &esp32s3->esp_xtensa_smp,
                &esp32s3_dm_cfg,
-               &esp32s3_chip_ops);
+               &esp32s3_chip_ops,
+               &esp32s3_semihost_ops);
        if (ret != ERROR_OK) {
                LOG_ERROR("Failed to init arch info!");
                free(esp32s3);
@@ -366,6 +370,8 @@ static int esp32s3_target_create(struct target *target, 
Jim_Interp *interp)
        return ERROR_OK;
 }
 
+extern const struct command_registration semihosting_common_handlers[];
+
 static const struct command_registration esp32s3_command_handlers[] = {
        {
                .usage = "",
@@ -376,6 +382,13 @@ static const struct command_registration 
esp32s3_command_handlers[] = {
                .usage = "",
                .chain = smp_command_handlers,
        },
+       {
+               .name = "arm",
+               .mode = COMMAND_ANY,
+               .help = "ARM Command Group",
+               .usage = "",
+               .chain = semihosting_common_handlers
+       },
        COMMAND_REGISTRATION_DONE
 };
 
diff --git a/src/target/espressif/esp_semihosting.c 
b/src/target/espressif/esp_semihosting.c
new file mode 100644
index 0000000000..447af6c798
--- /dev/null
+++ b/src/target/espressif/esp_semihosting.c
@@ -0,0 +1,130 @@
+/***************************************************************************
+ *   Semihosting API for Espressif chips                                   *
+ *   Copyright (C) 2022 Espressif Systems Ltd.                             *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/log.h>
+#include <target/target.h>
+#include <target/semihosting_common.h>
+#include "esp_semihosting.h"
+#include "esp_xtensa.h"
+
+struct esp_semihost_data *target_to_esp_semihost_data(struct target *target)
+{
+       const char *arch = target_get_gdb_arch(target);
+       if (arch) {
+               if (strncmp(arch, "xtensa", 6) == 0)
+                       return &target_to_esp_xtensa(target)->semihost;
+               /* TODO: add riscv */
+       }
+       LOG_ERROR("Unknown target arch!");
+       return NULL;
+}
+
+int esp_semihosting_sys_seek(struct target *target, uint64_t fd, uint32_t pos, 
size_t whence)
+{
+       struct semihosting *semihosting = target->semihosting;
+
+       semihosting->result = lseek(fd, pos, whence);
+       semihosting->sys_errno = errno;
+       LOG_DEBUG("lseek(%" PRIx64 ", %d %d)=%d", fd, (int)pos,
+               (int)semihosting->result, errno);
+       return ERROR_OK;
+}
+
+int esp_semihosting_common(struct target *target)
+{
+       struct semihosting *semihosting = target->semihosting;
+       if (!semihosting) {
+               /* Silently ignore if the semihosting field was not set. */
+               return ERROR_OK;
+       }
+
+       int retval = ERROR_NOT_IMPLEMENTED;
+       /* Enough space to hold 4 long words. */
+       uint8_t fields[4 * 8];
+
+       LOG_DEBUG("op=0x%x, param=0x%" PRIx64, semihosting->op, 
semihosting->param);
+
+       switch (semihosting->op) {
+       case ESP_SEMIHOSTING_SYS_DRV_INFO:
+               /* Return success to make esp-idf application happy */
+               retval = ERROR_OK;
+               semihosting->result = 0;
+               semihosting->sys_errno = 0;
+               break;
+       case ESP_SEMIHOSTING_SYS_SEEK:
+               retval = semihosting_read_fields(target, 3, fields);
+               if (retval == ERROR_OK) {
+                       uint64_t fd = semihosting_get_field(target, 0, fields);
+                       uint32_t pos = semihosting_get_field(target, 1, fields);
+                       size_t whence = semihosting_get_field(target, 2, 
fields);
+                       retval = esp_semihosting_sys_seek(target, fd, pos, 
whence);
+               }
+               break;
+       case ESP_SEMIHOSTING_SYS_APPTRACE_INIT:
+       case ESP_SEMIHOSTING_SYS_DEBUG_STUBS_INIT:
+       case ESP_SEMIHOSTING_SYS_BREAKPOINT_SET:
+       case ESP_SEMIHOSTING_SYS_WATCHPOINT_SET:
+               /* For the time being only riscv chips support these commands
+                * TODO: invoke riscv custom command handler */
+               break;
+       }
+
+       return retval;
+}
+
+int esp_semihosting_basedir_command(struct command_invocation *cmd)
+{
+       struct target *target = get_current_target(CMD_CTX);
+
+       if (!target) {
+               LOG_ERROR("No target selected");
+               return ERROR_FAIL;
+       }
+
+       struct semihosting *semihosting = target->semihosting;
+       if (!semihosting) {
+               command_print(CMD, "semihosting not supported for current 
target");
+               return ERROR_FAIL;
+       }
+
+       if (!semihosting->is_active) {
+               if (semihosting->setup(target, true) != ERROR_OK) {
+                       LOG_ERROR("Failed to Configure semihosting");
+                       return ERROR_FAIL;
+               }
+               semihosting->is_active = true;
+       }
+
+       if (CMD_ARGC > 0) {
+               free(semihosting->basedir);
+               semihosting->basedir = strdup(CMD_ARGV[0]);
+               if (!semihosting->basedir) {
+                       command_print(CMD, "semihosting failed to allocate 
memory for basedir!");
+                       return ERROR_FAIL;
+               }
+       }
+
+       command_print(CMD, "DEPRECATED! semihosting base dir: %s",
+               semihosting->basedir ? semihosting->basedir : "");
+
+       return ERROR_OK;
+}
diff --git a/src/target/espressif/esp_semihosting.h 
b/src/target/espressif/esp_semihosting.h
new file mode 100644
index 0000000000..b25c91b4b4
--- /dev/null
+++ b/src/target/espressif/esp_semihosting.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ *   Semihosting API for Espressif chips                                   *
+ *   Copyright (C) 2022 Espressif Systems Ltd.                             *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifndef OPENOCD_TARGET_ESP_SEMIHOSTING_H
+#define OPENOCD_TARGET_ESP_SEMIHOSTING_H
+
+/* Legacy syscalls */
+#define ESP_SYS_DRV_INFO_LEGACY                     0xE0
+
+/* syscalls compatible to ARM standard */
+#define ESP_SEMIHOSTING_SYS_DRV_INFO                0x100
+#define ESP_SEMIHOSTING_SYS_APPTRACE_INIT           0x101
+#define ESP_SEMIHOSTING_SYS_DEBUG_STUBS_INIT        0x102
+#define ESP_SEMIHOSTING_SYS_BREAKPOINT_SET          0x103
+#define ESP_SEMIHOSTING_SYS_WATCHPOINT_SET          0x104
+#define ESP_SEMIHOSTING_SYS_SEEK                    0x105      /* custom lseek 
with whence */
+/* not implemented yet */
+#define ESP_SEMIHOSTING_SYS_MKDIR                   0x106
+#define ESP_SEMIHOSTING_SYS_OPENDIR                 0x107
+#define ESP_SEMIHOSTING_SYS_READDIR                 0x108
+#define ESP_SEMIHOSTING_SYS_READDIR_R               0x109
+#define ESP_SEMIHOSTING_SYS_SEEKDIR                 0x10A
+#define ESP_SEMIHOSTING_SYS_TELLDIR                 0x10B
+#define ESP_SEMIHOSTING_SYS_CLOSEDIR                0x10C
+#define ESP_SEMIHOSTING_SYS_RMDIR                   0x10D
+#define ESP_SEMIHOSTING_SYS_ACCESS                  0x10E
+#define ESP_SEMIHOSTING_SYS_TRUNCATE                0x10F
+#define ESP_SEMIHOSTING_SYS_UTIME                   0x110
+#define ESP_SEMIHOSTING_SYS_FSTAT                   0x111
+#define ESP_SEMIHOSTING_SYS_STAT                    0x112
+#define ESP_SEMIHOSTING_SYS_FSYNC                   0x113
+#define ESP_SEMIHOSTING_SYS_LINK                    0x114
+#define ESP_SEMIHOSTING_SYS_UNLINK                  0x115
+
+/**
+ * Semihost calls handling operations.
+ */
+struct esp_semihost_ops {
+       /** Callback called before handling semihost call */
+       int (*prepare)(struct target *target);
+};
+
+struct esp_semihost_data {
+       bool need_resume;
+       struct esp_semihost_ops *ops;
+};
+
+int esp_semihosting_common(struct target *target);
+int esp_semihosting_basedir_command(struct command_invocation *cmd);
+
+#endif /* OPENOCD_TARGET_ESP_SEMIHOSTING_H */
diff --git a/src/target/espressif/esp_xtensa.c 
b/src/target/espressif/esp_xtensa.c
index 83f05faf07..b546defecc 100644
--- a/src/target/espressif/esp_xtensa.c
+++ b/src/target/espressif/esp_xtensa.c
@@ -24,14 +24,20 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <target/smp.h>
-#include "esp_xtensa.h"
 #include <target/register.h>
+#include "esp_xtensa.h"
+#include "esp_semihosting.h"
 
 int esp_xtensa_init_arch_info(struct target *target,
        struct esp_xtensa_common *esp_xtensa,
-       struct xtensa_debug_module_config *dm_cfg)
+       struct xtensa_debug_module_config *dm_cfg,
+       const struct esp_semihost_ops *semihost_ops)
 {
-       return xtensa_init_arch_info(target, &esp_xtensa->xtensa, dm_cfg);
+       int ret = xtensa_init_arch_info(target, &esp_xtensa->xtensa, dm_cfg);
+       if (ret != ERROR_OK)
+               return ret;
+       esp_xtensa->semihost.ops = (struct esp_semihost_ops *)semihost_ops;
+       return ERROR_OK;
 }
 
 int esp_xtensa_target_init(struct command_context *cmd_ctx, struct target 
*target)
diff --git a/src/target/espressif/esp_xtensa.h 
b/src/target/espressif/esp_xtensa.h
index e309a5a9a7..0b5b734d23 100644
--- a/src/target/espressif/esp_xtensa.h
+++ b/src/target/espressif/esp_xtensa.h
@@ -20,12 +20,14 @@
 #ifndef OPENOCD_TARGET_ESP_XTENSA_H
 #define OPENOCD_TARGET_ESP_XTENSA_H
 
-#include <helper/command.h>
 #include <target/target.h>
 #include <target/xtensa/xtensa.h>
+#include "esp_xtensa.h"
+#include "esp_semihosting.h"
 
 struct esp_xtensa_common {
        struct xtensa xtensa;   /* must be the first element */
+       struct esp_semihost_data semihost;
 };
 
 static inline struct esp_xtensa_common *target_to_esp_xtensa(struct target 
*target)
@@ -35,7 +37,8 @@ static inline struct esp_xtensa_common 
*target_to_esp_xtensa(struct target *targ
 
 int esp_xtensa_init_arch_info(struct target *target,
        struct esp_xtensa_common *esp_xtensa,
-       struct xtensa_debug_module_config *dm_cfg);
+       struct xtensa_debug_module_config *dm_cfg,
+       const struct esp_semihost_ops *semihost_ops);
 int esp_xtensa_target_init(struct command_context *cmd_ctx, struct target 
*target);
 void esp_xtensa_target_deinit(struct target *target);
 int esp_xtensa_arch_state(struct target *target);
diff --git a/src/target/espressif/esp_xtensa_semihosting.c 
b/src/target/espressif/esp_xtensa_semihosting.c
new file mode 100644
index 0000000000..e4dafbd2c6
--- /dev/null
+++ b/src/target/espressif/esp_xtensa_semihosting.c
@@ -0,0 +1,121 @@
+/***************************************************************************
+ *   Copyright (c) 2020 Espressif Systems (Shanghai) Co. Ltd.                  
              *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <target/semihosting_common.h>
+#include <target/xtensa/xtensa_regs.h>
+#include <target/xtensa/xtensa.h>
+#include "esp_xtensa.h"
+#include "esp_xtensa_semihosting.h"
+
+#define ESP_XTENSA_SYSCALL              0x41E0 /* XT_INS_BREAK(1, 14) */
+#define ESP_XTENSA_SYSCALL_SZ           3
+
+#define XTENSA_SYSCALL_OP_REG           XT_REG_IDX_A2
+#define XTENSA_SYSCALL_RETVAL_REG       XT_REG_IDX_A2
+#define XTENSA_SYSCALL_ERRNO_REG        XT_REG_IDX_A3
+
+static int esp_xtensa_semihosting_setup(struct target *target, int enable)
+{
+       LOG_DEBUG("[%s] semihosting enable=%d", target_name(target), enable);
+
+       return ERROR_OK;
+}
+
+static int esp_xtensa_semihosting_post_result(struct target *target)
+{
+       /* Even with the v2 and later, errno will not retrieved from A3 reg, it 
is safe to set */
+       xtensa_reg_set(target, XTENSA_SYSCALL_RETVAL_REG, 
target->semihosting->result);
+       xtensa_reg_set(target, XTENSA_SYSCALL_ERRNO_REG, 
target->semihosting->sys_errno);
+       return ERROR_OK;
+}
+
+/**
+ * Checks and processes an ESP Xtensa semihosting request. 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.
+ */
+int esp_xtensa_semihosting(struct target *target, int *retval)
+{
+       struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
+
+       xtensa_reg_val_t dbg_cause = xtensa_reg_get(target, 
XT_REG_IDX_DEBUGCAUSE);
+       if ((dbg_cause & (DEBUGCAUSE_BI | DEBUGCAUSE_BN)) == 0)
+               return SEMIHOSTING_NONE;
+
+       uint8_t brk_insn_buf[sizeof(uint32_t)] = { 0 };
+       xtensa_reg_val_t pc = xtensa_reg_get(target, XT_REG_IDX_PC);
+       *retval = target_read_memory(target, pc, ESP_XTENSA_SYSCALL_SZ, 1, 
brk_insn_buf);
+       if (*retval != ERROR_OK) {
+               LOG_ERROR("Failed to read break instruction!");
+               return SEMIHOSTING_NONE;
+       }
+
+       uint32_t syscall_ins = buf_get_u32(brk_insn_buf, 0, 32);
+       if (syscall_ins != ESP_XTENSA_SYSCALL)
+               return SEMIHOSTING_NONE;
+
+       if (esp_xtensa->semihost.ops && esp_xtensa->semihost.ops->prepare)
+               esp_xtensa->semihost.ops->prepare(target);
+
+       xtensa_reg_val_t a2 = xtensa_reg_get(target, XT_REG_IDX_A2);
+       xtensa_reg_val_t a3 = xtensa_reg_get(target, XT_REG_IDX_A3);
+       LOG_DEBUG("%s: Semihosting call 0x%" PRIx32 " 0x%" PRIx32 " Base dir 
'%s'",
+               target_name(target),
+               a2,
+               a3,
+               target->semihosting->basedir ? target->semihosting->basedir : 
"");
+
+       target->semihosting->op = a2;
+       target->semihosting->param = a3;
+
+       *retval = semihosting_common(target);
+       if (*retval != ERROR_OK) {
+               LOG_ERROR("Semihosting operation (op: 0x%x) error! Code: %d",
+                       target->semihosting->op,
+                       *retval);
+       }
+
+       /* Resume if target it is resumable and we are not waiting on a fileio 
operation to complete. */
+       if (target->semihosting->is_resumable && 
!target->semihosting->hit_fileio)
+               target_to_esp_xtensa(target)->semihost.need_resume = true;
+
+       return SEMIHOSTING_HANDLED;
+}
+
+static int xtensa_semihosting_init(struct target *target)
+{
+       int retval = semihosting_common_init(target,
+               esp_xtensa_semihosting_setup,
+               esp_xtensa_semihosting_post_result);
+       return retval;
+}
+
+int esp_xtensa_semihosting_init(struct target *target)
+{
+       int retval = xtensa_semihosting_init(target);
+       if (retval != ERROR_OK)
+               return retval;
+       target->semihosting->word_size_bytes = 4;                       /* 32 
bits */
+       target->semihosting->user_command_extension = esp_semihosting_common;
+       return retval;
+}
diff --git a/src/target/espressif/esp_xtensa_semihosting.h 
b/src/target/espressif/esp_xtensa_semihosting.h
new file mode 100644
index 0000000000..32ea2faa90
--- /dev/null
+++ b/src/target/espressif/esp_xtensa_semihosting.h
@@ -0,0 +1,26 @@
+/***************************************************************************
+ *   Copyright (c) 2020 Espressif Systems (Shanghai) Co. Ltd.                  
              *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifndef OPENOCD_TARGET_ESP_XTENSA_SEMIHOSTING_H
+#define OPENOCD_TARGET_ESP_XTENSA_SEMIHOSTING_H
+
+#include <target/target.h>
+
+int esp_xtensa_semihosting_init(struct target *target);
+int esp_xtensa_semihosting(struct target *target, int *retval);
+
+#endif /* OPENOCD_TARGET_ESP_XTENSA_SEMIHOSTING_H */
diff --git a/src/target/espressif/esp_xtensa_smp.c 
b/src/target/espressif/esp_xtensa_smp.c
index 658f846ff0..1865e62fd2 100644
--- a/src/target/espressif/esp_xtensa_smp.c
+++ b/src/target/espressif/esp_xtensa_smp.c
@@ -25,7 +25,9 @@
 #include <target/target.h>
 #include <target/target_type.h>
 #include <target/smp.h>
+#include <target/semihosting_common.h>
 #include "esp_xtensa_smp.h"
+#include "esp_xtensa_semihosting.h"
 
 /*
 Multiprocessor stuff common:
@@ -140,6 +142,7 @@ int esp_xtensa_smp_poll(struct target *target)
 {
        enum target_state old_state = target->state;
        struct esp_xtensa_smp_common *esp_xtensa_smp = 
target_to_esp_xtensa_smp(target);
+       struct esp_xtensa_common *esp_xtensa = target_to_esp_xtensa(target);
        struct target_list *head;
        struct target *curr;
        bool other_core_resume_req = false;
@@ -192,6 +195,19 @@ int esp_xtensa_smp_poll(struct target *target)
                if (old_state == TARGET_DEBUG_RUNNING) {
                        target_call_event_callbacks(target, 
TARGET_EVENT_DEBUG_HALTED);
                } else {
+                       if (esp_xtensa_semihosting(target, &ret) == 
SEMIHOSTING_HANDLED) {
+                               if (ret == ERROR_OK && 
esp_xtensa->semihost.need_resume &&
+                                       
!esp_xtensa_smp->other_core_does_resume) {
+                                       esp_xtensa->semihost.need_resume = 
false;
+                                       /* Resume xtensa_resume will handle 
BREAK instruction. */
+                                       ret = target_resume(target, 1, 0, 1, 0);
+                                       if (ret != ERROR_OK) {
+                                               LOG_ERROR("Failed to resume 
target");
+                                               return ret;
+                                       }
+                               }
+                               return ret;
+                       }
                        /* check whether any core polled by 
esp_xtensa_smp_update_halt_gdb() requested resume */
                        if (target->smp && other_core_resume_req) {
                                /* Resume xtensa_resume will handle BREAK 
instruction. */
@@ -265,6 +281,11 @@ static int esp_xtensa_smp_update_halt_gdb(struct target 
*target, bool *need_resu
                if (ret != ERROR_OK)
                        return ret;
                esp_xtensa_smp->other_core_does_resume = false;
+               struct esp_xtensa_common *curr_esp_xtensa = 
target_to_esp_xtensa(curr);
+               if (curr_esp_xtensa->semihost.need_resume) {
+                       curr_esp_xtensa->semihost.need_resume = false;
+                       *need_resume = true;
+               }
        }
 
        /* after all targets were updated, poll the gdb serving target */
@@ -463,9 +484,10 @@ int esp_xtensa_smp_watchpoint_remove(struct target 
*target, struct watchpoint *w
 int esp_xtensa_smp_init_arch_info(struct target *target,
        struct esp_xtensa_smp_common *esp_xtensa_smp,
        struct xtensa_debug_module_config *dm_cfg,
-       const struct esp_xtensa_smp_chip_ops *chip_ops)
+       const struct esp_xtensa_smp_chip_ops *chip_ops,
+       const struct esp_semihost_ops *semihost_ops)
 {
-       int ret = esp_xtensa_init_arch_info(target, 
&esp_xtensa_smp->esp_xtensa, dm_cfg);
+       int ret = esp_xtensa_init_arch_info(target, 
&esp_xtensa_smp->esp_xtensa, dm_cfg, semihost_ops);
        if (ret != ERROR_OK)
                return ret;
        esp_xtensa_smp->chip_ops = chip_ops;
@@ -475,7 +497,24 @@ int esp_xtensa_smp_init_arch_info(struct target *target,
 
 int esp_xtensa_smp_target_init(struct command_context *cmd_ctx, struct target 
*target)
 {
-       return esp_xtensa_target_init(cmd_ctx, target);
+       int ret = esp_xtensa_target_init(cmd_ctx, target);
+       if (ret != ERROR_OK)
+               return ret;
+
+       if (target->smp) {
+               struct target_list *head;
+               foreach_smp_target(head, target->smp_targets) {
+                       struct target *curr = head->target;
+                       ret = esp_xtensa_semihosting_init(curr);
+                       if (ret != ERROR_OK)
+                               return ret;
+               }
+       } else {
+               ret = esp_xtensa_semihosting_init(target);
+               if (ret != ERROR_OK)
+                       return ret;
+       }
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(esp_xtensa_smp_cmd_xtdef)
diff --git a/src/target/espressif/esp_xtensa_smp.h 
b/src/target/espressif/esp_xtensa_smp.h
index 5b16f3ee56..c1b4c969b1 100644
--- a/src/target/espressif/esp_xtensa_smp.h
+++ b/src/target/espressif/esp_xtensa_smp.h
@@ -55,7 +55,8 @@ int esp_xtensa_smp_target_init(struct command_context 
*cmd_ctx, struct target *t
 int esp_xtensa_smp_init_arch_info(struct target *target,
        struct esp_xtensa_smp_common *esp_xtensa_smp,
        struct xtensa_debug_module_config *dm_cfg,
-       const struct esp_xtensa_smp_chip_ops *chip_ops);
+       const struct esp_xtensa_smp_chip_ops *chip_ops,
+       const struct esp_semihost_ops *semihost_ops);
 
 extern const struct command_registration esp_xtensa_smp_command_handlers[];
 extern const struct command_registration 
esp_xtensa_smp_xtensa_command_handlers[];
diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c
index f45981192a..316c1faf36 100644
--- a/src/target/xtensa/xtensa.c
+++ b/src/target/xtensa/xtensa.c
@@ -36,7 +36,6 @@
 #include "xtensa_chip.h"
 #include "xtensa.h"
 
-
 /* Swap 4-bit Xtensa opcodes and fields */
 #define XT_NIBSWAP8(V)                                                         
        \
        ((((V) & 0x0F) << 4)                                                    
        \
@@ -277,9 +276,9 @@ struct xtensa_reg_desc xtensa_regs[XT_NUM_REGS] = {
        XT_MK_REG_DESC("icount", 0xEC, XT_REG_SPECIAL, 0),
        XT_MK_REG_DESC("icountlevel", 0xED, XT_REG_SPECIAL, 0),
 
-       /* WARNING: For these registers, regnum points to the */
-       /* index of the corresponding ARx registers, NOT to */
-       /* the processor register number! */
+       /* WARNING: For these registers, regnum points to the
+        * index of the corresponding ARx registers, NOT to
+        * the processor register number! */
        XT_MK_REG_DESC("a0", XT_REG_IDX_AR0, XT_REG_RELGEN, 0),
        XT_MK_REG_DESC("a1", XT_REG_IDX_AR1, XT_REG_RELGEN, 0),
        XT_MK_REG_DESC("a2", XT_REG_IDX_AR2, XT_REG_RELGEN, 0),
@@ -398,18 +397,17 @@ static inline bool xtensa_is_cacheable(const struct 
xtensa_cache_config *cache,
 static inline bool xtensa_is_icacheable(struct xtensa *xtensa, target_addr_t 
address)
 {
        return xtensa_is_cacheable(&xtensa->core_config->icache, 
&xtensa->core_config->iram, address) ||
-               xtensa_is_cacheable(&xtensa->core_config->icache, 
&xtensa->core_config->irom, address) ||
-               xtensa_is_cacheable(&xtensa->core_config->icache, 
&xtensa->core_config->sram, address) ||
-               xtensa_is_cacheable(&xtensa->core_config->icache, 
&xtensa->core_config->srom, address);
-
+              xtensa_is_cacheable(&xtensa->core_config->icache, 
&xtensa->core_config->irom, address) ||
+              xtensa_is_cacheable(&xtensa->core_config->icache, 
&xtensa->core_config->sram, address) ||
+              xtensa_is_cacheable(&xtensa->core_config->icache, 
&xtensa->core_config->srom, address);
 }
 
 static inline bool xtensa_is_dcacheable(struct xtensa *xtensa, target_addr_t 
address)
 {
        return xtensa_is_cacheable(&xtensa->core_config->dcache, 
&xtensa->core_config->dram, address) ||
-               xtensa_is_cacheable(&xtensa->core_config->dcache, 
&xtensa->core_config->drom, address) ||
-               xtensa_is_cacheable(&xtensa->core_config->dcache, 
&xtensa->core_config->sram, address) ||
-               xtensa_is_cacheable(&xtensa->core_config->dcache, 
&xtensa->core_config->srom, address);
+              xtensa_is_cacheable(&xtensa->core_config->dcache, 
&xtensa->core_config->drom, address) ||
+              xtensa_is_cacheable(&xtensa->core_config->dcache, 
&xtensa->core_config->sram, address) ||
+              xtensa_is_cacheable(&xtensa->core_config->dcache, 
&xtensa->core_config->srom, address);
 }
 
 static int xtensa_core_reg_get(struct reg *reg)
@@ -638,9 +636,13 @@ static int xtensa_write_dirty_registers(struct target 
*target)
                                        } else if (rlist[ridx].type == 
XT_REG_FR) {
                                                xtensa_queue_exec_ins(xtensa, 
XT_INS_WFR(xtensa, reg_num, XT_REG_A3));
                                        } else {/*SFR */
-                                               if (reg_num == 
XT_PC_REG_NUM_VIRTUAL)
-                                                       /* reg number of PC for 
debug interrupt depends on NDEBUGLEVEL */
-                                                       reg_num = 
(XT_PC_REG_NUM_BASE + xtensa->core_config->debug.irq_level);
+                                               if (reg_num == 
XT_PC_REG_NUM_VIRTUAL) {
+                                                       /* reg number of PC for 
debug interrupt depends on NDEBUGLEVEL
+                                                        **/
+                                                       reg_num =
+                                                               
(XT_PC_REG_NUM_BASE +
+                                                               
xtensa->core_config->debug.irq_level);
+                                               }
                                                xtensa_queue_exec_ins(xtensa, 
XT_INS_WSR(xtensa, reg_num, XT_REG_A3));
                                        }
                                }
@@ -656,8 +658,8 @@ static int xtensa_write_dirty_registers(struct target 
*target)
                xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, regval);
                xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, 
XT_REG_A3));
                xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa,
-                       xtensa_regs[XT_REG_IDX_CPENABLE].reg_num,
-                       XT_REG_A3));
+                               xtensa_regs[XT_REG_IDX_CPENABLE].reg_num,
+                               XT_REG_A3));
                reg_list[XT_REG_IDX_CPENABLE].dirty = false;
        }
 
@@ -696,7 +698,8 @@ static int xtensa_write_dirty_registers(struct target 
*target)
                                        }
                                        if (show_warning) {
                                                LOG_WARNING(
-                                                       "Warning: Both A%d 
[0x%08" PRIx32 "] as well as its underlying physical register "
+                                                       "Warning: Both A%d 
[0x%08" PRIx32
+                                                       "] as well as its 
underlying physical register "
                                                        "(AR%d) [0x%08" PRIx32 
"] are dirty and differ in value",
                                                        i - XT_REG_IDX_A0,
                                                        
buf_get_u32(reg_list[i].value, 0, 32),
@@ -946,7 +949,7 @@ void xtensa_reg_set_deep_relgen(struct target *target, enum 
xtensa_reg_id a_idx,
 {
        struct xtensa *xtensa = target_to_xtensa(target);
        uint32_t windowbase = (xtensa->core_config->windowed ?
-                       xtensa_reg_get(target, XT_REG_IDX_WINDOWBASE) : 0);
+               xtensa_reg_get(target, XT_REG_IDX_WINDOWBASE) : 0);
        int ar_idx = xtensa_windowbase_offset_to_canonical(xtensa, a_idx, 
windowbase);
        xtensa_reg_set(target, a_idx, value);
        xtensa_reg_set(target, ar_idx, value);
@@ -988,10 +991,11 @@ int xtensa_deassert_reset(struct target *target)
        struct xtensa *xtensa = target_to_xtensa(target);
 
        LOG_TARGET_DEBUG(target, "halt=%d", target->reset_halt);
-       if (target->reset_halt)
+       if (target->reset_halt) {
                xtensa_queue_dbg_reg_write(xtensa,
                        NARADR_DCRSET,
                        OCDDCR_ENABLEOCD | OCDDCR_DEBUGINTERRUPT);
+       }
        xtensa_queue_pwr_reg_write(xtensa,
                DMREG_PWRCTL,
                PWRCTL_JTAGDEBUGUSE | PWRCTL_DEBUGWAKEUP | PWRCTL_MEMWAKEUP | 
PWRCTL_COREWAKEUP);
@@ -1172,7 +1176,8 @@ int xtensa_fetch_all_regs(struct target *target)
                                /* The 64-value general register set is read 
from (windowbase) on down.
                                 * We need to get the real register address by 
subtracting windowbase and
                                 * wrapping around. */
-                               enum xtensa_reg_id realadr = 
xtensa_canonical_to_windowbase_offset(xtensa, i, windowbase);
+                               enum xtensa_reg_id realadr = 
xtensa_canonical_to_windowbase_offset(xtensa, i,
+                                       windowbase);
                                buf_cpy(regvals[realadr].buf, 
reg_list[i].value, reg_list[i].size);
                        } else if (rlist[ridx].type == XT_REG_RELGEN) {
                                buf_cpy(regvals[rlist[ridx].reg_num].buf, 
reg_list[i].value, reg_list[i].size);
@@ -1557,9 +1562,11 @@ int xtensa_do_step(struct target *target, int current, 
target_addr_t address, in
                ps_lowered = true;
                uint32_t newps = (oldps & ~0xf) | (icountlvl - 1);
                xtensa_reg_set(target, xtensa->eps_dbglevel_idx, newps);
-               LOG_TARGET_DEBUG(target, "Lowering PS.INTLEVEL to allow 
stepping: %s <- 0x%08" PRIx32 " (was 0x%08" PRIx32 ")",
+               LOG_TARGET_DEBUG(target,
+                       "Lowering PS.INTLEVEL to allow stepping: %s <- 0x%08" 
PRIx32 " (was 0x%08" PRIx32 ")",
                        
xtensa->core_cache->reg_list[xtensa->eps_dbglevel_idx].name,
-                       newps, oldps);
+                       newps,
+                       oldps);
        }
        do {
                xtensa_reg_set(target, XT_REG_IDX_ICOUNTLEVEL, icountlvl);
@@ -1738,8 +1745,7 @@ int xtensa_read_memory(struct target *target, 
target_addr_t address, uint32_t si
        }
 
        if (!xtensa->permissive_mode) {
-               if (!xtensa_memory_op_validate_range(xtensa, address, (size * 
count),
-                               XT_MEM_ACCESS_READ)) {
+               if (!xtensa_memory_op_validate_range(xtensa, address, (size * 
count), XT_MEM_ACCESS_READ)) {
                        LOG_DEBUG("address " TARGET_ADDR_FMT " not readable", 
address);
                        return ERROR_FAIL;
                }
@@ -2011,10 +2017,11 @@ int xtensa_write_memory(struct target *target,
                        /* Execute cache WB/INV instructions */
                        res = jtag_execute_queue();
                        xtensa_core_status_check(target);
-                       if (res != ERROR_OK)
+                       if (res != ERROR_OK) {
                                LOG_TARGET_ERROR(target,
                                        "Error issuing cache 
writeback/invaldate instruction(s): %d",
                                        res);
+                       }
                }
        }
        if (albuff != buffer)
@@ -2067,11 +2074,12 @@ int xtensa_poll(struct target *target)
        res = xtensa_dm_core_status_read(&xtensa->dbg_mod);
        if (res != ERROR_OK)
                return res;
-       if (prev_dsr != xtensa->dbg_mod.core_status.dsr)
+       if (prev_dsr != xtensa->dbg_mod.core_status.dsr) {
                LOG_TARGET_DEBUG(target,
                        "DSR has changed: was 0x%08" PRIx32 " now 0x%08" PRIx32,
                        prev_dsr,
                        xtensa->dbg_mod.core_status.dsr);
+       }
        if (xtensa->dbg_mod.power_status.stath & PWRSTAT_COREWASRESET) {
                /* if RESET state is persitent  */
                target->state = TARGET_RESET;
@@ -2104,9 +2112,10 @@ int xtensa_poll(struct target *target)
                                        target->debug_reason = 
DBG_REASON_WPTANDBKPT;
                                else
                                        target->debug_reason = 
DBG_REASON_BREAKPOINT;
-                       } else if (halt_cause & DEBUGCAUSE_DB)
+                       } else if (halt_cause & DEBUGCAUSE_DB) {
                                target->debug_reason = DBG_REASON_WATCHPOINT;
-                       LOG_TARGET_DEBUG(target, "Target halted, pc=0x%08" 
PRIx32
+                       }
+                       LOG_TARGET_INFO(target, "Target halted, pc=0x%08" PRIx32
                                ", debug_reason=%08" PRIx32 ", oldstate=%08" 
PRIx32,
                                xtensa_reg_get(target, XT_REG_IDX_PC),
                                target->debug_reason,
@@ -3382,8 +3391,8 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa)
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       /* "xtregfmt contiguous" must be specified prior to the first "xtreg" 
definition */
-       /* if general register (g-packet) requests or contiguous register maps 
are supported */
+       /* "xtregfmt contiguous" must be specified prior to the first "xtreg" 
definition
+        * if general register (g-packet) requests or contiguous register maps 
are supported */
        if (xtensa->regmap_contiguous && !xtensa->contiguous_regs_desc) {
                xtensa->contiguous_regs_desc = calloc(xtensa->total_regs_num, 
sizeof(struct xtensa_reg_desc *));
                if (!xtensa->contiguous_regs_desc) {
@@ -3443,9 +3452,9 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa)
                } else if ((regnum & XT_REG_SPECIAL_MASK) == 
XT_REG_SPECIAL_VAL) {
                        rptr->type = XT_REG_SPECIAL;
                } else if ((regnum & XT_REG_RELGEN_MASK) == XT_REG_RELGEN_VAL) {
-                       /* WARNING: For these registers, regnum points to the */
-                       /* index of the corresponding ARx registers, NOT to */
-                       /* the processor register number! */
+                       /* WARNING: For these registers, regnum points to the
+                        * index of the corresponding ARx registers, NOT to
+                        * the processor register number! */
                        rptr->type = XT_REG_RELGEN;
                        rptr->reg_num += XT_REG_IDX_ARFIRST;
                        rptr->dbreg_num += XT_REG_IDX_ARFIRST;
@@ -3468,8 +3477,9 @@ COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa)
                        xtensa->eps_dbglevel_idx = XT_NUM_REGS + 
xtensa->num_optregs - 1;
                        LOG_DEBUG("Setting PS (%s) index to %d", rptr->name, 
xtensa->eps_dbglevel_idx);
                }
-       } else if (strcmp(rptr->name, "cpenable") == 0)
+       } else if (strcmp(rptr->name, "cpenable") == 0) {
                xtensa->core_config->coproc = true;
+       }
 
        /* Build out list of contiguous registers in specified order */
        unsigned int running_reg_count = xtensa->num_optregs + 
xtensa->core_regs_num;
diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h
index d0246aadcd..56c13abc76 100644
--- a/src/target/xtensa/xtensa.h
+++ b/src/target/xtensa/xtensa.h
@@ -35,38 +35,38 @@
  */
 
 /* Big-endian vs. little-endian detection */
-#define XT_ISBE(X)                                             
((X)->core_config->bigendian)
+#define XT_ISBE(X)                                              
((X)->core_config->bigendian)
 
 /* 24-bit break; BE version field-swapped then byte-swapped for use in memory 
R/W fns */
-#define XT_INS_BREAK_LE(S, T)                  (0x004000 | (((S) & 0xF) << 8) 
| (((T) & 0xF) << 4))
-#define XT_INS_BREAK_BE(S, T)                  (0x000400 | (((S) & 0xF) << 12) 
| ((T) & 0xF))
-#define XT_INS_BREAK(X, S, T)                  (XT_ISBE(X) ? 
XT_INS_BREAK_BE(S, T) : XT_INS_BREAK_LE(S, T))
+#define XT_INS_BREAK_LE(S, T)                   (0x004000 | (((S) & 0xF) << 8) 
| (((T) & 0xF) << 4))
+#define XT_INS_BREAK_BE(S, T)                   (0x000400 | (((S) & 0xF) << 
12) | ((T) & 0xF))
+#define XT_INS_BREAK(X, S, T)                   (XT_ISBE(X) ? 
XT_INS_BREAK_BE(S, T) : XT_INS_BREAK_LE(S, T))
 
 /* 16-bit break; BE version field-swapped then byte-swapped for use in memory 
R/W fns */
-#define XT_INS_BREAKN_LE(IMM4)                 (0xF02D | (((IMM4) & 0xF) << 8))
-#define XT_INS_BREAKN_BE(IMM4)                 (0x0FD2 | (((IMM4) & 0xF) << 
12))
-#define XT_INS_BREAKN(X, IMM4)                 (XT_ISBE(X) ? 
XT_INS_BREAKN_BE(IMM4) : XT_INS_BREAKN_LE(IMM4))
+#define XT_INS_BREAKN_LE(IMM4)                  (0xF02D | (((IMM4) & 0xF) << 
8))
+#define XT_INS_BREAKN_BE(IMM4)                  (0x0FD2 | (((IMM4) & 0xF) << 
12))
+#define XT_INS_BREAKN(X, IMM4)                  (XT_ISBE(X) ? 
XT_INS_BREAKN_BE(IMM4) : XT_INS_BREAKN_LE(IMM4))
 
-#define XT_ISNS_SZ_MAX                                 3
+#define XT_ISNS_SZ_MAX                                  3
 
-#define XT_PS_RING(_v_)                                        
((uint32_t)((_v_) & 0x3) << 6)
-#define XT_PS_RING_MSK                                 (0x3 << 6)
-#define XT_PS_RING_GET(_v_)                            (((_v_) >> 6) & 0x3)
-#define XT_PS_CALLINC_MSK                              (0x3 << 16)
-#define XT_PS_OWB_MSK                                  (0xF << 8)
-#define XT_PS_WOE_MSK                                  BIT(18)
+#define XT_PS_RING(_v_)                                 ((uint32_t)((_v_) & 
0x3) << 6)
+#define XT_PS_RING_MSK                                  (0x3 << 6)
+#define XT_PS_RING_GET(_v_)                             (((_v_) >> 6) & 0x3)
+#define XT_PS_CALLINC_MSK                               (0x3 << 16)
+#define XT_PS_OWB_MSK                                   (0xF << 8)
+#define XT_PS_WOE_MSK                                   BIT(18)
 
-#define XT_LOCAL_MEM_REGIONS_NUM_MAX   8
+#define XT_LOCAL_MEM_REGIONS_NUM_MAX    8
 
-#define XT_AREGS_NUM_MAX                               64
-#define XT_USER_REGS_NUM_MAX                   256
+#define XT_AREGS_NUM_MAX                                64
+#define XT_USER_REGS_NUM_MAX                    256
 
-#define XT_MEM_ACCESS_NONE                             0x0
-#define XT_MEM_ACCESS_READ                             0x1
-#define XT_MEM_ACCESS_WRITE                            0x2
+#define XT_MEM_ACCESS_NONE                              0x0
+#define XT_MEM_ACCESS_READ                              0x1
+#define XT_MEM_ACCESS_WRITE                             0x2
 
-#define XT_MAX_TIE_REG_WIDTH                   (512)   /* TIE register file 
max 4096 bits */
-#define XT_QUERYPKT_RESP_MAX                   (XT_MAX_TIE_REG_WIDTH * 2 + 1)
+#define XT_MAX_TIE_REG_WIDTH                    (512)  /* TIE register file 
max 4096 bits */
+#define XT_QUERYPKT_RESP_MAX                    (XT_MAX_TIE_REG_WIDTH * 2 + 1)
 
 enum xtensa_qerr_e {
        XT_QERR_INTERNAL = 0,
diff --git a/src/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c
index 3a668a0348..2158cba520 100644
--- a/src/target/xtensa/xtensa_chip.c
+++ b/src/target/xtensa/xtensa_chip.c
@@ -29,7 +29,7 @@
 #include "xtensa_chip.h"
 
 int xtensa_chip_init_arch_info(struct target *target, void *arch_info,
-               struct xtensa_debug_module_config *dm_cfg)
+       struct xtensa_debug_module_config *dm_cfg)
 {
        struct xtensa_chip_common *xtensa_chip = (struct xtensa_chip_common 
*)arch_info;
        if (!dm_cfg->queue_tdi_idle && dm_cfg->tap) {
@@ -92,8 +92,9 @@ void xtensa_chip_queue_tdi_idle(struct target *target)
        } else if (xtensa_chip->flash_bootstrap == FBS_TMSHIGH) {
                /*Make sure tdi is 1 at the exit of queue execution */
                value = 1;
-       } else
+       } else {
                return;
+       }
 #endif
 
        /* Scan out 1 bit, do not move from IRPAUSE after we're done. */
@@ -154,7 +155,6 @@ static int xtensa_chip_target_create(struct target *target, 
Jim_Interp *interp)
        return ERROR_OK;
 }
 
-
 void xtensa_chip_target_deinit(struct target *target)
 {
        struct xtensa *xtensa = target_to_xtensa(target);
diff --git a/src/target/xtensa/xtensa_chip.h b/src/target/xtensa/xtensa_chip.h
index 989204b5aa..f366fccdd9 100644
--- a/src/target/xtensa/xtensa_chip.h
+++ b/src/target/xtensa/xtensa_chip.h
@@ -35,7 +35,7 @@ static inline struct xtensa_chip_common 
*target_to_xtensa_chip(struct target *ta
 }
 
 int xtensa_chip_init_arch_info(struct target *target, void *arch_info,
-               struct xtensa_debug_module_config *dm_cfg);
+       struct xtensa_debug_module_config *dm_cfg);
 int xtensa_chip_target_init(struct command_context *cmd_ctx, struct target 
*target);
 int xtensa_chip_arch_state(struct target *target);
 void xtensa_chip_queue_tdi_idle(struct target *target);
diff --git a/src/target/xtensa/xtensa_debug_module.h 
b/src/target/xtensa/xtensa_debug_module.h
index 692f0f60fc..11300aec65 100644
--- a/src/target/xtensa/xtensa_debug_module.h
+++ b/src/target/xtensa/xtensa_debug_module.h
@@ -352,7 +352,7 @@ static inline bool xtensa_dm_is_online(struct 
xtensa_debug_module *dm)
        int res = xtensa_dm_device_id_read(dm);
        if (res != ERROR_OK)
                return false;
-       return (dm->device_id != 0xffffffff && dm->device_id != 0);
+       return dm->device_id != 0xffffffff && dm->device_id != 0;
 }
 
 static inline bool xtensa_dm_tap_was_reset(struct xtensa_debug_module *dm)
diff --git a/src/target/xtensa/xtensa_regs.h b/src/target/xtensa/xtensa_regs.h
index 7c9148cf35..31a764d3f8 100644
--- a/src/target/xtensa/xtensa_regs.h
+++ b/src/target/xtensa/xtensa_regs.h
@@ -89,8 +89,8 @@ enum xtensa_reg_type {
        XT_REG_USER = 1,                /* User register, needs RUR to read */
        XT_REG_SPECIAL = 2,             /* Special register, needs RSR to read 
*/
        XT_REG_DEBUG = 3,               /* Register used for the debug 
interface. Don't mess with this. */
-       XT_REG_RELGEN = 4,              /* Relative general address. Points to 
the absolute addresses
-                                                        * plus the window 
index */
+       XT_REG_RELGEN = 4,              /* Relative general address. Points to 
the absolute addresses plus the window
+                                        * index */
        XT_REG_FR = 5,                  /* Floating-point register */
        XT_REG_TIE = 6,                 /* TIE (custom) register */
        XT_REG_OTHER = 7,               /* Other (typically legacy) register */
@@ -132,7 +132,6 @@ struct xtensa_reg_desc {
        enum xtensa_reg_flags flags;
 };
 
-
 #define _XT_MK_DBREGN(reg_num, reg_type)                                       
\
        ((reg_type ## _VAL) | (reg_num))
 
diff --git a/tcl/target/esp32.cfg b/tcl/target/esp32.cfg
index 4206080acb..f4c13aa5b9 100644
--- a/tcl/target/esp32.cfg
+++ b/tcl/target/esp32.cfg
@@ -3,6 +3,9 @@
 # The ESP32 only supports JTAG.
 transport select jtag
 
+# Source the ESP common configuration file
+source [find target/esp_common.cfg]
+
 if { [info exists CHIPNAME] } {
        set _CHIPNAME $CHIPNAME
 } else {
@@ -67,6 +70,30 @@ if { $_ONLYCPU != 1 } {
        $_TARGETNAME_1 configure -event reset-assert-post { soft_reset_halt }
 }
 
+$_TARGETNAME_0 configure -event examine-end {
+    # Need to enable to set 'semihosting_basedir'
+    arm semihosting enable
+    arm semihosting_resexit enable
+    if { [info exists _SEMIHOST_BASEDIR] } {
+        if { $_SEMIHOST_BASEDIR != "" } {
+            arm semihosting_basedir $_SEMIHOST_BASEDIR
+        }
+    }
+}
+
+if { $_ONLYCPU != 1 } {
+       $_TARGETNAME_1 configure -event examine-end {
+               # Need to enable to set 'semihosting_basedir'
+               arm semihosting enable
+               arm semihosting_resexit enable
+               if { [info exists _SEMIHOST_BASEDIR] } {
+                       if { $_SEMIHOST_BASEDIR != "" } {
+                               arm semihosting_basedir $_SEMIHOST_BASEDIR
+                       }
+               }
+       }
+}
+
 gdb_breakpoint_override hard
 
 source [find target/xtensa-core-esp32.cfg]
diff --git a/tcl/target/esp32s2.cfg b/tcl/target/esp32s2.cfg
index 85ce737a36..c91836d16b 100644
--- a/tcl/target/esp32s2.cfg
+++ b/tcl/target/esp32s2.cfg
@@ -3,6 +3,9 @@
 # The ESP32-S2 only supports JTAG.
 transport select jtag
 
+# Source the ESP common configuration file
+source [find target/esp_common.cfg]
+
 if { [info exists CHIPNAME] } {
        set _CHIPNAME $CHIPNAME
 } else {
@@ -25,6 +28,17 @@ target create $_TARGETNAME esp32s2 -endian little 
-chain-position $_TAPNAME
 
 xtensa maskisr on
 
+$_TARGETNAME configure -event examine-end {
+       # Need to enable to set 'semihosting_basedir'
+       arm semihosting enable
+       arm semihosting_resexit enable
+       if { [info exists _SEMIHOST_BASEDIR] } {
+               if { $_SEMIHOST_BASEDIR != "" } {
+                       arm semihosting_basedir $_SEMIHOST_BASEDIR
+               }
+       }
+}
+
 $_TARGETNAME configure -event reset-assert-post { soft_reset_halt }
 
 gdb_breakpoint_override hard
diff --git a/tcl/target/esp32s3.cfg b/tcl/target/esp32s3.cfg
index 7d92b94209..3eff2555c2 100644
--- a/tcl/target/esp32s3.cfg
+++ b/tcl/target/esp32s3.cfg
@@ -7,6 +7,9 @@ set CPU_MAX_ADDRESS 0xFFFFFFFF
 source [find bitsbytes.tcl]
 source [find memory.tcl]
 source [find mmr_helpers.tcl]
+# Source the ESP common configuration file
+source [find target/esp_common.cfg]
+
 
 if { [info exists CHIPNAME] } {
        set _CHIPNAME $CHIPNAME
@@ -53,6 +56,29 @@ if { $_ONLYCPU != 1 } {
 
 $_TARGETNAME_0 xtensa maskisr on
 $_TARGETNAME_0 xtensa smpbreak BreakIn BreakOut
+$_TARGETNAME_0 configure -event examine-end {
+       # Need to enable to set 'semihosting_basedir'
+       arm semihosting enable
+       arm semihosting_resexit enable
+       if { [info exists _SEMIHOST_BASEDIR] } {
+               if { $_SEMIHOST_BASEDIR != "" } {
+                       arm semihosting_basedir $_SEMIHOST_BASEDIR
+               }
+       }
+}
+
+if { $_ONLYCPU != 1 } {
+       $_TARGETNAME_1 configure -event examine-end {
+               # Need to enable to set 'semihosting_basedir'
+               arm semihosting enable
+               arm semihosting_resexit enable
+               if { [info exists _SEMIHOST_BASEDIR] } {
+                       if { $_SEMIHOST_BASEDIR != "" } {
+                               arm semihosting_basedir $_SEMIHOST_BASEDIR
+                       }
+               }
+       }
+}
 
 $_TARGETNAME_0 configure -event gdb-attach {
        $_TARGETNAME_0 xtensa smpbreak BreakIn BreakOut
diff --git a/tcl/target/xtensa-core-esp32s2.cfg 
b/tcl/target/xtensa-core-esp32s2.cfg
index 888781ed93..b17fbb0aac 100644
--- a/tcl/target/xtensa-core-esp32s2.cfg
+++ b/tcl/target/xtensa-core-esp32s2.cfg
@@ -18,7 +18,7 @@ xtensa xtmem  icache                          4 0 1
 xtensa xtmem   dcache                          4 0 1 0
 
 #  Memory Options
-xtensa xtmem   irom                            0x40800000      0x780000
+xtensa xtmem   irom                            0x40080000      0x780000
 xtensa xtmem   irom                            0x40000000      0x20000
 xtensa xtmem   iram                            0x40020000      0x50000
 xtensa xtmem   iram                            0x40070000      0x2000

-- 

Reply via email to