new file mode 100644
@@ -0,0 +1,296 @@
+From f8a6553e82919bcfd37436dd6b95e99bb261d04c Mon Sep 17 00:00:00 2001
+From: Paul Fertser <fercerpav@gmail.com>
+Date: Sun, 15 Jan 2023 02:33:06 +0300
+Subject: [PATCH] Restore normal development cycle
+
+Signed-off-by: Paul Fertser <fercerpav@gmail.com>
+---
+ NEWS | 99 +-------------------------------------
+ NEWS-0.12.0 | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ configure.ac | 2 +-
+ 3 files changed, 134 insertions(+), 99 deletions(-)
+ create mode 100644 NEWS-0.12.0
+
+diff --git a/NEWS b/NEWS
+index 208146a46..9db6c5fee 100644
+--- a/NEWS
++++ b/NEWS
+@@ -2,126 +2,29 @@ This file includes highlights of the changes made in the OpenOCD
+ source archive release.
+
+ JTAG Layer:
+- * add default to adapter speed when unspecified (100 kHz)
+- * AM335X gpio (BeagleBones) adapter driver
+- * BCM2835 support for SWD
+- * Cadence Virtual Debug (vdebug) adapter driver
+- * CMSIS-DAP support for SWO and SWD multidrop
+- * Espressif USB JTAG Programmer adapter driver
+- * Remote bitbang support for Windows host
+- * ST-LINK add TCP server support to adapter driver
+- * SWD multidrop support
+
+ Boundary Scan:
+
+ Target Layer:
+- * aarch64: support watchpoints
+- * arm: support independent TPIU and SWO for trace
+- * arm adi v5: support Large Physical Address Extension
+- * arm adi v6: support added, for jtag and swd transport
+- * cortex_a: support watchpoints
+- * elf 64bit load support
+- * Espressif: support ESP32, ESP32-S2 and ESP32-S3 cores
+- * semihosting: support user defined operations
+- * Xtensa: support Xtensa LX architecture via JTAG and ADIv5 DAP
+
+ Flash Layer:
+- * Atmel/Microchip SAM E51G18A, E51G19A, R35J18B, LAN9255 support
+- * GigaDevice GD32E23x, GD32F1x0/3x0, GD32VF103 support
+- * Nuvoton NPCX series support
+- * onsemi RSL10 support
+- * Raspberry Pi Pico RP2040 support
+- * ST BlueNRG-LPS support
+- * ST STM32 G05x, G06x, G0Bx, G0Cx, U57x, U58x, WB1x, WL5x support
+- * ST STM32 G0, G4, L4, L4+, L5, WB, WL OTP support
+
+ Board, Target, and Interface Configuration Scripts:
+- * Ampere Computing eMAG8180, Altra ("Quicksilver") and Altra Max ("Mystique") board config
+- * Cadence KC705 FPGA (Xtensa Development Platform) via JTAG and ADIv5 DAP board config
+- * Digilent Nexys Video board config
+- * Espressif ESP32 ETHERNET-KIT and WROVER-KIT board config
+- * Espressif ESP32 via ESP USB Bridge generic board config
+- * Espressif ESP32-S2 Kaluga 1 board config
+- * Espressif ESP32-S2 with ESP USB Bridge board config
+- * Espressif ESP32-S3 example board config
+- * Kontron SMARC-sAL28 board config
+- * LambdaConcept ECPIX-5 board config
+- * Microchip ATSAMA5D27-SOM1-EK1 board config
+- * Microchip EVB-LAN9255 board config
+- * Microchip SAME51 Curiosity Nano board config
+- * NXP FRDM-K64F, LS1046ARDB and LS1088ARDB board config
+- * NXP RT6XX board config
+- * Olimex H405 board config
+- * Radiona ULX3S board config
+- * Raspberry Pi 3 and Raspberry Pi 4 model B board config
+- * Raspberry Pi Pico-Debug board config
+- * Renesas R-Car V3U Falcon board config
+- * ST BlueNRG-LPS steval-idb012v1 board config
+- * ST NUCLEO-8S208RB board config
+- * ST NUCLEO-G031K8, NUCLEO-G070RB, NUCLEO-G071RB board config
+- * ST NUCLEO-G431KB, NUCLEO-G431RB, NUCLEO-G474RE board config
+- * ST STM32MP13x-DK board config
+- * TI AM625 EVM, AM642 EVM and AM654 EVM board config
+- * TI J721E EVM, J721S2 EVM and J7200 EVM board config
+- * Ampere Computing eMAG, Altra ("Quicksilver") and Altra Max ("Mystique") target config
+- * Cadence Xtensa generic and Xtensa VDebug target config
+- * Broadcom BCM2711, BCM2835, BCM2836 and BCM2837 target config
+- * Espressif ESP32, ESP32-S2 and ESP32-S3 target config
+- * Microchip ATSAMA5D2 series target config
+- * NanoXplore NG-Ultra SoC target config
+- * NXP IMX8QM target config
+- * NXP LS1028A, LS1046A and LS1088A target config
+- * NXP RT600 (Xtensa HiFi DSP) target config
+- * onsemi RSL10 target config
+- * Raspberry Pi Pico RP2040 target config
+- * Renesas R8A779A0 V3U target config
+- * Renesas RZ/Five target config
+- * Renesas RZ/G2 MPU family target config
+- * Rockchip RK3399 target config
+- * ST BlueNRG-LPS target config
+- * ST STM32MP13x target config
+- * TI AM625, AM654, J721E and J721S2 target config
+- * Ashling Opella-LD interface config
+- * Aspeed AST2600 linuxgpiod based interface config
+- * Blinkinlabs JTAG_Hat interface config
+- * Cadence Virtual Debug (vdebug) interface config
+- * Espressif ESP32-S2 Kaluga 1 board's interface config
+- * Espressif USB Bridge jtag interface config
+- * Infineon DAP miniWiggler V3 interface config
+- * PLS SPC5 interface config
+- * Tigard interface config
+- * Lattice MachXO3 family FPGA config
+
+ Server Layer:
+- * GDB: add per-target remote protocol extensions
+- * GDB: more 'Z' packets support
+- * IPDBG JtagHost server functionality
+- * semihosting: I/O redirection to TCP server
+- * telnet: support for command's autocomplete
+
+ RTOS:
+- * 'none' rtos support
+- * Zephyr rtos support
+
+ Documentation:
+
+ Build and Release:
+- * Add json extension to jimtcl build
+- * Drop dependency from libusb0
+- * Drop repository repo.or.cz for submodules
+- * Move gerrit to https://review.openocd.org/
+- * Require autoconf 2.69 or newer
+- * Update jep106 to revision JEP106BF.01
+- * Update jimtcl to version 0.81
+- * Update libjaylink to version 0.3.1
+- * New configure flag '--enable-jimtcl-maintainer' for jimtcl build
+
+
+ This release also contains a number of other important functional and
+ cosmetic bugfixes. For more details about what has changed since the
+ last release, see the git repository history:
+
+-http://sourceforge.net/p/openocd/code/ci/v0.12.0/log/?path=
++http://sourceforge.net/p/openocd/code/ci/v0.x.0/log/?path=
+
+
+ For older NEWS, see the NEWS files associated with each release
+diff --git a/NEWS-0.12.0 b/NEWS-0.12.0
+new file mode 100644
+index 000000000..208146a46
+--- /dev/null
++++ b/NEWS-0.12.0
+@@ -0,0 +1,132 @@
++This file includes highlights of the changes made in the OpenOCD
++source archive release.
++
++JTAG Layer:
++ * add default to adapter speed when unspecified (100 kHz)
++ * AM335X gpio (BeagleBones) adapter driver
++ * BCM2835 support for SWD
++ * Cadence Virtual Debug (vdebug) adapter driver
++ * CMSIS-DAP support for SWO and SWD multidrop
++ * Espressif USB JTAG Programmer adapter driver
++ * Remote bitbang support for Windows host
++ * ST-LINK add TCP server support to adapter driver
++ * SWD multidrop support
++
++Boundary Scan:
++
++Target Layer:
++ * aarch64: support watchpoints
++ * arm: support independent TPIU and SWO for trace
++ * arm adi v5: support Large Physical Address Extension
++ * arm adi v6: support added, for jtag and swd transport
++ * cortex_a: support watchpoints
++ * elf 64bit load support
++ * Espressif: support ESP32, ESP32-S2 and ESP32-S3 cores
++ * semihosting: support user defined operations
++ * Xtensa: support Xtensa LX architecture via JTAG and ADIv5 DAP
++
++Flash Layer:
++ * Atmel/Microchip SAM E51G18A, E51G19A, R35J18B, LAN9255 support
++ * GigaDevice GD32E23x, GD32F1x0/3x0, GD32VF103 support
++ * Nuvoton NPCX series support
++ * onsemi RSL10 support
++ * Raspberry Pi Pico RP2040 support
++ * ST BlueNRG-LPS support
++ * ST STM32 G05x, G06x, G0Bx, G0Cx, U57x, U58x, WB1x, WL5x support
++ * ST STM32 G0, G4, L4, L4+, L5, WB, WL OTP support
++
++Board, Target, and Interface Configuration Scripts:
++ * Ampere Computing eMAG8180, Altra ("Quicksilver") and Altra Max ("Mystique") board config
++ * Cadence KC705 FPGA (Xtensa Development Platform) via JTAG and ADIv5 DAP board config
++ * Digilent Nexys Video board config
++ * Espressif ESP32 ETHERNET-KIT and WROVER-KIT board config
++ * Espressif ESP32 via ESP USB Bridge generic board config
++ * Espressif ESP32-S2 Kaluga 1 board config
++ * Espressif ESP32-S2 with ESP USB Bridge board config
++ * Espressif ESP32-S3 example board config
++ * Kontron SMARC-sAL28 board config
++ * LambdaConcept ECPIX-5 board config
++ * Microchip ATSAMA5D27-SOM1-EK1 board config
++ * Microchip EVB-LAN9255 board config
++ * Microchip SAME51 Curiosity Nano board config
++ * NXP FRDM-K64F, LS1046ARDB and LS1088ARDB board config
++ * NXP RT6XX board config
++ * Olimex H405 board config
++ * Radiona ULX3S board config
++ * Raspberry Pi 3 and Raspberry Pi 4 model B board config
++ * Raspberry Pi Pico-Debug board config
++ * Renesas R-Car V3U Falcon board config
++ * ST BlueNRG-LPS steval-idb012v1 board config
++ * ST NUCLEO-8S208RB board config
++ * ST NUCLEO-G031K8, NUCLEO-G070RB, NUCLEO-G071RB board config
++ * ST NUCLEO-G431KB, NUCLEO-G431RB, NUCLEO-G474RE board config
++ * ST STM32MP13x-DK board config
++ * TI AM625 EVM, AM642 EVM and AM654 EVM board config
++ * TI J721E EVM, J721S2 EVM and J7200 EVM board config
++ * Ampere Computing eMAG, Altra ("Quicksilver") and Altra Max ("Mystique") target config
++ * Cadence Xtensa generic and Xtensa VDebug target config
++ * Broadcom BCM2711, BCM2835, BCM2836 and BCM2837 target config
++ * Espressif ESP32, ESP32-S2 and ESP32-S3 target config
++ * Microchip ATSAMA5D2 series target config
++ * NanoXplore NG-Ultra SoC target config
++ * NXP IMX8QM target config
++ * NXP LS1028A, LS1046A and LS1088A target config
++ * NXP RT600 (Xtensa HiFi DSP) target config
++ * onsemi RSL10 target config
++ * Raspberry Pi Pico RP2040 target config
++ * Renesas R8A779A0 V3U target config
++ * Renesas RZ/Five target config
++ * Renesas RZ/G2 MPU family target config
++ * Rockchip RK3399 target config
++ * ST BlueNRG-LPS target config
++ * ST STM32MP13x target config
++ * TI AM625, AM654, J721E and J721S2 target config
++ * Ashling Opella-LD interface config
++ * Aspeed AST2600 linuxgpiod based interface config
++ * Blinkinlabs JTAG_Hat interface config
++ * Cadence Virtual Debug (vdebug) interface config
++ * Espressif ESP32-S2 Kaluga 1 board's interface config
++ * Espressif USB Bridge jtag interface config
++ * Infineon DAP miniWiggler V3 interface config
++ * PLS SPC5 interface config
++ * Tigard interface config
++ * Lattice MachXO3 family FPGA config
++
++Server Layer:
++ * GDB: add per-target remote protocol extensions
++ * GDB: more 'Z' packets support
++ * IPDBG JtagHost server functionality
++ * semihosting: I/O redirection to TCP server
++ * telnet: support for command's autocomplete
++
++RTOS:
++ * 'none' rtos support
++ * Zephyr rtos support
++
++Documentation:
++
++Build and Release:
++ * Add json extension to jimtcl build
++ * Drop dependency from libusb0
++ * Drop repository repo.or.cz for submodules
++ * Move gerrit to https://review.openocd.org/
++ * Require autoconf 2.69 or newer
++ * Update jep106 to revision JEP106BF.01
++ * Update jimtcl to version 0.81
++ * Update libjaylink to version 0.3.1
++ * New configure flag '--enable-jimtcl-maintainer' for jimtcl build
++
++
++This release also contains a number of other important functional and
++cosmetic bugfixes. For more details about what has changed since the
++last release, see the git repository history:
++
++http://sourceforge.net/p/openocd/code/ci/v0.12.0/log/?path=
++
++
++For older NEWS, see the NEWS files associated with each release
++(i.e. NEWS-<version>).
++
++For more information about contributing test reports, bug fixes, or new
++features and device support, please read the new Developer Manual (or
++the BUGS and PATCHES.txt files in the source archive).
+diff --git a/configure.ac b/configure.ac
+index eee42d424..7f0955f13 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-or-later
+
+ AC_PREREQ([2.69])
+-AC_INIT([openocd], [0.12.0],
++AC_INIT([openocd], [0.12.0+dev],
+ [OpenOCD Mailing List <openocd-devel@lists.sourceforge.net>])
+ AC_CONFIG_SRCDIR([src/openocd.c])
+ AC_CONFIG_AUX_DIR([build-aux])
new file mode 100644
@@ -0,0 +1,67 @@
+From 8bb926eb01022998ceefe666f8df102e59404015 Mon Sep 17 00:00:00 2001
+From: Marc Schink <dev@zapb.de>
+Date: Sun, 22 May 2022 16:15:00 +0200
+Subject: [PATCH] Deprecate libjaylink Git submodule
+
+libjaylink was integrated into OpenOCD as a Git submodule, because at
+that time there was no official release and no packages for it.
+Today there are libjaylink packages for most popular distributions [1].
+
+Removing libjaylink from OpenOCD reduces build complexity in both
+projects and makes them more flexible with respect to the build system,
+for example.
+
+Disable the libjaylink submodule by default and announce it as
+deprecated feature that will be removed in the future. This gives
+package maintainers time to package libjaylink if not already done.
+
+[1] https://repology.org/project/libjaylink/versions
+
+Change-Id: I6166ba4757aee5c89a0506de867072f58fa5ec4b
+Signed-off-by: Marc Schink <dev@zapb.de>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7129
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ configure.ac | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 7f0955f13..4fcc91528 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -373,9 +373,9 @@ AC_ARG_ENABLE([jimtcl-maintainer],
+ [use_internal_jimtcl_maintainer=$enableval], [use_internal_jimtcl_maintainer=no])
+
+ AC_ARG_ENABLE([internal-libjaylink],
+- AS_HELP_STRING([--disable-internal-libjaylink],
+- [Disable building internal libjaylink]),
+- [use_internal_libjaylink=$enableval], [use_internal_libjaylink=yes])
++ AS_HELP_STRING([--enable-internal-libjaylink],
++ [Enable building internal libjaylink]),
++ [use_internal_libjaylink=$enableval], [use_internal_libjaylink=no])
+
+ AC_ARG_ENABLE([remote-bitbang],
+ AS_HELP_STRING([--enable-remote-bitbang], [Enable building support for the Remote Bitbang jtag driver]),
+@@ -713,7 +713,7 @@ AS_IF([test "x$enable_jlink" != "xno"], [
+ AX_CONFIG_SUBDIR_OPTION([src/jtag/drivers/libjaylink],
+ [--enable-subproject-build])
+ ], [
+- AC_MSG_ERROR([Internal libjaylink not found, run either 'git submodule init' and 'git submodule update' or disable internal libjaylink with --disable-internal-libjaylink.])
++ AC_MSG_ERROR([Internal libjaylink not found, run 'git submodule init' and 'git submodule update'.])
+ ])
+ ])
+ ])
+@@ -823,6 +823,12 @@ AC_CONFIG_FILES([
+ ])
+ AC_OUTPUT
+
++AS_IF([test "x$enable_jlink" != "xno"], [
++ AS_IF([test "x$use_internal_libjaylink" = "xyes"], [
++ AC_MSG_WARN([Using the internal libjaylink is deprecated and will not be possible in the future.])
++ ]])
++)
++
+ echo
+ echo
+ echo OpenOCD configuration summary
new file mode 100644
@@ -0,0 +1,19095 @@
+From da34e36cdb542eac9370957b10853184f870e495 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Sep 2022 23:14:41 +0200
+Subject: [PATCH] nds32: drop it, together with aice adapter driver
+
+The target nds32 and its companion adapter aice have not received
+any real improvement since 2013.
+It has been hard to keep them aligned during the evolution of
+OpenOCD code, with no way for maintainers to really check if they
+are still working.
+No real documentation is present for them in OpenOCD.
+The nds32 code triggers ~50 errors/warnings with scan-build.
+
+The arch nds32 has been dropped from Linux kernel v5.18-rc1.
+
+For all the reasons above, this code has been deprecated with
+commit 2e5df83de7f2 ("nds32: deprecate it, together with aice
+adapter driver") and tagged to be dropped before v0.13.0.
+
+Let it r.i.p. in OpenOCD git history.
+
+While there, drop from checkpatch list the camelcase symbols that
+where only used in this code.
+
+Change-Id: Ide52a217f2228e9da2f1cc5036c48f3536f26952
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7382
+Tested-by: jenkins
+---
+ README | 4 +-
+ configure.ac | 7 -
+ contrib/buildroot/openocd_be_defconfig | 1 -
+ doc/openocd.texi | 5 +-
+ src/jtag/Makefile.am | 5 -
+ src/jtag/aice/Makefile.am | 16 -
+ src/jtag/aice/aice_interface.c | 507 ---
+ src/jtag/aice/aice_interface.h | 14 -
+ src/jtag/aice/aice_pipe.c | 884 -----
+ src/jtag/aice/aice_pipe.h | 20 -
+ src/jtag/aice/aice_port.c | 34 -
+ src/jtag/aice/aice_port.h | 224 --
+ src/jtag/aice/aice_transport.c | 432 ---
+ src/jtag/aice/aice_transport.h | 13 -
+ src/jtag/aice/aice_usb.c | 4099 ------------------------
+ src/jtag/aice/aice_usb.h | 122 -
+ src/jtag/interfaces.c | 6 -
+ src/jtag/startup.tcl | 6 -
+ src/rtos/FreeRTOS.c | 14 -
+ src/rtos/rtos_standard_stackings.c | 47 -
+ src/rtos/rtos_standard_stackings.h | 1 -
+ src/target/Makefile.am | 27 +-
+ src/target/nds32.c | 2613 ---------------
+ src/target/nds32.h | 447 ---
+ src/target/nds32_aice.c | 147 -
+ src/target/nds32_aice.h | 150 -
+ src/target/nds32_cmd.c | 1123 -------
+ src/target/nds32_cmd.h | 15 -
+ src/target/nds32_disassembler.c | 3847 ----------------------
+ src/target/nds32_disassembler.h | 45 -
+ src/target/nds32_edm.h | 106 -
+ src/target/nds32_insn.h | 67 -
+ src/target/nds32_reg.c | 369 ---
+ src/target/nds32_reg.h | 314 --
+ src/target/nds32_tlb.c | 67 -
+ src/target/nds32_tlb.h | 36 -
+ src/target/nds32_v2.c | 774 -----
+ src/target/nds32_v2.h | 31 -
+ src/target/nds32_v3.c | 510 ---
+ src/target/nds32_v3.h | 34 -
+ src/target/nds32_v3_common.c | 664 ----
+ src/target/nds32_v3_common.h | 50 -
+ src/target/nds32_v3m.c | 495 ---
+ src/target/nds32_v3m.h | 40 -
+ src/target/target.c | 6 -
+ tcl/board/nds32_xc5.cfg | 7 -
+ tcl/interface/nds32-aice.cfg | 17 -
+ tcl/target/nds32v2.cfg | 12 -
+ tcl/target/nds32v3.cfg | 12 -
+ tcl/target/nds32v3m.cfg | 12 -
+ tools/scripts/camelcase.txt | 16 -
+ 51 files changed, 4 insertions(+), 18510 deletions(-)
+ delete mode 100644 src/jtag/aice/Makefile.am
+ delete mode 100644 src/jtag/aice/aice_interface.c
+ delete mode 100644 src/jtag/aice/aice_interface.h
+ delete mode 100644 src/jtag/aice/aice_pipe.c
+ delete mode 100644 src/jtag/aice/aice_pipe.h
+ delete mode 100644 src/jtag/aice/aice_port.c
+ delete mode 100644 src/jtag/aice/aice_port.h
+ delete mode 100644 src/jtag/aice/aice_transport.c
+ delete mode 100644 src/jtag/aice/aice_transport.h
+ delete mode 100644 src/jtag/aice/aice_usb.c
+ delete mode 100644 src/jtag/aice/aice_usb.h
+ delete mode 100644 src/target/nds32.c
+ delete mode 100644 src/target/nds32.h
+ delete mode 100644 src/target/nds32_aice.c
+ delete mode 100644 src/target/nds32_aice.h
+ delete mode 100644 src/target/nds32_cmd.c
+ delete mode 100644 src/target/nds32_cmd.h
+ delete mode 100644 src/target/nds32_disassembler.c
+ delete mode 100644 src/target/nds32_disassembler.h
+ delete mode 100644 src/target/nds32_edm.h
+ delete mode 100644 src/target/nds32_insn.h
+ delete mode 100644 src/target/nds32_reg.c
+ delete mode 100644 src/target/nds32_reg.h
+ delete mode 100644 src/target/nds32_tlb.c
+ delete mode 100644 src/target/nds32_tlb.h
+ delete mode 100644 src/target/nds32_v2.c
+ delete mode 100644 src/target/nds32_v2.h
+ delete mode 100644 src/target/nds32_v3.c
+ delete mode 100644 src/target/nds32_v3.h
+ delete mode 100644 src/target/nds32_v3_common.c
+ delete mode 100644 src/target/nds32_v3_common.h
+ delete mode 100644 src/target/nds32_v3m.c
+ delete mode 100644 src/target/nds32_v3m.h
+ delete mode 100644 tcl/board/nds32_xc5.cfg
+ delete mode 100644 tcl/interface/nds32-aice.cfg
+ delete mode 100644 tcl/target/nds32v2.cfg
+ delete mode 100644 tcl/target/nds32v3.cfg
+ delete mode 100644 tcl/target/nds32v3m.cfg
+
+diff --git a/README b/README
+index 08b8117db..2f71cfc6a 100644
+--- a/README
++++ b/README
+@@ -101,7 +101,7 @@ Supported hardware
+ JTAG adapters
+ -------------
+
+-AICE, AM335x, ARM-JTAG-EW, ARM-USB-OCD, ARM-USB-TINY, AT91RM9200, axm0432, BCM2835,
++AM335x, ARM-JTAG-EW, ARM-USB-OCD, ARM-USB-TINY, AT91RM9200, axm0432, BCM2835,
+ Bus Blaster, Buspirate, Cadence DPI, Cadence vdebug, Chameleon, CMSIS-DAP,
+ Cortino, Cypress KitProg, DENX, Digilent JTAG-SMT2, DLC 5, DLP-USB1232H,
+ embedded projects, Espressif USB JTAG Programmer,
+@@ -122,7 +122,7 @@ Debug targets
+ ARM: AArch64, ARM11, ARM7, ARM9, Cortex-A/R (v7-A/R), Cortex-M (ARMv{6/7/8}-M),
+ FA526, Feroceon/Dragonite, XScale.
+ ARCv2, AVR32, DSP563xx, DSP5680xx, EnSilica eSi-RISC, EJTAG (MIPS32, MIPS64),
+-ESP32, ESP32-S2, ESP32-S3, Intel Quark, LS102x-SAP, NDS32, RISC-V, ST STM8,
++ESP32, ESP32-S2, ESP32-S3, Intel Quark, LS102x-SAP, RISC-V, ST STM8,
+ Xtensa.
+
+ Flash drivers
+diff --git a/configure.ac b/configure.ac
+index 4fcc91528..cc7139c7c 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -130,9 +130,6 @@ m4_define([USB1_ADAPTERS],
+ [[usbprog], [USBProg JTAG Programmer], [USBPROG]],
+ [[esp_usb_jtag], [Espressif JTAG Programmer], [ESP_USB_JTAG]]])
+
+-m4_define([DEPRECATED_USB1_ADAPTERS],
+- [[[aice], [Andes JTAG Programmer (deprecated)], [AICE]]])
+-
+ m4_define([HIDAPI_ADAPTERS],
+ [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP_HID]],
+ [[nulink], [Nu-Link Programmer], [HLADAPTER_NULINK]]])
+@@ -264,8 +261,6 @@ AC_ARG_ADAPTERS([
+ LIBJAYLINK_ADAPTERS
+ ],[auto])
+
+-AC_ARG_ADAPTERS([DEPRECATED_USB1_ADAPTERS],[no])
+-
+ AC_ARG_ENABLE([parport],
+ AS_HELP_STRING([--enable-parport], [Enable building the pc parallel port driver]),
+ [build_parport=$enableval], [build_parport=no])
+@@ -684,7 +679,6 @@ m4_define([PROCESS_ADAPTERS], [
+ ])
+
+ PROCESS_ADAPTERS([USB1_ADAPTERS], ["x$use_libusb1" = "xyes"], [libusb-1.x])
+-PROCESS_ADAPTERS([DEPRECATED_USB1_ADAPTERS], ["x$use_libusb1" = "xyes"], [libusb-1.x])
+ PROCESS_ADAPTERS([HIDAPI_ADAPTERS], ["x$use_hidapi" = "xyes"], [hidapi])
+ PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libusb1" = "xyes"], [hidapi and libusb-1.x])
+ PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi])
+@@ -834,7 +828,6 @@ echo
+ echo OpenOCD configuration summary
+ echo --------------------------------------------------
+ m4_foreach([adapter], [USB1_ADAPTERS,
+- DEPRECATED_USB1_ADAPTERS,
+ HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS,
+ LIBFTDI_USB1_ADAPTERS,
+ LIBGPIOD_ADAPTERS,
+diff --git a/contrib/buildroot/openocd_be_defconfig b/contrib/buildroot/openocd_be_defconfig
+index 2fe28f647..49a6ec2ac 100644
+--- a/contrib/buildroot/openocd_be_defconfig
++++ b/contrib/buildroot/openocd_be_defconfig
+@@ -12,7 +12,6 @@ BR2_PACKAGE_OPENOCD_UBLASTER2=y
+ BR2_PACKAGE_OPENOCD_JLINK=y
+ BR2_PACKAGE_OPENOCD_OSDBM=y
+ BR2_PACKAGE_OPENOCD_OPENDOUS=y
+-BR2_PACKAGE_OPENOCD_AICE=y
+ BR2_PACKAGE_OPENOCD_VSLLINK=y
+ BR2_PACKAGE_OPENOCD_USBPROG=y
+ BR2_PACKAGE_OPENOCD_RLINK=y
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index d8a5e86b4..c7fee3e71 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -2480,7 +2480,7 @@ This command is only available if your libusb1 is at least version 1.0.16.
+ Specifies the @var{serial_string} of the adapter to use.
+ If this command is not specified, serial strings are not checked.
+ Only the following adapter drivers use the serial string from this command:
+-aice (aice_usb), arm-jtag-ew, cmsis_dap, ft232r, ftdi, hla (stlink, ti-icdi), jlink, kitprog, opendus,
++arm-jtag-ew, cmsis_dap, ft232r, ftdi, hla (stlink, ti-icdi), jlink, kitprog, opendus,
+ openjtag, osbdm, presto, rlink, st-link, usb_blaster (ublast2), usbprog, vsllink, xds110.
+ @end deffn
+
+@@ -4825,9 +4825,6 @@ specified, @xref{gdbportoverride,,option -gdb-port}.), and a fake ARM core will
+ be emulated to comply to GDB remote protocol.
+ @item @code{mips_m4k} -- a MIPS core.
+ @item @code{mips_mips64} -- a MIPS64 core.
+-@item @code{nds32_v2} -- this is an Andes NDS32 v2 core (deprecated; would be removed in v0.13.0).
+-@item @code{nds32_v3} -- this is an Andes NDS32 v3 core (deprecated; would be removed in v0.13.0).
+-@item @code{nds32_v3m} -- this is an Andes NDS32 v3m core (deprecated; would be removed in v0.13.0).
+ @item @code{or1k} -- this is an OpenRISC 1000 core.
+ The current implementation supports three JTAG TAP cores:
+ @itemize @minus
+diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am
+index 43c6f8b27..7ce4adc29 100644
+--- a/src/jtag/Makefile.am
++++ b/src/jtag/Makefile.am
+@@ -9,11 +9,6 @@ include %D%/hla/Makefile.am
+ %C%_libjtag_la_LIBADD += $(top_builddir)/%D%/hla/libocdhla.la
+ endif
+
+-if AICE
+-include %D%/aice/Makefile.am
+-%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/aice/libocdaice.la
+-endif
+-
+ include %D%/drivers/Makefile.am
+ %C%_libjtag_la_LIBADD += $(top_builddir)/%D%/drivers/libocdjtagdrivers.la
+
+diff --git a/src/jtag/aice/Makefile.am b/src/jtag/aice/Makefile.am
+deleted file mode 100644
+index bc5dac1e2..000000000
+--- a/src/jtag/aice/Makefile.am
++++ /dev/null
+@@ -1,16 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-noinst_LTLIBRARIES += %D%/libocdaice.la
+-
+-%C%_libocdaice_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS)
+-%C%_libocdaice_la_SOURCES = \
+- %D%/aice_transport.c \
+- %D%/aice_interface.c \
+- %D%/aice_port.c \
+- %D%/aice_usb.c \
+- %D%/aice_pipe.c \
+- %D%/aice_transport.h \
+- %D%/aice_interface.h \
+- %D%/aice_port.h \
+- %D%/aice_usb.h \
+- %D%/aice_pipe.h
+diff --git a/src/jtag/aice/aice_interface.c b/src/jtag/aice/aice_interface.c
+deleted file mode 100644
+index 89f82a0ae..000000000
+--- a/src/jtag/aice/aice_interface.c
++++ /dev/null
+@@ -1,507 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <jtag/adapter.h>
+-#include <jtag/interface.h>
+-#include <jtag/commands.h>
+-#include <transport/transport.h>
+-#include <target/target.h>
+-#include <jtag/aice/aice_transport.h>
+-#include "aice_usb.h"
+-
+-#define AICE_KHZ_TO_SPEED_MAP_SIZE 16
+-static const int aice_khz_to_speed_map[AICE_KHZ_TO_SPEED_MAP_SIZE] = {
+- 30000,
+- 15000,
+- 7500,
+- 3750,
+- 1875,
+- 937,
+- 468,
+- 234,
+- 48000,
+- 24000,
+- 12000,
+- 6000,
+- 3000,
+- 1500,
+- 750,
+- 375,
+-};
+-
+-static const struct aice_port *aice_port;
+-static struct aice_port_param_s param;
+-static uint32_t retry_times;
+-static uint32_t count_to_check_dbger;
+-
+-/***************************************************************************/
+-/* External interface implementation */
+-static uint32_t aice_target_id_codes[AICE_MAX_NUM_CORE];
+-static uint8_t aice_num_of_target_id_codes;
+-
+-/***************************************************************************/
+-/* AICE operations */
+-int aice_init_targets(void)
+-{
+- int res;
+- struct target *target;
+- struct aice_port_s *aice;
+-
+- LOG_DEBUG("aice_init_targets");
+-
+- if (aice_num_of_target_id_codes == 0) {
+- res = aice_port->api->idcode(aice_target_id_codes, &aice_num_of_target_id_codes);
+- if (res != ERROR_OK) {
+- LOG_ERROR("<-- TARGET ERROR! Failed to identify AndesCore "
+- "JTAG Manufacture ID in the JTAG scan chain. "
+- "Failed to access EDM registers. -->");
+- return res;
+- }
+- }
+-
+- for (target = all_targets; target; target = target->next) {
+- target->tap->idcode = aice_target_id_codes[target->tap->abs_chain_position];
+-
+- unsigned ii, limit = target->tap->expected_ids_cnt;
+- int found = 0;
+-
+- for (ii = 0; ii < limit; ii++) {
+- uint32_t expected = target->tap->expected_ids[ii];
+-
+- /* treat "-expected-id 0" as a "don't-warn" wildcard */
+- if (!expected || (target->tap->idcode == expected)) {
+- found = 1;
+- break;
+- }
+- }
+-
+- if (found == 0) {
+- LOG_ERROR
+- ("aice_init_targets: target not found: idcode: %" PRIx32,
+- target->tap->idcode);
+- return ERROR_FAIL;
+- }
+-
+- aice = calloc(1, sizeof(struct aice_port_s));
+- aice->port = aice_port;
+- aice->coreid = target->tap->abs_chain_position;
+-
+- target->tap->priv = aice;
+- target->tap->hasidcode = 1;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-/***************************************************************************/
+-/* End of External interface implementation */
+-
+-/* initial aice
+- * 1. open usb
+- * 2. get/show version number
+- * 3. reset
+- */
+-static int aice_init(void)
+-{
+- if (aice_port->api->open(¶m) != ERROR_OK) {
+- LOG_ERROR("Cannot find AICE Interface! Please check "
+- "connection and permissions.");
+- return ERROR_JTAG_INIT_FAILED;
+- }
+-
+- aice_port->api->set_retry_times(retry_times);
+- aice_port->api->set_count_to_check_dbger(count_to_check_dbger);
+-
+- LOG_INFO("AICE JTAG Interface ready");
+-
+- return ERROR_OK;
+-}
+-
+-/* cleanup aice resource
+- * close usb
+- */
+-static int aice_quit(void)
+-{
+- aice_port->api->close();
+- return ERROR_OK;
+-}
+-
+-static int aice_execute_reset(struct jtag_command *cmd)
+-{
+- static int last_trst;
+- int retval = ERROR_OK;
+-
+- LOG_DEBUG_IO("reset trst: %d", cmd->cmd.reset->trst);
+-
+- if (cmd->cmd.reset->trst != last_trst) {
+- if (cmd->cmd.reset->trst)
+- retval = aice_port->api->reset();
+-
+- last_trst = cmd->cmd.reset->trst;
+- }
+-
+- return retval;
+-}
+-
+-static int aice_execute_command(struct jtag_command *cmd)
+-{
+- int retval;
+-
+- switch (cmd->type) {
+- case JTAG_RESET:
+- retval = aice_execute_reset(cmd);
+- break;
+- default:
+- retval = ERROR_OK;
+- break;
+- }
+- return retval;
+-}
+-
+-/* aice has no need to implement jtag execution model
+-*/
+-static int aice_execute_queue(void)
+-{
+- struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
+- int retval;
+-
+- retval = ERROR_OK;
+-
+- while (cmd) {
+- if (aice_execute_command(cmd) != ERROR_OK)
+- retval = ERROR_JTAG_QUEUE_FAILED;
+-
+- cmd = cmd->next;
+- }
+-
+- return retval;
+-}
+-
+-/* set jtag frequency(base frequency/frequency divider) to your jtag adapter */
+-static int aice_speed(int speed)
+-{
+- return aice_port->api->set_jtag_clock(speed);
+-}
+-
+-/* convert jtag adapter frequency(base frequency/frequency divider) to
+- * human readable KHz value */
+-static int aice_speed_div(int speed, int *khz)
+-{
+- *khz = aice_khz_to_speed_map[speed];
+-
+- return ERROR_OK;
+-}
+-
+-/* convert human readable KHz value to jtag adapter frequency
+- * (base frequency/frequency divider) */
+-static int aice_khz(int khz, int *jtag_speed)
+-{
+- int i;
+- for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++) {
+- if (khz == aice_khz_to_speed_map[i]) {
+- if (i >= 8)
+- *jtag_speed = i | AICE_TCK_CONTROL_TCK3048;
+- else
+- *jtag_speed = i;
+- break;
+- }
+- }
+-
+- if (i == AICE_KHZ_TO_SPEED_MAP_SIZE) {
+- LOG_INFO("No support the jtag clock: %d", khz);
+- LOG_INFO("Supported jtag clocks are:");
+-
+- for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++)
+- LOG_INFO("* %d", aice_khz_to_speed_map[i]);
+-
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int aice_scan_jtag_chain(void)
+-{
+- LOG_DEBUG("=== %s ===", __func__);
+- uint8_t num_of_idcode = 0;
+- struct target *target;
+-
+- int res = aice_port->api->idcode(aice_target_id_codes, &num_of_idcode);
+- if (res != ERROR_OK) {
+- LOG_ERROR("<-- TARGET ERROR! Failed to identify AndesCore "
+- "JTAG Manufacture ID in the JTAG scan chain. "
+- "Failed to access EDM registers. -->");
+- return res;
+- }
+-
+- for (unsigned int i = 0; i < num_of_idcode; i++)
+- LOG_DEBUG("id_codes[%u] = 0x%" PRIx32, i, aice_target_id_codes[i]);
+-
+- /* Update tap idcode */
+- for (target = all_targets; target; target = target->next)
+- target->tap->idcode = aice_target_id_codes[target->tap->abs_chain_position];
+-
+- return ERROR_OK;
+-}
+-
+-/***************************************************************************/
+-/* Command handlers */
+-COMMAND_HANDLER(aice_handle_aice_info_command)
+-{
+- LOG_DEBUG("aice_handle_aice_info_command");
+-
+- command_print(CMD, "Description: %s", param.device_desc);
+- command_print(CMD, "Serial number: %s", adapter_get_required_serial());
+- if (strncmp(aice_port->name, "aice_pipe", 9) == 0)
+- command_print(CMD, "Adapter: %s", param.adapter_name);
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_port_command)
+-{
+- LOG_DEBUG("aice_handle_aice_port_command");
+-
+- if (CMD_ARGC != 1) {
+- LOG_ERROR("Need exactly one argument to 'aice port'");
+- return ERROR_COMMAND_SYNTAX_ERROR;
+- }
+-
+- for (const struct aice_port *l = aice_port_get_list(); l->name; l++) {
+- if (strcmp(l->name, CMD_ARGV[0]) == 0) {
+- aice_port = l;
+- return ERROR_OK;
+- }
+- }
+-
+- LOG_ERROR("No AICE port '%s' found", CMD_ARGV[0]);
+- return ERROR_FAIL;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_desc_command)
+-{
+- LOG_DEBUG("aice_handle_aice_desc_command");
+-
+- if (CMD_ARGC == 1)
+- param.device_desc = strdup(CMD_ARGV[0]);
+- else
+- LOG_ERROR("expected exactly one argument to aice desc <description>");
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_vid_pid_command)
+-{
+- LOG_DEBUG("aice_handle_aice_vid_pid_command");
+-
+- if (CMD_ARGC != 2) {
+- LOG_WARNING("ignoring extra IDs in aice vid_pid (maximum is 1 pair)");
+- return ERROR_COMMAND_SYNTAX_ERROR;
+- }
+-
+- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], param.vid);
+- COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], param.pid);
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_adapter_command)
+-{
+- LOG_DEBUG("aice_handle_aice_adapter_command");
+-
+- if (CMD_ARGC == 1)
+- param.adapter_name = strdup(CMD_ARGV[0]);
+- else
+- LOG_ERROR("expected exactly one argument to aice adapter <adapter-name>");
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_retry_times_command)
+-{
+- LOG_DEBUG("aice_handle_aice_retry_times_command");
+-
+- if (CMD_ARGC == 1)
+- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], retry_times);
+- else
+- LOG_ERROR("expected exactly one argument to aice retry_times <num_of_retry>");
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_count_to_check_dbger_command)
+-{
+- LOG_DEBUG("aice_handle_aice_count_to_check_dbger_command");
+-
+- if (CMD_ARGC == 1)
+- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], count_to_check_dbger);
+- else
+- LOG_ERROR("expected exactly one argument to aice count_to_check_dbger "
+- "<count_of_checking>");
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_custom_srst_script_command)
+-{
+- LOG_DEBUG("aice_handle_aice_custom_srst_script_command");
+-
+- if (CMD_ARGC > 0) {
+- aice_port->api->set_custom_srst_script(CMD_ARGV[0]);
+- return ERROR_OK;
+- }
+-
+- return ERROR_FAIL;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_custom_trst_script_command)
+-{
+- LOG_DEBUG("aice_handle_aice_custom_trst_script_command");
+-
+- if (CMD_ARGC > 0) {
+- aice_port->api->set_custom_trst_script(CMD_ARGV[0]);
+- return ERROR_OK;
+- }
+-
+- return ERROR_FAIL;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_custom_restart_script_command)
+-{
+- LOG_DEBUG("aice_handle_aice_custom_restart_script_command");
+-
+- if (CMD_ARGC > 0) {
+- aice_port->api->set_custom_restart_script(CMD_ARGV[0]);
+- return ERROR_OK;
+- }
+-
+- return ERROR_FAIL;
+-}
+-
+-COMMAND_HANDLER(aice_handle_aice_reset_command)
+-{
+- LOG_DEBUG("aice_handle_aice_reset_command");
+-
+- return aice_port->api->reset();
+-}
+-
+-
+-static const struct command_registration aice_subcommand_handlers[] = {
+- {
+- .name = "info",
+- .handler = &aice_handle_aice_info_command,
+- .mode = COMMAND_EXEC,
+- .help = "show aice info",
+- .usage = "",
+- },
+- {
+- .name = "port",
+- .handler = &aice_handle_aice_port_command,
+- .mode = COMMAND_CONFIG,
+- .help = "set the port of the AICE",
+- .usage = "['aice_pipe'|'aice_usb']",
+- },
+- {
+- .name = "desc",
+- .handler = &aice_handle_aice_desc_command,
+- .mode = COMMAND_CONFIG,
+- .help = "set the aice device description",
+- .usage = "[description string]",
+- },
+- {
+- .name = "vid_pid",
+- .handler = &aice_handle_aice_vid_pid_command,
+- .mode = COMMAND_CONFIG,
+- .help = "the vendor and product ID of the AICE device",
+- .usage = "(vid pid)*",
+- },
+- {
+- .name = "adapter",
+- .handler = &aice_handle_aice_adapter_command,
+- .mode = COMMAND_CONFIG,
+- .help = "set the file name of adapter",
+- .usage = "[adapter name]",
+- },
+- {
+- .name = "retry_times",
+- .handler = &aice_handle_aice_retry_times_command,
+- .mode = COMMAND_CONFIG,
+- .help = "set retry times as AICE timeout",
+- .usage = "num_of_retry",
+- },
+- {
+- .name = "count_to_check_dbger",
+- .handler = &aice_handle_aice_count_to_check_dbger_command,
+- .mode = COMMAND_CONFIG,
+- .help = "set retry times as checking $DBGER status",
+- .usage = "count_of_checking",
+- },
+- {
+- .name = "custom_srst_script",
+- .handler = &aice_handle_aice_custom_srst_script_command,
+- .mode = COMMAND_CONFIG,
+- .usage = "script_file_name",
+- .help = "set custom srst script",
+- },
+- {
+- .name = "custom_trst_script",
+- .handler = &aice_handle_aice_custom_trst_script_command,
+- .mode = COMMAND_CONFIG,
+- .usage = "script_file_name",
+- .help = "set custom trst script",
+- },
+- {
+- .name = "custom_restart_script",
+- .handler = &aice_handle_aice_custom_restart_script_command,
+- .mode = COMMAND_CONFIG,
+- .usage = "script_file_name",
+- .help = "set custom restart script",
+- },
+- {
+- .name = "reset",
+- .handler = &aice_handle_aice_reset_command,
+- .mode = COMMAND_EXEC,
+- .usage = "",
+- .help = "reset AICE",
+- },
+- COMMAND_REGISTRATION_DONE
+-};
+-
+-static const struct command_registration aice_command_handlers[] = {
+- {
+- .name = "aice",
+- .mode = COMMAND_ANY,
+- .help = "perform aice management",
+- .usage = "[subcommand]",
+- .chain = aice_subcommand_handlers,
+- },
+- COMMAND_REGISTRATION_DONE
+-};
+-/***************************************************************************/
+-/* End of Command handlers */
+-
+-static struct jtag_interface aice_interface = {
+- .execute_queue = aice_execute_queue,
+-};
+-
+-struct adapter_driver aice_adapter_driver = {
+- .name = "aice",
+- .transports = aice_transports,
+- .commands = aice_command_handlers,
+-
+- .init = aice_init,
+- .quit = aice_quit,
+- .speed = aice_speed, /* set interface speed */
+- .khz = aice_khz, /* convert khz to interface speed value */
+- .speed_div = aice_speed_div, /* return readable value */
+-
+- .jtag_ops = &aice_interface,
+-};
+diff --git a/src/jtag/aice/aice_interface.h b/src/jtag/aice/aice_interface.h
+deleted file mode 100644
+index 615e90f2e..000000000
+--- a/src/jtag/aice/aice_interface.h
++++ /dev/null
+@@ -1,14 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_JTAG_AICE_AICE_INTERFACE_H
+-#define OPENOCD_JTAG_AICE_AICE_INTERFACE_H
+-
+-int aice_init_targets(void);
+-int aice_scan_jtag_chain(void);
+-
+-#endif /* OPENOCD_JTAG_AICE_AICE_INTERFACE_H */
+diff --git a/src/jtag/aice/aice_pipe.c b/src/jtag/aice/aice_pipe.c
+deleted file mode 100644
+index 1ee2d88b4..000000000
+--- a/src/jtag/aice/aice_pipe.c
++++ /dev/null
+@@ -1,884 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <helper/system.h>
+-
+-#ifdef _WIN32
+-#include <windows.h>
+-#else
+-#include <signal.h>
+-#endif
+-
+-#include <helper/log.h>
+-#include <helper/time_support.h>
+-#include "aice_port.h"
+-#include "aice_pipe.h"
+-
+-#define AICE_PIPE_MAXLINE 8192
+-
+-#ifdef _WIN32
+-PROCESS_INFORMATION proc_info;
+-
+-static HANDLE aice_pipe_output[2];
+-static HANDLE aice_pipe_input[2];
+-
+-static int aice_pipe_write(const void *buffer, int count)
+-{
+- BOOL success;
+- DWORD written;
+-
+- success = WriteFile(aice_pipe_output[1], buffer, count, &written, NULL);
+- if (!success) {
+- LOG_ERROR("(WIN32) write to pipe failed, error code: 0x%08l" PRIx32, GetLastError());
+- return -1;
+- }
+-
+- return written;
+-}
+-
+-static int aice_pipe_read(void *buffer, int count)
+-{
+- BOOL success;
+- DWORD has_read;
+-
+- success = ReadFile(aice_pipe_input[0], buffer, count, &has_read, NULL);
+- if (!success || (has_read == 0)) {
+- LOG_ERROR("(WIN32) read from pipe failed, error code: 0x%08l" PRIx32, GetLastError());
+- return -1;
+- }
+-
+- return has_read;
+-}
+-
+-static int aice_pipe_child_init(struct aice_port_param_s *param)
+-{
+- STARTUPINFO start_info;
+- BOOL success;
+-
+- ZeroMemory(&proc_info, sizeof(PROCESS_INFORMATION));
+- ZeroMemory(&start_info, sizeof(STARTUPINFO));
+- start_info.cb = sizeof(STARTUPINFO);
+- start_info.hStdError = aice_pipe_input[1];
+- start_info.hStdOutput = aice_pipe_input[1];
+- start_info.hStdInput = aice_pipe_output[0];
+- start_info.dwFlags |= STARTF_USESTDHANDLES;
+-
+- success = CreateProcess(NULL,
+- param->adapter_name,
+- NULL,
+- NULL,
+- TRUE,
+- 0,
+- NULL,
+- NULL,
+- &start_info,
+- &proc_info);
+-
+- if (!success) {
+- LOG_ERROR("Create new process failed");
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_parent_init(struct aice_port_param_s *param)
+-{
+- /* send open to adapter */
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_OPEN;
+- set_u16(command + 1, param->vid);
+- set_u16(command + 3, param->pid);
+-
+- if (aice_pipe_write(command, 5) != 5) {
+- LOG_ERROR("write failed\n");
+- return ERROR_FAIL;
+- }
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) {
+- LOG_ERROR("read failed\n");
+- return ERROR_FAIL;
+- }
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_open(struct aice_port_param_s *param)
+-{
+- SECURITY_ATTRIBUTES attribute;
+-
+- attribute.nLength = sizeof(SECURITY_ATTRIBUTES);
+- attribute.bInheritHandle = TRUE;
+- attribute.lpSecurityDescriptor = NULL;
+-
+- if (!CreatePipe(&aice_pipe_output[0], &aice_pipe_output[1],
+- &attribute, AICE_PIPE_MAXLINE)) {
+- LOG_ERROR("Create pipes failed");
+- return ERROR_FAIL;
+- }
+- if (!CreatePipe(&aice_pipe_input[0], &aice_pipe_input[1],
+- &attribute, AICE_PIPE_MAXLINE)) {
+- LOG_ERROR("Create pipes failed");
+- return ERROR_FAIL;
+- }
+-
+- /* do not inherit aice_pipe_output[1] & aice_pipe_input[0] to child process */
+- if (!SetHandleInformation(aice_pipe_output[1], HANDLE_FLAG_INHERIT, 0))
+- return ERROR_FAIL;
+- if (!SetHandleInformation(aice_pipe_input[0], HANDLE_FLAG_INHERIT, 0))
+- return ERROR_FAIL;
+-
+- aice_pipe_child_init(param);
+-
+- aice_pipe_parent_init(param);
+-
+- return ERROR_OK;
+-}
+-
+-#else
+-
+-static int aice_pipe_output[2];
+-static int aice_pipe_input[2];
+-
+-static int aice_pipe_write(const void *buffer, int count)
+-{
+- if (write(aice_pipe_output[1], buffer, count) != count) {
+- LOG_ERROR("write to pipe failed");
+- return -1;
+- }
+-
+- return count;
+-}
+-
+-static int aice_pipe_read(void *buffer, int count)
+-{
+- int n;
+- int64_t then, cur;
+-
+- then = timeval_ms();
+-
+- while (1) {
+- n = read(aice_pipe_input[0], buffer, count);
+-
+- if ((n == -1) && (errno == EAGAIN)) {
+- cur = timeval_ms();
+- if (cur - then > 500)
+- keep_alive();
+- continue;
+- } else if (n > 0)
+- break;
+- else {
+- LOG_ERROR("read from pipe failed");
+- break;
+- }
+- }
+-
+- return n;
+-}
+-
+-static int aice_pipe_child_init(struct aice_port_param_s *param)
+-{
+- close(aice_pipe_output[1]);
+- close(aice_pipe_input[0]);
+-
+- if (aice_pipe_output[0] != STDIN_FILENO) {
+- if (dup2(aice_pipe_output[0], STDIN_FILENO) != STDIN_FILENO) {
+- LOG_ERROR("Map aice_pipe to STDIN failed");
+- return ERROR_FAIL;
+- }
+- close(aice_pipe_output[0]);
+- }
+-
+- if (aice_pipe_input[1] != STDOUT_FILENO) {
+- if (dup2(aice_pipe_input[1], STDOUT_FILENO) != STDOUT_FILENO) {
+- LOG_ERROR("Map aice_pipe to STDOUT failed");
+- return ERROR_FAIL;
+- }
+- close(aice_pipe_input[1]);
+- }
+-
+- if (execl(param->adapter_name, param->adapter_name, (char *)0) < 0) {
+- LOG_ERROR("Execute aice_pipe failed");
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_parent_init(struct aice_port_param_s *param)
+-{
+- close(aice_pipe_output[0]);
+- close(aice_pipe_input[1]);
+-
+- /* set read end of pipe as non-blocking */
+- if (fcntl(aice_pipe_input[0], F_SETFL, O_NONBLOCK))
+- return ERROR_FAIL;
+-
+- /* send open to adapter */
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_OPEN;
+- set_u16(command + 1, param->vid);
+- set_u16(command + 3, param->pid);
+-
+- if (aice_pipe_write(command, 5) != 5) {
+- LOG_ERROR("write failed\n");
+- return ERROR_FAIL;
+- }
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) {
+- LOG_ERROR("read failed\n");
+- return ERROR_FAIL;
+- }
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static void sig_pipe(int signo)
+-{
+- exit(1);
+-}
+-
+-static int aice_pipe_open(struct aice_port_param_s *param)
+-{
+- pid_t pid;
+-
+- if (signal(SIGPIPE, sig_pipe) == SIG_ERR) {
+- LOG_ERROR("Register SIGPIPE handler failed");
+- return ERROR_FAIL;
+- }
+-
+- if (pipe(aice_pipe_output) < 0 || pipe(aice_pipe_input) < 0) {
+- LOG_ERROR("Create pipes failed");
+- return ERROR_FAIL;
+- }
+-
+- pid = fork();
+- if (pid < 0) {
+- LOG_ERROR("Fork new process failed");
+- return ERROR_FAIL;
+- } else if (pid == 0) {
+- if (aice_pipe_child_init(param) != ERROR_OK) {
+- LOG_ERROR("AICE_PIPE child process initial error");
+- return ERROR_FAIL;
+- } else {
+- if (aice_pipe_parent_init(param) != ERROR_OK) {
+- LOG_ERROR("AICE_PIPE parent process initial error");
+- return ERROR_FAIL;
+- }
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-#endif
+-
+-static int aice_pipe_close(void)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_CLOSE;
+-
+- if (aice_pipe_write(command, 1) != 1)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK) {
+-#ifdef _WIN32
+- WaitForSingleObject(proc_info.hProcess, INFINITE);
+- CloseHandle(proc_info.hProcess);
+- CloseHandle(proc_info.hThread);
+-#endif
+- return ERROR_OK;
+- } else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_idcode(uint32_t *idcode, uint8_t *num_of_idcode)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_IDCODE;
+-
+- if (aice_pipe_write(command, 1) != 1)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- *num_of_idcode = line[0];
+-
+- if ((*num_of_idcode == 0) || (*num_of_idcode >= 16))
+- return ERROR_FAIL;
+-
+- for (int i = 0 ; i < *num_of_idcode ; i++)
+- idcode[i] = get_u32(line + i * 4 + 1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_state(uint32_t coreid, enum aice_target_state_s *state)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_STATE;
+-
+- if (aice_pipe_write(command, 1) != 1)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- *state = (enum aice_target_state_s)line[0];
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_reset(void)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_RESET;
+-
+- if (aice_pipe_write(command, 1) != 1)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_assert_srst(uint32_t coreid, enum aice_srst_type_s srst)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_ASSERT_SRST;
+- command[1] = srst;
+-
+- if (aice_pipe_write(command, 2) != 2)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_run(uint32_t coreid)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_RUN;
+-
+- if (aice_pipe_write(command, 1) != 1)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_halt(uint32_t coreid)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_HALT;
+-
+- if (aice_pipe_write(command, 1) != 1)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_READ_REG;
+- set_u32(command + 1, num);
+-
+- if (aice_pipe_write(command, 5) != 5)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- *val = get_u32(line);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_WRITE_REG;
+- set_u32(command + 1, num);
+- set_u32(command + 5, val);
+-
+- if (aice_pipe_write(command, 9) != 9)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_read_reg_64(uint32_t coreid, uint32_t num, uint64_t *val)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_READ_REG_64;
+- set_u32(command + 1, num);
+-
+- if (aice_pipe_write(command, 5) != 5)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- *val = (((uint64_t)get_u32(line + 4)) << 32) | get_u32(line);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_write_reg_64(uint32_t coreid, uint32_t num, uint64_t val)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_WRITE_REG_64;
+- set_u32(command + 1, num);
+- set_u32(command + 5, val & 0xFFFFFFFF);
+- set_u32(command + 9, (val >> 32) & 0xFFFFFFFF);
+-
+- if (aice_pipe_write(command, 13) != 9)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_step(uint32_t coreid)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_STEP;
+-
+- if (aice_pipe_write(command, 1) != 1)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_read_mem_unit(uint32_t coreid, uint32_t addr, uint32_t size,
+- uint32_t count, uint8_t *buffer)
+-{
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_READ_MEM_UNIT;
+- set_u32(command + 1, addr);
+- set_u32(command + 5, size);
+- set_u32(command + 9, count);
+-
+- if (aice_pipe_write(command, 13) != 13)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(buffer, size * count) < 0)
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_write_mem_unit(uint32_t coreid, uint32_t addr, uint32_t size,
+- uint32_t count, const uint8_t *buffer)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_WRITE_MEM_UNIT;
+- set_u32(command + 1, addr);
+- set_u32(command + 5, size);
+- set_u32(command + 9, count);
+-
+- /* WRITE_MEM_UNIT|addr|size|count|data */
+- memcpy(command + 13, buffer, size * count);
+-
+- if (aice_pipe_write(command, 13 + size * count) < 0)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_read_mem_bulk(uint32_t coreid, uint32_t addr,
+- uint32_t length, uint8_t *buffer)
+-{
+- char line[AICE_PIPE_MAXLINE + 1];
+- char command[AICE_PIPE_MAXLINE];
+- uint32_t remain_len = length;
+- uint32_t prepare_len;
+- char *received_line;
+- uint32_t received_len;
+- int read_len;
+-
+- command[0] = AICE_READ_MEM_BULK;
+- set_u32(command + 1, addr);
+- set_u32(command + 5, length);
+-
+- if (aice_pipe_write(command, 9) < 0)
+- return ERROR_FAIL;
+-
+- while (remain_len > 0) {
+- if (remain_len > AICE_PIPE_MAXLINE)
+- prepare_len = AICE_PIPE_MAXLINE;
+- else
+- prepare_len = remain_len;
+-
+- prepare_len++;
+- received_len = 0;
+- received_line = line;
+- do {
+- read_len = aice_pipe_read(received_line, prepare_len - received_len);
+- if (read_len < 0)
+- return ERROR_FAIL;
+- received_line += read_len;
+- received_len += read_len;
+- } while (received_len < prepare_len);
+-
+- if (line[0] != AICE_OK)
+- return ERROR_FAIL;
+-
+- prepare_len--;
+- memcpy(buffer, line + 1, prepare_len);
+- remain_len -= prepare_len;
+- buffer += prepare_len;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_write_mem_bulk(uint32_t coreid, uint32_t addr,
+- uint32_t length, const uint8_t *buffer)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE + 4];
+- uint32_t remain_len = length;
+- uint32_t written_len = 0;
+- uint32_t write_len;
+-
+- command[0] = AICE_WRITE_MEM_BULK;
+- set_u32(command + 1, addr);
+- set_u32(command + 5, length);
+-
+- /* Send command first */
+- if (aice_pipe_write(command, 9) < 0)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_ERROR)
+- return ERROR_FAIL;
+-
+- while (remain_len > 0) {
+- if (remain_len > AICE_PIPE_MAXLINE)
+- write_len = AICE_PIPE_MAXLINE;
+- else
+- write_len = remain_len;
+-
+- set_u32(command, write_len);
+- memcpy(command + 4, buffer + written_len, write_len); /* data only */
+-
+- if (aice_pipe_write(command, write_len + 4) < 0)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_ERROR)
+- return ERROR_FAIL;
+-
+- remain_len -= write_len;
+- written_len += write_len;
+- }
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_read_debug_reg(uint32_t coreid, uint32_t addr, uint32_t *val)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_READ_DEBUG_REG;
+- set_u32(command + 1, addr);
+-
+- if (aice_pipe_write(command, 5) != 5)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- *val = get_u32(line);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_pipe_write_debug_reg(uint32_t coreid, uint32_t addr, const uint32_t val)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_WRITE_DEBUG_REG;
+- set_u32(command + 1, addr);
+- set_u32(command + 5, val);
+-
+- if (aice_pipe_write(command, 9) != 9)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_set_jtag_clock(uint32_t a_clock)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_SET_JTAG_CLOCK;
+- set_u32(command + 1, a_clock);
+-
+- if (aice_pipe_write(command, 5) != 5)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_memory_access(uint32_t coreid, enum nds_memory_access access_channel)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_MEMORY_ACCESS;
+- set_u32(command + 1, access_channel);
+-
+- if (aice_pipe_write(command, 5) != 5)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_memory_mode(uint32_t coreid, enum nds_memory_select mem_select)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_MEMORY_MODE;
+- set_u32(command + 1, mem_select);
+-
+- if (aice_pipe_write(command, 5) != 5)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_read_tlb(uint32_t coreid, target_addr_t virtual_address,
+- target_addr_t *physical_address)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_READ_TLB;
+- set_u32(command + 1, virtual_address);
+-
+- if (aice_pipe_write(command, 5) != 5)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK) {
+- *physical_address = get_u32(line + 1);
+- return ERROR_OK;
+- } else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_cache_ctl(uint32_t coreid, uint32_t subtype, uint32_t address)
+-{
+- char line[AICE_PIPE_MAXLINE];
+- char command[AICE_PIPE_MAXLINE];
+-
+- command[0] = AICE_CACHE_CTL;
+- set_u32(command + 1, subtype);
+- set_u32(command + 5, address);
+-
+- if (aice_pipe_write(command, 9) != 9)
+- return ERROR_FAIL;
+-
+- if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
+- return ERROR_FAIL;
+-
+- if (line[0] == AICE_OK)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+-}
+-
+-static int aice_pipe_set_retry_times(uint32_t a_retry_times)
+-{
+- return ERROR_OK;
+-}
+-
+-/** */
+-struct aice_port_api_s aice_pipe = {
+- /** */
+- .open = aice_pipe_open,
+- /** */
+- .close = aice_pipe_close,
+- /** */
+- .idcode = aice_pipe_idcode,
+- /** */
+- .set_jtag_clock = aice_pipe_set_jtag_clock,
+- /** */
+- .state = aice_pipe_state,
+- /** */
+- .reset = aice_pipe_reset,
+- /** */
+- .assert_srst = aice_pipe_assert_srst,
+- /** */
+- .run = aice_pipe_run,
+- /** */
+- .halt = aice_pipe_halt,
+- /** */
+- .step = aice_pipe_step,
+- /** */
+- .read_reg = aice_pipe_read_reg,
+- /** */
+- .write_reg = aice_pipe_write_reg,
+- /** */
+- .read_reg_64 = aice_pipe_read_reg_64,
+- /** */
+- .write_reg_64 = aice_pipe_write_reg_64,
+- /** */
+- .read_mem_unit = aice_pipe_read_mem_unit,
+- /** */
+- .write_mem_unit = aice_pipe_write_mem_unit,
+- /** */
+- .read_mem_bulk = aice_pipe_read_mem_bulk,
+- /** */
+- .write_mem_bulk = aice_pipe_write_mem_bulk,
+- /** */
+- .read_debug_reg = aice_pipe_read_debug_reg,
+- /** */
+- .write_debug_reg = aice_pipe_write_debug_reg,
+-
+- /** */
+- .memory_access = aice_pipe_memory_access,
+- /** */
+- .memory_mode = aice_pipe_memory_mode,
+-
+- /** */
+- .read_tlb = aice_pipe_read_tlb,
+-
+- /** */
+- .cache_ctl = aice_pipe_cache_ctl,
+-
+- /** */
+- .set_retry_times = aice_pipe_set_retry_times,
+-};
+diff --git a/src/jtag/aice/aice_pipe.h b/src/jtag/aice/aice_pipe.h
+deleted file mode 100644
+index 5a1f4107f..000000000
+--- a/src/jtag/aice/aice_pipe.h
++++ /dev/null
+@@ -1,20 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_JTAG_AICE_AICE_PIPE_H
+-#define OPENOCD_JTAG_AICE_AICE_PIPE_H
+-
+-#include <helper/types.h>
+-
+-#define set_u32(buffer, value) h_u32_to_le((uint8_t *)buffer, value)
+-#define set_u16(buffer, value) h_u16_to_le((uint8_t *)buffer, value)
+-#define get_u32(buffer) le_to_h_u32((const uint8_t *)buffer)
+-#define get_u16(buffer) le_to_h_u16((const uint8_t *)buffer)
+-
+-extern struct aice_port_api_s aice_pipe;
+-
+-#endif /* OPENOCD_JTAG_AICE_AICE_PIPE_H */
+diff --git a/src/jtag/aice/aice_port.c b/src/jtag/aice/aice_port.c
+deleted file mode 100644
+index ac38cec3a..000000000
+--- a/src/jtag/aice/aice_port.c
++++ /dev/null
+@@ -1,34 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <helper/log.h>
+-#include "aice_usb.h"
+-#include "aice_pipe.h"
+-#include "aice_port.h"
+-
+-static const struct aice_port aice_ports[] = {
+- {
+- .name = "aice_usb",
+- .type = AICE_PORT_AICE_USB,
+- .api = &aice_usb_api,
+- },
+- {
+- .name = "aice_pipe",
+- .type = AICE_PORT_AICE_PIPE,
+- .api = &aice_pipe,
+- },
+- {.name = NULL, /* END OF TABLE */ },
+-};
+-
+-/** */
+-const struct aice_port *aice_port_get_list(void)
+-{
+- return aice_ports;
+-}
+diff --git a/src/jtag/aice/aice_port.h b/src/jtag/aice/aice_port.h
+deleted file mode 100644
+index fb914d853..000000000
+--- a/src/jtag/aice/aice_port.h
++++ /dev/null
+@@ -1,224 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_JTAG_AICE_AICE_PORT_H
+-#define OPENOCD_JTAG_AICE_AICE_PORT_H
+-
+-#include <target/nds32_edm.h>
+-
+-#define AICE_MAX_NUM_CORE (0x10)
+-
+-#define ERROR_AICE_DISCONNECT (-200)
+-#define ERROR_AICE_TIMEOUT (-201)
+-
+-enum aice_target_state_s {
+- AICE_DISCONNECT = 0,
+- AICE_TARGET_DETACH,
+- AICE_TARGET_UNKNOWN,
+- AICE_TARGET_RUNNING,
+- AICE_TARGET_HALTED,
+- AICE_TARGET_RESET,
+- AICE_TARGET_DEBUG_RUNNING,
+-};
+-
+-enum aice_srst_type_s {
+- AICE_SRST = 0x1,
+- AICE_RESET_HOLD = 0x8,
+-};
+-
+-enum aice_target_endian {
+- AICE_LITTLE_ENDIAN = 0,
+- AICE_BIG_ENDIAN,
+-};
+-
+-enum aice_api_s {
+- AICE_OPEN = 0x0,
+- AICE_CLOSE,
+- AICE_RESET,
+- AICE_IDCODE,
+- AICE_SET_JTAG_CLOCK,
+- AICE_ASSERT_SRST,
+- AICE_RUN,
+- AICE_HALT,
+- AICE_STEP,
+- AICE_READ_REG,
+- AICE_WRITE_REG,
+- AICE_READ_REG_64,
+- AICE_WRITE_REG_64,
+- AICE_READ_MEM_UNIT,
+- AICE_WRITE_MEM_UNIT,
+- AICE_READ_MEM_BULK,
+- AICE_WRITE_MEM_BULK,
+- AICE_READ_DEBUG_REG,
+- AICE_WRITE_DEBUG_REG,
+- AICE_STATE,
+- AICE_MEMORY_ACCESS,
+- AICE_MEMORY_MODE,
+- AICE_READ_TLB,
+- AICE_CACHE_CTL,
+- AICE_SET_RETRY_TIMES,
+- AICE_PROGRAM_EDM,
+- AICE_SET_COMMAND_MODE,
+- AICE_EXECUTE,
+- AICE_SET_CUSTOM_SRST_SCRIPT,
+- AICE_SET_CUSTOM_TRST_SCRIPT,
+- AICE_SET_CUSTOM_RESTART_SCRIPT,
+- AICE_SET_COUNT_TO_CHECK_DBGER,
+- AICE_SET_DATA_ENDIAN,
+-};
+-
+-enum aice_error_s {
+- AICE_OK,
+- AICE_ACK,
+- AICE_ERROR,
+-};
+-
+-enum aice_cache_ctl_type {
+- AICE_CACHE_CTL_L1D_INVALALL = 0,
+- AICE_CACHE_CTL_L1D_VA_INVAL,
+- AICE_CACHE_CTL_L1D_WBALL,
+- AICE_CACHE_CTL_L1D_VA_WB,
+- AICE_CACHE_CTL_L1I_INVALALL,
+- AICE_CACHE_CTL_L1I_VA_INVAL,
+-};
+-
+-enum aice_command_mode {
+- AICE_COMMAND_MODE_NORMAL,
+- AICE_COMMAND_MODE_PACK,
+- AICE_COMMAND_MODE_BATCH,
+-};
+-
+-struct aice_port_param_s {
+- /** */
+- const char *device_desc;
+- /** */
+- uint16_t vid;
+- /** */
+- uint16_t pid;
+- /** */
+- char *adapter_name;
+-};
+-
+-struct aice_port_s {
+- /** */
+- uint32_t coreid;
+- /** */
+- const struct aice_port *port;
+-};
+-
+-/** */
+-extern struct aice_port_api_s aice_usb_layout_api;
+-
+-/** */
+-struct aice_port_api_s {
+- /** */
+- int (*open)(struct aice_port_param_s *param);
+- /** */
+- int (*close)(void);
+- /** */
+- int (*reset)(void);
+- /** */
+- int (*idcode)(uint32_t *idcode, uint8_t *num_of_idcode);
+- /** */
+- int (*set_jtag_clock)(uint32_t a_clock);
+- /** */
+- int (*assert_srst)(uint32_t coreid, enum aice_srst_type_s srst);
+- /** */
+- int (*run)(uint32_t coreid);
+- /** */
+- int (*halt)(uint32_t coreid);
+- /** */
+- int (*step)(uint32_t coreid);
+- /** */
+- int (*read_reg)(uint32_t coreid, uint32_t num, uint32_t *val);
+- /** */
+- int (*write_reg)(uint32_t coreid, uint32_t num, uint32_t val);
+- /** */
+- int (*read_reg_64)(uint32_t coreid, uint32_t num, uint64_t *val);
+- /** */
+- int (*write_reg_64)(uint32_t coreid, uint32_t num, uint64_t val);
+- /** */
+- int (*read_mem_unit)(uint32_t coreid, uint32_t addr, uint32_t size,
+- uint32_t count, uint8_t *buffer);
+- /** */
+- int (*write_mem_unit)(uint32_t coreid, uint32_t addr, uint32_t size,
+- uint32_t count, const uint8_t *buffer);
+- /** */
+- int (*read_mem_bulk)(uint32_t coreid, uint32_t addr, uint32_t length,
+- uint8_t *buffer);
+- /** */
+- int (*write_mem_bulk)(uint32_t coreid, uint32_t addr, uint32_t length,
+- const uint8_t *buffer);
+- /** */
+- int (*read_debug_reg)(uint32_t coreid, uint32_t addr, uint32_t *val);
+- /** */
+- int (*write_debug_reg)(uint32_t coreid, uint32_t addr, const uint32_t val);
+-
+- /** */
+- int (*state)(uint32_t coreid, enum aice_target_state_s *state);
+-
+- /** */
+- int (*memory_access)(uint32_t coreid, enum nds_memory_access a_access);
+- /** */
+- int (*memory_mode)(uint32_t coreid, enum nds_memory_select mem_select);
+-
+- /** */
+- int (*read_tlb)(uint32_t coreid, target_addr_t virtual_address, target_addr_t *physical_address);
+-
+- /** */
+- int (*cache_ctl)(uint32_t coreid, uint32_t subtype, uint32_t address);
+-
+- /** */
+- int (*set_retry_times)(uint32_t a_retry_times);
+-
+- /** */
+- int (*program_edm)(uint32_t coreid, char *command_sequence);
+-
+- /** */
+- int (*set_command_mode)(enum aice_command_mode command_mode);
+-
+- /** */
+- int (*execute)(uint32_t coreid, uint32_t *instructions, uint32_t instruction_num);
+-
+- /** */
+- int (*set_custom_srst_script)(const char *script);
+-
+- /** */
+- int (*set_custom_trst_script)(const char *script);
+-
+- /** */
+- int (*set_custom_restart_script)(const char *script);
+-
+- /** */
+- int (*set_count_to_check_dbger)(uint32_t count_to_check);
+-
+- /** */
+- int (*set_data_endian)(uint32_t coreid, enum aice_target_endian target_data_endian);
+-
+- /** */
+- int (*profiling)(uint32_t coreid, uint32_t interval, uint32_t iteration,
+- uint32_t reg_no, uint32_t *samples, uint32_t *num_samples);
+-};
+-
+-#define AICE_PORT_UNKNOWN 0
+-#define AICE_PORT_AICE_USB 1
+-#define AICE_PORT_AICE_PIPE 2
+-
+-/** */
+-struct aice_port {
+- /** */
+- const char *name;
+- /** */
+- int type;
+- /** */
+- struct aice_port_api_s *const api;
+-};
+-
+-/** */
+-const struct aice_port *aice_port_get_list(void);
+-
+-#endif /* OPENOCD_JTAG_AICE_AICE_PORT_H */
+diff --git a/src/jtag/aice/aice_transport.c b/src/jtag/aice/aice_transport.c
+deleted file mode 100644
+index 49f899ddc..000000000
+--- a/src/jtag/aice/aice_transport.c
++++ /dev/null
+@@ -1,432 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-/* project specific includes */
+-#include <jtag/interface.h>
+-#include <jtag/tcl.h>
+-#include <transport/transport.h>
+-#include <target/target.h>
+-#include <jtag/aice/aice_interface.h>
+-#include <jtag/aice/aice_transport.h>
+-#include <string.h>
+-
+-/* */
+-static int jim_newtap_expected_id(struct jim_nvp *n, struct jim_getopt_info *goi,
+- struct jtag_tap *tap)
+-{
+- jim_wide w;
+- int e = jim_getopt_wide(goi, &w);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi->interp, "option: %s bad parameter",
+- n->name);
+- return e;
+- }
+-
+- unsigned expected_len = sizeof(uint32_t) * tap->expected_ids_cnt;
+- uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t));
+- if (!new_expected_ids) {
+- Jim_SetResultFormatted(goi->interp, "no memory");
+- return JIM_ERR;
+- }
+-
+- assert(tap->expected_ids);
+- memcpy(new_expected_ids, tap->expected_ids, expected_len);
+-
+- new_expected_ids[tap->expected_ids_cnt] = w;
+-
+- free(tap->expected_ids);
+- tap->expected_ids = new_expected_ids;
+- tap->expected_ids_cnt++;
+-
+- return JIM_OK;
+-}
+-
+-#define NTAP_OPT_EXPECTED_ID 0
+-
+-/* */
+-static int jim_aice_newtap_cmd(struct jim_getopt_info *goi)
+-{
+- struct jtag_tap *tap;
+- int x;
+- int e;
+- struct jim_nvp *n;
+- char *cp;
+- const struct jim_nvp opts[] = {
+- {.name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID},
+- {.name = NULL, .value = -1},
+- };
+-
+- tap = calloc(1, sizeof(struct jtag_tap));
+- if (!tap) {
+- Jim_SetResultFormatted(goi->interp, "no memory");
+- return JIM_ERR;
+- }
+-
+- /*
+- * we expect CHIP + TAP + OPTIONS
+- * */
+- if (goi->argc < 3) {
+- Jim_SetResultFormatted(goi->interp,
+- "Missing CHIP TAP OPTIONS ....");
+- free(tap);
+- return JIM_ERR;
+- }
+-
+- const char *tmp;
+- jim_getopt_string(goi, &tmp, NULL);
+- tap->chip = strdup(tmp);
+-
+- jim_getopt_string(goi, &tmp, NULL);
+- tap->tapname = strdup(tmp);
+-
+- /* name + dot + name + null */
+- x = strlen(tap->chip) + 1 + strlen(tap->tapname) + 1;
+- cp = malloc(x);
+- sprintf(cp, "%s.%s", tap->chip, tap->tapname);
+- tap->dotted_name = cp;
+-
+- LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
+- tap->chip, tap->tapname, tap->dotted_name, goi->argc);
+-
+- while (goi->argc) {
+- e = jim_getopt_nvp(goi, opts, &n);
+- if (e != JIM_OK) {
+- jim_getopt_nvp_unknown(goi, opts, 0);
+- free(cp);
+- free(tap);
+- return e;
+- }
+- LOG_DEBUG("Processing option: %s", n->name);
+- switch (n->value) {
+- case NTAP_OPT_EXPECTED_ID:
+- e = jim_newtap_expected_id(n, goi, tap);
+- if (e != JIM_OK) {
+- free(cp);
+- free(tap);
+- return e;
+- }
+- break;
+- } /* switch (n->value) */
+- } /* while (goi->argc) */
+-
+- /* default is enabled-after-reset */
+- tap->enabled = !tap->disabled_after_reset;
+-
+- jtag_tap_init(tap);
+- return JIM_OK;
+-}
+-
+-/* */
+-static int jim_aice_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+- return jim_aice_newtap_cmd(&goi);
+-}
+-
+-/* */
+-COMMAND_HANDLER(handle_aice_init_command)
+-{
+- if (CMD_ARGC != 0)
+- return ERROR_COMMAND_SYNTAX_ERROR;
+-
+- static bool jtag_initialized;
+- if (jtag_initialized) {
+- LOG_INFO("'jtag init' has already been called");
+- return ERROR_OK;
+- }
+- jtag_initialized = true;
+-
+- LOG_DEBUG("Initializing jtag devices...");
+- return jtag_init(CMD_CTX);
+-}
+-
+-COMMAND_HANDLER(handle_scan_chain_command)
+-{
+- struct jtag_tap *tap;
+- char expected_id[12];
+-
+- aice_scan_jtag_chain();
+- tap = jtag_all_taps();
+- command_print(CMD,
+- " TapName Enabled IdCode Expected IrLen IrCap IrMask");
+- command_print(CMD,
+- "-- ------------------- -------- ---------- ---------- ----- ----- ------");
+-
+- while (tap) {
+- uint32_t expected, expected_mask, ii;
+-
+- snprintf(expected_id, sizeof(expected_id), "0x%08x",
+- (unsigned)((tap->expected_ids_cnt > 0)
+- ? tap->expected_ids[0]
+- : 0));
+- if (tap->ignore_version)
+- expected_id[2] = '*';
+-
+- expected = buf_get_u32(tap->expected, 0, tap->ir_length);
+- expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
+-
+- command_print(CMD,
+- "%2d %-18s %c 0x%08x %s %5d 0x%02x 0x%02x",
+- tap->abs_chain_position,
+- tap->dotted_name,
+- tap->enabled ? 'Y' : 'n',
+- (unsigned int)(tap->idcode),
+- expected_id,
+- (unsigned int)(tap->ir_length),
+- (unsigned int)(expected),
+- (unsigned int)(expected_mask));
+-
+- for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
+- snprintf(expected_id, sizeof(expected_id), "0x%08x",
+- (unsigned) tap->expected_ids[ii]);
+- if (tap->ignore_version)
+- expected_id[2] = '*';
+-
+- command_print(CMD,
+- " %s",
+- expected_id);
+- }
+-
+- tap = tap->next_tap;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int jim_aice_arp_init(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- LOG_DEBUG("No implement: jim_aice_arp_init");
+-
+- return JIM_OK;
+-}
+-
+-/* */
+-static int aice_init_reset(struct command_context *cmd_ctx)
+-{
+- LOG_DEBUG("Initializing with hard TRST+SRST reset");
+-
+- int retval;
+- enum reset_types jtag_reset_config = jtag_get_reset_config();
+-
+- jtag_add_reset(1, 0); /* TAP_RESET */
+- if (jtag_reset_config & RESET_HAS_SRST) {
+- jtag_add_reset(1, 1);
+- if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
+- jtag_add_reset(0, 1);
+- }
+- jtag_add_reset(0, 0);
+- retval = jtag_execute_queue();
+- if (retval != ERROR_OK)
+- return retval;
+-
+- return ERROR_OK;
+-}
+-
+-/* */
+-static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- int e = ERROR_OK;
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+- if (goi.argc != 0) {
+- Jim_WrongNumArgs(goi.interp, 1, goi.argv - 1, "(no params)");
+- return JIM_ERR;
+- }
+- struct command_context *context = current_command_context(interp);
+- e = aice_init_reset(context);
+-
+- if (e != ERROR_OK) {
+- Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
+- Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
+- return JIM_ERR;
+- }
+- return JIM_OK;
+-}
+-
+-static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+-{
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+- if (goi.argc != 0) {
+- Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
+- return JIM_ERR;
+- }
+- Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
+- struct jtag_tap *tap;
+-
+- for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
+- Jim_ListAppendElement(goi.interp,
+- Jim_GetResult(goi.interp),
+- Jim_NewStringObj(goi.interp,
+- tap->dotted_name, -1));
+-
+- return JIM_OK;
+-}
+-
+-/* */
+-static const struct command_registration aice_transport_jtag_subcommand_handlers[] = {
+- {
+- .name = "init",
+- .mode = COMMAND_ANY,
+- .handler = handle_aice_init_command,
+- .help = "initialize jtag scan chain",
+- .usage = ""
+- },
+- {
+- .name = "arp_init",
+- .mode = COMMAND_ANY,
+- .jim_handler = jim_aice_arp_init,
+- .help = "Validates JTAG scan chain against the list of "
+- "declared TAPs.",
+- },
+- {
+- .name = "arp_init-reset",
+- .mode = COMMAND_ANY,
+- .jim_handler = jim_aice_arp_init_reset,
+- .help = "Uses TRST and SRST to try resetting everything on "
+- "the JTAG scan chain, then performs 'jtag arp_init'."
+- },
+- {
+- .name = "newtap",
+- .mode = COMMAND_CONFIG,
+- .jim_handler = jim_aice_newtap,
+- .help = "Create a new TAP instance named basename.tap_type, "
+- "and appends it to the scan chain.",
+- .usage = "basename tap_type ['-expected_id' number]"
+- },
+- {
+- .name = "tapisenabled",
+- .mode = COMMAND_EXEC,
+- .jim_handler = jim_jtag_tap_enabler,
+- .help = "Returns a Tcl boolean (0/1) indicating whether "
+- "the TAP is enabled (1) or not (0).",
+- .usage = "tap_name",
+- },
+- {
+- .name = "tapenable",
+- .mode = COMMAND_EXEC,
+- .jim_handler = jim_jtag_tap_enabler,
+- .help = "Try to enable the specified TAP using the "
+- "'tap-enable' TAP event.",
+- .usage = "tap_name",
+- },
+- {
+- .name = "tapdisable",
+- .mode = COMMAND_EXEC,
+- .jim_handler = jim_jtag_tap_enabler,
+- .help = "Try to disable the specified TAP using the "
+- "'tap-disable' TAP event.",
+- .usage = "tap_name",
+- },
+- {
+- .name = "configure",
+- .mode = COMMAND_ANY,
+- .jim_handler = jim_jtag_configure,
+- .help = "Provide a Tcl handler for the specified "
+- "TAP event.",
+- .usage = "tap_name '-event' event_name handler",
+- },
+- {
+- .name = "cget",
+- .mode = COMMAND_EXEC,
+- .jim_handler = jim_jtag_configure,
+- .help = "Return any Tcl handler for the specified "
+- "TAP event.",
+- .usage = "tap_name '-event' event_name",
+- },
+- {
+- .name = "names",
+- .mode = COMMAND_ANY,
+- .jim_handler = jim_aice_names,
+- .help = "Returns list of all JTAG tap names.",
+- },
+- {
+- .name = "scan_chain",
+- .handler = handle_scan_chain_command,
+- .mode = COMMAND_ANY,
+- .help = "print current scan chain configuration",
+- .usage = ""
+- },
+-
+- COMMAND_REGISTRATION_DONE
+-};
+-
+-/* */
+-static const struct command_registration aice_transport_command_handlers[] = {
+- {
+- .name = "jtag",
+- .mode = COMMAND_ANY,
+- .usage = "",
+- .chain = aice_transport_jtag_subcommand_handlers,
+- },
+- COMMAND_REGISTRATION_DONE
+-
+-};
+-
+-/* */
+-static int aice_transport_register_commands(struct command_context *cmd_ctx)
+-{
+- return register_commands(cmd_ctx, NULL, aice_transport_command_handlers);
+-}
+-
+-/* */
+-static int aice_transport_init(struct command_context *cmd_ctx)
+-{
+- LOG_DEBUG("aice_transport_init");
+- struct target *t = get_current_target(cmd_ctx);
+- struct transport *transport;
+-
+- if (!t) {
+- LOG_ERROR("no current target");
+- return ERROR_FAIL;
+- }
+-
+- transport = get_current_transport();
+-
+- if (!transport) {
+- LOG_ERROR("no transport selected");
+- return ERROR_FAIL;
+- }
+-
+- LOG_DEBUG("current transport %s", transport->name);
+-
+- return aice_init_targets();
+-}
+-
+-/* */
+-static int aice_transport_select(struct command_context *ctx)
+-{
+- LOG_DEBUG("aice_transport_select");
+-
+- int retval;
+-
+- retval = aice_transport_register_commands(ctx);
+-
+- if (retval != ERROR_OK)
+- return retval;
+-
+- return ERROR_OK;
+-}
+-
+-static struct transport aice_jtag_transport = {
+- .name = "aice_jtag",
+- .select = aice_transport_select,
+- .init = aice_transport_init,
+-};
+-
+-const char *aice_transports[] = { "aice_jtag", NULL };
+-
+-static void aice_constructor(void) __attribute__((constructor));
+-static void aice_constructor(void)
+-{
+- transport_register(&aice_jtag_transport);
+-}
+diff --git a/src/jtag/aice/aice_transport.h b/src/jtag/aice/aice_transport.h
+deleted file mode 100644
+index b00003198..000000000
+--- a/src/jtag/aice/aice_transport.h
++++ /dev/null
+@@ -1,13 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_JTAG_AICE_AICE_TRANSPORT_H
+-#define OPENOCD_JTAG_AICE_AICE_TRANSPORT_H
+-
+-extern const char *aice_transports[];
+-
+-#endif /* OPENOCD_JTAG_AICE_AICE_TRANSPORT_H */
+diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c
+deleted file mode 100644
+index b5d0f0b6e..000000000
+--- a/src/jtag/aice/aice_usb.c
++++ /dev/null
+@@ -1,4099 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <helper/system.h>
+-#include <jtag/drivers/libusb_helper.h>
+-#include <helper/log.h>
+-#include <helper/time_support.h>
+-#include <target/target.h>
+-#include <jtag/jtag.h>
+-#include <target/nds32_insn.h>
+-#include <target/nds32_reg.h>
+-#include "aice_usb.h"
+-
+-
+-/* Global USB buffers */
+-static uint8_t usb_in_buffer[AICE_IN_BUFFER_SIZE];
+-static uint8_t usb_out_buffer[AICE_OUT_BUFFER_SIZE];
+-static uint32_t jtag_clock;
+-static struct aice_usb_handler_s aice_handler;
+-/* AICE max retry times. If AICE command timeout, retry it. */
+-static int aice_max_retry_times = 50;
+-/* Default endian is little endian. */
+-static enum aice_target_endian data_endian;
+-
+-/* Constants for AICE command format length */
+-#define AICE_FORMAT_HTDA (3)
+-#define AICE_FORMAT_HTDC (7)
+-#define AICE_FORMAT_HTDMA (4)
+-#define AICE_FORMAT_HTDMB (8)
+-#define AICE_FORMAT_HTDMC (8)
+-#define AICE_FORMAT_HTDMD (12)
+-#define AICE_FORMAT_DTHA (6)
+-#define AICE_FORMAT_DTHB (2)
+-#define AICE_FORMAT_DTHMA (8)
+-#define AICE_FORMAT_DTHMB (4)
+-
+-/* Constants for AICE command */
+-#define AICE_CMD_SCAN_CHAIN 0x00
+-#define AICE_CMD_T_READ_MISC 0x20
+-#define AICE_CMD_T_READ_EDMSR 0x21
+-#define AICE_CMD_T_READ_DTR 0x22
+-#define AICE_CMD_T_READ_MEM_B 0x24
+-#define AICE_CMD_T_READ_MEM_H 0x25
+-#define AICE_CMD_T_READ_MEM 0x26
+-#define AICE_CMD_T_FASTREAD_MEM 0x27
+-#define AICE_CMD_T_WRITE_MISC 0x28
+-#define AICE_CMD_T_WRITE_EDMSR 0x29
+-#define AICE_CMD_T_WRITE_DTR 0x2A
+-#define AICE_CMD_T_WRITE_DIM 0x2B
+-#define AICE_CMD_T_WRITE_MEM_B 0x2C
+-#define AICE_CMD_T_WRITE_MEM_H 0x2D
+-#define AICE_CMD_T_WRITE_MEM 0x2E
+-#define AICE_CMD_T_FASTWRITE_MEM 0x2F
+-#define AICE_CMD_T_EXECUTE 0x3E
+-#define AICE_CMD_READ_CTRL 0x50
+-#define AICE_CMD_WRITE_CTRL 0x51
+-#define AICE_CMD_BATCH_BUFFER_READ 0x60
+-#define AICE_CMD_READ_DTR_TO_BUFFER 0x61
+-#define AICE_CMD_BATCH_BUFFER_WRITE 0x68
+-#define AICE_CMD_WRITE_DTR_FROM_BUFFER 0x69
+-
+-/***************************************************************************/
+-/* AICE commands' pack/unpack functions */
+-static void aice_pack_htda(uint8_t cmd_code, uint8_t extra_word_length,
+- uint32_t address)
+-{
+- usb_out_buffer[0] = cmd_code;
+- usb_out_buffer[1] = extra_word_length;
+- usb_out_buffer[2] = (uint8_t)(address & 0xFF);
+-}
+-
+-static void aice_pack_htdc(uint8_t cmd_code, uint8_t extra_word_length,
+- uint32_t address, uint32_t word, enum aice_target_endian access_endian)
+-{
+- usb_out_buffer[0] = cmd_code;
+- usb_out_buffer[1] = extra_word_length;
+- usb_out_buffer[2] = (uint8_t)(address & 0xFF);
+- if (access_endian == AICE_BIG_ENDIAN) {
+- usb_out_buffer[6] = (uint8_t)((word >> 24) & 0xFF);
+- usb_out_buffer[5] = (uint8_t)((word >> 16) & 0xFF);
+- usb_out_buffer[4] = (uint8_t)((word >> 8) & 0xFF);
+- usb_out_buffer[3] = (uint8_t)(word & 0xFF);
+- } else {
+- usb_out_buffer[3] = (uint8_t)((word >> 24) & 0xFF);
+- usb_out_buffer[4] = (uint8_t)((word >> 16) & 0xFF);
+- usb_out_buffer[5] = (uint8_t)((word >> 8) & 0xFF);
+- usb_out_buffer[6] = (uint8_t)(word & 0xFF);
+- }
+-}
+-
+-static void aice_pack_htdma(uint8_t cmd_code, uint8_t target_id,
+- uint8_t extra_word_length, uint32_t address)
+-{
+- usb_out_buffer[0] = cmd_code;
+- usb_out_buffer[1] = target_id;
+- usb_out_buffer[2] = extra_word_length;
+- usb_out_buffer[3] = (uint8_t)(address & 0xFF);
+-}
+-
+-static void aice_pack_htdmb(uint8_t cmd_code, uint8_t target_id,
+- uint8_t extra_word_length, uint32_t address)
+-{
+- usb_out_buffer[0] = cmd_code;
+- usb_out_buffer[1] = target_id;
+- usb_out_buffer[2] = extra_word_length;
+- usb_out_buffer[3] = 0;
+- usb_out_buffer[4] = (uint8_t)((address >> 24) & 0xFF);
+- usb_out_buffer[5] = (uint8_t)((address >> 16) & 0xFF);
+- usb_out_buffer[6] = (uint8_t)((address >> 8) & 0xFF);
+- usb_out_buffer[7] = (uint8_t)(address & 0xFF);
+-}
+-
+-static void aice_pack_htdmc(uint8_t cmd_code, uint8_t target_id,
+- uint8_t extra_word_length, uint32_t address, uint32_t word,
+- enum aice_target_endian access_endian)
+-{
+- usb_out_buffer[0] = cmd_code;
+- usb_out_buffer[1] = target_id;
+- usb_out_buffer[2] = extra_word_length;
+- usb_out_buffer[3] = (uint8_t)(address & 0xFF);
+- if (access_endian == AICE_BIG_ENDIAN) {
+- usb_out_buffer[7] = (uint8_t)((word >> 24) & 0xFF);
+- usb_out_buffer[6] = (uint8_t)((word >> 16) & 0xFF);
+- usb_out_buffer[5] = (uint8_t)((word >> 8) & 0xFF);
+- usb_out_buffer[4] = (uint8_t)(word & 0xFF);
+- } else {
+- usb_out_buffer[4] = (uint8_t)((word >> 24) & 0xFF);
+- usb_out_buffer[5] = (uint8_t)((word >> 16) & 0xFF);
+- usb_out_buffer[6] = (uint8_t)((word >> 8) & 0xFF);
+- usb_out_buffer[7] = (uint8_t)(word & 0xFF);
+- }
+-}
+-
+-static void aice_pack_htdmc_multiple_data(uint8_t cmd_code, uint8_t target_id,
+- uint8_t extra_word_length, uint32_t address, uint32_t *word,
+- uint8_t num_of_words, enum aice_target_endian access_endian)
+-{
+- usb_out_buffer[0] = cmd_code;
+- usb_out_buffer[1] = target_id;
+- usb_out_buffer[2] = extra_word_length;
+- usb_out_buffer[3] = (uint8_t)(address & 0xFF);
+-
+- uint8_t i;
+- for (i = 0 ; i < num_of_words ; i++, word++) {
+- if (access_endian == AICE_BIG_ENDIAN) {
+- usb_out_buffer[7 + i * 4] = (uint8_t)((*word >> 24) & 0xFF);
+- usb_out_buffer[6 + i * 4] = (uint8_t)((*word >> 16) & 0xFF);
+- usb_out_buffer[5 + i * 4] = (uint8_t)((*word >> 8) & 0xFF);
+- usb_out_buffer[4 + i * 4] = (uint8_t)(*word & 0xFF);
+- } else {
+- usb_out_buffer[4 + i * 4] = (uint8_t)((*word >> 24) & 0xFF);
+- usb_out_buffer[5 + i * 4] = (uint8_t)((*word >> 16) & 0xFF);
+- usb_out_buffer[6 + i * 4] = (uint8_t)((*word >> 8) & 0xFF);
+- usb_out_buffer[7 + i * 4] = (uint8_t)(*word & 0xFF);
+- }
+- }
+-}
+-
+-static void aice_pack_htdmd(uint8_t cmd_code, uint8_t target_id,
+- uint8_t extra_word_length, uint32_t address, uint32_t word,
+- enum aice_target_endian access_endian)
+-{
+- usb_out_buffer[0] = cmd_code;
+- usb_out_buffer[1] = target_id;
+- usb_out_buffer[2] = extra_word_length;
+- usb_out_buffer[3] = 0;
+- usb_out_buffer[4] = (uint8_t)((address >> 24) & 0xFF);
+- usb_out_buffer[5] = (uint8_t)((address >> 16) & 0xFF);
+- usb_out_buffer[6] = (uint8_t)((address >> 8) & 0xFF);
+- usb_out_buffer[7] = (uint8_t)(address & 0xFF);
+- if (access_endian == AICE_BIG_ENDIAN) {
+- usb_out_buffer[11] = (uint8_t)((word >> 24) & 0xFF);
+- usb_out_buffer[10] = (uint8_t)((word >> 16) & 0xFF);
+- usb_out_buffer[9] = (uint8_t)((word >> 8) & 0xFF);
+- usb_out_buffer[8] = (uint8_t)(word & 0xFF);
+- } else {
+- usb_out_buffer[8] = (uint8_t)((word >> 24) & 0xFF);
+- usb_out_buffer[9] = (uint8_t)((word >> 16) & 0xFF);
+- usb_out_buffer[10] = (uint8_t)((word >> 8) & 0xFF);
+- usb_out_buffer[11] = (uint8_t)(word & 0xFF);
+- }
+-}
+-
+-static void aice_pack_htdmd_multiple_data(uint8_t cmd_code, uint8_t target_id,
+- uint8_t extra_word_length, uint32_t address, const uint8_t *word,
+- enum aice_target_endian access_endian)
+-{
+- usb_out_buffer[0] = cmd_code;
+- usb_out_buffer[1] = target_id;
+- usb_out_buffer[2] = extra_word_length;
+- usb_out_buffer[3] = 0;
+- usb_out_buffer[4] = (uint8_t)((address >> 24) & 0xFF);
+- usb_out_buffer[5] = (uint8_t)((address >> 16) & 0xFF);
+- usb_out_buffer[6] = (uint8_t)((address >> 8) & 0xFF);
+- usb_out_buffer[7] = (uint8_t)(address & 0xFF);
+-
+- uint32_t i;
+- /* num_of_words may be over 0xFF, so use uint32_t */
+- uint32_t num_of_words = extra_word_length + 1;
+-
+- for (i = 0 ; i < num_of_words ; i++, word += 4) {
+- if (access_endian == AICE_BIG_ENDIAN) {
+- usb_out_buffer[11 + i * 4] = word[3];
+- usb_out_buffer[10 + i * 4] = word[2];
+- usb_out_buffer[9 + i * 4] = word[1];
+- usb_out_buffer[8 + i * 4] = word[0];
+- } else {
+- usb_out_buffer[8 + i * 4] = word[3];
+- usb_out_buffer[9 + i * 4] = word[2];
+- usb_out_buffer[10 + i * 4] = word[1];
+- usb_out_buffer[11 + i * 4] = word[0];
+- }
+- }
+-}
+-
+-static void aice_unpack_dtha(uint8_t *cmd_ack_code, uint8_t *extra_word_length,
+- uint32_t *word, enum aice_target_endian access_endian)
+-{
+- *cmd_ack_code = usb_in_buffer[0];
+- *extra_word_length = usb_in_buffer[1];
+-
+- if (access_endian == AICE_BIG_ENDIAN) {
+- *word = (usb_in_buffer[5] << 24) |
+- (usb_in_buffer[4] << 16) |
+- (usb_in_buffer[3] << 8) |
+- (usb_in_buffer[2]);
+- } else {
+- *word = (usb_in_buffer[2] << 24) |
+- (usb_in_buffer[3] << 16) |
+- (usb_in_buffer[4] << 8) |
+- (usb_in_buffer[5]);
+- }
+-}
+-
+-static void aice_unpack_dtha_multiple_data(uint8_t *cmd_ack_code,
+- uint8_t *extra_word_length, uint32_t *word, uint8_t num_of_words,
+- enum aice_target_endian access_endian)
+-{
+- *cmd_ack_code = usb_in_buffer[0];
+- *extra_word_length = usb_in_buffer[1];
+-
+- uint8_t i;
+- for (i = 0 ; i < num_of_words ; i++, word++) {
+- if (access_endian == AICE_BIG_ENDIAN) {
+- *word = (usb_in_buffer[5 + i * 4] << 24) |
+- (usb_in_buffer[4 + i * 4] << 16) |
+- (usb_in_buffer[3 + i * 4] << 8) |
+- (usb_in_buffer[2 + i * 4]);
+- } else {
+- *word = (usb_in_buffer[2 + i * 4] << 24) |
+- (usb_in_buffer[3 + i * 4] << 16) |
+- (usb_in_buffer[4 + i * 4] << 8) |
+- (usb_in_buffer[5 + i * 4]);
+- }
+- }
+-}
+-
+-static void aice_unpack_dthb(uint8_t *cmd_ack_code, uint8_t *extra_word_length)
+-{
+- *cmd_ack_code = usb_in_buffer[0];
+- *extra_word_length = usb_in_buffer[1];
+-}
+-
+-static void aice_unpack_dthma(uint8_t *cmd_ack_code, uint8_t *target_id,
+- uint8_t *extra_word_length, uint32_t *word,
+- enum aice_target_endian access_endian)
+-{
+- *cmd_ack_code = usb_in_buffer[0];
+- *target_id = usb_in_buffer[1];
+- *extra_word_length = usb_in_buffer[2];
+- if (access_endian == AICE_BIG_ENDIAN) {
+- *word = (usb_in_buffer[7] << 24) |
+- (usb_in_buffer[6] << 16) |
+- (usb_in_buffer[5] << 8) |
+- (usb_in_buffer[4]);
+- } else {
+- *word = (usb_in_buffer[4] << 24) |
+- (usb_in_buffer[5] << 16) |
+- (usb_in_buffer[6] << 8) |
+- (usb_in_buffer[7]);
+- }
+-}
+-
+-static void aice_unpack_dthma_multiple_data(uint8_t *cmd_ack_code,
+- uint8_t *target_id, uint8_t *extra_word_length, uint8_t *word,
+- enum aice_target_endian access_endian)
+-{
+- *cmd_ack_code = usb_in_buffer[0];
+- *target_id = usb_in_buffer[1];
+- *extra_word_length = usb_in_buffer[2];
+- if (access_endian == AICE_BIG_ENDIAN) {
+- word[0] = usb_in_buffer[4];
+- word[1] = usb_in_buffer[5];
+- word[2] = usb_in_buffer[6];
+- word[3] = usb_in_buffer[7];
+- } else {
+- word[0] = usb_in_buffer[7];
+- word[1] = usb_in_buffer[6];
+- word[2] = usb_in_buffer[5];
+- word[3] = usb_in_buffer[4];
+- }
+- word += 4;
+-
+- uint8_t i;
+- for (i = 0; i < *extra_word_length; i++) {
+- if (access_endian == AICE_BIG_ENDIAN) {
+- word[0] = usb_in_buffer[8 + i * 4];
+- word[1] = usb_in_buffer[9 + i * 4];
+- word[2] = usb_in_buffer[10 + i * 4];
+- word[3] = usb_in_buffer[11 + i * 4];
+- } else {
+- word[0] = usb_in_buffer[11 + i * 4];
+- word[1] = usb_in_buffer[10 + i * 4];
+- word[2] = usb_in_buffer[9 + i * 4];
+- word[3] = usb_in_buffer[8 + i * 4];
+- }
+- word += 4;
+- }
+-}
+-
+-static void aice_unpack_dthmb(uint8_t *cmd_ack_code, uint8_t *target_id,
+- uint8_t *extra_word_length)
+-{
+- *cmd_ack_code = usb_in_buffer[0];
+- *target_id = usb_in_buffer[1];
+- *extra_word_length = usb_in_buffer[2];
+-}
+-
+-/***************************************************************************/
+-/* End of AICE commands' pack/unpack functions */
+-
+-/* calls the given usb_bulk_* function, allowing for the data to
+- * trickle in with some timeouts */
+-static int usb_bulk_with_retries(
+- int (*f)(struct libusb_device_handle *, int, char *, int, int, int *),
+- struct libusb_device_handle *dev, int ep,
+- char *bytes, int size, int timeout, int *transferred)
+-{
+- int tries = 3, count = 0;
+-
+- while (tries && (count < size)) {
+- int result, ret;
+-
+- ret = f(dev, ep, bytes + count, size - count, timeout, &result);
+- if (ret == ERROR_OK)
+- count += result;
+- else if ((ret != ERROR_TIMEOUT_REACHED) || !--tries)
+- return ret;
+- }
+-
+- *transferred = count;
+- return ERROR_OK;
+-}
+-
+-static int wrap_usb_bulk_write(struct libusb_device_handle *dev, int ep,
+- char *buff, int size, int timeout, int *transferred)
+-{
+-
+- /* usb_bulk_write() takes const char *buff */
+- jtag_libusb_bulk_write(dev, ep, buff, size, timeout, transferred);
+-
+- return 0;
+-}
+-
+-static inline int usb_bulk_write_ex(struct libusb_device_handle *dev, int ep,
+- char *bytes, int size, int timeout)
+-{
+- int tr = 0;
+-
+- usb_bulk_with_retries(&wrap_usb_bulk_write,
+- dev, ep, bytes, size, timeout, &tr);
+- return tr;
+-}
+-
+-static inline int usb_bulk_read_ex(struct libusb_device_handle *dev, int ep,
+- char *bytes, int size, int timeout)
+-{
+- int tr = 0;
+- usb_bulk_with_retries(&jtag_libusb_bulk_read,
+- dev, ep, bytes, size, timeout, &tr);
+- return tr;
+-}
+-
+-/* Write data from out_buffer to USB. */
+-static int aice_usb_write(uint8_t *out_buffer, int out_length)
+-{
+- int result;
+-
+- if (out_length > AICE_OUT_BUFFER_SIZE) {
+- LOG_ERROR("aice_write illegal out_length=%i (max=%i)",
+- out_length, AICE_OUT_BUFFER_SIZE);
+- return -1;
+- }
+-
+- result = usb_bulk_write_ex(aice_handler.usb_handle, aice_handler.usb_write_ep,
+- (char *)out_buffer, out_length, AICE_USB_TIMEOUT);
+-
+- LOG_DEBUG_IO("aice_usb_write, out_length = %i, result = %i",
+- out_length, result);
+-
+- return result;
+-}
+-
+-/* Read data from USB into in_buffer. */
+-static int aice_usb_read(uint8_t *in_buffer, int expected_size)
+-{
+- int result = usb_bulk_read_ex(aice_handler.usb_handle, aice_handler.usb_read_ep,
+- (char *)in_buffer, expected_size, AICE_USB_TIMEOUT);
+-
+- LOG_DEBUG_IO("aice_usb_read, result = %d", result);
+-
+- return result;
+-}
+-
+-static uint8_t usb_out_packets_buffer[AICE_OUT_PACKETS_BUFFER_SIZE];
+-static uint8_t usb_in_packets_buffer[AICE_IN_PACKETS_BUFFER_SIZE];
+-static uint32_t usb_out_packets_buffer_length;
+-static uint32_t usb_in_packets_buffer_length;
+-static enum aice_command_mode aice_command_mode;
+-
+-static int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word,
+- uint32_t num_of_words);
+-
+-static int aice_usb_packet_flush(void)
+-{
+- if (usb_out_packets_buffer_length == 0)
+- return 0;
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- LOG_DEBUG("Flush usb packets (AICE_COMMAND_MODE_PACK)");
+-
+- if (aice_usb_write(usb_out_packets_buffer,
+- usb_out_packets_buffer_length) < 0)
+- return ERROR_FAIL;
+-
+- if (aice_usb_read(usb_in_packets_buffer,
+- usb_in_packets_buffer_length) < 0)
+- return ERROR_FAIL;
+-
+- usb_out_packets_buffer_length = 0;
+- usb_in_packets_buffer_length = 0;
+-
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- LOG_DEBUG("Flush usb packets (AICE_COMMAND_MODE_BATCH)");
+-
+- /* use BATCH_BUFFER_WRITE to fill command-batch-buffer */
+- if (aice_batch_buffer_write(AICE_BATCH_COMMAND_BUFFER_0,
+- usb_out_packets_buffer,
+- (usb_out_packets_buffer_length + 3) / 4) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- usb_out_packets_buffer_length = 0;
+- usb_in_packets_buffer_length = 0;
+-
+- /* enable BATCH command */
+- aice_command_mode = AICE_COMMAND_MODE_NORMAL;
+- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CTRL, 0x80000000) != ERROR_OK)
+- return ERROR_FAIL;
+- aice_command_mode = AICE_COMMAND_MODE_BATCH;
+-
+- /* wait 1 second (AICE bug, workaround) */
+- alive_sleep(1000);
+-
+- /* check status */
+- uint32_t i;
+- uint32_t batch_status;
+-
+- i = 0;
+- while (1) {
+- int retval = aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
+- if (retval != ERROR_OK)
+- return retval;
+-
+- if (batch_status & 0x1)
+- return ERROR_OK;
+- else if (batch_status & 0xE)
+- return ERROR_FAIL;
+-
+- if ((i % 30) == 0)
+- keep_alive();
+-
+- i++;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_packet_append(uint8_t *out_buffer, int out_length, int in_length)
+-{
+- uint32_t max_packet_size = AICE_OUT_PACKETS_BUFFER_SIZE;
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- max_packet_size = AICE_OUT_PACK_COMMAND_SIZE;
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- max_packet_size = AICE_OUT_BATCH_COMMAND_SIZE;
+- } else {
+- /* AICE_COMMAND_MODE_NORMAL */
+- if (aice_usb_packet_flush() != ERROR_OK)
+- return ERROR_FAIL;
+- }
+-
+- if (usb_out_packets_buffer_length + out_length > max_packet_size)
+- if (aice_usb_packet_flush() != ERROR_OK) {
+- LOG_DEBUG("Flush usb packets failed");
+- return ERROR_FAIL;
+- }
+-
+- LOG_DEBUG("Append usb packets 0x%02x", out_buffer[0]);
+-
+- memcpy(usb_out_packets_buffer + usb_out_packets_buffer_length, out_buffer, out_length);
+- usb_out_packets_buffer_length += out_length;
+- usb_in_packets_buffer_length += in_length;
+-
+- return ERROR_OK;
+-}
+-
+-/***************************************************************************/
+-/* AICE commands */
+-static int aice_reset_box(void)
+-{
+- if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /* turn off FASTMODE */
+- uint32_t pin_status;
+- if (aice_read_ctrl(AICE_READ_CTRL_GET_JTAG_PIN_STATUS, &pin_status)
+- != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status & (~0x2))
+- != ERROR_OK)
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_scan_chain(uint32_t *id_codes, uint8_t *num_of_ids)
+-{
+- int retry_times = 0;
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH))
+- aice_usb_packet_flush();
+-
+- do {
+- aice_pack_htda(AICE_CMD_SCAN_CHAIN, 0x0F, 0x0);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDA);
+-
+- LOG_DEBUG("SCAN_CHAIN, length: 0x0F");
+-
+- /** TODO: modify receive length */
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHA);
+- if (result != AICE_FORMAT_DTHA) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHA, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- aice_unpack_dtha_multiple_data(&cmd_ack_code, num_of_ids, id_codes,
+- 0x10, AICE_LITTLE_ENDIAN);
+-
+- if (cmd_ack_code != AICE_CMD_SCAN_CHAIN) {
+-
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_SCAN_CHAIN, cmd_ack_code);
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- continue;
+- }
+-
+- LOG_DEBUG("SCAN_CHAIN response, # of IDs: %" PRIu8, *num_of_ids);
+-
+- if (*num_of_ids == 0xFF) {
+- LOG_ERROR("No target connected");
+- return ERROR_FAIL;
+- } else if (*num_of_ids == AICE_MAX_NUM_CORE) {
+- LOG_INFO("The ice chain over 16 targets");
+- } else {
+- (*num_of_ids)++;
+- }
+- break;
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-int aice_read_ctrl(uint32_t address, uint32_t *data)
+-{
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH))
+- aice_usb_packet_flush();
+-
+- aice_pack_htda(AICE_CMD_READ_CTRL, 0, address);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDA);
+-
+- LOG_DEBUG("READ_CTRL, address: 0x%" PRIx32, address);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHA);
+- if (result != AICE_FORMAT_DTHA) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHA, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- aice_unpack_dtha(&cmd_ack_code, &extra_length, data, AICE_LITTLE_ENDIAN);
+-
+- LOG_DEBUG("READ_CTRL response, data: 0x%" PRIx32, *data);
+-
+- if (cmd_ack_code != AICE_CMD_READ_CTRL) {
+- LOG_ERROR("aice command error (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_READ_CTRL, cmd_ack_code);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int aice_write_ctrl(uint32_t address, uint32_t data)
+-{
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- aice_usb_packet_flush();
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- aice_pack_htdc(AICE_CMD_WRITE_CTRL, 0, address, data, AICE_LITTLE_ENDIAN);
+- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDC,
+- AICE_FORMAT_DTHB);
+- }
+-
+- aice_pack_htdc(AICE_CMD_WRITE_CTRL, 0, address, data, AICE_LITTLE_ENDIAN);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDC);
+-
+- LOG_DEBUG("WRITE_CTRL, address: 0x%" PRIx32 ", data: 0x%" PRIx32, address, data);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHB);
+- if (result != AICE_FORMAT_DTHB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- aice_unpack_dthb(&cmd_ack_code, &extra_length);
+-
+- LOG_DEBUG("WRITE_CTRL response");
+-
+- if (cmd_ack_code != AICE_CMD_WRITE_CTRL) {
+- LOG_ERROR("aice command error (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_WRITE_CTRL, cmd_ack_code);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_read_dtr(uint8_t target_id, uint32_t *data)
+-{
+- int retry_times = 0;
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH))
+- aice_usb_packet_flush();
+-
+- do {
+- aice_pack_htdma(AICE_CMD_T_READ_DTR, target_id, 0, 0);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
+-
+- LOG_DEBUG("READ_DTR, COREID: %" PRIu8, target_id);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
+- if (result != AICE_FORMAT_DTHMA) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMA, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
+- data, AICE_LITTLE_ENDIAN);
+-
+- if (cmd_ack_code == AICE_CMD_T_READ_DTR) {
+- LOG_DEBUG("READ_DTR response, data: 0x%" PRIx32, *data);
+- break;
+- } else {
+-
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_READ_DTR, cmd_ack_code);
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_read_dtr_to_buffer(uint8_t target_id, uint32_t buffer_idx)
+-{
+- int retry_times = 0;
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- aice_usb_packet_flush();
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- aice_pack_htdma(AICE_CMD_READ_DTR_TO_BUFFER, target_id, 0, buffer_idx);
+- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMA,
+- AICE_FORMAT_DTHMB);
+- }
+-
+- do {
+- aice_pack_htdma(AICE_CMD_READ_DTR_TO_BUFFER, target_id, 0, buffer_idx);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
+-
+- LOG_DEBUG("READ_DTR_TO_BUFFER, COREID: %" PRIu8, target_id);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)", AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_READ_DTR_TO_BUFFER) {
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_READ_DTR_TO_BUFFER, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_write_dtr(uint8_t target_id, uint32_t data)
+-{
+- int retry_times = 0;
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- aice_usb_packet_flush();
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- aice_pack_htdmc(AICE_CMD_T_WRITE_DTR, target_id, 0, 0, data, AICE_LITTLE_ENDIAN);
+- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC,
+- AICE_FORMAT_DTHMB);
+- }
+-
+- do {
+- aice_pack_htdmc(AICE_CMD_T_WRITE_DTR, target_id, 0, 0, data, AICE_LITTLE_ENDIAN);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
+-
+- LOG_DEBUG("WRITE_DTR, COREID: %" PRIu8 ", data: 0x%" PRIx32, target_id, data);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)", AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_T_WRITE_DTR) {
+- LOG_DEBUG("WRITE_DTR response");
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_WRITE_DTR, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_write_dtr_from_buffer(uint8_t target_id, uint32_t buffer_idx)
+-{
+- int retry_times = 0;
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- aice_usb_packet_flush();
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- aice_pack_htdma(AICE_CMD_WRITE_DTR_FROM_BUFFER, target_id, 0, buffer_idx);
+- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMA,
+- AICE_FORMAT_DTHMB);
+- }
+-
+- do {
+- aice_pack_htdma(AICE_CMD_WRITE_DTR_FROM_BUFFER, target_id, 0, buffer_idx);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
+-
+- LOG_DEBUG("WRITE_DTR_FROM_BUFFER, COREID: %" PRIu8 "", target_id);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)", AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_WRITE_DTR_FROM_BUFFER) {
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_WRITE_DTR_FROM_BUFFER, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_read_misc(uint8_t target_id, uint32_t address, uint32_t *data)
+-{
+- int retry_times = 0;
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH))
+- aice_usb_packet_flush();
+-
+- do {
+- aice_pack_htdma(AICE_CMD_T_READ_MISC, target_id, 0, address);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
+-
+- LOG_DEBUG("READ_MISC, COREID: %" PRIu8 ", address: 0x%" PRIx32, target_id, address);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
+- if (result != AICE_FORMAT_DTHMA) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMA, result);
+- return ERROR_AICE_DISCONNECT;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
+- data, AICE_LITTLE_ENDIAN);
+-
+- if (cmd_ack_code == AICE_CMD_T_READ_MISC) {
+- LOG_DEBUG("READ_MISC response, data: 0x%" PRIx32, *data);
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_READ_MISC, cmd_ack_code);
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_write_misc(uint8_t target_id, uint32_t address, uint32_t data)
+-{
+- int retry_times = 0;
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- aice_usb_packet_flush();
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- aice_pack_htdmc(AICE_CMD_T_WRITE_MISC, target_id, 0, address, data,
+- AICE_LITTLE_ENDIAN);
+- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC,
+- AICE_FORMAT_DTHMB);
+- }
+-
+- do {
+- aice_pack_htdmc(AICE_CMD_T_WRITE_MISC, target_id, 0, address,
+- data, AICE_LITTLE_ENDIAN);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
+-
+- LOG_DEBUG("WRITE_MISC, COREID: %" PRIu8 ", address: 0x%" PRIx32 ", data: 0x%" PRIx32,
+- target_id, address, data);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_T_WRITE_MISC) {
+- LOG_DEBUG("WRITE_MISC response");
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_WRITE_MISC, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_read_edmsr(uint8_t target_id, uint32_t address, uint32_t *data)
+-{
+- int retry_times = 0;
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH))
+- aice_usb_packet_flush();
+-
+- do {
+- aice_pack_htdma(AICE_CMD_T_READ_EDMSR, target_id, 0, address);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
+-
+- LOG_DEBUG("READ_EDMSR, COREID: %" PRIu8 ", address: 0x%" PRIx32, target_id, address);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
+- if (result != AICE_FORMAT_DTHMA) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMA, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
+- data, AICE_LITTLE_ENDIAN);
+-
+- if (cmd_ack_code == AICE_CMD_T_READ_EDMSR) {
+- LOG_DEBUG("READ_EDMSR response, data: 0x%" PRIx32, *data);
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_READ_EDMSR, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_write_edmsr(uint8_t target_id, uint32_t address, uint32_t data)
+-{
+- int retry_times = 0;
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- aice_usb_packet_flush();
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- aice_pack_htdmc(AICE_CMD_T_WRITE_EDMSR, target_id, 0, address, data,
+- AICE_LITTLE_ENDIAN);
+- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC,
+- AICE_FORMAT_DTHMB);
+- }
+-
+- do {
+- aice_pack_htdmc(AICE_CMD_T_WRITE_EDMSR, target_id, 0, address,
+- data, AICE_LITTLE_ENDIAN);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
+-
+- LOG_DEBUG("WRITE_EDMSR, COREID: %" PRIu8 ", address: 0x%" PRIx32 ", data: 0x%" PRIx32,
+- target_id, address, data);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_T_WRITE_EDMSR) {
+- LOG_DEBUG("WRITE_EDMSR response");
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_WRITE_EDMSR, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_switch_to_big_endian(uint32_t *word, uint8_t num_of_words)
+-{
+- uint32_t tmp;
+-
+- for (uint8_t i = 0 ; i < num_of_words ; i++) {
+- tmp = ((word[i] >> 24) & 0x000000FF) |
+- ((word[i] >> 8) & 0x0000FF00) |
+- ((word[i] << 8) & 0x00FF0000) |
+- ((word[i] << 24) & 0xFF000000);
+- word[i] = tmp;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_write_dim(uint8_t target_id, uint32_t *word, uint8_t num_of_words)
+-{
+- uint32_t big_endian_word[4];
+- int retry_times = 0;
+-
+- /** instruction is big-endian */
+- memcpy(big_endian_word, word, sizeof(big_endian_word));
+- aice_switch_to_big_endian(big_endian_word, num_of_words);
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- aice_usb_packet_flush();
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- aice_pack_htdmc_multiple_data(AICE_CMD_T_WRITE_DIM, target_id,
+- num_of_words - 1, 0, big_endian_word, num_of_words,
+- AICE_LITTLE_ENDIAN);
+- return aice_usb_packet_append(usb_out_buffer,
+- AICE_FORMAT_HTDMC + (num_of_words - 1) * 4,
+- AICE_FORMAT_DTHMB);
+- }
+-
+- do {
+- aice_pack_htdmc_multiple_data(AICE_CMD_T_WRITE_DIM, target_id, num_of_words - 1, 0,
+- big_endian_word, num_of_words, AICE_LITTLE_ENDIAN);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC + (num_of_words - 1) * 4);
+-
+- LOG_DEBUG("WRITE_DIM, COREID: %" PRIu8
+- ", data: 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32,
+- target_id,
+- big_endian_word[0],
+- big_endian_word[1],
+- big_endian_word[2],
+- big_endian_word[3]);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)", AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+-
+- if (cmd_ack_code == AICE_CMD_T_WRITE_DIM) {
+- LOG_DEBUG("WRITE_DIM response");
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_WRITE_DIM, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_do_execute(uint8_t target_id)
+-{
+- int retry_times = 0;
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- aice_usb_packet_flush();
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- aice_pack_htdmc(AICE_CMD_T_EXECUTE, target_id, 0, 0, 0, AICE_LITTLE_ENDIAN);
+- return aice_usb_packet_append(usb_out_buffer,
+- AICE_FORMAT_HTDMC,
+- AICE_FORMAT_DTHMB);
+- }
+-
+- do {
+- aice_pack_htdmc(AICE_CMD_T_EXECUTE, target_id, 0, 0, 0, AICE_LITTLE_ENDIAN);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
+-
+- LOG_DEBUG("EXECUTE, COREID: %" PRIu8 "", target_id);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_T_EXECUTE) {
+- LOG_DEBUG("EXECUTE response");
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_EXECUTE, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_write_mem_b(uint8_t target_id, uint32_t address, uint32_t data)
+-{
+- int retry_times = 0;
+-
+- LOG_DEBUG("WRITE_MEM_B, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 " VALUE %08" PRIx32,
+- target_id,
+- address,
+- data);
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH)) {
+- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_B, target_id, 0, address,
+- data & 0x000000FF, data_endian);
+- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD,
+- AICE_FORMAT_DTHMB);
+- } else {
+- do {
+- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_B, target_id, 0,
+- address, data & 0x000000FF, data_endian);
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)", AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_T_WRITE_MEM_B) {
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_WRITE_MEM_B, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_write_mem_h(uint8_t target_id, uint32_t address, uint32_t data)
+-{
+- int retry_times = 0;
+-
+- LOG_DEBUG("WRITE_MEM_H, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 " VALUE %08" PRIx32,
+- target_id,
+- address,
+- data);
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH)) {
+- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_H, target_id, 0,
+- (address >> 1) & 0x7FFFFFFF, data & 0x0000FFFF, data_endian);
+- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD,
+- AICE_FORMAT_DTHMB);
+- } else {
+- do {
+- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_H, target_id, 0,
+- (address >> 1) & 0x7FFFFFFF, data & 0x0000FFFF, data_endian);
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_T_WRITE_MEM_H) {
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_WRITE_MEM_H, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_write_mem(uint8_t target_id, uint32_t address, uint32_t data)
+-{
+- int retry_times = 0;
+-
+- LOG_DEBUG("WRITE_MEM, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 " VALUE %08" PRIx32,
+- target_id,
+- address,
+- data);
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH)) {
+- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM, target_id, 0,
+- (address >> 2) & 0x3FFFFFFF, data, data_endian);
+- return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD,
+- AICE_FORMAT_DTHMB);
+- } else {
+- do {
+- aice_pack_htdmd(AICE_CMD_T_WRITE_MEM, target_id, 0,
+- (address >> 2) & 0x3FFFFFFF, data, data_endian);
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_T_WRITE_MEM) {
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_WRITE_MEM, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_fastread_mem(uint8_t target_id, uint8_t *word, uint32_t num_of_words)
+-{
+- int retry_times = 0;
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH))
+- aice_usb_packet_flush();
+-
+- do {
+- aice_pack_htdmb(AICE_CMD_T_FASTREAD_MEM, target_id, num_of_words - 1, 0);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
+-
+- LOG_DEBUG("FASTREAD_MEM, COREID: %" PRIu8 ", # of DATA %08" PRIx32,
+- target_id, num_of_words);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA + (num_of_words - 1) * 4);
+- if (result < 0) {
+- LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%d)",
+- AICE_FORMAT_DTHMA + (num_of_words - 1) * 4, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthma_multiple_data(&cmd_ack_code, &res_target_id,
+- &extra_length, word, data_endian);
+-
+- if (cmd_ack_code == AICE_CMD_T_FASTREAD_MEM) {
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_FASTREAD_MEM, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_fastwrite_mem(uint8_t target_id, const uint8_t *word, uint32_t num_of_words)
+-{
+- int retry_times = 0;
+-
+- if (aice_command_mode == AICE_COMMAND_MODE_PACK) {
+- aice_usb_packet_flush();
+- } else if (aice_command_mode == AICE_COMMAND_MODE_BATCH) {
+- aice_pack_htdmd_multiple_data(AICE_CMD_T_FASTWRITE_MEM, target_id,
+- num_of_words - 1, 0, word, data_endian);
+- return aice_usb_packet_append(usb_out_buffer,
+- AICE_FORMAT_HTDMD + (num_of_words - 1) * 4,
+- AICE_FORMAT_DTHMB);
+- }
+-
+- do {
+- aice_pack_htdmd_multiple_data(AICE_CMD_T_FASTWRITE_MEM, target_id,
+- num_of_words - 1, 0, word, data_endian);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD + (num_of_words - 1) * 4);
+-
+- LOG_DEBUG("FASTWRITE_MEM, COREID: %" PRIu8 ", # of DATA %08" PRIx32,
+- target_id, num_of_words);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_T_FASTWRITE_MEM) {
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_FASTWRITE_MEM, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_read_mem_b(uint8_t target_id, uint32_t address, uint32_t *data)
+-{
+- int retry_times = 0;
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH))
+- aice_usb_packet_flush();
+-
+- do {
+- aice_pack_htdmb(AICE_CMD_T_READ_MEM_B, target_id, 0, address);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
+-
+- LOG_DEBUG("READ_MEM_B, COREID: %" PRIu8 "", target_id);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
+- if (result != AICE_FORMAT_DTHMA) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMA, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
+- data, data_endian);
+-
+- if (cmd_ack_code == AICE_CMD_T_READ_MEM_B) {
+- LOG_DEBUG("READ_MEM_B response, data: 0x%02" PRIx32, *data);
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_READ_MEM_B, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_read_mem_h(uint8_t target_id, uint32_t address, uint32_t *data)
+-{
+- int retry_times = 0;
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH))
+- aice_usb_packet_flush();
+-
+- do {
+- aice_pack_htdmb(AICE_CMD_T_READ_MEM_H, target_id, 0, (address >> 1) & 0x7FFFFFFF);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
+-
+- LOG_DEBUG("READ_MEM_H, CORE_ID: %" PRIu8 "", target_id);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
+- if (result != AICE_FORMAT_DTHMA) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMA, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
+- data, data_endian);
+-
+- if (cmd_ack_code == AICE_CMD_T_READ_MEM_H) {
+- LOG_DEBUG("READ_MEM_H response, data: 0x%" PRIx32, *data);
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_READ_MEM_H, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_read_mem(uint8_t target_id, uint32_t address, uint32_t *data)
+-{
+- int retry_times = 0;
+-
+- if ((aice_command_mode == AICE_COMMAND_MODE_PACK) ||
+- (aice_command_mode == AICE_COMMAND_MODE_BATCH))
+- aice_usb_packet_flush();
+-
+- do {
+- aice_pack_htdmb(AICE_CMD_T_READ_MEM, target_id, 0,
+- (address >> 2) & 0x3FFFFFFF);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
+-
+- LOG_DEBUG("READ_MEM, COREID: %" PRIu8 "", target_id);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
+- if (result != AICE_FORMAT_DTHMA) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMA, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
+- data, data_endian);
+-
+- if (cmd_ack_code == AICE_CMD_T_READ_MEM) {
+- LOG_DEBUG("READ_MEM response, data: 0x%" PRIx32, *data);
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_T_READ_MEM, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_batch_buffer_read(uint8_t buf_index, uint32_t *word, uint32_t num_of_words)
+-{
+- int retry_times = 0;
+-
+- do {
+- aice_pack_htdma(AICE_CMD_BATCH_BUFFER_READ, 0, num_of_words - 1, buf_index);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
+-
+- LOG_DEBUG("BATCH_BUFFER_READ, # of DATA %08" PRIx32, num_of_words);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA + (num_of_words - 1) * 4);
+- if (result < 0) {
+- LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%d)",
+- AICE_FORMAT_DTHMA + (num_of_words - 1) * 4, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthma_multiple_data(&cmd_ack_code, &res_target_id,
+- &extra_length, (uint8_t *)word, data_endian);
+-
+- if (cmd_ack_code == AICE_CMD_BATCH_BUFFER_READ) {
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_BATCH_BUFFER_READ, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word, uint32_t num_of_words)
+-{
+- int retry_times = 0;
+-
+- if (num_of_words == 0)
+- return ERROR_OK;
+-
+- do {
+- /* only pack AICE_CMD_BATCH_BUFFER_WRITE command header */
+- aice_pack_htdmc(AICE_CMD_BATCH_BUFFER_WRITE, 0, num_of_words - 1, buf_index,
+- 0, data_endian);
+-
+- /* use append instead of pack */
+- memcpy(usb_out_buffer + 4, word, num_of_words * 4);
+-
+- aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC + (num_of_words - 1) * 4);
+-
+- LOG_DEBUG("BATCH_BUFFER_WRITE, # of DATA %08" PRIx32, num_of_words);
+-
+- int result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+- if (result != AICE_FORMAT_DTHMB) {
+- LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+- AICE_FORMAT_DTHMB, result);
+- return ERROR_FAIL;
+- }
+-
+- uint8_t cmd_ack_code;
+- uint8_t extra_length;
+- uint8_t res_target_id;
+- aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+-
+- if (cmd_ack_code == AICE_CMD_BATCH_BUFFER_WRITE) {
+- break;
+- } else {
+- if (retry_times > aice_max_retry_times) {
+- LOG_ERROR("aice command timeout (command=0x%x, response=0x%" PRIx8 ")",
+- AICE_CMD_BATCH_BUFFER_WRITE, cmd_ack_code);
+-
+- return ERROR_FAIL;
+- }
+-
+- /* clear timeout and retry */
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- retry_times++;
+- }
+- } while (1);
+-
+- return ERROR_OK;
+-}
+-
+-/***************************************************************************/
+-/* End of AICE commands */
+-
+-typedef int (*read_mem_func_t)(uint32_t coreid, uint32_t address, uint32_t *data);
+-typedef int (*write_mem_func_t)(uint32_t coreid, uint32_t address, uint32_t data);
+-
+-static struct aice_nds32_info core_info[AICE_MAX_NUM_CORE];
+-static uint8_t total_num_of_core;
+-
+-static char *custom_srst_script;
+-static char *custom_trst_script;
+-static char *custom_restart_script;
+-static uint32_t aice_count_to_check_dbger = 30;
+-
+-static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val);
+-static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val);
+-
+-static int check_suppressed_exception(uint32_t coreid, uint32_t dbger_value)
+-{
+- uint32_t ir4_value = 0;
+- uint32_t ir6_value = 0;
+- /* the default value of handling_suppressed_exception is false */
+- static bool handling_suppressed_exception;
+-
+- if (handling_suppressed_exception)
+- return ERROR_OK;
+-
+- if ((dbger_value & NDS_DBGER_ALL_SUPRS_EX) == NDS_DBGER_ALL_SUPRS_EX) {
+- LOG_ERROR("<-- TARGET WARNING! Exception is detected and suppressed. -->");
+- handling_suppressed_exception = true;
+-
+- aice_read_reg(coreid, IR4, &ir4_value);
+- /* Clear IR6.SUPRS_EXC, IR6.IMP_EXC */
+- aice_read_reg(coreid, IR6, &ir6_value);
+- /*
+- * For MCU version(MSC_CFG.MCU == 1) like V3m
+- * | SWID[30:16] | Reserved[15:10] | SUPRS_EXC[9] | IMP_EXC[8]
+- * |VECTOR[7:5] | INST[4] | Exc Type[3:0] |
+- *
+- * For non-MCU version(MSC_CFG.MCU == 0) like V3
+- * | SWID[30:16] | Reserved[15:14] | SUPRS_EXC[13] | IMP_EXC[12]
+- * | VECTOR[11:5] | INST[4] | Exc Type[3:0] |
+- */
+- LOG_INFO("EVA: 0x%08" PRIx32, ir4_value);
+- LOG_INFO("ITYPE: 0x%08" PRIx32, ir6_value);
+-
+- ir6_value = ir6_value & (~0x300); /* for MCU */
+- ir6_value = ir6_value & (~0x3000); /* for non-MCU */
+- aice_write_reg(coreid, IR6, ir6_value);
+-
+- handling_suppressed_exception = false;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int check_privilege(uint32_t coreid, uint32_t dbger_value)
+-{
+- if ((dbger_value & NDS_DBGER_ILL_SEC_ACC) == NDS_DBGER_ILL_SEC_ACC) {
+- LOG_ERROR("<-- TARGET ERROR! Insufficient security privilege "
+- "to execute the debug operations. -->");
+-
+- /* Clear DBGER.ILL_SEC_ACC */
+- if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
+- NDS_DBGER_ILL_SEC_ACC) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_check_dbger(uint32_t coreid, uint32_t expect_status)
+-{
+- uint32_t i = 0;
+- uint32_t value_dbger = 0;
+-
+- while (1) {
+- aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &value_dbger);
+-
+- if ((value_dbger & expect_status) == expect_status) {
+- if (check_suppressed_exception(coreid, value_dbger) != ERROR_OK)
+- return ERROR_FAIL;
+- if (check_privilege(coreid, value_dbger) != ERROR_OK)
+- return ERROR_FAIL;
+- return ERROR_OK;
+- }
+-
+- if ((i % 30) == 0)
+- keep_alive();
+-
+- int64_t then = 0;
+- if (i == aice_count_to_check_dbger)
+- then = timeval_ms();
+- if (i >= aice_count_to_check_dbger) {
+- if ((timeval_ms() - then) > 1000) {
+- LOG_ERROR("Timeout (1000ms) waiting for $DBGER status "
+- "being 0x%08" PRIx32, expect_status);
+- return ERROR_FAIL;
+- }
+- }
+- i++;
+- }
+-
+- return ERROR_FAIL;
+-}
+-
+-static int aice_execute_dim(uint32_t coreid, uint32_t *insts, uint8_t n_inst)
+-{
+- /** fill DIM */
+- if (aice_write_dim(coreid, insts, n_inst) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /** clear DBGER.DPED */
+- if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_DPED) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /** execute DIM */
+- if (aice_do_execute(coreid) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /** read DBGER.DPED */
+- if (aice_check_dbger(coreid, NDS_DBGER_DPED) != ERROR_OK) {
+- LOG_ERROR("<-- TARGET ERROR! Debug operations do not finish properly: "
+- "0x%08" PRIx32 "0x%08" PRIx32 "0x%08" PRIx32 "0x%08" PRIx32 ". -->",
+- insts[0],
+- insts[1],
+- insts[2],
+- insts[3]);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
+-{
+- LOG_DEBUG("aice_read_reg, reg_no: 0x%08" PRIx32, num);
+-
+- uint32_t instructions[4]; /** execute instructions in DIM */
+-
+- if (nds32_reg_type(num) == NDS32_REG_TYPE_GPR) { /* general registers */
+- instructions[0] = MTSR_DTR(num);
+- instructions[1] = DSB;
+- instructions[2] = NOP;
+- instructions[3] = BEQ_MINUS_12;
+- } else if (nds32_reg_type(num) == NDS32_REG_TYPE_SPR) { /* user special registers */
+- instructions[0] = MFUSR_G0(0, nds32_reg_sr_index(num));
+- instructions[1] = MTSR_DTR(0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- } else if (nds32_reg_type(num) == NDS32_REG_TYPE_AUMR) { /* audio registers */
+- if ((num >= CB_CTL) && (num <= CBE3)) {
+- instructions[0] = AMFAR2(0, nds32_reg_sr_index(num));
+- instructions[1] = MTSR_DTR(0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- } else {
+- instructions[0] = AMFAR(0, nds32_reg_sr_index(num));
+- instructions[1] = MTSR_DTR(0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- }
+- } else if (nds32_reg_type(num) == NDS32_REG_TYPE_FPU) { /* fpu registers */
+- if (num == FPCSR) {
+- instructions[0] = FMFCSR;
+- instructions[1] = MTSR_DTR(0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- } else if (num == FPCFG) {
+- instructions[0] = FMFCFG;
+- instructions[1] = MTSR_DTR(0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- } else {
+- if (num >= FS0 && num <= FS31) { /* single precision */
+- instructions[0] = FMFSR(0, nds32_reg_sr_index(num));
+- instructions[1] = MTSR_DTR(0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- } else if (num >= FD0 && num <= FD31) { /* double precision */
+- instructions[0] = FMFDR(0, nds32_reg_sr_index(num));
+- instructions[1] = MTSR_DTR(0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- }
+- }
+- } else { /* system registers */
+- instructions[0] = MFSR(0, nds32_reg_sr_index(num));
+- instructions[1] = MTSR_DTR(0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- }
+-
+- aice_execute_dim(coreid, instructions, 4);
+-
+- uint32_t value_edmsw = 0;
+- aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
+- if (value_edmsw & NDS_EDMSW_WDV)
+- aice_read_dtr(coreid, val);
+- else {
+- LOG_ERROR("<-- TARGET ERROR! The debug target failed to update "
+- "the DTR register. -->");
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
+-{
+- LOG_DEBUG("aice_usb_read_reg");
+-
+- if (num == R0) {
+- *val = core_info[coreid].r0_backup;
+- } else if (num == R1) {
+- *val = core_info[coreid].r1_backup;
+- } else if (num == DR41) {
+- /* As target is halted, OpenOCD will backup DR41/DR42/DR43.
+- * As user wants to read these registers, OpenOCD should return
+- * the backup values, instead of reading the real values.
+- * As user wants to write these registers, OpenOCD should write
+- * to the backup values, instead of writing to real registers. */
+- *val = core_info[coreid].edmsw_backup;
+- } else if (num == DR42) {
+- *val = core_info[coreid].edm_ctl_backup;
+- } else if ((core_info[coreid].target_dtr_valid == true) && (num == DR43)) {
+- *val = core_info[coreid].target_dtr_backup;
+- } else {
+- if (aice_read_reg(coreid, num, val) != ERROR_OK)
+- *val = 0xBBADBEEF;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
+-{
+- LOG_DEBUG("aice_write_reg, reg_no: 0x%08" PRIx32 ", value: 0x%08" PRIx32, num, val);
+-
+- uint32_t instructions[4]; /** execute instructions in DIM */
+- uint32_t value_edmsw = 0;
+-
+- aice_write_dtr(coreid, val);
+- aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
+- if (0 == (value_edmsw & NDS_EDMSW_RDV)) {
+- LOG_ERROR("<-- TARGET ERROR! AICE failed to write to the DTR register. -->");
+- return ERROR_FAIL;
+- }
+-
+- if (nds32_reg_type(num) == NDS32_REG_TYPE_GPR) { /* general registers */
+- instructions[0] = MFSR_DTR(num);
+- instructions[1] = DSB;
+- instructions[2] = NOP;
+- instructions[3] = BEQ_MINUS_12;
+- } else if (nds32_reg_type(num) == NDS32_REG_TYPE_SPR) { /* user special registers */
+- instructions[0] = MFSR_DTR(0);
+- instructions[1] = MTUSR_G0(0, nds32_reg_sr_index(num));
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- } else if (nds32_reg_type(num) == NDS32_REG_TYPE_AUMR) { /* audio registers */
+- if ((num >= CB_CTL) && (num <= CBE3)) {
+- instructions[0] = MFSR_DTR(0);
+- instructions[1] = AMTAR2(0, nds32_reg_sr_index(num));
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- } else {
+- instructions[0] = MFSR_DTR(0);
+- instructions[1] = AMTAR(0, nds32_reg_sr_index(num));
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- }
+- } else if (nds32_reg_type(num) == NDS32_REG_TYPE_FPU) { /* fpu registers */
+- if (num == FPCSR) {
+- instructions[0] = MFSR_DTR(0);
+- instructions[1] = FMTCSR;
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- } else if (num == FPCFG) {
+- /* FPCFG is readonly */
+- } else {
+- if (num >= FS0 && num <= FS31) { /* single precision */
+- instructions[0] = MFSR_DTR(0);
+- instructions[1] = FMTSR(0, nds32_reg_sr_index(num));
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- } else if (num >= FD0 && num <= FD31) { /* double precision */
+- instructions[0] = MFSR_DTR(0);
+- instructions[1] = FMTDR(0, nds32_reg_sr_index(num));
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- }
+- }
+- } else {
+- instructions[0] = MFSR_DTR(0);
+- instructions[1] = MTSR(0, nds32_reg_sr_index(num));
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- }
+-
+- return aice_execute_dim(coreid, instructions, 4);
+-}
+-
+-static int aice_usb_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
+-{
+- LOG_DEBUG("aice_usb_write_reg");
+-
+- if (num == R0)
+- core_info[coreid].r0_backup = val;
+- else if (num == R1)
+- core_info[coreid].r1_backup = val;
+- else if (num == DR42)
+- /* As target is halted, OpenOCD will backup DR41/DR42/DR43.
+- * As user wants to read these registers, OpenOCD should return
+- * the backup values, instead of reading the real values.
+- * As user wants to write these registers, OpenOCD should write
+- * to the backup values, instead of writing to real registers. */
+- core_info[coreid].edm_ctl_backup = val;
+- else if ((core_info[coreid].target_dtr_valid == true) && (num == DR43))
+- core_info[coreid].target_dtr_backup = val;
+- else
+- return aice_write_reg(coreid, num, val);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_open(struct aice_port_param_s *param)
+-{
+- const uint16_t vids[] = { param->vid, 0 };
+- const uint16_t pids[] = { param->pid, 0 };
+- struct libusb_device_handle *devh;
+-
+- if (jtag_libusb_open(vids, pids, &devh, NULL) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
+- * AREA!!!!!!!!!!! The behavior of libusb is not completely
+- * consistent across Windows, Linux, and Mac OS X platforms.
+- * The actions taken in the following compiler conditionals may
+- * not agree with published documentation for libusb, but were
+- * found to be necessary through trials and tribulations. Even
+- * little tweaks can break one or more platforms, so if you do
+- * make changes test them carefully on all platforms before
+- * committing them!
+- */
+-
+-#if IS_WIN32 == 0
+-
+- libusb_reset_device(devh);
+-
+-#if IS_DARWIN == 0
+-
+- int timeout = 5;
+- /* reopen jlink after usb_reset
+- * on win32 this may take a second or two to re-enumerate */
+- int retval;
+- while ((retval = jtag_libusb_open(vids, pids, &devh, NULL)) != ERROR_OK) {
+- usleep(1000);
+- timeout--;
+- if (!timeout)
+- break;
+- }
+- if (retval != ERROR_OK)
+- return ERROR_FAIL;
+-#endif
+-
+-#endif
+-
+- /* usb_set_configuration required under win32 */
+- libusb_set_configuration(devh, 0);
+- libusb_claim_interface(devh, 0);
+-
+- unsigned int aice_read_ep;
+- unsigned int aice_write_ep;
+-
+- jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, LIBUSB_TRANSFER_TYPE_BULK);
+- LOG_DEBUG("aice_read_ep=0x%x, aice_write_ep=0x%x", aice_read_ep, aice_write_ep);
+-
+- aice_handler.usb_read_ep = aice_read_ep;
+- aice_handler.usb_write_ep = aice_write_ep;
+- aice_handler.usb_handle = devh;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_read_reg_64(uint32_t coreid, uint32_t num, uint64_t *val)
+-{
+- LOG_DEBUG("aice_usb_read_reg_64, %s", nds32_reg_simple_name(num));
+-
+- uint32_t value;
+- uint32_t high_value;
+-
+- if (aice_read_reg(coreid, num, &value) != ERROR_OK)
+- value = 0xBBADBEEF;
+-
+- aice_read_reg(coreid, R1, &high_value);
+-
+- LOG_DEBUG("low: 0x%08" PRIx32 ", high: 0x%08" PRIx32 "\n", value, high_value);
+-
+- if (data_endian == AICE_BIG_ENDIAN)
+- *val = (((uint64_t)high_value) << 32) | value;
+- else
+- *val = (((uint64_t)value) << 32) | high_value;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_write_reg_64(uint32_t coreid, uint32_t num, uint64_t val)
+-{
+- uint32_t value;
+- uint32_t high_value;
+-
+- if (data_endian == AICE_BIG_ENDIAN) {
+- value = val & 0xFFFFFFFF;
+- high_value = (val >> 32) & 0xFFFFFFFF;
+- } else {
+- high_value = val & 0xFFFFFFFF;
+- value = (val >> 32) & 0xFFFFFFFF;
+- }
+-
+- LOG_DEBUG("aice_usb_write_reg_64, %s, low: 0x%08" PRIx32 ", high: 0x%08" PRIx32 "\n",
+- nds32_reg_simple_name(num), value, high_value);
+-
+- aice_write_reg(coreid, R1, high_value);
+- return aice_write_reg(coreid, num, value);
+-}
+-
+-static int aice_get_version_info(void)
+-{
+- uint32_t hardware_version;
+- uint32_t firmware_version;
+- uint32_t fpga_version;
+-
+- if (aice_read_ctrl(AICE_READ_CTRL_GET_HARDWARE_VERSION, &hardware_version) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (aice_read_ctrl(AICE_READ_CTRL_GET_FIRMWARE_VERSION, &firmware_version) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (aice_read_ctrl(AICE_READ_CTRL_GET_FPGA_VERSION, &fpga_version) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- LOG_INFO("AICE version: hw_ver = 0x%" PRIx32 ", fw_ver = 0x%" PRIx32 ", fpga_ver = 0x%" PRIx32,
+- hardware_version, firmware_version, fpga_version);
+-
+- return ERROR_OK;
+-}
+-
+-#define LINE_BUFFER_SIZE 1024
+-
+-static int aice_execute_custom_script(const char *script)
+-{
+- FILE *script_fd;
+- char line_buffer[LINE_BUFFER_SIZE];
+- char *op_str;
+- char *reset_str;
+- uint32_t delay;
+- uint32_t write_ctrl_value;
+- bool set_op;
+-
+- script_fd = fopen(script, "r");
+- if (!script_fd) {
+- return ERROR_FAIL;
+- } else {
+- while (fgets(line_buffer, LINE_BUFFER_SIZE, script_fd)) {
+- /* execute operations */
+- set_op = false;
+- op_str = strstr(line_buffer, "set");
+- if (op_str) {
+- set_op = true;
+- goto get_reset_type;
+- }
+-
+- op_str = strstr(line_buffer, "clear");
+- if (!op_str)
+- continue;
+-get_reset_type:
+- reset_str = strstr(op_str, "srst");
+- if (reset_str) {
+- if (set_op)
+- write_ctrl_value = AICE_CUSTOM_DELAY_SET_SRST;
+- else
+- write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_SRST;
+- goto get_delay;
+- }
+- reset_str = strstr(op_str, "dbgi");
+- if (reset_str) {
+- if (set_op)
+- write_ctrl_value = AICE_CUSTOM_DELAY_SET_DBGI;
+- else
+- write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_DBGI;
+- goto get_delay;
+- }
+- reset_str = strstr(op_str, "trst");
+- if (reset_str) {
+- if (set_op)
+- write_ctrl_value = AICE_CUSTOM_DELAY_SET_TRST;
+- else
+- write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_TRST;
+- goto get_delay;
+- }
+- continue;
+-get_delay:
+- /* get delay */
+- delay = strtoul(reset_str + 4, NULL, 0);
+- write_ctrl_value |= (delay << 16);
+-
+- if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY,
+- write_ctrl_value) != ERROR_OK) {
+- fclose(script_fd);
+- return ERROR_FAIL;
+- }
+- }
+- fclose(script_fd);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_set_clock(int set_clock)
+-{
+- if (set_clock & AICE_TCK_CONTROL_TCK_SCAN) {
+- if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL,
+- AICE_TCK_CONTROL_TCK_SCAN) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /* Read out TCK_SCAN clock value */
+- uint32_t scan_clock;
+- if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &scan_clock) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- scan_clock &= 0x0F;
+-
+- uint32_t scan_base_freq;
+- if (scan_clock & 0x8)
+- scan_base_freq = 48000; /* 48 MHz */
+- else
+- scan_base_freq = 30000; /* 30 MHz */
+-
+- uint32_t set_base_freq;
+- if (set_clock & 0x8)
+- set_base_freq = 48000;
+- else
+- set_base_freq = 30000;
+-
+- uint32_t set_freq;
+- uint32_t scan_freq;
+- set_freq = set_base_freq >> (set_clock & 0x7);
+- scan_freq = scan_base_freq >> (scan_clock & 0x7);
+-
+- if (scan_freq < set_freq) {
+- LOG_ERROR("User specifies higher jtag clock than TCK_SCAN clock");
+- return ERROR_FAIL;
+- }
+- }
+-
+- if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL, set_clock) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- uint32_t check_speed;
+- if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &check_speed) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (((int)check_speed & 0x0F) != set_clock) {
+- LOG_ERROR("Set jtag clock failed");
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_edm_init(uint32_t coreid)
+-{
+- aice_write_edmsr(coreid, NDS_EDM_SR_DIMBR, 0xFFFF0000);
+- aice_write_misc(coreid, NDS_EDM_MISC_DIMIR, 0);
+-
+- /* unconditionally try to turn on V3_EDM_MODE */
+- uint32_t edm_ctl_value;
+- aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
+- aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value | 0x00000040);
+-
+- /* clear DBGER */
+- aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
+- NDS_DBGER_DPED | NDS_DBGER_CRST | NDS_DBGER_AT_MAX);
+-
+- /* get EDM version */
+- uint32_t value_edmcfg;
+- aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CFG, &value_edmcfg);
+- core_info[coreid].edm_version = (value_edmcfg >> 16) & 0xFFFF;
+-
+- return ERROR_OK;
+-}
+-
+-static bool is_v2_edm(uint32_t coreid)
+-{
+- if ((core_info[coreid].edm_version & 0x1000) == 0)
+- return true;
+- else
+- return false;
+-}
+-
+-static int aice_init_edm_registers(uint32_t coreid, bool clear_dex_use_psw)
+-{
+- /* enable DEH_SEL & MAX_STOP & V3_EDM_MODE & DBGI_MASK */
+- uint32_t host_edm_ctl = core_info[coreid].edm_ctl_backup | 0xA000004F;
+- if (clear_dex_use_psw)
+- /* After entering debug mode, OpenOCD may set
+- * DEX_USE_PSW accidentally through backup value
+- * of target EDM_CTL.
+- * So, clear DEX_USE_PSW by force. */
+- host_edm_ctl &= ~(0x40000000);
+-
+- LOG_DEBUG("aice_init_edm_registers - EDM_CTL: 0x%08" PRIx32, host_edm_ctl);
+-
+- int result = aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, host_edm_ctl);
+-
+- return result;
+-}
+-
+-/**
+- * EDM_CTL will be modified by OpenOCD as debugging. OpenOCD has the
+- * responsibility to keep EDM_CTL untouched after debugging.
+- *
+- * There are two scenarios to consider:
+- * 1. single step/running as debugging (running under debug session)
+- * 2. detached from gdb (exit debug session)
+- *
+- * So, we need to bakcup EDM_CTL before halted and restore it after
+- * running. The difference of these two scenarios is EDM_CTL.DEH_SEL
+- * is on for scenario 1, and off for scenario 2.
+- */
+-static int aice_backup_edm_registers(uint32_t coreid)
+-{
+- int result = aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL,
+- &core_info[coreid].edm_ctl_backup);
+-
+- /* To call aice_backup_edm_registers() after DEX on, DEX_USE_PSW
+- * may be not correct. (For example, hit breakpoint, then backup
+- * EDM_CTL. EDM_CTL.DEX_USE_PSW will be cleared.) Because debug
+- * interrupt will clear DEX_USE_PSW, DEX_USE_PSW is always off after
+- * DEX is on. It only backups correct value before OpenOCD issues DBGI.
+- * (Backup EDM_CTL, then issue DBGI actively (refer aice_usb_halt())) */
+- if (core_info[coreid].edm_ctl_backup & 0x40000000)
+- core_info[coreid].dex_use_psw_on = true;
+- else
+- core_info[coreid].dex_use_psw_on = false;
+-
+- LOG_DEBUG("aice_backup_edm_registers - EDM_CTL: 0x%08" PRIx32 ", DEX_USE_PSW: %s",
+- core_info[coreid].edm_ctl_backup,
+- core_info[coreid].dex_use_psw_on ? "on" : "off");
+-
+- return result;
+-}
+-
+-static int aice_restore_edm_registers(uint32_t coreid)
+-{
+- LOG_DEBUG("aice_restore_edm_registers -");
+-
+- /* set DEH_SEL, because target still under EDM control */
+- int result = aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL,
+- core_info[coreid].edm_ctl_backup | 0x80000000);
+-
+- return result;
+-}
+-
+-static int aice_backup_tmp_registers(uint32_t coreid)
+-{
+- LOG_DEBUG("backup_tmp_registers -");
+-
+- /* backup target DTR first(if the target DTR is valid) */
+- uint32_t value_edmsw = 0;
+- aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
+- core_info[coreid].edmsw_backup = value_edmsw;
+- if (value_edmsw & 0x1) { /* EDMSW.WDV == 1 */
+- aice_read_dtr(coreid, &core_info[coreid].target_dtr_backup);
+- core_info[coreid].target_dtr_valid = true;
+-
+- LOG_DEBUG("Backup target DTR: 0x%08" PRIx32, core_info[coreid].target_dtr_backup);
+- } else {
+- core_info[coreid].target_dtr_valid = false;
+- }
+-
+- /* Target DTR has been backup, then backup $R0 and $R1 */
+- aice_read_reg(coreid, R0, &core_info[coreid].r0_backup);
+- aice_read_reg(coreid, R1, &core_info[coreid].r1_backup);
+-
+- /* backup host DTR(if the host DTR is valid) */
+- if (value_edmsw & 0x2) { /* EDMSW.RDV == 1*/
+- /* read out host DTR and write into target DTR, then use aice_read_edmsr to
+- * read out */
+- uint32_t instructions[4] = {
+- MFSR_DTR(R0), /* R0 has already been backup */
+- DSB,
+- MTSR_DTR(R0),
+- BEQ_MINUS_12
+- };
+- aice_execute_dim(coreid, instructions, 4);
+-
+- aice_read_dtr(coreid, &core_info[coreid].host_dtr_backup);
+- core_info[coreid].host_dtr_valid = true;
+-
+- LOG_DEBUG("Backup host DTR: 0x%08" PRIx32, core_info[coreid].host_dtr_backup);
+- } else {
+- core_info[coreid].host_dtr_valid = false;
+- }
+-
+- LOG_DEBUG("r0: 0x%08" PRIx32 ", r1: 0x%08" PRIx32,
+- core_info[coreid].r0_backup, core_info[coreid].r1_backup);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_restore_tmp_registers(uint32_t coreid)
+-{
+- LOG_DEBUG("restore_tmp_registers - r0: 0x%08" PRIx32 ", r1: 0x%08" PRIx32,
+- core_info[coreid].r0_backup, core_info[coreid].r1_backup);
+-
+- if (core_info[coreid].target_dtr_valid) {
+- uint32_t instructions[4] = {
+- SETHI(R0, core_info[coreid].target_dtr_backup >> 12),
+- ORI(R0, R0, core_info[coreid].target_dtr_backup & 0x00000FFF),
+- NOP,
+- BEQ_MINUS_12
+- };
+- aice_execute_dim(coreid, instructions, 4);
+-
+- instructions[0] = MTSR_DTR(R0);
+- instructions[1] = DSB;
+- instructions[2] = NOP;
+- instructions[3] = BEQ_MINUS_12;
+- aice_execute_dim(coreid, instructions, 4);
+-
+- LOG_DEBUG("Restore target DTR: 0x%08" PRIx32, core_info[coreid].target_dtr_backup);
+- }
+-
+- aice_write_reg(coreid, R0, core_info[coreid].r0_backup);
+- aice_write_reg(coreid, R1, core_info[coreid].r1_backup);
+-
+- if (core_info[coreid].host_dtr_valid) {
+- aice_write_dtr(coreid, core_info[coreid].host_dtr_backup);
+-
+- LOG_DEBUG("Restore host DTR: 0x%08" PRIx32, core_info[coreid].host_dtr_backup);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_open_device(struct aice_port_param_s *param)
+-{
+- if (aice_usb_open(param) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (aice_get_version_info() == ERROR_FAIL) {
+- LOG_ERROR("Cannot get AICE version!");
+- return ERROR_FAIL;
+- }
+-
+- LOG_INFO("AICE initialization started");
+-
+- /* attempt to reset Andes EDM */
+- if (aice_reset_box() == ERROR_FAIL) {
+- LOG_ERROR("Cannot initial AICE box!");
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_set_jtag_clock(uint32_t a_clock)
+-{
+- jtag_clock = a_clock;
+-
+- if (aice_usb_set_clock(a_clock) != ERROR_OK) {
+- LOG_ERROR("Cannot set AICE JTAG clock!");
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_close(void)
+-{
+- jtag_libusb_close(aice_handler.usb_handle);
+-
+- free(custom_srst_script);
+- free(custom_trst_script);
+- free(custom_restart_script);
+- return ERROR_OK;
+-}
+-
+-static int aice_core_init(uint32_t coreid)
+-{
+- core_info[coreid].access_channel = NDS_MEMORY_ACC_CPU;
+- core_info[coreid].memory_select = NDS_MEMORY_SELECT_AUTO;
+- core_info[coreid].core_state = AICE_TARGET_UNKNOWN;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_idcode(uint32_t *idcode, uint8_t *num_of_idcode)
+-{
+- int retval;
+-
+- retval = aice_scan_chain(idcode, num_of_idcode);
+- if (retval == ERROR_OK) {
+- for (int i = 0; i < *num_of_idcode; i++) {
+- aice_core_init(i);
+- aice_edm_init(i);
+- }
+- total_num_of_core = *num_of_idcode;
+- }
+-
+- return retval;
+-}
+-
+-static int aice_usb_halt(uint32_t coreid)
+-{
+- if (core_info[coreid].core_state == AICE_TARGET_HALTED) {
+- LOG_DEBUG("aice_usb_halt check halted");
+- return ERROR_OK;
+- }
+-
+- LOG_DEBUG("aice_usb_halt");
+-
+- /** backup EDM registers */
+- aice_backup_edm_registers(coreid);
+- /** init EDM for host debugging */
+- /** no need to clear dex_use_psw, because dbgi will clear it */
+- aice_init_edm_registers(coreid, false);
+-
+- /** Clear EDM_CTL.DBGIM & EDM_CTL.DBGACKM */
+- uint32_t edm_ctl_value = 0;
+- aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
+- if (edm_ctl_value & 0x3)
+- aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value & ~(0x3));
+-
+- uint32_t dbger = 0;
+- uint32_t acc_ctl_value = 0;
+-
+- core_info[coreid].debug_under_dex_on = false;
+- aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger);
+-
+- if (dbger & NDS_DBGER_AT_MAX)
+- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level. -->");
+-
+- if (dbger & NDS_DBGER_DEX) {
+- if (is_v2_edm(coreid) == false) {
+- /** debug 'debug mode'. use force_debug to issue dbgi */
+- aice_read_misc(coreid, NDS_EDM_MISC_ACC_CTL, &acc_ctl_value);
+- acc_ctl_value |= 0x8;
+- aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL, acc_ctl_value);
+- core_info[coreid].debug_under_dex_on = true;
+-
+- aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0);
+- /* If CPU stalled due to AT_MAX, clear AT_MAX status. */
+- if (dbger & NDS_DBGER_AT_MAX)
+- aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX);
+- }
+- } else {
+- /** Issue DBGI normally */
+- aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0);
+- /* If CPU stalled due to AT_MAX, clear AT_MAX status. */
+- if (dbger & NDS_DBGER_AT_MAX)
+- aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX);
+- }
+-
+- if (aice_check_dbger(coreid, NDS_DBGER_DEX) != ERROR_OK) {
+- LOG_ERROR("<-- TARGET ERROR! Unable to stop the debug target through DBGI. -->");
+- return ERROR_FAIL;
+- }
+-
+- if (core_info[coreid].debug_under_dex_on) {
+- if (core_info[coreid].dex_use_psw_on == false) {
+- /* under debug 'debug mode', force $psw to 'debug mode' behavior */
+- /* !!!NOTICE!!! this is workaround for debug 'debug mode'.
+- * it is only for debugging 'debug exception handler' purpose.
+- * after openocd detaches from target, target behavior is
+- * undefined. */
+- uint32_t ir0_value = 0;
+- uint32_t debug_mode_ir0_value;
+- aice_read_reg(coreid, IR0, &ir0_value);
+- debug_mode_ir0_value = ir0_value | 0x408; /* turn on DEX, set POM = 1 */
+- debug_mode_ir0_value &= ~(0x000000C1); /* turn off DT/IT/GIE */
+- aice_write_reg(coreid, IR0, debug_mode_ir0_value);
+- }
+- }
+-
+- /** set EDM_CTL.DBGIM & EDM_CTL.DBGACKM after halt */
+- if (edm_ctl_value & 0x3)
+- aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value);
+-
+- /* backup r0 & r1 */
+- aice_backup_tmp_registers(coreid);
+- core_info[coreid].core_state = AICE_TARGET_HALTED;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_state(uint32_t coreid, enum aice_target_state_s *state)
+-{
+- uint32_t dbger_value;
+- uint32_t ice_state;
+-
+- int result = aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger_value);
+-
+- if (result == ERROR_AICE_TIMEOUT) {
+- if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &ice_state) != ERROR_OK) {
+- LOG_ERROR("<-- AICE ERROR! AICE is unplugged. -->");
+- return ERROR_FAIL;
+- }
+-
+- if ((ice_state & 0x20) == 0) {
+- LOG_ERROR("<-- TARGET ERROR! Target is disconnected with AICE. -->");
+- return ERROR_FAIL;
+- } else {
+- return ERROR_FAIL;
+- }
+- } else if (result == ERROR_AICE_DISCONNECT) {
+- LOG_ERROR("<-- AICE ERROR! AICE is unplugged. -->");
+- return ERROR_FAIL;
+- }
+-
+- if ((dbger_value & NDS_DBGER_ILL_SEC_ACC) == NDS_DBGER_ILL_SEC_ACC) {
+- LOG_ERROR("<-- TARGET ERROR! Insufficient security privilege. -->");
+-
+- /* Clear ILL_SEC_ACC */
+- aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_ILL_SEC_ACC);
+-
+- *state = AICE_TARGET_RUNNING;
+- core_info[coreid].core_state = AICE_TARGET_RUNNING;
+- } else if ((dbger_value & NDS_DBGER_AT_MAX) == NDS_DBGER_AT_MAX) {
+- /* Issue DBGI to exit cpu stall */
+- aice_usb_halt(coreid);
+-
+- /* Read OIPC to find out the trigger point */
+- uint32_t ir11_value;
+- aice_read_reg(coreid, IR11, &ir11_value);
+-
+- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level; "
+- "CPU is stalled at 0x%08" PRIx32 " for debugging. -->", ir11_value);
+-
+- *state = AICE_TARGET_HALTED;
+- } else if ((dbger_value & NDS_DBGER_CRST) == NDS_DBGER_CRST) {
+- LOG_DEBUG("DBGER.CRST is on.");
+-
+- *state = AICE_TARGET_RESET;
+- core_info[coreid].core_state = AICE_TARGET_RUNNING;
+-
+- /* Clear CRST */
+- aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_CRST);
+- } else if ((dbger_value & NDS_DBGER_DEX) == NDS_DBGER_DEX) {
+- if (core_info[coreid].core_state == AICE_TARGET_RUNNING) {
+- /* enter debug mode, init EDM registers */
+- /* backup EDM registers */
+- aice_backup_edm_registers(coreid);
+- /* init EDM for host debugging */
+- aice_init_edm_registers(coreid, true);
+- aice_backup_tmp_registers(coreid);
+- core_info[coreid].core_state = AICE_TARGET_HALTED;
+- } else if (core_info[coreid].core_state == AICE_TARGET_UNKNOWN) {
+- /* debug 'debug mode', use force debug to halt core */
+- aice_usb_halt(coreid);
+- }
+- *state = AICE_TARGET_HALTED;
+- } else {
+- *state = AICE_TARGET_RUNNING;
+- core_info[coreid].core_state = AICE_TARGET_RUNNING;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_reset(void)
+-{
+- if (aice_reset_box() != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /* issue TRST */
+- if (!custom_trst_script) {
+- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
+- AICE_JTAG_PIN_CONTROL_TRST) != ERROR_OK)
+- return ERROR_FAIL;
+- } else {
+- /* custom trst operations */
+- if (aice_execute_custom_script(custom_trst_script) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+-
+- if (aice_usb_set_clock(jtag_clock) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_issue_srst(uint32_t coreid)
+-{
+- LOG_DEBUG("aice_issue_srst");
+-
+- /* After issuing srst, target will be running. So we need to restore EDM_CTL. */
+- aice_restore_edm_registers(coreid);
+-
+- if (!custom_srst_script) {
+- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
+- AICE_JTAG_PIN_CONTROL_SRST) != ERROR_OK)
+- return ERROR_FAIL;
+- } else {
+- /* custom srst operations */
+- if (aice_execute_custom_script(custom_srst_script) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+-
+- /* wait CRST infinitely */
+- uint32_t dbger_value;
+- int i = 0;
+- while (1) {
+- if (aice_read_misc(coreid,
+- NDS_EDM_MISC_DBGER, &dbger_value) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (dbger_value & NDS_DBGER_CRST)
+- break;
+-
+- if ((i % 30) == 0)
+- keep_alive();
+- i++;
+- }
+-
+- core_info[coreid].host_dtr_valid = false;
+- core_info[coreid].target_dtr_valid = false;
+-
+- core_info[coreid].core_state = AICE_TARGET_RUNNING;
+- return ERROR_OK;
+-}
+-
+-static int aice_issue_reset_hold(uint32_t coreid)
+-{
+- LOG_DEBUG("aice_issue_reset_hold");
+-
+- /* set no_dbgi_pin to 0 */
+- uint32_t pin_status;
+- aice_read_ctrl(AICE_READ_CTRL_GET_JTAG_PIN_STATUS, &pin_status);
+- if (pin_status & 0x4)
+- aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status & (~0x4));
+-
+- /* issue restart */
+- if (!custom_restart_script) {
+- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
+- AICE_JTAG_PIN_CONTROL_RESTART) != ERROR_OK)
+- return ERROR_FAIL;
+- } else {
+- /* custom restart operations */
+- if (aice_execute_custom_script(custom_restart_script) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+-
+- if (aice_check_dbger(coreid, NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) {
+- aice_backup_tmp_registers(coreid);
+- core_info[coreid].core_state = AICE_TARGET_HALTED;
+-
+- return ERROR_OK;
+- } else {
+- /* set no_dbgi_pin to 1 */
+- aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status | 0x4);
+-
+- /* issue restart again */
+- if (!custom_restart_script) {
+- if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
+- AICE_JTAG_PIN_CONTROL_RESTART) != ERROR_OK)
+- return ERROR_FAIL;
+- } else {
+- /* custom restart operations */
+- if (aice_execute_custom_script(custom_restart_script) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+-
+- if (aice_check_dbger(coreid, NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) {
+- aice_backup_tmp_registers(coreid);
+- core_info[coreid].core_state = AICE_TARGET_HALTED;
+-
+- return ERROR_OK;
+- }
+-
+- /* do software reset-and-hold */
+- aice_issue_srst(coreid);
+- aice_usb_halt(coreid);
+-
+- uint32_t value_ir3;
+- aice_read_reg(coreid, IR3, &value_ir3);
+- aice_write_reg(coreid, PC, value_ir3 & 0xFFFF0000);
+- }
+-
+- return ERROR_FAIL;
+-}
+-
+-static int aice_issue_reset_hold_multi(void)
+-{
+- uint32_t write_ctrl_value = 0;
+-
+- /* set SRST */
+- write_ctrl_value = AICE_CUSTOM_DELAY_SET_SRST;
+- write_ctrl_value |= (0x200 << 16);
+- if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY,
+- write_ctrl_value) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- for (uint8_t i = 0 ; i < total_num_of_core ; i++)
+- aice_write_misc(i, NDS_EDM_MISC_EDM_CMDR, 0);
+-
+- /* clear SRST */
+- write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_SRST;
+- write_ctrl_value |= (0x200 << 16);
+- if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY,
+- write_ctrl_value) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- for (uint8_t i = 0; i < total_num_of_core; i++)
+- aice_edm_init(i);
+-
+- return ERROR_FAIL;
+-}
+-
+-static int aice_usb_assert_srst(uint32_t coreid, enum aice_srst_type_s srst)
+-{
+- if ((srst != AICE_SRST) && (srst != AICE_RESET_HOLD))
+- return ERROR_FAIL;
+-
+- /* clear DBGER */
+- if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
+- NDS_DBGER_CLEAR_ALL) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- int result = ERROR_OK;
+- if (srst == AICE_SRST)
+- result = aice_issue_srst(coreid);
+- else {
+- if (total_num_of_core == 1)
+- result = aice_issue_reset_hold(coreid);
+- else
+- result = aice_issue_reset_hold_multi();
+- }
+-
+- /* Clear DBGER.CRST after reset to avoid 'core-reset checking' errors.
+- * assert_srst is user-intentional reset behavior, so we could
+- * clear DBGER.CRST safely.
+- */
+- if (aice_write_misc(coreid,
+- NDS_EDM_MISC_DBGER, NDS_DBGER_CRST) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- return result;
+-}
+-
+-static int aice_usb_run(uint32_t coreid)
+-{
+- LOG_DEBUG("aice_usb_run");
+-
+- uint32_t dbger_value;
+- if (aice_read_misc(coreid,
+- NDS_EDM_MISC_DBGER, &dbger_value) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if ((dbger_value & NDS_DBGER_DEX) != NDS_DBGER_DEX) {
+- LOG_WARNING("<-- TARGET WARNING! The debug target exited "
+- "the debug mode unexpectedly. -->");
+- return ERROR_FAIL;
+- }
+-
+- /* restore r0 & r1 before free run */
+- aice_restore_tmp_registers(coreid);
+- core_info[coreid].core_state = AICE_TARGET_RUNNING;
+-
+- /* clear DBGER */
+- aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
+- NDS_DBGER_CLEAR_ALL);
+-
+- /** restore EDM registers */
+- /** OpenOCD should restore EDM_CTL **before** to exit debug state.
+- * Otherwise, following instruction will read wrong EDM_CTL value.
+- *
+- * pc -> mfsr $p0, EDM_CTL (single step)
+- * slli $p0, $p0, 1
+- * slri $p0, $p0, 31
+- */
+- aice_restore_edm_registers(coreid);
+-
+- /** execute instructions in DIM */
+- uint32_t instructions[4] = {
+- NOP,
+- NOP,
+- NOP,
+- IRET
+- };
+- int result = aice_execute_dim(coreid, instructions, 4);
+-
+- return result;
+-}
+-
+-static int aice_usb_step(uint32_t coreid)
+-{
+- LOG_DEBUG("aice_usb_step");
+-
+- uint32_t ir0_value;
+- uint32_t ir0_reg_num;
+-
+- if (is_v2_edm(coreid) == true)
+- /* V2 EDM will push interrupt stack as debug exception */
+- ir0_reg_num = IR1;
+- else
+- ir0_reg_num = IR0;
+-
+- /** enable HSS */
+- aice_read_reg(coreid, ir0_reg_num, &ir0_value);
+- if ((ir0_value & 0x800) == 0) {
+- /** set PSW.HSS */
+- ir0_value |= (0x01 << 11);
+- aice_write_reg(coreid, ir0_reg_num, ir0_value);
+- }
+-
+- if (aice_usb_run(coreid) == ERROR_FAIL)
+- return ERROR_FAIL;
+-
+- int i = 0;
+- enum aice_target_state_s state;
+- while (1) {
+- /* read DBGER */
+- if (aice_usb_state(coreid, &state) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (state == AICE_TARGET_HALTED)
+- break;
+-
+- int64_t then = 0;
+- if (i == 30)
+- then = timeval_ms();
+-
+- if (i >= 30) {
+- if ((timeval_ms() - then) > 1000)
+- LOG_WARNING("Timeout (1000ms) waiting for halt to complete");
+-
+- return ERROR_FAIL;
+- }
+- i++;
+- }
+-
+- /** disable HSS */
+- aice_read_reg(coreid, ir0_reg_num, &ir0_value);
+- ir0_value &= ~(0x01 << 11);
+- aice_write_reg(coreid, ir0_reg_num, ir0_value);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_read_mem_b_bus(uint32_t coreid, uint32_t address, uint32_t *data)
+-{
+- return aice_read_mem_b(coreid, address, data);
+-}
+-
+-static int aice_usb_read_mem_h_bus(uint32_t coreid, uint32_t address, uint32_t *data)
+-{
+- return aice_read_mem_h(coreid, address, data);
+-}
+-
+-static int aice_usb_read_mem_w_bus(uint32_t coreid, uint32_t address, uint32_t *data)
+-{
+- return aice_read_mem(coreid, address, data);
+-}
+-
+-static int aice_usb_read_mem_b_dim(uint32_t coreid, uint32_t address, uint32_t *data)
+-{
+- uint32_t value;
+- uint32_t instructions[4] = {
+- LBI_BI(R1, R0),
+- MTSR_DTR(R1),
+- DSB,
+- BEQ_MINUS_12
+- };
+-
+- aice_execute_dim(coreid, instructions, 4);
+-
+- aice_read_dtr(coreid, &value);
+- *data = value & 0xFF;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_read_mem_h_dim(uint32_t coreid, uint32_t address, uint32_t *data)
+-{
+- uint32_t value;
+- uint32_t instructions[4] = {
+- LHI_BI(R1, R0),
+- MTSR_DTR(R1),
+- DSB,
+- BEQ_MINUS_12
+- };
+-
+- aice_execute_dim(coreid, instructions, 4);
+-
+- aice_read_dtr(coreid, &value);
+- *data = value & 0xFFFF;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_read_mem_w_dim(uint32_t coreid, uint32_t address, uint32_t *data)
+-{
+- uint32_t instructions[4] = {
+- LWI_BI(R1, R0),
+- MTSR_DTR(R1),
+- DSB,
+- BEQ_MINUS_12
+- };
+-
+- aice_execute_dim(coreid, instructions, 4);
+-
+- aice_read_dtr(coreid, data);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_set_address_dim(uint32_t coreid, uint32_t address)
+-{
+- uint32_t instructions[4] = {
+- SETHI(R0, address >> 12),
+- ORI(R0, R0, address & 0x00000FFF),
+- NOP,
+- BEQ_MINUS_12
+- };
+-
+- return aice_execute_dim(coreid, instructions, 4);
+-}
+-
+-static int aice_usb_read_memory_unit(uint32_t coreid, uint32_t addr, uint32_t size,
+- uint32_t count, uint8_t *buffer)
+-{
+- LOG_DEBUG("aice_usb_read_memory_unit, addr: 0x%08" PRIx32
+- ", size: %" PRIu32 ", count: %" PRIu32 "",
+- addr, size, count);
+-
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_CPU)
+- aice_usb_set_address_dim(coreid, addr);
+-
+- uint32_t value;
+- size_t i;
+- read_mem_func_t read_mem_func;
+-
+- switch (size) {
+- case 1:
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_BUS)
+- read_mem_func = aice_usb_read_mem_b_bus;
+- else
+- read_mem_func = aice_usb_read_mem_b_dim;
+-
+- for (i = 0; i < count; i++) {
+- read_mem_func(coreid, addr, &value);
+- *buffer++ = (uint8_t)value;
+- addr++;
+- }
+- break;
+- case 2:
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_BUS)
+- read_mem_func = aice_usb_read_mem_h_bus;
+- else
+- read_mem_func = aice_usb_read_mem_h_dim;
+-
+- for (i = 0; i < count; i++) {
+- read_mem_func(coreid, addr, &value);
+- uint16_t svalue = value;
+- memcpy(buffer, &svalue, sizeof(uint16_t));
+- buffer += 2;
+- addr += 2;
+- }
+- break;
+- case 4:
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_BUS)
+- read_mem_func = aice_usb_read_mem_w_bus;
+- else
+- read_mem_func = aice_usb_read_mem_w_dim;
+-
+- for (i = 0; i < count; i++) {
+- read_mem_func(coreid, addr, &value);
+- memcpy(buffer, &value, sizeof(uint32_t));
+- buffer += 4;
+- addr += 4;
+- }
+- break;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_write_mem_b_bus(uint32_t coreid, uint32_t address, uint32_t data)
+-{
+- return aice_write_mem_b(coreid, address, data);
+-}
+-
+-static int aice_usb_write_mem_h_bus(uint32_t coreid, uint32_t address, uint32_t data)
+-{
+- return aice_write_mem_h(coreid, address, data);
+-}
+-
+-static int aice_usb_write_mem_w_bus(uint32_t coreid, uint32_t address, uint32_t data)
+-{
+- return aice_write_mem(coreid, address, data);
+-}
+-
+-static int aice_usb_write_mem_b_dim(uint32_t coreid, uint32_t address, uint32_t data)
+-{
+- uint32_t instructions[4] = {
+- MFSR_DTR(R1),
+- SBI_BI(R1, R0),
+- DSB,
+- BEQ_MINUS_12
+- };
+-
+- aice_write_dtr(coreid, data & 0xFF);
+- aice_execute_dim(coreid, instructions, 4);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_write_mem_h_dim(uint32_t coreid, uint32_t address, uint32_t data)
+-{
+- uint32_t instructions[4] = {
+- MFSR_DTR(R1),
+- SHI_BI(R1, R0),
+- DSB,
+- BEQ_MINUS_12
+- };
+-
+- aice_write_dtr(coreid, data & 0xFFFF);
+- aice_execute_dim(coreid, instructions, 4);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_write_mem_w_dim(uint32_t coreid, uint32_t address, uint32_t data)
+-{
+- uint32_t instructions[4] = {
+- MFSR_DTR(R1),
+- SWI_BI(R1, R0),
+- DSB,
+- BEQ_MINUS_12
+- };
+-
+- aice_write_dtr(coreid, data);
+- aice_execute_dim(coreid, instructions, 4);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_write_memory_unit(uint32_t coreid, uint32_t addr, uint32_t size,
+- uint32_t count, const uint8_t *buffer)
+-{
+- LOG_DEBUG("aice_usb_write_memory_unit, addr: 0x%08" PRIx32
+- ", size: %" PRIu32 ", count: %" PRIu32 "",
+- addr, size, count);
+-
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_CPU)
+- aice_usb_set_address_dim(coreid, addr);
+-
+- size_t i;
+- write_mem_func_t write_mem_func;
+-
+- switch (size) {
+- case 1:
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_BUS)
+- write_mem_func = aice_usb_write_mem_b_bus;
+- else
+- write_mem_func = aice_usb_write_mem_b_dim;
+-
+- for (i = 0; i < count; i++) {
+- write_mem_func(coreid, addr, *buffer);
+- buffer++;
+- addr++;
+- }
+- break;
+- case 2:
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_BUS)
+- write_mem_func = aice_usb_write_mem_h_bus;
+- else
+- write_mem_func = aice_usb_write_mem_h_dim;
+-
+- for (i = 0; i < count; i++) {
+- uint16_t value;
+- memcpy(&value, buffer, sizeof(uint16_t));
+-
+- write_mem_func(coreid, addr, value);
+- buffer += 2;
+- addr += 2;
+- }
+- break;
+- case 4:
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_BUS)
+- write_mem_func = aice_usb_write_mem_w_bus;
+- else
+- write_mem_func = aice_usb_write_mem_w_dim;
+-
+- for (i = 0; i < count; i++) {
+- uint32_t value;
+- memcpy(&value, buffer, sizeof(uint32_t));
+-
+- write_mem_func(coreid, addr, value);
+- buffer += 4;
+- addr += 4;
+- }
+- break;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_bulk_read_mem(uint32_t coreid, uint32_t addr, uint32_t count,
+- uint8_t *buffer)
+-{
+- uint32_t packet_size;
+-
+- while (count > 0) {
+- packet_size = (count >= 0x100) ? 0x100 : count;
+-
+- /** set address */
+- addr &= 0xFFFFFFFC;
+- if (aice_write_misc(coreid, NDS_EDM_MISC_SBAR, addr) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (aice_fastread_mem(coreid, buffer,
+- packet_size) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- buffer += (packet_size * 4);
+- addr += (packet_size * 4);
+- count -= packet_size;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_bulk_write_mem(uint32_t coreid, uint32_t addr, uint32_t count,
+- const uint8_t *buffer)
+-{
+- uint32_t packet_size;
+-
+- while (count > 0) {
+- packet_size = (count >= 0x100) ? 0x100 : count;
+-
+- /** set address */
+- addr &= 0xFFFFFFFC;
+- if (aice_write_misc(coreid, NDS_EDM_MISC_SBAR, addr | 1) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (aice_fastwrite_mem(coreid, buffer,
+- packet_size) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- buffer += (packet_size * 4);
+- addr += (packet_size * 4);
+- count -= packet_size;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_bulk_read_mem(uint32_t coreid, uint32_t addr,
+- uint32_t length, uint8_t *buffer)
+-{
+- LOG_DEBUG("aice_usb_bulk_read_mem, addr: 0x%08" PRIx32 ", length: 0x%08" PRIx32, addr, length);
+-
+- int retval;
+-
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_CPU)
+- aice_usb_set_address_dim(coreid, addr);
+-
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_CPU)
+- retval = aice_usb_read_memory_unit(coreid, addr, 4, length / 4, buffer);
+- else
+- retval = aice_bulk_read_mem(coreid, addr, length / 4, buffer);
+-
+- return retval;
+-}
+-
+-static int aice_usb_bulk_write_mem(uint32_t coreid, uint32_t addr,
+- uint32_t length, const uint8_t *buffer)
+-{
+- LOG_DEBUG("aice_usb_bulk_write_mem, addr: 0x%08" PRIx32 ", length: 0x%08" PRIx32, addr, length);
+-
+- int retval;
+-
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_CPU)
+- aice_usb_set_address_dim(coreid, addr);
+-
+- if (core_info[coreid].access_channel == NDS_MEMORY_ACC_CPU)
+- retval = aice_usb_write_memory_unit(coreid, addr, 4, length / 4, buffer);
+- else
+- retval = aice_bulk_write_mem(coreid, addr, length / 4, buffer);
+-
+- return retval;
+-}
+-
+-static int aice_usb_read_debug_reg(uint32_t coreid, uint32_t addr, uint32_t *val)
+-{
+- if (core_info[coreid].core_state == AICE_TARGET_HALTED) {
+- if (addr == NDS_EDM_SR_EDMSW) {
+- *val = core_info[coreid].edmsw_backup;
+- } else if (addr == NDS_EDM_SR_EDM_DTR) {
+- if (core_info[coreid].target_dtr_valid) {
+- /* if EDM_DTR has read out, clear it. */
+- *val = core_info[coreid].target_dtr_backup;
+- core_info[coreid].edmsw_backup &= (~0x1);
+- core_info[coreid].target_dtr_valid = false;
+- } else {
+- *val = 0;
+- }
+- }
+- }
+-
+- return aice_read_edmsr(coreid, addr, val);
+-}
+-
+-static int aice_usb_write_debug_reg(uint32_t coreid, uint32_t addr, const uint32_t val)
+-{
+- if (core_info[coreid].core_state == AICE_TARGET_HALTED) {
+- if (addr == NDS_EDM_SR_EDM_DTR) {
+- core_info[coreid].host_dtr_backup = val;
+- core_info[coreid].edmsw_backup |= 0x2;
+- core_info[coreid].host_dtr_valid = true;
+- }
+- }
+-
+- return aice_write_edmsr(coreid, addr, val);
+-}
+-
+-static int aice_usb_memory_access(uint32_t coreid, enum nds_memory_access channel)
+-{
+- LOG_DEBUG("aice_usb_memory_access, access channel: %u", channel);
+-
+- core_info[coreid].access_channel = channel;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_memory_mode(uint32_t coreid, enum nds_memory_select mem_select)
+-{
+- if (core_info[coreid].memory_select == mem_select)
+- return ERROR_OK;
+-
+- LOG_DEBUG("aice_usb_memory_mode, memory select: %u", mem_select);
+-
+- core_info[coreid].memory_select = mem_select;
+-
+- if (core_info[coreid].memory_select != NDS_MEMORY_SELECT_AUTO)
+- aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL,
+- core_info[coreid].memory_select - 1);
+- else
+- aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL,
+- NDS_MEMORY_SELECT_MEM - 1);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_read_tlb(uint32_t coreid, target_addr_t virtual_address,
+- target_addr_t *physical_address)
+-{
+- LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" TARGET_PRIxADDR, virtual_address);
+-
+- uint32_t instructions[4];
+- uint32_t probe_result;
+- uint32_t value_mr3;
+- uint32_t value_mr4;
+- uint32_t access_page_size;
+- uint32_t virtual_offset;
+- uint32_t physical_page_number;
+-
+- aice_write_dtr(coreid, virtual_address);
+-
+- /* probe TLB first */
+- instructions[0] = MFSR_DTR(R0);
+- instructions[1] = TLBOP_TARGET_PROBE(R1, R0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- aice_execute_dim(coreid, instructions, 4);
+-
+- aice_read_reg(coreid, R1, &probe_result);
+-
+- if (probe_result & 0x80000000)
+- return ERROR_FAIL;
+-
+- /* read TLB entry */
+- aice_write_dtr(coreid, probe_result & 0x7FF);
+-
+- /* probe TLB first */
+- instructions[0] = MFSR_DTR(R0);
+- instructions[1] = TLBOP_TARGET_READ(R0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+- aice_execute_dim(coreid, instructions, 4);
+-
+- /* TODO: it should backup mr3, mr4 */
+- aice_read_reg(coreid, MR3, &value_mr3);
+- aice_read_reg(coreid, MR4, &value_mr4);
+-
+- access_page_size = value_mr4 & 0xF;
+- if (access_page_size == 0) { /* 4K page */
+- virtual_offset = virtual_address & 0x00000FFF;
+- physical_page_number = value_mr3 & 0xFFFFF000;
+- } else if (access_page_size == 1) { /* 8K page */
+- virtual_offset = virtual_address & 0x00001FFF;
+- physical_page_number = value_mr3 & 0xFFFFE000;
+- } else if (access_page_size == 5) { /* 1M page */
+- virtual_offset = virtual_address & 0x000FFFFF;
+- physical_page_number = value_mr3 & 0xFFF00000;
+- } else {
+- return ERROR_FAIL;
+- }
+-
+- *physical_address = physical_page_number | virtual_offset;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_init_cache(uint32_t coreid)
+-{
+- LOG_DEBUG("aice_usb_init_cache");
+-
+- uint32_t value_cr1;
+- uint32_t value_cr2;
+-
+- aice_read_reg(coreid, CR1, &value_cr1);
+- aice_read_reg(coreid, CR2, &value_cr2);
+-
+- struct cache_info *icache = &core_info[coreid].icache;
+-
+- icache->set = value_cr1 & 0x7;
+- icache->log2_set = icache->set + 6;
+- icache->set = 64 << icache->set;
+- icache->way = ((value_cr1 >> 3) & 0x7) + 1;
+- icache->line_size = (value_cr1 >> 6) & 0x7;
+- if (icache->line_size != 0) {
+- icache->log2_line_size = icache->line_size + 2;
+- icache->line_size = 8 << (icache->line_size - 1);
+- } else {
+- icache->log2_line_size = 0;
+- }
+-
+- LOG_DEBUG("\ticache set: %" PRIu32 ", way: %" PRIu32 ", line size: %" PRIu32 ", "
+- "log2(set): %" PRIu32 ", log2(line_size): %" PRIu32 "",
+- icache->set, icache->way, icache->line_size,
+- icache->log2_set, icache->log2_line_size);
+-
+- struct cache_info *dcache = &core_info[coreid].dcache;
+-
+- dcache->set = value_cr2 & 0x7;
+- dcache->log2_set = dcache->set + 6;
+- dcache->set = 64 << dcache->set;
+- dcache->way = ((value_cr2 >> 3) & 0x7) + 1;
+- dcache->line_size = (value_cr2 >> 6) & 0x7;
+- if (dcache->line_size != 0) {
+- dcache->log2_line_size = dcache->line_size + 2;
+- dcache->line_size = 8 << (dcache->line_size - 1);
+- } else {
+- dcache->log2_line_size = 0;
+- }
+-
+- LOG_DEBUG("\tdcache set: %" PRIu32 ", way: %" PRIu32 ", line size: %" PRIu32 ", "
+- "log2(set): %" PRIu32 ", log2(line_size): %" PRIu32 "",
+- dcache->set, dcache->way, dcache->line_size,
+- dcache->log2_set, dcache->log2_line_size);
+-
+- core_info[coreid].cache_init = true;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_dcache_inval_all(uint32_t coreid)
+-{
+- LOG_DEBUG("aice_usb_dcache_inval_all");
+-
+- uint32_t set_index;
+- uint32_t way_index;
+- uint32_t cache_index;
+- uint32_t instructions[4];
+-
+- instructions[0] = MFSR_DTR(R0);
+- instructions[1] = L1D_IX_INVAL(R0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+-
+- struct cache_info *dcache = &core_info[coreid].dcache;
+-
+- for (set_index = 0; set_index < dcache->set; set_index++) {
+- for (way_index = 0; way_index < dcache->way; way_index++) {
+- cache_index = (way_index << (dcache->log2_set + dcache->log2_line_size)) |
+- (set_index << dcache->log2_line_size);
+-
+- if (aice_write_dtr(coreid, cache_index) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (aice_execute_dim(coreid, instructions, 4) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_dcache_va_inval(uint32_t coreid, uint32_t address)
+-{
+- LOG_DEBUG("aice_usb_dcache_va_inval");
+-
+- uint32_t instructions[4];
+-
+- aice_write_dtr(coreid, address);
+-
+- instructions[0] = MFSR_DTR(R0);
+- instructions[1] = L1D_VA_INVAL(R0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+-
+- return aice_execute_dim(coreid, instructions, 4);
+-}
+-
+-static int aice_usb_dcache_wb_all(uint32_t coreid)
+-{
+- LOG_DEBUG("aice_usb_dcache_wb_all");
+-
+- uint32_t set_index;
+- uint32_t way_index;
+- uint32_t cache_index;
+- uint32_t instructions[4];
+-
+- instructions[0] = MFSR_DTR(R0);
+- instructions[1] = L1D_IX_WB(R0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+-
+- struct cache_info *dcache = &core_info[coreid].dcache;
+-
+- for (set_index = 0; set_index < dcache->set; set_index++) {
+- for (way_index = 0; way_index < dcache->way; way_index++) {
+- cache_index = (way_index << (dcache->log2_set + dcache->log2_line_size)) |
+- (set_index << dcache->log2_line_size);
+-
+- if (aice_write_dtr(coreid, cache_index) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (aice_execute_dim(coreid, instructions, 4) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_dcache_va_wb(uint32_t coreid, uint32_t address)
+-{
+- LOG_DEBUG("aice_usb_dcache_va_wb");
+-
+- uint32_t instructions[4];
+-
+- aice_write_dtr(coreid, address);
+-
+- instructions[0] = MFSR_DTR(R0);
+- instructions[1] = L1D_VA_WB(R0);
+- instructions[2] = DSB;
+- instructions[3] = BEQ_MINUS_12;
+-
+- return aice_execute_dim(coreid, instructions, 4);
+-}
+-
+-static int aice_usb_icache_inval_all(uint32_t coreid)
+-{
+- LOG_DEBUG("aice_usb_icache_inval_all");
+-
+- uint32_t set_index;
+- uint32_t way_index;
+- uint32_t cache_index;
+- uint32_t instructions[4];
+-
+- instructions[0] = MFSR_DTR(R0);
+- instructions[1] = L1I_IX_INVAL(R0);
+- instructions[2] = ISB;
+- instructions[3] = BEQ_MINUS_12;
+-
+- struct cache_info *icache = &core_info[coreid].icache;
+-
+- for (set_index = 0; set_index < icache->set; set_index++) {
+- for (way_index = 0; way_index < icache->way; way_index++) {
+- cache_index = (way_index << (icache->log2_set + icache->log2_line_size)) |
+- (set_index << icache->log2_line_size);
+-
+- if (aice_write_dtr(coreid, cache_index) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (aice_execute_dim(coreid, instructions, 4) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_icache_va_inval(uint32_t coreid, uint32_t address)
+-{
+- LOG_DEBUG("aice_usb_icache_va_inval");
+-
+- uint32_t instructions[4];
+-
+- aice_write_dtr(coreid, address);
+-
+- instructions[0] = MFSR_DTR(R0);
+- instructions[1] = L1I_VA_INVAL(R0);
+- instructions[2] = ISB;
+- instructions[3] = BEQ_MINUS_12;
+-
+- return aice_execute_dim(coreid, instructions, 4);
+-}
+-
+-static int aice_usb_cache_ctl(uint32_t coreid, uint32_t subtype, uint32_t address)
+-{
+- LOG_DEBUG("aice_usb_cache_ctl");
+-
+- int result;
+-
+- if (core_info[coreid].cache_init == false)
+- aice_usb_init_cache(coreid);
+-
+- switch (subtype) {
+- case AICE_CACHE_CTL_L1D_INVALALL:
+- result = aice_usb_dcache_inval_all(coreid);
+- break;
+- case AICE_CACHE_CTL_L1D_VA_INVAL:
+- result = aice_usb_dcache_va_inval(coreid, address);
+- break;
+- case AICE_CACHE_CTL_L1D_WBALL:
+- result = aice_usb_dcache_wb_all(coreid);
+- break;
+- case AICE_CACHE_CTL_L1D_VA_WB:
+- result = aice_usb_dcache_va_wb(coreid, address);
+- break;
+- case AICE_CACHE_CTL_L1I_INVALALL:
+- result = aice_usb_icache_inval_all(coreid);
+- break;
+- case AICE_CACHE_CTL_L1I_VA_INVAL:
+- result = aice_usb_icache_va_inval(coreid, address);
+- break;
+- default:
+- result = ERROR_FAIL;
+- break;
+- }
+-
+- return result;
+-}
+-
+-static int aice_usb_set_retry_times(uint32_t a_retry_times)
+-{
+- aice_max_retry_times = a_retry_times;
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_program_edm(uint32_t coreid, char *command_sequence)
+-{
+- char *command_str;
+- char *reg_name_0;
+- char *reg_name_1;
+- uint32_t data_value;
+- int i;
+-
+- /* init strtok() */
+- command_str = strtok(command_sequence, ";");
+- if (!command_str)
+- return ERROR_OK;
+-
+- do {
+- i = 0;
+- /* process one command */
+- while (command_str[i] == ' ' ||
+- command_str[i] == '\n' ||
+- command_str[i] == '\r' ||
+- command_str[i] == '\t')
+- i++;
+-
+- /* skip ' ', '\r', '\n', '\t' */
+- command_str = command_str + i;
+-
+- if (strncmp(command_str, "write_misc", 10) == 0) {
+- reg_name_0 = strstr(command_str, "gen_port0");
+- reg_name_1 = strstr(command_str, "gen_port1");
+-
+- if (reg_name_0) {
+- data_value = strtoul(reg_name_0 + 9, NULL, 0);
+-
+- if (aice_write_misc(coreid,
+- NDS_EDM_MISC_GEN_PORT0, data_value) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- } else if (reg_name_1) {
+- data_value = strtoul(reg_name_1 + 9, NULL, 0);
+-
+- if (aice_write_misc(coreid,
+- NDS_EDM_MISC_GEN_PORT1, data_value) != ERROR_OK)
+- return ERROR_FAIL;
+- } else {
+- LOG_ERROR("program EDM, unsupported misc register: %s", command_str);
+- }
+- } else {
+- LOG_ERROR("program EDM, unsupported command: %s", command_str);
+- }
+-
+- /* update command_str */
+- command_str = strtok(NULL, ";");
+-
+- } while (command_str);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_set_command_mode(enum aice_command_mode command_mode)
+-{
+- int retval = ERROR_OK;
+-
+- /* flush usb_packets_buffer as users change mode */
+- retval = aice_usb_packet_flush();
+-
+- if (command_mode == AICE_COMMAND_MODE_BATCH) {
+- /* reset batch buffer */
+- aice_command_mode = AICE_COMMAND_MODE_NORMAL;
+- retval = aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CMD_BUF0_CTRL, 0x40000);
+- }
+-
+- aice_command_mode = command_mode;
+-
+- return retval;
+-}
+-
+-static int aice_usb_execute(uint32_t coreid, uint32_t *instructions,
+- uint32_t instruction_num)
+-{
+- uint32_t i, j;
+- uint8_t current_instruction_num;
+- uint32_t dim_instructions[4] = {NOP, NOP, NOP, BEQ_MINUS_12};
+-
+- /* To execute 4 instructions as a special case */
+- if (instruction_num == 4)
+- return aice_execute_dim(coreid, instructions, 4);
+-
+- for (i = 0 ; i < instruction_num ; i += 3) {
+- if (instruction_num - i < 3) {
+- current_instruction_num = instruction_num - i;
+- for (j = current_instruction_num ; j < 3 ; j++)
+- dim_instructions[j] = NOP;
+- } else {
+- current_instruction_num = 3;
+- }
+-
+- memcpy(dim_instructions, instructions + i,
+- current_instruction_num * sizeof(uint32_t));
+-
+- /** fill DIM */
+- if (aice_write_dim(coreid,
+- dim_instructions,
+- 4) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /** clear DBGER.DPED */
+- if (aice_write_misc(coreid,
+- NDS_EDM_MISC_DBGER, NDS_DBGER_DPED) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /** execute DIM */
+- if (aice_do_execute(coreid) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /** check DBGER.DPED */
+- if (aice_check_dbger(coreid, NDS_DBGER_DPED) != ERROR_OK) {
+-
+- LOG_ERROR("<-- TARGET ERROR! Debug operations do not finish properly:"
+- "0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 ". -->",
+- dim_instructions[0],
+- dim_instructions[1],
+- dim_instructions[2],
+- dim_instructions[3]);
+- return ERROR_FAIL;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_set_custom_srst_script(const char *script)
+-{
+- custom_srst_script = strdup(script);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_set_custom_trst_script(const char *script)
+-{
+- custom_trst_script = strdup(script);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_set_custom_restart_script(const char *script)
+-{
+- custom_restart_script = strdup(script);
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_set_count_to_check_dbger(uint32_t count_to_check)
+-{
+- aice_count_to_check_dbger = count_to_check;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_set_data_endian(uint32_t coreid,
+- enum aice_target_endian target_data_endian)
+-{
+- data_endian = target_data_endian;
+-
+- return ERROR_OK;
+-}
+-
+-static int fill_profiling_batch_commands(uint32_t coreid, uint32_t reg_no)
+-{
+- uint32_t dim_instructions[4];
+-
+- aice_usb_set_command_mode(AICE_COMMAND_MODE_BATCH);
+-
+- /* halt */
+- if (aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /* backup $r0 */
+- dim_instructions[0] = MTSR_DTR(0);
+- dim_instructions[1] = DSB;
+- dim_instructions[2] = NOP;
+- dim_instructions[3] = BEQ_MINUS_12;
+- if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK)
+- return ERROR_FAIL;
+- aice_read_dtr_to_buffer(coreid, AICE_BATCH_DATA_BUFFER_0);
+-
+- /* get samples */
+- if (nds32_reg_type(reg_no) == NDS32_REG_TYPE_GPR) {
+- /* general registers */
+- dim_instructions[0] = MTSR_DTR(reg_no);
+- dim_instructions[1] = DSB;
+- dim_instructions[2] = NOP;
+- dim_instructions[3] = BEQ_MINUS_12;
+- } else if (nds32_reg_type(reg_no) == NDS32_REG_TYPE_SPR) {
+- /* user special registers */
+- dim_instructions[0] = MFUSR_G0(0, nds32_reg_sr_index(reg_no));
+- dim_instructions[1] = MTSR_DTR(0);
+- dim_instructions[2] = DSB;
+- dim_instructions[3] = BEQ_MINUS_12;
+- } else { /* system registers */
+- dim_instructions[0] = MFSR(0, nds32_reg_sr_index(reg_no));
+- dim_instructions[1] = MTSR_DTR(0);
+- dim_instructions[2] = DSB;
+- dim_instructions[3] = BEQ_MINUS_12;
+- }
+- if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK)
+- return ERROR_FAIL;
+- aice_read_dtr_to_buffer(coreid, AICE_BATCH_DATA_BUFFER_1);
+-
+- /* restore $r0 */
+- aice_write_dtr_from_buffer(coreid, AICE_BATCH_DATA_BUFFER_0);
+- dim_instructions[0] = MFSR_DTR(0);
+- dim_instructions[1] = DSB;
+- dim_instructions[2] = NOP;
+- dim_instructions[3] = IRET; /* free run */
+- if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- aice_command_mode = AICE_COMMAND_MODE_NORMAL;
+-
+- /* use BATCH_BUFFER_WRITE to fill command-batch-buffer */
+- if (aice_batch_buffer_write(AICE_BATCH_COMMAND_BUFFER_0,
+- usb_out_packets_buffer,
+- (usb_out_packets_buffer_length + 3) / 4) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- usb_out_packets_buffer_length = 0;
+- usb_in_packets_buffer_length = 0;
+-
+- return ERROR_OK;
+-}
+-
+-static int aice_usb_profiling(uint32_t coreid, uint32_t interval, uint32_t iteration,
+- uint32_t reg_no, uint32_t *samples, uint32_t *num_samples)
+-{
+- uint32_t iteration_count;
+- uint32_t this_iteration;
+- int retval = ERROR_OK;
+- const uint32_t MAX_ITERATION = 250;
+-
+- *num_samples = 0;
+-
+- /* init DIM size */
+- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DIM_SIZE, 4) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /* Use AICE_BATCH_DATA_BUFFER_0 to read/write $DTR.
+- * Set it to circular buffer */
+- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF0_CTRL, 0xC0000) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- fill_profiling_batch_commands(coreid, reg_no);
+-
+- iteration_count = 0;
+- while (iteration_count < iteration) {
+- if (iteration - iteration_count < MAX_ITERATION)
+- this_iteration = iteration - iteration_count;
+- else
+- this_iteration = MAX_ITERATION;
+-
+- /* set number of iterations */
+- uint32_t val_iteration;
+- val_iteration = interval << 16 | this_iteration;
+- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_ITERATION,
+- val_iteration) != ERROR_OK) {
+- retval = ERROR_FAIL;
+- goto end_profiling;
+- }
+-
+- /* init AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL to store $PC */
+- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL,
+- 0x40000) != ERROR_OK) {
+- retval = ERROR_FAIL;
+- goto end_profiling;
+- }
+-
+- aice_usb_run(coreid);
+-
+- /* enable BATCH command */
+- if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CTRL,
+- 0x80000000) != ERROR_OK) {
+- aice_usb_halt(coreid);
+- retval = ERROR_FAIL;
+- goto end_profiling;
+- }
+-
+- /* wait a while (AICE bug, workaround) */
+- alive_sleep(this_iteration);
+-
+- /* check status */
+- uint32_t i;
+- uint32_t batch_status = 0;
+-
+- i = 0;
+- while (1) {
+- aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
+-
+- if (batch_status & 0x1) {
+- break;
+- } else if (batch_status & 0xE) {
+- aice_usb_halt(coreid);
+- retval = ERROR_FAIL;
+- goto end_profiling;
+- }
+-
+- if ((i % 30) == 0)
+- keep_alive();
+-
+- i++;
+- }
+-
+- aice_usb_halt(coreid);
+-
+- /* get samples from batch data buffer */
+- if (aice_batch_buffer_read(AICE_BATCH_DATA_BUFFER_1,
+- samples + iteration_count, this_iteration) != ERROR_OK) {
+- retval = ERROR_FAIL;
+- goto end_profiling;
+- }
+-
+- iteration_count += this_iteration;
+- }
+-
+-end_profiling:
+- *num_samples = iteration_count;
+-
+- return retval;
+-}
+-
+-/** */
+-struct aice_port_api_s aice_usb_api = {
+- /** */
+- .open = aice_open_device,
+- /** */
+- .close = aice_usb_close,
+- /** */
+- .idcode = aice_usb_idcode,
+- /** */
+- .state = aice_usb_state,
+- /** */
+- .reset = aice_usb_reset,
+- /** */
+- .assert_srst = aice_usb_assert_srst,
+- /** */
+- .run = aice_usb_run,
+- /** */
+- .halt = aice_usb_halt,
+- /** */
+- .step = aice_usb_step,
+- /** */
+- .read_reg = aice_usb_read_reg,
+- /** */
+- .write_reg = aice_usb_write_reg,
+- /** */
+- .read_reg_64 = aice_usb_read_reg_64,
+- /** */
+- .write_reg_64 = aice_usb_write_reg_64,
+- /** */
+- .read_mem_unit = aice_usb_read_memory_unit,
+- /** */
+- .write_mem_unit = aice_usb_write_memory_unit,
+- /** */
+- .read_mem_bulk = aice_usb_bulk_read_mem,
+- /** */
+- .write_mem_bulk = aice_usb_bulk_write_mem,
+- /** */
+- .read_debug_reg = aice_usb_read_debug_reg,
+- /** */
+- .write_debug_reg = aice_usb_write_debug_reg,
+- /** */
+- .set_jtag_clock = aice_usb_set_jtag_clock,
+- /** */
+- .memory_access = aice_usb_memory_access,
+- /** */
+- .memory_mode = aice_usb_memory_mode,
+- /** */
+- .read_tlb = aice_usb_read_tlb,
+- /** */
+- .cache_ctl = aice_usb_cache_ctl,
+- /** */
+- .set_retry_times = aice_usb_set_retry_times,
+- /** */
+- .program_edm = aice_usb_program_edm,
+- /** */
+- .set_command_mode = aice_usb_set_command_mode,
+- /** */
+- .execute = aice_usb_execute,
+- /** */
+- .set_custom_srst_script = aice_usb_set_custom_srst_script,
+- /** */
+- .set_custom_trst_script = aice_usb_set_custom_trst_script,
+- /** */
+- .set_custom_restart_script = aice_usb_set_custom_restart_script,
+- /** */
+- .set_count_to_check_dbger = aice_usb_set_count_to_check_dbger,
+- /** */
+- .set_data_endian = aice_usb_set_data_endian,
+- /** */
+- .profiling = aice_usb_profiling,
+-};
+diff --git a/src/jtag/aice/aice_usb.h b/src/jtag/aice/aice_usb.h
+deleted file mode 100644
+index d85d25f89..000000000
+--- a/src/jtag/aice/aice_usb.h
++++ /dev/null
+@@ -1,122 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 by Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_JTAG_AICE_AICE_USB_H
+-#define OPENOCD_JTAG_AICE_AICE_USB_H
+-
+-#include "aice_port.h"
+-
+-/* AICE USB timeout value */
+-#define AICE_USB_TIMEOUT 5000
+-
+-/* AICE USB buffer size */
+-#define AICE_IN_BUFFER_SIZE 2048
+-#define AICE_OUT_BUFFER_SIZE 2048
+-#define AICE_IN_PACKETS_BUFFER_SIZE 2048
+-#define AICE_OUT_PACKETS_BUFFER_SIZE 2048
+-#define AICE_IN_BATCH_COMMAND_SIZE 512
+-#define AICE_OUT_BATCH_COMMAND_SIZE 512
+-#define AICE_IN_PACK_COMMAND_SIZE 2048
+-#define AICE_OUT_PACK_COMMAND_SIZE 2048
+-
+-/* Constants for AICE command READ_CTRL */
+-#define AICE_READ_CTRL_GET_ICE_STATE 0x00
+-#define AICE_READ_CTRL_GET_HARDWARE_VERSION 0x01
+-#define AICE_READ_CTRL_GET_FPGA_VERSION 0x02
+-#define AICE_READ_CTRL_GET_FIRMWARE_VERSION 0x03
+-#define AICE_READ_CTRL_GET_JTAG_PIN_STATUS 0x04
+-#define AICE_READ_CTRL_BATCH_BUF_INFO 0x22
+-#define AICE_READ_CTRL_BATCH_STATUS 0x23
+-#define AICE_READ_CTRL_BATCH_BUF0_STATE 0x31
+-#define AICE_READ_CTRL_BATCH_BUF4_STATE 0x39
+-#define AICE_READ_CTRL_BATCH_BUF5_STATE 0x3b
+-
+-/* Constants for AICE command WRITE_CTRL */
+-#define AICE_WRITE_CTRL_TCK_CONTROL 0x00
+-#define AICE_WRITE_CTRL_JTAG_PIN_CONTROL 0x01
+-#define AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS 0x02
+-#define AICE_WRITE_CTRL_RESERVED 0x03
+-#define AICE_WRITE_CTRL_JTAG_PIN_STATUS 0x04
+-#define AICE_WRITE_CTRL_CUSTOM_DELAY 0x0d
+-#define AICE_WRITE_CTRL_BATCH_CTRL 0x20
+-#define AICE_WRITE_CTRL_BATCH_ITERATION 0x21
+-#define AICE_WRITE_CTRL_BATCH_DIM_SIZE 0x22
+-#define AICE_WRITE_CTRL_BATCH_CMD_BUF0_CTRL 0x30
+-#define AICE_WRITE_CTRL_BATCH_DATA_BUF0_CTRL 0x38
+-#define AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL 0x3a
+-
+-#define AICE_BATCH_COMMAND_BUFFER_0 0x0
+-#define AICE_BATCH_COMMAND_BUFFER_1 0x1
+-#define AICE_BATCH_COMMAND_BUFFER_2 0x2
+-#define AICE_BATCH_COMMAND_BUFFER_3 0x3
+-#define AICE_BATCH_DATA_BUFFER_0 0x4
+-#define AICE_BATCH_DATA_BUFFER_1 0x5
+-#define AICE_BATCH_DATA_BUFFER_2 0x6
+-#define AICE_BATCH_DATA_BUFFER_3 0x7
+-
+-/* Constants for AICE command WRITE_CTRL:TCK_CONTROL */
+-#define AICE_TCK_CONTROL_TCK3048 0x08
+-#define AICE_TCK_CONTROL_TCK_SCAN 0x10
+-
+-/* Constants for AICE command WRITE_CTRL:JTAG_PIN_CONTROL */
+-#define AICE_JTAG_PIN_CONTROL_SRST 0x01
+-#define AICE_JTAG_PIN_CONTROL_TRST 0x02
+-#define AICE_JTAG_PIN_CONTROL_STOP 0x04
+-#define AICE_JTAG_PIN_CONTROL_RESTART 0x08
+-
+-/* Constants for AICE command WRITE_CTRL:TCK_CONTROL */
+-#define AICE_TCK_CONTROL_TCK_SCAN 0x10
+-
+-/* Custom SRST/DBGI/TRST */
+-#define AICE_CUSTOM_DELAY_SET_SRST 0x01
+-#define AICE_CUSTOM_DELAY_CLEAN_SRST 0x02
+-#define AICE_CUSTOM_DELAY_SET_DBGI 0x04
+-#define AICE_CUSTOM_DELAY_CLEAN_DBGI 0x08
+-#define AICE_CUSTOM_DELAY_SET_TRST 0x10
+-#define AICE_CUSTOM_DELAY_CLEAN_TRST 0x20
+-
+-struct aice_usb_handler_s {
+- unsigned int usb_read_ep;
+- unsigned int usb_write_ep;
+- struct libusb_device_handle *usb_handle;
+-};
+-
+-struct cache_info {
+- uint32_t set;
+- uint32_t way;
+- uint32_t line_size;
+-
+- uint32_t log2_set;
+- uint32_t log2_line_size;
+-};
+-
+-struct aice_nds32_info {
+- uint32_t edm_version;
+- uint32_t r0_backup;
+- uint32_t r1_backup;
+- uint32_t host_dtr_backup;
+- uint32_t target_dtr_backup;
+- uint32_t edmsw_backup;
+- uint32_t edm_ctl_backup;
+- bool debug_under_dex_on;
+- bool dex_use_psw_on;
+- bool host_dtr_valid;
+- bool target_dtr_valid;
+- enum nds_memory_access access_channel;
+- enum nds_memory_select memory_select;
+- enum aice_target_state_s core_state;
+- bool cache_init;
+- struct cache_info icache;
+- struct cache_info dcache;
+-};
+-
+-extern struct aice_port_api_s aice_usb_api;
+-
+-int aice_read_ctrl(uint32_t address, uint32_t *data);
+-int aice_write_ctrl(uint32_t address, uint32_t data);
+-
+-#endif /* OPENOCD_JTAG_AICE_AICE_USB_H */
+diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
+index 67bbb3b36..12848be03 100644
+--- a/src/jtag/interfaces.c
++++ b/src/jtag/interfaces.c
+@@ -118,9 +118,6 @@ extern struct adapter_driver linuxgpiod_adapter_driver;
+ #if BUILD_XLNX_PCIE_XVC == 1
+ extern struct adapter_driver xlnx_pcie_xvc_adapter_driver;
+ #endif
+-#if BUILD_AICE == 1
+-extern struct adapter_driver aice_adapter_driver;
+-#endif
+ #if BUILD_BCM2835GPIO == 1
+ extern struct adapter_driver bcm2835gpio_adapter_driver;
+ #endif
+@@ -238,9 +235,6 @@ struct adapter_driver *adapter_drivers[] = {
+ #if BUILD_XLNX_PCIE_XVC == 1
+ &xlnx_pcie_xvc_adapter_driver,
+ #endif
+-#if BUILD_AICE == 1
+- &aice_adapter_driver,
+-#endif
+ #if BUILD_BCM2835GPIO == 1
+ &bcm2835gpio_adapter_driver,
+ #endif
+diff --git a/src/jtag/startup.tcl b/src/jtag/startup.tcl
+index aeb42ed4f..b74775a74 100644
+--- a/src/jtag/startup.tcl
++++ b/src/jtag/startup.tcl
+@@ -865,12 +865,6 @@ proc ft232r_restore_serial args {
+ eval ft232r restore_serial $args
+ }
+
+-lappend _telnet_autocomplete_skip "aice serial"
+-proc "aice serial" {args} {
+- echo "DEPRECATED! use 'adapter serial' not 'aice serial'"
+- eval adapter serial $args
+-}
+-
+ lappend _telnet_autocomplete_skip cmsis_dap_serial
+ proc cmsis_dap_serial args {
+ echo "DEPRECATED! use 'adapter serial' not 'cmsis_dap_serial'"
+diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c
+index 8403a4802..945c4b875 100644
+--- a/src/rtos/FreeRTOS.c
++++ b/src/rtos/FreeRTOS.c
+@@ -71,20 +71,6 @@ static const struct freertos_params freertos_params_list[] = {
+ &rtos_standard_cortex_m4f_stacking,
+ &rtos_standard_cortex_m4f_fpu_stacking,
+ },
+- {
+- "nds32_v3", /* target_name */
+- 4, /* thread_count_width; */
+- 4, /* pointer_width; */
+- 16, /* list_next_offset; */
+- 20, /* list_width; */
+- 8, /* list_elem_next_offset; */
+- 12, /* list_elem_content_offset */
+- 0, /* thread_stack_offset; */
+- 52, /* thread_name_offset; */
+- &rtos_standard_nds32_n1068_stacking, /* stacking_info */
+- &rtos_standard_cortex_m4f_stacking,
+- &rtos_standard_cortex_m4f_fpu_stacking,
+- },
+ };
+
+ static bool freertos_detect_rtos(struct target *target);
+diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c
+index 594511749..f83f0a1fb 100644
+--- a/src/rtos/rtos_standard_stackings.c
++++ b/src/rtos/rtos_standard_stackings.c
+@@ -102,45 +102,6 @@ static const struct stack_register_offset rtos_standard_cortex_r4_stack_offsets[
+ { 26, 0x04, 32 }, /* CSPR */
+ };
+
+-static const struct stack_register_offset rtos_standard_nds32_n1068_stack_offsets[] = {
+- { 0, 0x88, 32 }, /* R0 */
+- { 1, 0x8C, 32 }, /* R1 */
+- { 2, 0x14, 32 }, /* R2 */
+- { 3, 0x18, 32 }, /* R3 */
+- { 4, 0x1C, 32 }, /* R4 */
+- { 5, 0x20, 32 }, /* R5 */
+- { 6, 0x24, 32 }, /* R6 */
+- { 7, 0x28, 32 }, /* R7 */
+- { 8, 0x2C, 32 }, /* R8 */
+- { 9, 0x30, 32 }, /* R9 */
+- { 10, 0x34, 32 }, /* R10 */
+- { 11, 0x38, 32 }, /* R11 */
+- { 12, 0x3C, 32 }, /* R12 */
+- { 13, 0x40, 32 }, /* R13 */
+- { 14, 0x44, 32 }, /* R14 */
+- { 15, 0x48, 32 }, /* R15 */
+- { 16, 0x4C, 32 }, /* R16 */
+- { 17, 0x50, 32 }, /* R17 */
+- { 18, 0x54, 32 }, /* R18 */
+- { 19, 0x58, 32 }, /* R19 */
+- { 20, 0x5C, 32 }, /* R20 */
+- { 21, 0x60, 32 }, /* R21 */
+- { 22, 0x64, 32 }, /* R22 */
+- { 23, 0x68, 32 }, /* R23 */
+- { 24, 0x6C, 32 }, /* R24 */
+- { 25, 0x70, 32 }, /* R25 */
+- { 26, 0x74, 32 }, /* R26 */
+- { 27, 0x78, 32 }, /* R27 */
+- { 28, 0x7C, 32 }, /* R28 */
+- { 29, 0x80, 32 }, /* R29 */
+- { 30, 0x84, 32 }, /* R30 (LP) */
+- { 31, 0x00, 32 }, /* R31 (SP) */
+- { 32, 0x04, 32 }, /* PSW */
+- { 33, 0x08, 32 }, /* IPC */
+- { 34, 0x0C, 32 }, /* IPSW */
+- { 35, 0x10, 32 }, /* IFC_LP */
+-};
+-
+ static target_addr_t rtos_generic_stack_align(struct target *target,
+ const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
+ target_addr_t stack_ptr, int align)
+@@ -268,11 +229,3 @@ const struct rtos_register_stacking rtos_standard_cortex_r4_stacking = {
+ .calculate_process_stack = rtos_generic_stack_align8,
+ .register_offsets = rtos_standard_cortex_r4_stack_offsets
+ };
+-
+-const struct rtos_register_stacking rtos_standard_nds32_n1068_stacking = {
+- .stack_registers_size = 0x90,
+- .stack_growth_direction = -1,
+- .num_output_registers = 32,
+- .calculate_process_stack = rtos_generic_stack_align8,
+- .register_offsets = rtos_standard_nds32_n1068_stack_offsets
+-};
+diff --git a/src/rtos/rtos_standard_stackings.h b/src/rtos/rtos_standard_stackings.h
+index 83ca07f9e..2477fffd1 100644
+--- a/src/rtos/rtos_standard_stackings.h
++++ b/src/rtos/rtos_standard_stackings.h
+@@ -18,7 +18,6 @@ extern const struct rtos_register_stacking rtos_standard_cortex_m3_stacking;
+ extern const struct rtos_register_stacking rtos_standard_cortex_m4f_stacking;
+ extern const struct rtos_register_stacking rtos_standard_cortex_m4f_fpu_stacking;
+ extern const struct rtos_register_stacking rtos_standard_cortex_r4_stacking;
+-extern const struct rtos_register_stacking rtos_standard_nds32_n1068_stacking;
+ target_addr_t rtos_generic_stack_align8(struct target *target,
+ const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
+ target_addr_t stack_ptr);
+diff --git a/src/target/Makefile.am b/src/target/Makefile.am
+index 46870922a..2084de65e 100644
+--- a/src/target/Makefile.am
++++ b/src/target/Makefile.am
+@@ -19,7 +19,6 @@ noinst_LTLIBRARIES += %D%/libtarget.la
+ $(ARM_MISC_SRC) \
+ $(AVR32_SRC) \
+ $(MIPS32_SRC) \
+- $(NDS32_SRC) \
+ $(STM8_SRC) \
+ $(INTEL_IA32_SRC) \
+ $(ESIRISC_SRC) \
+@@ -134,18 +133,6 @@ MIPS64_SRC = \
+ %D%/trace.c \
+ %D%/mips_ejtag.c
+
+-NDS32_SRC = \
+- %D%/nds32.c \
+- %D%/nds32_reg.c \
+- %D%/nds32_cmd.c \
+- %D%/nds32_disassembler.c \
+- %D%/nds32_tlb.c \
+- %D%/nds32_v2.c \
+- %D%/nds32_v3_common.c \
+- %D%/nds32_v3.c \
+- %D%/nds32_v3m.c \
+- %D%/nds32_aice.c
+-
+ STM8_SRC = \
+ %D%/stm8.c
+
+@@ -235,18 +222,6 @@ ARC_SRC = \
+ %D%/avr32_jtag.h \
+ %D%/avr32_mem.h \
+ %D%/avr32_regs.h \
+- %D%/nds32.h \
+- %D%/nds32_cmd.h \
+- %D%/nds32_disassembler.h \
+- %D%/nds32_edm.h \
+- %D%/nds32_insn.h \
+- %D%/nds32_reg.h \
+- %D%/nds32_tlb.h \
+- %D%/nds32_v2.h \
+- %D%/nds32_v3_common.h \
+- %D%/nds32_v3.h \
+- %D%/nds32_v3m.h \
+- %D%/nds32_aice.h \
+ %D%/semihosting_common.h \
+ %D%/stm8.h \
+ %D%/lakemont.h \
+@@ -265,4 +240,4 @@ ARC_SRC = \
+ include %D%/openrisc/Makefile.am
+ include %D%/riscv/Makefile.am
+ include %D%/xtensa/Makefile.am
+-include %D%/espressif/Makefile.am
+\ No newline at end of file
++include %D%/espressif/Makefile.am
+diff --git a/src/target/nds32.c b/src/target/nds32.c
+deleted file mode 100644
+index bd3097683..000000000
+--- a/src/target/nds32.c
++++ /dev/null
+@@ -1,2613 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <helper/log.h>
+-#include <helper/binarybuffer.h>
+-#include "nds32.h"
+-#include "nds32_aice.h"
+-#include "nds32_tlb.h"
+-#include "nds32_disassembler.h"
+-
+-struct nds32_edm_operation nds32_edm_ops[NDS32_EDM_OPERATION_MAX_NUM];
+-uint32_t nds32_edm_ops_num;
+-
+-const char *nds32_debug_type_name[11] = {
+- "SOFTWARE BREAK",
+- "SOFTWARE BREAK_16",
+- "HARDWARE BREAKPOINT",
+- "DATA ADDR WATCHPOINT PRECISE",
+- "DATA VALUE WATCHPOINT PRECISE",
+- "DATA VALUE WATCHPOINT IMPRECISE",
+- "DEBUG INTERRUPT",
+- "HARDWARE SINGLE STEP",
+- "DATA ADDR WATCHPOINT NEXT PRECISE",
+- "DATA VALUE WATCHPOINT NEXT PRECISE",
+- "LOAD STORE GLOBAL STOP",
+-};
+-
+-static const int nds32_lm_size_table[16] = {
+- 4 * 1024,
+- 8 * 1024,
+- 16 * 1024,
+- 32 * 1024,
+- 64 * 1024,
+- 128 * 1024,
+- 256 * 1024,
+- 512 * 1024,
+- 1024 * 1024,
+- 1 * 1024,
+- 2 * 1024,
+-};
+-
+-static const int nds32_line_size_table[6] = {
+- 0,
+- 8,
+- 16,
+- 32,
+- 64,
+- 128,
+-};
+-
+-static int nds32_get_core_reg(struct reg *reg)
+-{
+- int retval;
+- struct nds32_reg *reg_arch_info = reg->arch_info;
+- struct target *target = reg_arch_info->target;
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- if (target->state != TARGET_HALTED) {
+- LOG_ERROR("Target not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- if (reg->valid) {
+- uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32);
+- LOG_DEBUG("reading register(cached) %" PRIi32 "(%s), value: 0x%8.8" PRIx32,
+- reg_arch_info->num, reg->name, val);
+- return ERROR_OK;
+- }
+-
+- int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num);
+-
+- if (reg_arch_info->enable == false) {
+- buf_set_u32(reg_arch_info->value, 0, 32, NDS32_REGISTER_DISABLE);
+- retval = ERROR_FAIL;
+- } else {
+- uint32_t val = 0;
+- if ((nds32->fpu_enable == false)
+- && (nds32_reg_type(mapped_regnum) == NDS32_REG_TYPE_FPU)) {
+- retval = ERROR_OK;
+- } else if ((nds32->audio_enable == false)
+- && (nds32_reg_type(mapped_regnum) == NDS32_REG_TYPE_AUMR)) {
+- retval = ERROR_OK;
+- } else {
+- retval = aice_read_register(aice, mapped_regnum, &val);
+- }
+- buf_set_u32(reg_arch_info->value, 0, 32, val);
+-
+- LOG_DEBUG("reading register %" PRIi32 "(%s), value: 0x%8.8" PRIx32,
+- reg_arch_info->num, reg->name, val);
+- }
+-
+- if (retval == ERROR_OK) {
+- reg->valid = true;
+- reg->dirty = false;
+- }
+-
+- return retval;
+-}
+-
+-static int nds32_get_core_reg_64(struct reg *reg)
+-{
+- int retval;
+- struct nds32_reg *reg_arch_info = reg->arch_info;
+- struct target *target = reg_arch_info->target;
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- if (target->state != TARGET_HALTED) {
+- LOG_ERROR("Target not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- if (reg->valid)
+- return ERROR_OK;
+-
+- if (reg_arch_info->enable == false) {
+- buf_set_u64(reg_arch_info->value, 0, 64, NDS32_REGISTER_DISABLE);
+- retval = ERROR_FAIL;
+- } else {
+- uint64_t val = 0;
+- if ((nds32->fpu_enable == false)
+- && ((reg_arch_info->num >= FD0) && (reg_arch_info->num <= FD31))) {
+- retval = ERROR_OK;
+- } else {
+- retval = aice_read_reg_64(aice, reg_arch_info->num, &val);
+- }
+- buf_set_u64(reg_arch_info->value, 0, 64, val);
+- }
+-
+- if (retval == ERROR_OK) {
+- reg->valid = true;
+- reg->dirty = false;
+- }
+-
+- return retval;
+-}
+-
+-static int nds32_update_psw(struct nds32 *nds32)
+-{
+- uint32_t value_ir0;
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+-
+- nds32_get_mapped_reg(nds32, IR0, &value_ir0);
+-
+- /* Save data memory endian */
+- if ((value_ir0 >> 5) & 0x1) {
+- nds32->data_endian = TARGET_BIG_ENDIAN;
+- aice_set_data_endian(aice, AICE_BIG_ENDIAN);
+- } else {
+- nds32->data_endian = TARGET_LITTLE_ENDIAN;
+- aice_set_data_endian(aice, AICE_LITTLE_ENDIAN);
+- }
+-
+- /* Save translation status */
+- nds32->memory.address_translation = ((value_ir0 >> 7) & 0x1) ? true : false;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_update_mmu_info(struct nds32 *nds32)
+-{
+- uint32_t value;
+-
+- /* Update MMU control status */
+- nds32_get_mapped_reg(nds32, MR0, &value);
+- nds32->mmu_config.default_min_page_size = value & 0x1;
+- nds32->mmu_config.multiple_page_size_in_use = (value >> 10) & 0x1;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_update_cache_info(struct nds32 *nds32)
+-{
+- uint32_t value;
+-
+- if (nds32_get_mapped_reg(nds32, MR8, &value) == ERROR_OK) {
+- if (value & 0x1)
+- nds32->memory.icache.enable = true;
+- else
+- nds32->memory.icache.enable = false;
+-
+- if (value & 0x2)
+- nds32->memory.dcache.enable = true;
+- else
+- nds32->memory.dcache.enable = false;
+- } else {
+- nds32->memory.icache.enable = false;
+- nds32->memory.dcache.enable = false;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_update_lm_info(struct nds32 *nds32)
+-{
+- struct nds32_memory *memory = &(nds32->memory);
+- uint32_t value_mr6;
+- uint32_t value_mr7;
+-
+- nds32_get_mapped_reg(nds32, MR6, &value_mr6);
+- if (value_mr6 & 0x1)
+- memory->ilm_enable = true;
+- else
+- memory->ilm_enable = false;
+-
+- if (memory->ilm_align_ver == 0) { /* 1MB aligned */
+- memory->ilm_start = value_mr6 & 0xFFF00000;
+- memory->ilm_end = memory->ilm_start + memory->ilm_size;
+- } else if (memory->ilm_align_ver == 1) { /* aligned to local memory size */
+- memory->ilm_start = value_mr6 & 0xFFFFFC00;
+- memory->ilm_end = memory->ilm_start + memory->ilm_size;
+- } else {
+- memory->ilm_start = -1;
+- memory->ilm_end = -1;
+- }
+-
+- nds32_get_mapped_reg(nds32, MR7, &value_mr7);
+- if (value_mr7 & 0x1)
+- memory->dlm_enable = true;
+- else
+- memory->dlm_enable = false;
+-
+- if (memory->dlm_align_ver == 0) { /* 1MB aligned */
+- memory->dlm_start = value_mr7 & 0xFFF00000;
+- memory->dlm_end = memory->dlm_start + memory->dlm_size;
+- } else if (memory->dlm_align_ver == 1) { /* aligned to local memory size */
+- memory->dlm_start = value_mr7 & 0xFFFFFC00;
+- memory->dlm_end = memory->dlm_start + memory->dlm_size;
+- } else {
+- memory->dlm_start = -1;
+- memory->dlm_end = -1;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-/**
+- * If fpu/audio is disabled, to access fpu/audio registers will cause
+- * exceptions. So, we need to check if fpu/audio is enabled or not as
+- * target is halted. If fpu/audio is disabled, as users access fpu/audio
+- * registers, OpenOCD will return fake value 0 instead of accessing
+- * registers through DIM.
+- */
+-static int nds32_check_extension(struct nds32 *nds32)
+-{
+- uint32_t value;
+-
+- nds32_get_mapped_reg(nds32, FUCPR, &value);
+- if (value == NDS32_REGISTER_DISABLE) {
+- nds32->fpu_enable = false;
+- nds32->audio_enable = false;
+- return ERROR_OK;
+- }
+-
+- if (value & 0x1)
+- nds32->fpu_enable = true;
+- else
+- nds32->fpu_enable = false;
+-
+- if (value & 0x80000000)
+- nds32->audio_enable = true;
+- else
+- nds32->audio_enable = false;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_set_core_reg(struct reg *reg, uint8_t *buf)
+-{
+- struct nds32_reg *reg_arch_info = reg->arch_info;
+- struct target *target = reg_arch_info->target;
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- uint32_t value = buf_get_u32(buf, 0, 32);
+-
+- if (target->state != TARGET_HALTED) {
+- LOG_ERROR("Target not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num);
+-
+- /* ignore values that will generate exception */
+- if (nds32_reg_exception(mapped_regnum, value))
+- return ERROR_OK;
+-
+- LOG_DEBUG("writing register %" PRIi32 "(%s) with value 0x%8.8" PRIx32,
+- reg_arch_info->num, reg->name, value);
+-
+- if ((nds32->fpu_enable == false) &&
+- (nds32_reg_type(mapped_regnum) == NDS32_REG_TYPE_FPU)) {
+-
+- buf_set_u32(reg->value, 0, 32, 0);
+- } else if ((nds32->audio_enable == false) &&
+- (nds32_reg_type(mapped_regnum) == NDS32_REG_TYPE_AUMR)) {
+-
+- buf_set_u32(reg->value, 0, 32, 0);
+- } else {
+- buf_set_u32(reg->value, 0, 32, value);
+- uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32);
+- aice_write_register(aice, mapped_regnum, val);
+-
+- /* After set value to registers, read the value from target
+- * to avoid W1C inconsistency. */
+- aice_read_register(aice, mapped_regnum, &val);
+- buf_set_u32(reg_arch_info->value, 0, 32, val);
+- }
+-
+- reg->valid = true;
+- reg->dirty = false;
+-
+- /* update registers to take effect right now */
+- if (mapped_regnum == IR0) {
+- nds32_update_psw(nds32);
+- } else if (mapped_regnum == MR0) {
+- nds32_update_mmu_info(nds32);
+- } else if ((mapped_regnum == MR6) || (mapped_regnum == MR7)) {
+- /* update lm information */
+- nds32_update_lm_info(nds32);
+- } else if (mapped_regnum == MR8) {
+- nds32_update_cache_info(nds32);
+- } else if (mapped_regnum == FUCPR) {
+- /* update audio/fpu setting */
+- nds32_check_extension(nds32);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_set_core_reg_64(struct reg *reg, uint8_t *buf)
+-{
+- struct nds32_reg *reg_arch_info = reg->arch_info;
+- struct target *target = reg_arch_info->target;
+- struct nds32 *nds32 = target_to_nds32(target);
+- uint32_t low_part = buf_get_u32(buf, 0, 32);
+- uint32_t high_part = buf_get_u32(buf, 32, 32);
+-
+- if (target->state != TARGET_HALTED) {
+- LOG_ERROR("Target not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- if ((nds32->fpu_enable == false) &&
+- ((reg_arch_info->num >= FD0) && (reg_arch_info->num <= FD31))) {
+-
+- buf_set_u32(reg->value, 0, 32, 0);
+- buf_set_u32(reg->value, 32, 32, 0);
+-
+- reg->valid = true;
+- reg->dirty = false;
+- } else {
+- buf_set_u32(reg->value, 0, 32, low_part);
+- buf_set_u32(reg->value, 32, 32, high_part);
+-
+- reg->valid = true;
+- reg->dirty = true;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static const struct reg_arch_type nds32_reg_access_type = {
+- .get = nds32_get_core_reg,
+- .set = nds32_set_core_reg,
+-};
+-
+-static const struct reg_arch_type nds32_reg_access_type_64 = {
+- .get = nds32_get_core_reg_64,
+- .set = nds32_set_core_reg_64,
+-};
+-
+-static struct reg_cache *nds32_build_reg_cache(struct target *target,
+- struct nds32 *nds32)
+-{
+- struct reg_cache *cache = calloc(sizeof(struct reg_cache), 1);
+- struct reg *reg_list = calloc(TOTAL_REG_NUM, sizeof(struct reg));
+- struct nds32_reg *reg_arch_info = calloc(TOTAL_REG_NUM, sizeof(struct nds32_reg));
+- int i;
+-
+- if (!cache || !reg_list || !reg_arch_info) {
+- free(cache);
+- free(reg_list);
+- free(reg_arch_info);
+- return NULL;
+- }
+-
+- cache->name = "Andes registers";
+- cache->next = NULL;
+- cache->reg_list = reg_list;
+- cache->num_regs = 0;
+-
+- for (i = 0; i < TOTAL_REG_NUM; i++) {
+- reg_arch_info[i].num = i;
+- reg_arch_info[i].target = target;
+- reg_arch_info[i].nds32 = nds32;
+- reg_arch_info[i].enable = false;
+-
+- reg_list[i].name = nds32_reg_simple_name(i);
+- reg_list[i].number = reg_arch_info[i].num;
+- reg_list[i].size = nds32_reg_size(i);
+- reg_list[i].arch_info = ®_arch_info[i];
+-
+- reg_list[i].reg_data_type = calloc(sizeof(struct reg_data_type), 1);
+-
+- if (reg_arch_info[i].num >= FD0 && reg_arch_info[i].num <= FD31) {
+- reg_list[i].value = reg_arch_info[i].value;
+- reg_list[i].type = &nds32_reg_access_type_64;
+-
+- reg_list[i].reg_data_type->type = REG_TYPE_IEEE_DOUBLE;
+- reg_list[i].reg_data_type->id = "ieee_double";
+- reg_list[i].group = "float";
+- } else {
+- reg_list[i].value = reg_arch_info[i].value;
+- reg_list[i].type = &nds32_reg_access_type;
+- reg_list[i].group = "general";
+-
+- if ((reg_arch_info[i].num >= FS0) && (reg_arch_info[i].num <= FS31)) {
+- reg_list[i].reg_data_type->type = REG_TYPE_IEEE_SINGLE;
+- reg_list[i].reg_data_type->id = "ieee_single";
+- reg_list[i].group = "float";
+- } else if ((reg_arch_info[i].num == FPCSR) ||
+- (reg_arch_info[i].num == FPCFG)) {
+- reg_list[i].group = "float";
+- } else if ((reg_arch_info[i].num == R28) ||
+- (reg_arch_info[i].num == R29) ||
+- (reg_arch_info[i].num == R31)) {
+- reg_list[i].reg_data_type->type = REG_TYPE_DATA_PTR;
+- reg_list[i].reg_data_type->id = "data_ptr";
+- } else if ((reg_arch_info[i].num == R30) ||
+- (reg_arch_info[i].num == PC)) {
+- reg_list[i].reg_data_type->type = REG_TYPE_CODE_PTR;
+- reg_list[i].reg_data_type->id = "code_ptr";
+- } else {
+- reg_list[i].reg_data_type->type = REG_TYPE_UINT32;
+- reg_list[i].reg_data_type->id = "uint32";
+- }
+- }
+-
+- if (reg_arch_info[i].num >= R16 && reg_arch_info[i].num <= R25)
+- reg_list[i].caller_save = true;
+- else
+- reg_list[i].caller_save = false;
+-
+- reg_list[i].feature = malloc(sizeof(struct reg_feature));
+-
+- if (reg_arch_info[i].num >= R0 && reg_arch_info[i].num <= IFC_LP)
+- reg_list[i].feature->name = "org.gnu.gdb.nds32.core";
+- else if (reg_arch_info[i].num >= CR0 && reg_arch_info[i].num <= SECUR0)
+- reg_list[i].feature->name = "org.gnu.gdb.nds32.system";
+- else if (reg_arch_info[i].num >= D0L24 && reg_arch_info[i].num <= CBE3)
+- reg_list[i].feature->name = "org.gnu.gdb.nds32.audio";
+- else if (reg_arch_info[i].num >= FPCSR && reg_arch_info[i].num <= FD31)
+- reg_list[i].feature->name = "org.gnu.gdb.nds32.fpu";
+-
+- cache->num_regs++;
+- }
+-
+- nds32->core_cache = cache;
+-
+- return cache;
+-}
+-
+-static int nds32_reg_cache_init(struct target *target, struct nds32 *nds32)
+-{
+- struct reg_cache *cache;
+-
+- cache = nds32_build_reg_cache(target, nds32);
+- if (!cache)
+- return ERROR_FAIL;
+-
+- *register_get_last_cache_p(&target->reg_cache) = cache;
+-
+- return ERROR_OK;
+-}
+-
+-static struct reg *nds32_reg_current(struct nds32 *nds32, unsigned regnum)
+-{
+- struct reg *r;
+-
+- r = nds32->core_cache->reg_list + regnum;
+-
+- return r;
+-}
+-
+-int nds32_full_context(struct nds32 *nds32)
+-{
+- uint32_t value, value_ir0;
+-
+- /* save $pc & $psw */
+- nds32_get_mapped_reg(nds32, PC, &value);
+- nds32_get_mapped_reg(nds32, IR0, &value_ir0);
+-
+- nds32_update_psw(nds32);
+- nds32_update_mmu_info(nds32);
+- nds32_update_cache_info(nds32);
+- nds32_update_lm_info(nds32);
+-
+- nds32_check_extension(nds32);
+-
+- return ERROR_OK;
+-}
+-
+-/* get register value internally */
+-int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t *value)
+-{
+- struct reg_cache *reg_cache = nds32->core_cache;
+- struct reg *r;
+-
+- if (regnum > reg_cache->num_regs)
+- return ERROR_FAIL;
+-
+- r = nds32_reg_current(nds32, regnum);
+-
+- if (r->type->get(r) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- *value = buf_get_u32(r->value, 0, 32);
+-
+- return ERROR_OK;
+-}
+-
+-/** set register internally */
+-int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value)
+-{
+- struct reg_cache *reg_cache = nds32->core_cache;
+- struct reg *r;
+- uint8_t set_value[4];
+-
+- if (regnum > reg_cache->num_regs)
+- return ERROR_FAIL;
+-
+- r = nds32_reg_current(nds32, regnum);
+-
+- buf_set_u32(set_value, 0, 32, value);
+-
+- return r->type->set(r, set_value);
+-}
+-
+-/** get general register list */
+-static int nds32_get_general_reg_list(struct nds32 *nds32,
+- struct reg **reg_list[], int *reg_list_size)
+-{
+- struct reg *reg_current;
+- int i;
+- int current_idx;
+-
+- /** freed in gdb_server.c */
+- *reg_list = malloc(sizeof(struct reg *) * (IFC_LP - R0 + 1));
+- current_idx = 0;
+-
+- for (i = R0; i < IFC_LP + 1; i++) {
+- reg_current = nds32_reg_current(nds32, i);
+- if (((struct nds32_reg *)reg_current->arch_info)->enable) {
+- (*reg_list)[current_idx] = reg_current;
+- current_idx++;
+- }
+- }
+- *reg_list_size = current_idx;
+-
+- return ERROR_OK;
+-}
+-
+-/** get all register list */
+-static int nds32_get_all_reg_list(struct nds32 *nds32,
+- struct reg **reg_list[], int *reg_list_size)
+-{
+- struct reg_cache *reg_cache = nds32->core_cache;
+- struct reg *reg_current;
+- unsigned int i;
+-
+- *reg_list_size = reg_cache->num_regs;
+-
+- /** freed in gdb_server.c */
+- *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+-
+- for (i = 0; i < reg_cache->num_regs; i++) {
+- reg_current = nds32_reg_current(nds32, i);
+- reg_current->exist = ((struct nds32_reg *)
+- reg_current->arch_info)->enable;
+- (*reg_list)[i] = reg_current;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-/** get all register list */
+-int nds32_get_gdb_reg_list(struct target *target,
+- struct reg **reg_list[], int *reg_list_size,
+- enum target_register_class reg_class)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- switch (reg_class) {
+- case REG_CLASS_ALL:
+- return nds32_get_all_reg_list(nds32, reg_list, reg_list_size);
+- case REG_CLASS_GENERAL:
+- return nds32_get_general_reg_list(nds32, reg_list, reg_list_size);
+- default:
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_FAIL;
+-}
+-
+-static int nds32_select_memory_mode(struct target *target, uint32_t address,
+- uint32_t length, uint32_t *end_address)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_memory *memory = &(nds32->memory);
+- struct nds32_edm *edm = &(nds32->edm);
+- uint32_t dlm_start, dlm_end;
+- uint32_t ilm_start, ilm_end;
+- uint32_t address_end = address + length;
+-
+- /* init end_address */
+- *end_address = address_end;
+-
+- if (memory->access_channel == NDS_MEMORY_ACC_CPU)
+- return ERROR_OK;
+-
+- if (edm->access_control == false) {
+- LOG_DEBUG("EDM does not support ACC_CTL");
+- return ERROR_OK;
+- }
+-
+- if (edm->direct_access_local_memory == false) {
+- LOG_DEBUG("EDM does not support DALM");
+- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+- return ERROR_OK;
+- }
+-
+- if (memory->mode != NDS_MEMORY_SELECT_AUTO) {
+- LOG_DEBUG("Memory mode is not AUTO");
+- return ERROR_OK;
+- }
+-
+- /* set default mode */
+- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+-
+- if ((memory->ilm_base != 0) && (memory->ilm_enable == true)) {
+- ilm_start = memory->ilm_start;
+- ilm_end = memory->ilm_end;
+-
+- /* case 1, address < ilm_start */
+- if (address < ilm_start) {
+- if (ilm_start < address_end) {
+- /* update end_address to split non-ILM from ILM */
+- *end_address = ilm_start;
+- }
+- /* MEM mode */
+- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+- } else if ((ilm_start <= address) && (address < ilm_end)) {
+- /* case 2, ilm_start <= address < ilm_end */
+- if (ilm_end < address_end) {
+- /* update end_address to split non-ILM from ILM */
+- *end_address = ilm_end;
+- }
+- /* ILM mode */
+- aice_memory_mode(aice, NDS_MEMORY_SELECT_ILM);
+- } else { /* case 3, ilm_end <= address */
+- /* MEM mode */
+- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+- }
+-
+- return ERROR_OK;
+- } else {
+- LOG_DEBUG("ILM is not enabled");
+- }
+-
+- if ((memory->dlm_base != 0) && (memory->dlm_enable == true)) {
+- dlm_start = memory->dlm_start;
+- dlm_end = memory->dlm_end;
+-
+- /* case 1, address < dlm_start */
+- if (address < dlm_start) {
+- if (dlm_start < address_end) {
+- /* update end_address to split non-DLM from DLM */
+- *end_address = dlm_start;
+- }
+- /* MEM mode */
+- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+- } else if ((dlm_start <= address) && (address < dlm_end)) {
+- /* case 2, dlm_start <= address < dlm_end */
+- if (dlm_end < address_end) {
+- /* update end_address to split non-DLM from DLM */
+- *end_address = dlm_end;
+- }
+- /* DLM mode */
+- aice_memory_mode(aice, NDS_MEMORY_SELECT_DLM);
+- } else { /* case 3, dlm_end <= address */
+- /* MEM mode */
+- aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+- }
+-
+- return ERROR_OK;
+- } else {
+- LOG_DEBUG("DLM is not enabled");
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_read_buffer(struct target *target, uint32_t address,
+- uint32_t size, uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- LOG_DEBUG("READ BUFFER: ADDR %08" PRIx32 " SIZE %08" PRIx32,
+- address,
+- size);
+-
+- int retval = ERROR_OK;
+- struct aice_port_s *aice = target_to_aice(target);
+- uint32_t end_address;
+-
+- if (((address % 2) == 0) && (size == 2)) {
+- nds32_select_memory_mode(target, address, 2, &end_address);
+- return aice_read_mem_unit(aice, address, 2, 1, buffer);
+- }
+-
+- /* handle unaligned head bytes */
+- if (address % 4) {
+- uint32_t unaligned = 4 - (address % 4);
+-
+- if (unaligned > size)
+- unaligned = size;
+-
+- nds32_select_memory_mode(target, address, unaligned, &end_address);
+- retval = aice_read_mem_unit(aice, address, 1, unaligned, buffer);
+- if (retval != ERROR_OK)
+- return retval;
+-
+- buffer += unaligned;
+- address += unaligned;
+- size -= unaligned;
+- }
+-
+- /* handle aligned words */
+- if (size >= 4) {
+- int aligned = size - (size % 4);
+- int read_len;
+-
+- do {
+- nds32_select_memory_mode(target, address, aligned, &end_address);
+-
+- read_len = end_address - address;
+-
+- if (read_len > 8)
+- retval = aice_read_mem_bulk(aice, address, read_len, buffer);
+- else
+- retval = aice_read_mem_unit(aice, address, 4, read_len / 4, buffer);
+-
+- if (retval != ERROR_OK)
+- return retval;
+-
+- buffer += read_len;
+- address += read_len;
+- size -= read_len;
+- aligned -= read_len;
+-
+- } while (aligned != 0);
+- }
+-
+- /*prevent byte access when possible (avoid AHB access limitations in some cases)*/
+- if (size >= 2) {
+- int aligned = size - (size % 2);
+- nds32_select_memory_mode(target, address, aligned, &end_address);
+- retval = aice_read_mem_unit(aice, address, 2, aligned / 2, buffer);
+- if (retval != ERROR_OK)
+- return retval;
+-
+- buffer += aligned;
+- address += aligned;
+- size -= aligned;
+- }
+- /* handle tail writes of less than 4 bytes */
+- if (size > 0) {
+- nds32_select_memory_mode(target, address, size, &end_address);
+- retval = aice_read_mem_unit(aice, address, 1, size, buffer);
+- if (retval != ERROR_OK)
+- return retval;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_read_memory(struct target *target, uint32_t address,
+- uint32_t size, uint32_t count, uint8_t *buffer)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- return aice_read_mem_unit(aice, address, size, count, buffer);
+-}
+-
+-int nds32_read_phys_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, uint8_t *buffer)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+- enum nds_memory_access orig_channel;
+- int result;
+-
+- /* switch to BUS access mode to skip MMU */
+- orig_channel = memory->access_channel;
+- memory->access_channel = NDS_MEMORY_ACC_BUS;
+- aice_memory_access(aice, memory->access_channel);
+-
+- /* The input address is physical address. No need to do address translation. */
+- result = aice_read_mem_unit(aice, address, size, count, buffer);
+-
+- /* restore to origin access mode */
+- memory->access_channel = orig_channel;
+- aice_memory_access(aice, memory->access_channel);
+-
+- return result;
+-}
+-
+-int nds32_write_buffer(struct target *target, uint32_t address,
+- uint32_t size, const uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- LOG_DEBUG("WRITE BUFFER: ADDR %08" PRIx32 " SIZE %08" PRIx32,
+- address,
+- size);
+-
+- struct aice_port_s *aice = target_to_aice(target);
+- int retval = ERROR_OK;
+- uint32_t end_address;
+-
+- if (((address % 2) == 0) && (size == 2)) {
+- nds32_select_memory_mode(target, address, 2, &end_address);
+- return aice_write_mem_unit(aice, address, 2, 1, buffer);
+- }
+-
+- /* handle unaligned head bytes */
+- if (address % 4) {
+- uint32_t unaligned = 4 - (address % 4);
+-
+- if (unaligned > size)
+- unaligned = size;
+-
+- nds32_select_memory_mode(target, address, unaligned, &end_address);
+- retval = aice_write_mem_unit(aice, address, 1, unaligned, buffer);
+- if (retval != ERROR_OK)
+- return retval;
+-
+- buffer += unaligned;
+- address += unaligned;
+- size -= unaligned;
+- }
+-
+- /* handle aligned words */
+- if (size >= 4) {
+- int aligned = size - (size % 4);
+- int write_len;
+-
+- do {
+- nds32_select_memory_mode(target, address, aligned, &end_address);
+-
+- write_len = end_address - address;
+- if (write_len > 8)
+- retval = aice_write_mem_bulk(aice, address, write_len, buffer);
+- else
+- retval = aice_write_mem_unit(aice, address, 4, write_len / 4, buffer);
+- if (retval != ERROR_OK)
+- return retval;
+-
+- buffer += write_len;
+- address += write_len;
+- size -= write_len;
+- aligned -= write_len;
+-
+- } while (aligned != 0);
+- }
+-
+- /* handle tail writes of less than 4 bytes */
+- if (size > 0) {
+- nds32_select_memory_mode(target, address, size, &end_address);
+- retval = aice_write_mem_unit(aice, address, 1, size, buffer);
+- if (retval != ERROR_OK)
+- return retval;
+- }
+-
+- return retval;
+-}
+-
+-int nds32_write_memory(struct target *target, uint32_t address,
+- uint32_t size, uint32_t count, const uint8_t *buffer)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- return aice_write_mem_unit(aice, address, size, count, buffer);
+-}
+-
+-int nds32_write_phys_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, const uint8_t *buffer)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+- enum nds_memory_access orig_channel;
+- int result;
+-
+- /* switch to BUS access mode to skip MMU */
+- orig_channel = memory->access_channel;
+- memory->access_channel = NDS_MEMORY_ACC_BUS;
+- aice_memory_access(aice, memory->access_channel);
+-
+- /* The input address is physical address. No need to do address translation. */
+- result = aice_write_mem_unit(aice, address, size, count, buffer);
+-
+- /* restore to origin access mode */
+- memory->access_channel = orig_channel;
+- aice_memory_access(aice, memory->access_channel);
+-
+- return result;
+-}
+-
+-int nds32_mmu(struct target *target, int *enabled)
+-{
+- if (target->state != TARGET_HALTED) {
+- LOG_ERROR("%s: target not halted", __func__);
+- return ERROR_TARGET_INVALID;
+- }
+-
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+- struct nds32_mmu_config *mmu_config = &(nds32->mmu_config);
+-
+- if ((mmu_config->memory_protection == 2) && (memory->address_translation == true))
+- *enabled = 1;
+- else
+- *enabled = 0;
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_arch_state(struct target *target)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (nds32->common_magic != NDS32_COMMON_MAGIC) {
+- LOG_ERROR("BUG: called for a non-Andes target");
+- return ERROR_FAIL;
+- }
+-
+- uint32_t value_pc, value_psw;
+-
+- nds32_get_mapped_reg(nds32, PC, &value_pc);
+- nds32_get_mapped_reg(nds32, IR0, &value_psw);
+-
+- LOG_USER("target halted due to %s\n"
+- "psw: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s",
+- debug_reason_name(target),
+- value_psw,
+- value_pc,
+- nds32->virtual_hosting ? ", virtual hosting" : "");
+-
+- /* save pc value to pseudo register pc */
+- struct reg *reg = register_get_by_name(target->reg_cache, "pc", true);
+- buf_set_u32(reg->value, 0, 32, value_pc);
+-
+- return ERROR_OK;
+-}
+-
+-static void nds32_init_must_have_registers(struct nds32 *nds32)
+-{
+- struct reg_cache *reg_cache = nds32->core_cache;
+-
+- /** MUST have general registers */
+- ((struct nds32_reg *)reg_cache->reg_list[R0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R3].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R4].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R5].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R6].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R7].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R8].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R9].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R10].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R15].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R28].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R29].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R30].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R31].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[PC].arch_info)->enable = true;
+-
+- /** MUST have configuration system registers */
+- ((struct nds32_reg *)reg_cache->reg_list[CR0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CR1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CR2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CR3].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CR4].arch_info)->enable = true;
+-
+- /** MUST have interrupt system registers */
+- ((struct nds32_reg *)reg_cache->reg_list[IR0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR3].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR4].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR6].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR9].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR11].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR14].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR15].arch_info)->enable = true;
+-
+- /** MUST have MMU system registers */
+- ((struct nds32_reg *)reg_cache->reg_list[MR0].arch_info)->enable = true;
+-
+- /** MUST have EDM system registers */
+- ((struct nds32_reg *)reg_cache->reg_list[DR40].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DR42].arch_info)->enable = true;
+-}
+-
+-static int nds32_init_memory_config(struct nds32 *nds32)
+-{
+- uint32_t value_cr1; /* ICM_CFG */
+- uint32_t value_cr2; /* DCM_CFG */
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- /* read $cr1 to init instruction memory information */
+- nds32_get_mapped_reg(nds32, CR1, &value_cr1);
+- memory->icache.set = value_cr1 & 0x7;
+- memory->icache.way = (value_cr1 >> 3) & 0x7;
+- memory->icache.line_size = (value_cr1 >> 6) & 0x7;
+- memory->icache.lock_support = (value_cr1 >> 9) & 0x1;
+-
+- memory->ilm_base = (value_cr1 >> 10) & 0x7;
+- memory->ilm_align_ver = (value_cr1 >> 13) & 0x3;
+-
+- /* read $cr2 to init data memory information */
+- nds32_get_mapped_reg(nds32, CR2, &value_cr2);
+- memory->dcache.set = value_cr2 & 0x7;
+- memory->dcache.way = (value_cr2 >> 3) & 0x7;
+- memory->dcache.line_size = (value_cr2 >> 6) & 0x7;
+- memory->dcache.lock_support = (value_cr2 >> 9) & 0x1;
+-
+- memory->dlm_base = (value_cr2 >> 10) & 0x7;
+- memory->dlm_align_ver = (value_cr2 >> 13) & 0x3;
+-
+- return ERROR_OK;
+-}
+-
+-static void nds32_init_config(struct nds32 *nds32)
+-{
+- uint32_t value_cr0;
+- uint32_t value_cr3;
+- uint32_t value_cr4;
+- struct nds32_cpu_version *cpu_version = &(nds32->cpu_version);
+- struct nds32_mmu_config *mmu_config = &(nds32->mmu_config);
+- struct nds32_misc_config *misc_config = &(nds32->misc_config);
+-
+- nds32_get_mapped_reg(nds32, CR0, &value_cr0);
+- nds32_get_mapped_reg(nds32, CR3, &value_cr3);
+- nds32_get_mapped_reg(nds32, CR4, &value_cr4);
+-
+- /* config cpu version */
+- cpu_version->performance_extension = value_cr0 & 0x1;
+- cpu_version->_16bit_extension = (value_cr0 >> 1) & 0x1;
+- cpu_version->performance_extension_2 = (value_cr0 >> 2) & 0x1;
+- cpu_version->cop_fpu_extension = (value_cr0 >> 3) & 0x1;
+- cpu_version->string_extension = (value_cr0 >> 4) & 0x1;
+- cpu_version->revision = (value_cr0 >> 16) & 0xFF;
+- cpu_version->cpu_id_family = (value_cr0 >> 24) & 0xF;
+- cpu_version->cpu_id_version = (value_cr0 >> 28) & 0xF;
+-
+- /* config MMU */
+- mmu_config->memory_protection = value_cr3 & 0x3;
+- mmu_config->memory_protection_version = (value_cr3 >> 2) & 0x1F;
+- mmu_config->fully_associative_tlb = (value_cr3 >> 7) & 0x1;
+- if (mmu_config->fully_associative_tlb) {
+- mmu_config->tlb_size = (value_cr3 >> 8) & 0x7F;
+- } else {
+- mmu_config->tlb_ways = (value_cr3 >> 8) & 0x7;
+- mmu_config->tlb_sets = (value_cr3 >> 11) & 0x7;
+- }
+- mmu_config->_8k_page_support = (value_cr3 >> 15) & 0x1;
+- mmu_config->extra_page_size_support = (value_cr3 >> 16) & 0xFF;
+- mmu_config->tlb_lock = (value_cr3 >> 24) & 0x1;
+- mmu_config->hardware_page_table_walker = (value_cr3 >> 25) & 0x1;
+- mmu_config->default_endian = (value_cr3 >> 26) & 0x1;
+- mmu_config->partition_num = (value_cr3 >> 27) & 0x1;
+- mmu_config->invisible_tlb = (value_cr3 >> 28) & 0x1;
+- mmu_config->vlpt = (value_cr3 >> 29) & 0x1;
+- mmu_config->ntme = (value_cr3 >> 30) & 0x1;
+- mmu_config->drde = (value_cr3 >> 31) & 0x1;
+-
+- /* config misc */
+- misc_config->edm = value_cr4 & 0x1;
+- misc_config->local_memory_dma = (value_cr4 >> 1) & 0x1;
+- misc_config->performance_monitor = (value_cr4 >> 2) & 0x1;
+- misc_config->high_speed_memory_port = (value_cr4 >> 3) & 0x1;
+- misc_config->debug_tracer = (value_cr4 >> 4) & 0x1;
+- misc_config->div_instruction = (value_cr4 >> 5) & 0x1;
+- misc_config->mac_instruction = (value_cr4 >> 6) & 0x1;
+- misc_config->audio_isa = (value_cr4 >> 7) & 0x3;
+- misc_config->l2_cache = (value_cr4 >> 9) & 0x1;
+- misc_config->reduce_register = (value_cr4 >> 10) & 0x1;
+- misc_config->addr_24 = (value_cr4 >> 11) & 0x1;
+- misc_config->interruption_level = (value_cr4 >> 12) & 0x1;
+- misc_config->baseline_instruction = (value_cr4 >> 13) & 0x7;
+- misc_config->no_dx_register = (value_cr4 >> 16) & 0x1;
+- misc_config->implement_dependant_register = (value_cr4 >> 17) & 0x1;
+- misc_config->implement_dependant_sr_encoding = (value_cr4 >> 18) & 0x1;
+- misc_config->ifc = (value_cr4 >> 19) & 0x1;
+- misc_config->mcu = (value_cr4 >> 20) & 0x1;
+- misc_config->shadow = (value_cr4 >> 21) & 0x7;
+- misc_config->ex9 = (value_cr4 >> 24) & 0x1;
+-
+- nds32_init_memory_config(nds32);
+-}
+-
+-static int nds32_init_option_registers(struct nds32 *nds32)
+-{
+- struct reg_cache *reg_cache = nds32->core_cache;
+- struct nds32_cpu_version *cpu_version = &(nds32->cpu_version);
+- struct nds32_mmu_config *mmu_config = &(nds32->mmu_config);
+- struct nds32_misc_config *misc_config = &(nds32->misc_config);
+- struct nds32_memory *memory_config = &(nds32->memory);
+-
+- bool no_cr5;
+- bool mr10_exist;
+- bool no_racr0;
+-
+- if (((cpu_version->cpu_id_family == 0xC) || (cpu_version->cpu_id_family == 0xD)) &&
+- ((cpu_version->revision & 0xFC) == 0)) {
+- no_cr5 = true;
+- mr10_exist = true;
+- no_racr0 = true;
+- } else {
+- no_cr5 = false;
+- mr10_exist = false;
+- no_racr0 = false;
+- }
+-
+- if (misc_config->reduce_register == false) {
+- ((struct nds32_reg *)reg_cache->reg_list[R11].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R12].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R13].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R14].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R16].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R17].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R18].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R19].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R20].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R21].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R22].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R23].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R24].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R25].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R26].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[R27].arch_info)->enable = true;
+- }
+-
+- if (misc_config->no_dx_register == false) {
+- ((struct nds32_reg *)reg_cache->reg_list[D0LO].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[D0HI].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[D1LO].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[D1HI].arch_info)->enable = true;
+- }
+-
+- if (misc_config->ex9)
+- ((struct nds32_reg *)reg_cache->reg_list[ITB].arch_info)->enable = true;
+-
+- if (no_cr5 == false)
+- ((struct nds32_reg *)reg_cache->reg_list[CR5].arch_info)->enable = true;
+-
+- if (cpu_version->cop_fpu_extension) {
+- ((struct nds32_reg *)reg_cache->reg_list[CR6].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[FPCSR].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[FPCFG].arch_info)->enable = true;
+- }
+-
+- if (mmu_config->memory_protection == 1) {
+- /* Secure MPU has no IPC, IPSW, P_ITYPE */
+- ((struct nds32_reg *)reg_cache->reg_list[IR1].arch_info)->enable = false;
+- ((struct nds32_reg *)reg_cache->reg_list[IR9].arch_info)->enable = false;
+- }
+-
+- if (nds32->privilege_level != 0)
+- ((struct nds32_reg *)reg_cache->reg_list[IR3].arch_info)->enable = false;
+-
+- if (misc_config->mcu == true)
+- ((struct nds32_reg *)reg_cache->reg_list[IR4].arch_info)->enable = false;
+-
+- if (misc_config->interruption_level == false) {
+- ((struct nds32_reg *)reg_cache->reg_list[IR2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR5].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR10].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR12].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR13].arch_info)->enable = true;
+-
+- /* Secure MPU has no IPC, IPSW, P_ITYPE */
+- if (mmu_config->memory_protection != 1)
+- ((struct nds32_reg *)reg_cache->reg_list[IR7].arch_info)->enable = true;
+- }
+-
+- if ((cpu_version->cpu_id_family == 0x9) ||
+- (cpu_version->cpu_id_family == 0xA) ||
+- (cpu_version->cpu_id_family == 0xC) ||
+- (cpu_version->cpu_id_family == 0xD))
+- ((struct nds32_reg *)reg_cache->reg_list[IR8].arch_info)->enable = true;
+-
+- if (misc_config->shadow == 1) {
+- ((struct nds32_reg *)reg_cache->reg_list[IR16].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR17].arch_info)->enable = true;
+- }
+-
+- if (misc_config->ifc)
+- ((struct nds32_reg *)reg_cache->reg_list[IFC_LP].arch_info)->enable = true;
+-
+- if (nds32->privilege_level != 0)
+- ((struct nds32_reg *)reg_cache->reg_list[MR0].arch_info)->enable = false;
+-
+- if (mmu_config->memory_protection == 1) {
+- if (mmu_config->memory_protection_version == 24)
+- ((struct nds32_reg *)reg_cache->reg_list[MR4].arch_info)->enable = true;
+-
+- if (nds32->privilege_level == 0) {
+- if ((mmu_config->memory_protection_version == 16) ||
+- (mmu_config->memory_protection_version == 24)) {
+- ((struct nds32_reg *)reg_cache->reg_list[MR11].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[SECUR0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR20].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR22].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR24].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR30].arch_info)->enable = true;
+-
+- if (misc_config->shadow == 1) {
+- ((struct nds32_reg *)reg_cache->reg_list[IR21].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR23].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR25].arch_info)->enable = true;
+- }
+- }
+- }
+- } else if (mmu_config->memory_protection == 2) {
+- ((struct nds32_reg *)reg_cache->reg_list[MR1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[MR4].arch_info)->enable = true;
+-
+- if ((cpu_version->cpu_id_family != 0xA) && (cpu_version->cpu_id_family != 0xC) &&
+- (cpu_version->cpu_id_family != 0xD))
+- ((struct nds32_reg *)reg_cache->reg_list[MR5].arch_info)->enable = true;
+- }
+-
+- if (mmu_config->memory_protection > 0) {
+- ((struct nds32_reg *)reg_cache->reg_list[MR2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[MR3].arch_info)->enable = true;
+- }
+-
+- if (memory_config->ilm_base != 0)
+- if (nds32->privilege_level == 0)
+- ((struct nds32_reg *)reg_cache->reg_list[MR6].arch_info)->enable = true;
+-
+- if (memory_config->dlm_base != 0)
+- if (nds32->privilege_level == 0)
+- ((struct nds32_reg *)reg_cache->reg_list[MR7].arch_info)->enable = true;
+-
+- if ((memory_config->icache.line_size != 0) && (memory_config->dcache.line_size != 0))
+- ((struct nds32_reg *)reg_cache->reg_list[MR8].arch_info)->enable = true;
+-
+- if (misc_config->high_speed_memory_port)
+- ((struct nds32_reg *)reg_cache->reg_list[MR9].arch_info)->enable = true;
+-
+- if (mr10_exist)
+- ((struct nds32_reg *)reg_cache->reg_list[MR10].arch_info)->enable = true;
+-
+- if (misc_config->edm) {
+- int dr_reg_n = nds32->edm.breakpoint_num * 5;
+-
+- for (int i = 0 ; i < dr_reg_n ; i++)
+- ((struct nds32_reg *)reg_cache->reg_list[DR0 + i].arch_info)->enable = true;
+-
+- ((struct nds32_reg *)reg_cache->reg_list[DR41].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DR43].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DR44].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DR45].arch_info)->enable = true;
+- }
+-
+- if (misc_config->debug_tracer) {
+- ((struct nds32_reg *)reg_cache->reg_list[DR46].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DR47].arch_info)->enable = true;
+- }
+-
+- if (misc_config->performance_monitor) {
+- ((struct nds32_reg *)reg_cache->reg_list[PFR0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[PFR1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[PFR2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[PFR3].arch_info)->enable = true;
+- }
+-
+- if (misc_config->local_memory_dma) {
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR3].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR4].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR5].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR6].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR7].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR8].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR9].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[DMAR10].arch_info)->enable = true;
+- }
+-
+- if ((misc_config->local_memory_dma || misc_config->performance_monitor) &&
+- (no_racr0 == false))
+- ((struct nds32_reg *)reg_cache->reg_list[RACR].arch_info)->enable = true;
+-
+- if (cpu_version->cop_fpu_extension || (misc_config->audio_isa != 0))
+- ((struct nds32_reg *)reg_cache->reg_list[FUCPR].arch_info)->enable = true;
+-
+- if (misc_config->audio_isa != 0) {
+- if (misc_config->audio_isa > 1) {
+- ((struct nds32_reg *)reg_cache->reg_list[D0L24].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[D1L24].arch_info)->enable = true;
+- }
+-
+- ((struct nds32_reg *)reg_cache->reg_list[I0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[I1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[I2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[I3].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[I4].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[I5].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[I6].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[I7].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[M1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[M2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[M3].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[M5].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[M6].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[M7].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[MOD].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[LBE].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[LE].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[LC].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[ADM_VBASE].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[SHFT_CTL0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[SHFT_CTL1].arch_info)->enable = true;
+-
+- uint32_t value_mod;
+- uint32_t fucpr_backup;
+- /* enable fpu and get configuration */
+- nds32_get_mapped_reg(nds32, FUCPR, &fucpr_backup);
+- if ((fucpr_backup & 0x80000000) == 0)
+- nds32_set_mapped_reg(nds32, FUCPR, fucpr_backup | 0x80000000);
+- nds32_get_mapped_reg(nds32, MOD, &value_mod);
+- /* restore origin fucpr value */
+- if ((fucpr_backup & 0x80000000) == 0)
+- nds32_set_mapped_reg(nds32, FUCPR, fucpr_backup);
+-
+- if ((value_mod >> 6) & 0x1) {
+- ((struct nds32_reg *)reg_cache->reg_list[CB_CTL].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CBB0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CBB1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CBB2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CBB3].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CBE0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CBE1].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CBE2].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[CBE3].arch_info)->enable = true;
+- }
+- }
+-
+- if ((cpu_version->cpu_id_family == 0x9) ||
+- (cpu_version->cpu_id_family == 0xA) ||
+- (cpu_version->cpu_id_family == 0xC)) {
+-
+- ((struct nds32_reg *)reg_cache->reg_list[IDR0].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IDR1].arch_info)->enable = true;
+-
+- if ((cpu_version->cpu_id_family == 0xC) && (cpu_version->revision == 0x0C))
+- ((struct nds32_reg *)reg_cache->reg_list[IDR0].arch_info)->enable = false;
+- }
+-
+- uint32_t ir3_value;
+- uint32_t ivb_prog_pri_lvl;
+- uint32_t ivb_ivic_ver;
+-
+- nds32_get_mapped_reg(nds32, IR3, &ir3_value);
+- ivb_prog_pri_lvl = ir3_value & 0x1;
+- ivb_ivic_ver = (ir3_value >> 11) & 0x3;
+-
+- if ((ivb_prog_pri_lvl == 1) || (ivb_ivic_ver >= 1)) {
+- ((struct nds32_reg *)reg_cache->reg_list[IR18].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR19].arch_info)->enable = true;
+- }
+-
+- if (ivb_ivic_ver >= 1) {
+- ((struct nds32_reg *)reg_cache->reg_list[IR26].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR27].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR28].arch_info)->enable = true;
+- ((struct nds32_reg *)reg_cache->reg_list[IR29].arch_info)->enable = true;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_init_register_table(struct nds32 *nds32)
+-{
+- nds32_init_must_have_registers(nds32);
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_add_software_breakpoint(struct target *target,
+- struct breakpoint *breakpoint)
+-{
+- uint32_t data;
+- uint32_t check_data;
+- uint32_t break_insn;
+-
+- /* check the breakpoint size */
+- target->type->read_buffer(target, breakpoint->address, 4, (uint8_t *)&data);
+-
+- /* backup origin instruction
+- * instruction is big-endian */
+- if (*(char *)&data & 0x80) { /* 16-bits instruction */
+- breakpoint->length = 2;
+- break_insn = NDS32_BREAK_16;
+- } else { /* 32-bits instruction */
+- breakpoint->length = 4;
+- break_insn = NDS32_BREAK_32;
+- }
+-
+- free(breakpoint->orig_instr);
+-
+- breakpoint->orig_instr = malloc(breakpoint->length);
+- memcpy(breakpoint->orig_instr, &data, breakpoint->length);
+-
+- /* self-modified code */
+- target->type->write_buffer(target, breakpoint->address, breakpoint->length, (const uint8_t *)&break_insn);
+- /* write_back & invalidate dcache & invalidate icache */
+- nds32_cache_sync(target, breakpoint->address, breakpoint->length);
+-
+- /* read back to check */
+- target->type->read_buffer(target, breakpoint->address, breakpoint->length, (uint8_t *)&check_data);
+- if (memcmp(&check_data, &break_insn, breakpoint->length) == 0)
+- return ERROR_OK;
+-
+- return ERROR_FAIL;
+-}
+-
+-int nds32_remove_software_breakpoint(struct target *target,
+- struct breakpoint *breakpoint)
+-{
+- uint32_t check_data;
+- uint32_t break_insn;
+-
+- if (breakpoint->length == 2)
+- break_insn = NDS32_BREAK_16;
+- else if (breakpoint->length == 4)
+- break_insn = NDS32_BREAK_32;
+- else
+- return ERROR_FAIL;
+-
+- target->type->read_buffer(target, breakpoint->address, breakpoint->length,
+- (uint8_t *)&check_data);
+-
+- /* break instruction is modified */
+- if (memcmp(&check_data, &break_insn, breakpoint->length) != 0)
+- return ERROR_FAIL;
+-
+- /* self-modified code */
+- target->type->write_buffer(target, breakpoint->address, breakpoint->length,
+- breakpoint->orig_instr);
+-
+- /* write_back & invalidate dcache & invalidate icache */
+- nds32_cache_sync(target, breakpoint->address, breakpoint->length);
+-
+- return ERROR_OK;
+-}
+-
+-/**
+- * Restore the processor context on an Andes target. The full processor
+- * context is analyzed to see if any of the registers are dirty on this end, but
+- * have a valid new value. If this is the case, the processor is changed to the
+- * appropriate mode and the new register values are written out to the
+- * processor. If there happens to be a dirty register with an invalid value, an
+- * error will be logged.
+- *
+- * @param target Pointer to the Andes target to have its context restored
+- * @return Error status if the target is not halted.
+- */
+-int nds32_restore_context(struct target *target)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct reg_cache *reg_cache = nds32->core_cache;
+- struct reg *reg;
+- struct nds32_reg *reg_arch_info;
+- unsigned int i;
+-
+- LOG_DEBUG("-");
+-
+- if (target->state != TARGET_HALTED) {
+- LOG_WARNING("target not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- /* check if there are dirty registers */
+- for (i = 0; i < reg_cache->num_regs; i++) {
+- reg = &(reg_cache->reg_list[i]);
+- if (reg->dirty == true) {
+- if (reg->valid == true) {
+-
+- LOG_DEBUG("examining dirty reg: %s", reg->name);
+- LOG_DEBUG("writing register %d with value 0x%8.8" PRIx32,
+- i, buf_get_u32(reg->value, 0, 32));
+-
+- reg_arch_info = reg->arch_info;
+- if (reg_arch_info->num >= FD0 && reg_arch_info->num <= FD31) {
+- uint64_t val = buf_get_u64(reg_arch_info->value, 0, 64);
+- aice_write_reg_64(aice, reg_arch_info->num, val);
+- } else {
+- uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32);
+- aice_write_register(aice, reg_arch_info->num, val);
+- }
+-
+- reg->valid = true;
+- reg->dirty = false;
+- }
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_edm_config(struct nds32 *nds32)
+-{
+- struct target *target = nds32->target;
+- struct aice_port_s *aice = target_to_aice(target);
+- uint32_t edm_cfg;
+- uint32_t edm_ctl;
+-
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
+-
+- nds32->edm.version = (edm_cfg >> 16) & 0xFFFF;
+- LOG_INFO("EDM version 0x%04x", nds32->edm.version);
+-
+- nds32->edm.breakpoint_num = (edm_cfg & 0x7) + 1;
+-
+- if ((nds32->edm.version & 0x1000) || (nds32->edm.version >= 0x60))
+- nds32->edm.access_control = true;
+- else
+- nds32->edm.access_control = false;
+-
+- if ((edm_cfg >> 4) & 0x1)
+- nds32->edm.direct_access_local_memory = true;
+- else
+- nds32->edm.direct_access_local_memory = false;
+-
+- if (nds32->edm.version <= 0x20)
+- nds32->edm.direct_access_local_memory = false;
+-
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
+- if (edm_ctl & (0x1 << 29))
+- nds32->edm.support_max_stop = true;
+- else
+- nds32->edm.support_max_stop = false;
+-
+- /* set passcode for secure MCU */
+- nds32_login(nds32);
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_config(struct nds32 *nds32)
+-{
+- nds32_init_config(nds32);
+-
+- /* init optional system registers according to config registers */
+- nds32_init_option_registers(nds32);
+-
+- /* get max interrupt level */
+- if (nds32->misc_config.interruption_level)
+- nds32->max_interrupt_level = 2;
+- else
+- nds32->max_interrupt_level = 3;
+-
+- /* get ILM/DLM size from MR6/MR7 */
+- uint32_t value_mr6, value_mr7;
+- uint32_t size_index;
+- nds32_get_mapped_reg(nds32, MR6, &value_mr6);
+- size_index = (value_mr6 >> 1) & 0xF;
+- nds32->memory.ilm_size = nds32_lm_size_table[size_index];
+-
+- nds32_get_mapped_reg(nds32, MR7, &value_mr7);
+- size_index = (value_mr7 >> 1) & 0xF;
+- nds32->memory.dlm_size = nds32_lm_size_table[size_index];
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_init_arch_info(struct target *target, struct nds32 *nds32)
+-{
+- target->arch_info = nds32;
+- nds32->target = target;
+-
+- nds32->common_magic = NDS32_COMMON_MAGIC;
+- nds32->init_arch_info_after_halted = false;
+- nds32->auto_convert_hw_bp = true;
+- nds32->global_stop = false;
+- nds32->soft_reset_halt = false;
+- nds32->edm_passcode = NULL;
+- nds32->privilege_level = 0;
+- nds32->boot_time = 1500;
+- nds32->reset_halt_as_examine = false;
+- nds32->keep_target_edm_ctl = false;
+- nds32->word_access_mem = false;
+- nds32->virtual_hosting = true;
+- nds32->hit_syscall = false;
+- nds32->active_syscall_id = NDS32_SYSCALL_UNDEFINED;
+- nds32->virtual_hosting_errno = 0;
+- nds32->virtual_hosting_ctrl_c = false;
+- nds32->attached = false;
+-
+- nds32->syscall_break.asid = 0;
+- nds32->syscall_break.length = 4;
+- nds32->syscall_break.is_set = false;
+- nds32->syscall_break.orig_instr = NULL;
+- nds32->syscall_break.next = NULL;
+- nds32->syscall_break.unique_id = 0x515CAll + target->target_number;
+- nds32->syscall_break.linked_brp = 0;
+-
+- nds32_reg_init();
+-
+- if (nds32_reg_cache_init(target, nds32) == ERROR_FAIL)
+- return ERROR_FAIL;
+-
+- if (nds32_init_register_table(nds32) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_virtual_to_physical(struct target *target, target_addr_t address, target_addr_t *physical)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (nds32->memory.address_translation == false) {
+- *physical = address;
+- return ERROR_OK;
+- }
+-
+- if (nds32_probe_tlb(nds32, address, physical) == ERROR_OK)
+- return ERROR_OK;
+-
+- if (nds32_walk_page_table(nds32, address, physical) == ERROR_OK)
+- return ERROR_OK;
+-
+- return ERROR_FAIL;
+-}
+-
+-int nds32_cache_sync(struct target *target, target_addr_t address, uint32_t length)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_cache *dcache = &(nds32->memory.dcache);
+- struct nds32_cache *icache = &(nds32->memory.icache);
+- uint32_t dcache_line_size = nds32_line_size_table[dcache->line_size];
+- uint32_t icache_line_size = nds32_line_size_table[icache->line_size];
+- uint32_t cur_address;
+- int result;
+- uint32_t start_line, end_line;
+- uint32_t cur_line;
+-
+- if ((dcache->line_size != 0) && (dcache->enable == true)) {
+- /* address / dcache_line_size */
+- start_line = address >> (dcache->line_size + 2);
+- /* (address + length - 1) / dcache_line_size */
+- end_line = (address + length - 1) >> (dcache->line_size + 2);
+-
+- for (cur_address = address, cur_line = start_line;
+- cur_line <= end_line;
+- cur_address += dcache_line_size, cur_line++) {
+- /* D$ write back */
+- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_VA_WB, cur_address);
+- if (result != ERROR_OK)
+- return result;
+-
+- /* D$ invalidate */
+- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_VA_INVAL, cur_address);
+- if (result != ERROR_OK)
+- return result;
+- }
+- }
+-
+- if ((icache->line_size != 0) && (icache->enable == true)) {
+- /* address / icache_line_size */
+- start_line = address >> (icache->line_size + 2);
+- /* (address + length - 1) / icache_line_size */
+- end_line = (address + length - 1) >> (icache->line_size + 2);
+-
+- for (cur_address = address, cur_line = start_line;
+- cur_line <= end_line;
+- cur_address += icache_line_size, cur_line++) {
+- /* Because PSW.IT is turned off under debug exception, address MUST
+- * be physical address. L1I_VA_INVALIDATE uses PSW.IT to decide
+- * address translation or not. */
+- target_addr_t physical_addr;
+- if (target->type->virt2phys(target, cur_address, &physical_addr) == ERROR_FAIL)
+- return ERROR_FAIL;
+-
+- /* I$ invalidate */
+- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_VA_INVAL, physical_addr);
+- if (result != ERROR_OK)
+- return result;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address)
+-{
+- if (!current)
+- nds32_set_mapped_reg(nds32, PC, address);
+- else
+- nds32_get_mapped_reg(nds32, PC, &address);
+-
+- return address;
+-}
+-
+-int nds32_step(struct target *target, int current,
+- target_addr_t address, int handle_breakpoints)
+-{
+- LOG_DEBUG("target->state: %s",
+- target_state_name(target));
+-
+- if (target->state != TARGET_HALTED) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- address = nds32_nextpc(nds32, current, address);
+-
+- LOG_DEBUG("STEP PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : "");
+-
+- /** set DSSIM */
+- uint32_t ir14_value;
+- nds32_get_mapped_reg(nds32, IR14, &ir14_value);
+- if (nds32->step_isr_enable)
+- ir14_value |= (0x1 << 31);
+- else
+- ir14_value &= ~(0x1 << 31);
+- nds32_set_mapped_reg(nds32, IR14, ir14_value);
+-
+- /* check hit_syscall before leave_debug_state() because
+- * leave_debug_state() may clear hit_syscall flag */
+- bool no_step = false;
+- if (nds32->hit_syscall)
+- /* step after hit_syscall should be ignored because
+- * leave_debug_state will step implicitly to skip the
+- * syscall */
+- no_step = true;
+-
+- /********* TODO: maybe create another function to handle this part */
+- CHECK_RETVAL(nds32->leave_debug_state(nds32, true));
+- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
+-
+- if (no_step == false) {
+- struct aice_port_s *aice = target_to_aice(target);
+- if (aice_step(aice) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+-
+- /* save state */
+- CHECK_RETVAL(nds32->enter_debug_state(nds32, true));
+- /********* TODO: maybe create another function to handle this part */
+-
+- /* restore DSSIM */
+- if (nds32->step_isr_enable) {
+- nds32_get_mapped_reg(nds32, IR14, &ir14_value);
+- ir14_value &= ~(0x1 << 31);
+- nds32_set_mapped_reg(nds32, IR14, ir14_value);
+- }
+-
+- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_step_without_watchpoint(struct nds32 *nds32)
+-{
+- struct target *target = nds32->target;
+-
+- if (target->state != TARGET_HALTED) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- /** set DSSIM */
+- uint32_t ir14_value;
+- nds32_get_mapped_reg(nds32, IR14, &ir14_value);
+- if (nds32->step_isr_enable)
+- ir14_value |= (0x1 << 31);
+- else
+- ir14_value &= ~(0x1 << 31);
+- nds32_set_mapped_reg(nds32, IR14, ir14_value);
+-
+- /********* TODO: maybe create another function to handle this part */
+- CHECK_RETVAL(nds32->leave_debug_state(nds32, false));
+-
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- if (aice_step(aice) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /* save state */
+- CHECK_RETVAL(nds32->enter_debug_state(nds32, false));
+- /********* TODO: maybe create another function to handle this part */
+-
+- /* restore DSSIM */
+- if (nds32->step_isr_enable) {
+- nds32_get_mapped_reg(nds32, IR14, &ir14_value);
+- ir14_value &= ~(0x1 << 31);
+- nds32_set_mapped_reg(nds32, IR14, ir14_value);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_target_state(struct nds32 *nds32, enum target_state *state)
+-{
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+- enum aice_target_state_s nds32_state;
+-
+- if (aice_state(aice, &nds32_state) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- switch (nds32_state) {
+- case AICE_DISCONNECT:
+- LOG_INFO("USB is disconnected");
+- return ERROR_FAIL;
+- case AICE_TARGET_DETACH:
+- LOG_INFO("Target is disconnected");
+- return ERROR_FAIL;
+- case AICE_TARGET_UNKNOWN:
+- *state = TARGET_UNKNOWN;
+- break;
+- case AICE_TARGET_RUNNING:
+- *state = TARGET_RUNNING;
+- break;
+- case AICE_TARGET_HALTED:
+- *state = TARGET_HALTED;
+- break;
+- case AICE_TARGET_RESET:
+- *state = TARGET_RESET;
+- break;
+- case AICE_TARGET_DEBUG_RUNNING:
+- *state = TARGET_DEBUG_RUNNING;
+- break;
+- default:
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_examine_debug_reason(struct nds32 *nds32)
+-{
+- uint32_t reason;
+- struct target *target = nds32->target;
+-
+- if (nds32->hit_syscall == true) {
+- LOG_DEBUG("Hit syscall breakpoint");
+- target->debug_reason = DBG_REASON_BREAKPOINT;
+- return ERROR_OK;
+- }
+-
+- nds32->get_debug_reason(nds32, &reason);
+-
+- LOG_DEBUG("nds32 examines debug reason: %s", nds32_debug_type_name[reason]);
+-
+- /* Examine debug reason */
+- switch (reason) {
+- case NDS32_DEBUG_BREAK:
+- case NDS32_DEBUG_BREAK_16:
+- case NDS32_DEBUG_INST_BREAK:
+- {
+- uint32_t value_pc;
+- uint32_t opcode;
+- struct nds32_instruction instruction;
+-
+- nds32_get_mapped_reg(nds32, PC, &value_pc);
+-
+- if (nds32_read_opcode(nds32, value_pc, &opcode) != ERROR_OK)
+- return ERROR_FAIL;
+- if (nds32_evaluate_opcode(nds32, opcode, value_pc, &instruction) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /* hit 'break 0x7FFF' */
+- if ((instruction.info.opc_6 == 0x32) &&
+- (instruction.info.sub_opc == 0xA) &&
+- (instruction.info.imm == 0x7FFF)) {
+- target->debug_reason = DBG_REASON_EXIT;
+- } else
+- target->debug_reason = DBG_REASON_BREAKPOINT;
+- }
+- break;
+- case NDS32_DEBUG_DATA_ADDR_WATCHPOINT_PRECISE:
+- case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_PRECISE:
+- case NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP: /* GLOBAL_STOP is precise exception */
+- {
+- int result;
+-
+- result = nds32->get_watched_address(nds32,
+- &(nds32->watched_address), reason);
+- /* do single step(without watchpoints) to skip the "watched" instruction */
+- nds32_step_without_watchpoint(nds32);
+-
+- /* before single_step, save exception address */
+- if (result != ERROR_OK)
+- return ERROR_FAIL;
+-
+- target->debug_reason = DBG_REASON_WATCHPOINT;
+- }
+- break;
+- case NDS32_DEBUG_DEBUG_INTERRUPT:
+- target->debug_reason = DBG_REASON_DBGRQ;
+- break;
+- case NDS32_DEBUG_HARDWARE_SINGLE_STEP:
+- target->debug_reason = DBG_REASON_SINGLESTEP;
+- break;
+- case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_IMPRECISE:
+- case NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE:
+- case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE:
+- if (nds32->get_watched_address(nds32, &(nds32->watched_address), reason) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- target->debug_reason = DBG_REASON_WATCHPOINT;
+- break;
+- default:
+- target->debug_reason = DBG_REASON_UNDEFINED;
+- break;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_login(struct nds32 *nds32)
+-{
+- struct target *target = nds32->target;
+- struct aice_port_s *aice = target_to_aice(target);
+- uint32_t passcode_length;
+- char command_sequence[129];
+- char command_str[33];
+- char code_str[9];
+- uint32_t copy_length;
+- uint32_t code;
+- uint32_t i;
+-
+- LOG_DEBUG("nds32_login");
+-
+- if (nds32->edm_passcode) {
+- /* convert EDM passcode to command sequences */
+- passcode_length = strlen(nds32->edm_passcode);
+- command_sequence[0] = '\0';
+- for (i = 0; i < passcode_length; i += 8) {
+- if (passcode_length - i < 8)
+- copy_length = passcode_length - i;
+- else
+- copy_length = 8;
+-
+- strncpy(code_str, nds32->edm_passcode + i, copy_length);
+- code_str[copy_length] = '\0';
+- code = strtoul(code_str, NULL, 16);
+-
+- sprintf(command_str, "write_misc gen_port0 0x%" PRIx32 ";", code);
+- strcat(command_sequence, command_str);
+- }
+-
+- if (aice_program_edm(aice, command_sequence) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- /* get current privilege level */
+- uint32_t value_edmsw;
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &value_edmsw);
+- nds32->privilege_level = (value_edmsw >> 16) & 0x3;
+- LOG_INFO("Current privilege level: %d", nds32->privilege_level);
+- }
+-
+- if (nds32_edm_ops_num > 0) {
+- const char *reg_name;
+- for (i = 0 ; i < nds32_edm_ops_num ; i++) {
+- code = nds32_edm_ops[i].value;
+- if (nds32_edm_ops[i].reg_no == 6)
+- reg_name = "gen_port0";
+- else if (nds32_edm_ops[i].reg_no == 7)
+- reg_name = "gen_port1";
+- else
+- return ERROR_FAIL;
+-
+- sprintf(command_str, "write_misc %s 0x%" PRIx32 ";", reg_name, code);
+- if (aice_program_edm(aice, command_str) != ERROR_OK)
+- return ERROR_FAIL;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_halt(struct target *target)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- enum target_state state;
+-
+- LOG_DEBUG("target->state: %s",
+- target_state_name(target));
+-
+- if (target->state == TARGET_HALTED) {
+- LOG_DEBUG("target was already halted");
+- return ERROR_OK;
+- }
+-
+- if (nds32_target_state(nds32, &state) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (state != TARGET_HALTED)
+- /* TODO: if state == TARGET_HALTED, check ETYPE is DBGI or not */
+- if (aice_halt(aice) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- CHECK_RETVAL(nds32->enter_debug_state(nds32, true));
+-
+- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
+-
+- return ERROR_OK;
+-}
+-
+-/* poll current target status */
+-int nds32_poll(struct target *target)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- enum target_state state;
+-
+- if (nds32_target_state(nds32, &state) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- if (state == TARGET_HALTED) {
+- if (target->state != TARGET_HALTED) {
+- /* if false_hit, continue free_run */
+- if (nds32->enter_debug_state(nds32, true) != ERROR_OK) {
+- struct aice_port_s *aice = target_to_aice(target);
+- aice_run(aice);
+- return ERROR_OK;
+- }
+-
+- LOG_DEBUG("Change target state to TARGET_HALTED.");
+-
+- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+- }
+- } else if (state == TARGET_RESET) {
+- if (target->state == TARGET_HALTED) {
+- /* similar to assert srst */
+- register_cache_invalidate(nds32->core_cache);
+- target->state = TARGET_RESET;
+-
+- /* TODO: deassert srst */
+- } else if (target->state == TARGET_RUNNING) {
+- /* reset as running */
+- LOG_WARNING("<-- TARGET WARNING! The debug target has been reset. -->");
+- }
+- } else {
+- if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING) {
+- LOG_DEBUG("Change target state to TARGET_RUNNING.");
+- target->state = TARGET_RUNNING;
+- target->debug_reason = DBG_REASON_NOTHALTED;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_resume(struct target *target, int current,
+- target_addr_t address, int handle_breakpoints, int debug_execution)
+-{
+- LOG_DEBUG("current %d address %08" TARGET_PRIxADDR
+- " handle_breakpoints %d"
+- " debug_execution %d",
+- current, address, handle_breakpoints, debug_execution);
+-
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (target->state != TARGET_HALTED) {
+- LOG_ERROR("Target not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- address = nds32_nextpc(nds32, current, address);
+-
+- LOG_DEBUG("RESUME PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : "");
+-
+- if (!debug_execution)
+- target_free_all_working_areas(target);
+-
+- /* Disable HSS to avoid users misuse HSS */
+- if (nds32_reach_max_interrupt_level(nds32) == false) {
+- uint32_t value_ir0;
+- nds32_get_mapped_reg(nds32, IR0, &value_ir0);
+- value_ir0 &= ~(0x1 << 11);
+- nds32_set_mapped_reg(nds32, IR0, value_ir0);
+- }
+-
+- CHECK_RETVAL(nds32->leave_debug_state(nds32, true));
+- CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
+-
+- if (nds32->virtual_hosting_ctrl_c == false) {
+- struct aice_port_s *aice = target_to_aice(target);
+- aice_run(aice);
+- } else
+- nds32->virtual_hosting_ctrl_c = false;
+-
+- target->debug_reason = DBG_REASON_NOTHALTED;
+- if (!debug_execution)
+- target->state = TARGET_RUNNING;
+- else
+- target->state = TARGET_DEBUG_RUNNING;
+-
+- LOG_DEBUG("target->state: %s",
+- target_state_name(target));
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_soft_reset_halt(struct target *target)
+-{
+- /* TODO: test it */
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- aice_assert_srst(aice, AICE_SRST);
+-
+- /* halt core and set pc to 0x0 */
+- int retval = target_halt(target);
+- if (retval != ERROR_OK)
+- return retval;
+-
+- /* start fetching from IVB */
+- uint32_t value_ir3;
+- nds32_get_mapped_reg(nds32, IR3, &value_ir3);
+- nds32_set_mapped_reg(nds32, PC, value_ir3 & 0xFFFF0000);
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_assert_reset(struct target *target)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_cpu_version *cpu_version = &(nds32->cpu_version);
+-
+- /* TODO: apply hw reset signal in not examined state */
+- if (!(target_was_examined(target))) {
+- LOG_WARNING("Reset is not asserted because the target is not examined.");
+- LOG_WARNING("Use a reset button or power cycle the target.");
+- return ERROR_TARGET_NOT_EXAMINED;
+- }
+-
+- if (target->reset_halt) {
+- if ((nds32->soft_reset_halt)
+- || (nds32->edm.version < 0x51)
+- || ((nds32->edm.version == 0x51)
+- && (cpu_version->revision == 0x1C)
+- && (cpu_version->cpu_id_family == 0xC)
+- && (cpu_version->cpu_id_version == 0x0)))
+- nds32_soft_reset_halt(target);
+- else
+- aice_assert_srst(aice, AICE_RESET_HOLD);
+- } else {
+- aice_assert_srst(aice, AICE_SRST);
+- alive_sleep(nds32->boot_time);
+- }
+-
+- /* set passcode for secure MCU after core reset */
+- nds32_login(nds32);
+-
+- /* registers are now invalid */
+- register_cache_invalidate(nds32->core_cache);
+-
+- target->state = TARGET_RESET;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_gdb_attach(struct nds32 *nds32)
+-{
+- LOG_DEBUG("nds32_gdb_attach, target coreid: %" PRId32, nds32->target->coreid);
+-
+- if (nds32->attached == false) {
+-
+- if (nds32->keep_target_edm_ctl) {
+- /* backup target EDM_CTL */
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &nds32->backup_edm_ctl);
+- }
+-
+- target_halt(nds32->target);
+-
+- nds32->attached = true;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_gdb_detach(struct nds32 *nds32)
+-{
+- LOG_DEBUG("nds32_gdb_detach");
+- bool backup_virtual_hosting_setting;
+-
+- if (nds32->attached) {
+-
+- backup_virtual_hosting_setting = nds32->virtual_hosting;
+- /* turn off virtual hosting before resume as gdb-detach */
+- nds32->virtual_hosting = false;
+- target_resume(nds32->target, 1, 0, 0, 0);
+- nds32->virtual_hosting = backup_virtual_hosting_setting;
+-
+- if (nds32->keep_target_edm_ctl) {
+- /* restore target EDM_CTL */
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, nds32->backup_edm_ctl);
+- }
+-
+- nds32->attached = false;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_callback_event_handler(struct target *target,
+- enum target_event event, void *priv)
+-{
+- int retval = ERROR_OK;
+- int target_number = *(int *)priv;
+-
+- if (target_number != target->target_number)
+- return ERROR_OK;
+-
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- switch (event) {
+- case TARGET_EVENT_GDB_ATTACH:
+- retval = nds32_gdb_attach(nds32);
+- break;
+- case TARGET_EVENT_GDB_DETACH:
+- retval = nds32_gdb_detach(nds32);
+- break;
+- default:
+- break;
+- }
+-
+- return retval;
+-}
+-
+-int nds32_init(struct nds32 *nds32)
+-{
+- /* Initialize anything we can set up without talking to the target */
+- nds32->memory.access_channel = NDS_MEMORY_ACC_CPU;
+-
+- /* register event callback */
+- target_register_event_callback(nds32_callback_event_handler,
+- &(nds32->target->target_number));
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
+-{
+- /* fill syscall parameters to file-I/O info */
+- if (!fileio_info) {
+- LOG_ERROR("Target has not initial file-I/O data structure");
+- return ERROR_FAIL;
+- }
+-
+- struct nds32 *nds32 = target_to_nds32(target);
+- uint32_t value_ir6;
+- uint32_t syscall_id;
+-
+- if (nds32->hit_syscall == false)
+- return ERROR_FAIL;
+-
+- nds32_get_mapped_reg(nds32, IR6, &value_ir6);
+- syscall_id = (value_ir6 >> 16) & 0x7FFF;
+- nds32->active_syscall_id = syscall_id;
+-
+- LOG_DEBUG("hit syscall ID: 0x%" PRIx32, syscall_id);
+-
+- /* free previous identifier storage */
+- free(fileio_info->identifier);
+- fileio_info->identifier = NULL;
+-
+- uint32_t reg_r0, reg_r1, reg_r2;
+- nds32_get_mapped_reg(nds32, R0, ®_r0);
+- nds32_get_mapped_reg(nds32, R1, ®_r1);
+- nds32_get_mapped_reg(nds32, R2, ®_r2);
+-
+- switch (syscall_id) {
+- case NDS32_SYSCALL_EXIT:
+- fileio_info->identifier = malloc(5);
+- sprintf(fileio_info->identifier, "exit");
+- fileio_info->param_1 = reg_r0;
+- break;
+- case NDS32_SYSCALL_OPEN:
+- {
+- uint8_t filename[256];
+- fileio_info->identifier = malloc(5);
+- sprintf(fileio_info->identifier, "open");
+- fileio_info->param_1 = reg_r0;
+- /* reserve fileio_info->param_2 for length of path */
+- fileio_info->param_3 = reg_r1;
+- fileio_info->param_4 = reg_r2;
+-
+- target->type->read_buffer(target, reg_r0, 256, filename);
+- fileio_info->param_2 = strlen((char *)filename);
+- }
+- break;
+- case NDS32_SYSCALL_CLOSE:
+- fileio_info->identifier = malloc(6);
+- sprintf(fileio_info->identifier, "close");
+- fileio_info->param_1 = reg_r0;
+- break;
+- case NDS32_SYSCALL_READ:
+- fileio_info->identifier = malloc(5);
+- sprintf(fileio_info->identifier, "read");
+- fileio_info->param_1 = reg_r0;
+- fileio_info->param_2 = reg_r1;
+- fileio_info->param_3 = reg_r2;
+- break;
+- case NDS32_SYSCALL_WRITE:
+- fileio_info->identifier = malloc(6);
+- sprintf(fileio_info->identifier, "write");
+- fileio_info->param_1 = reg_r0;
+- fileio_info->param_2 = reg_r1;
+- fileio_info->param_3 = reg_r2;
+- break;
+- case NDS32_SYSCALL_LSEEK:
+- fileio_info->identifier = malloc(6);
+- sprintf(fileio_info->identifier, "lseek");
+- fileio_info->param_1 = reg_r0;
+- fileio_info->param_2 = reg_r1;
+- fileio_info->param_3 = reg_r2;
+- break;
+- case NDS32_SYSCALL_UNLINK:
+- {
+- uint8_t filename[256];
+- fileio_info->identifier = malloc(7);
+- sprintf(fileio_info->identifier, "unlink");
+- fileio_info->param_1 = reg_r0;
+- /* reserve fileio_info->param_2 for length of path */
+-
+- target->type->read_buffer(target, reg_r0, 256, filename);
+- fileio_info->param_2 = strlen((char *)filename);
+- }
+- break;
+- case NDS32_SYSCALL_RENAME:
+- {
+- uint8_t filename[256];
+- fileio_info->identifier = malloc(7);
+- sprintf(fileio_info->identifier, "rename");
+- fileio_info->param_1 = reg_r0;
+- /* reserve fileio_info->param_2 for length of old path */
+- fileio_info->param_3 = reg_r1;
+- /* reserve fileio_info->param_4 for length of new path */
+-
+- target->type->read_buffer(target, reg_r0, 256, filename);
+- fileio_info->param_2 = strlen((char *)filename);
+-
+- target->type->read_buffer(target, reg_r1, 256, filename);
+- fileio_info->param_4 = strlen((char *)filename);
+- }
+- break;
+- case NDS32_SYSCALL_FSTAT:
+- fileio_info->identifier = malloc(6);
+- sprintf(fileio_info->identifier, "fstat");
+- fileio_info->param_1 = reg_r0;
+- fileio_info->param_2 = reg_r1;
+- break;
+- case NDS32_SYSCALL_STAT:
+- {
+- uint8_t filename[256];
+- fileio_info->identifier = malloc(5);
+- sprintf(fileio_info->identifier, "stat");
+- fileio_info->param_1 = reg_r0;
+- /* reserve fileio_info->param_2 for length of old path */
+- fileio_info->param_3 = reg_r1;
+-
+- target->type->read_buffer(target, reg_r0, 256, filename);
+- fileio_info->param_2 = strlen((char *)filename) + 1;
+- }
+- break;
+- case NDS32_SYSCALL_GETTIMEOFDAY:
+- fileio_info->identifier = malloc(13);
+- sprintf(fileio_info->identifier, "gettimeofday");
+- fileio_info->param_1 = reg_r0;
+- fileio_info->param_2 = reg_r1;
+- break;
+- case NDS32_SYSCALL_ISATTY:
+- fileio_info->identifier = malloc(7);
+- sprintf(fileio_info->identifier, "isatty");
+- fileio_info->param_1 = reg_r0;
+- break;
+- case NDS32_SYSCALL_SYSTEM:
+- {
+- uint8_t command[256];
+- fileio_info->identifier = malloc(7);
+- sprintf(fileio_info->identifier, "system");
+- fileio_info->param_1 = reg_r0;
+- /* reserve fileio_info->param_2 for length of old path */
+-
+- target->type->read_buffer(target, reg_r0, 256, command);
+- fileio_info->param_2 = strlen((char *)command);
+- }
+- break;
+- case NDS32_SYSCALL_ERRNO:
+- fileio_info->identifier = malloc(6);
+- sprintf(fileio_info->identifier, "errno");
+- nds32_set_mapped_reg(nds32, R0, nds32->virtual_hosting_errno);
+- break;
+- default:
+- fileio_info->identifier = malloc(8);
+- sprintf(fileio_info->identifier, "unknown");
+- break;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
+-{
+- LOG_DEBUG("syscall return code: 0x%x, errno: 0x%x , ctrl_c: %s",
+- retcode, fileio_errno, ctrl_c ? "true" : "false");
+-
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- nds32_set_mapped_reg(nds32, R0, (uint32_t)retcode);
+-
+- nds32->virtual_hosting_errno = fileio_errno;
+- nds32->virtual_hosting_ctrl_c = ctrl_c;
+- nds32->active_syscall_id = NDS32_SYSCALL_UNDEFINED;
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_profiling(struct target *target, uint32_t *samples,
+- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
+-{
+- /* sample $PC every 10 milliseconds */
+- uint32_t iteration = seconds * 100;
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- /* REVISIT: can nds32 profile without halting? */
+- if (target->state != TARGET_HALTED) {
+- LOG_WARNING("target %s is not halted (profiling)", target->cmd_name);
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- if (max_num_samples < iteration)
+- iteration = max_num_samples;
+-
+- int pc_regnum = nds32->register_map(nds32, PC);
+- aice_profiling(aice, 10, iteration, pc_regnum, samples, num_samples);
+-
+- register_cache_invalidate(nds32->core_cache);
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_gdb_fileio_write_memory(struct nds32 *nds32, uint32_t address,
+- uint32_t size, const uint8_t *buffer)
+-{
+- if ((nds32->active_syscall_id == NDS32_SYSCALL_FSTAT) ||
+- (nds32->active_syscall_id == NDS32_SYSCALL_STAT)) {
+- /* If doing GDB file-I/O, target should convert 'struct stat'
+- * from gdb-format to target-format */
+- uint8_t stat_buffer[NDS32_STRUCT_STAT_SIZE];
+- /* st_dev 2 */
+- stat_buffer[0] = buffer[3];
+- stat_buffer[1] = buffer[2];
+- /* st_ino 2 */
+- stat_buffer[2] = buffer[7];
+- stat_buffer[3] = buffer[6];
+- /* st_mode 4 */
+- stat_buffer[4] = buffer[11];
+- stat_buffer[5] = buffer[10];
+- stat_buffer[6] = buffer[9];
+- stat_buffer[7] = buffer[8];
+- /* st_nlink 2 */
+- stat_buffer[8] = buffer[15];
+- stat_buffer[9] = buffer[16];
+- /* st_uid 2 */
+- stat_buffer[10] = buffer[19];
+- stat_buffer[11] = buffer[18];
+- /* st_gid 2 */
+- stat_buffer[12] = buffer[23];
+- stat_buffer[13] = buffer[22];
+- /* st_rdev 2 */
+- stat_buffer[14] = buffer[27];
+- stat_buffer[15] = buffer[26];
+- /* st_size 4 */
+- stat_buffer[16] = buffer[35];
+- stat_buffer[17] = buffer[34];
+- stat_buffer[18] = buffer[33];
+- stat_buffer[19] = buffer[32];
+- /* st_atime 4 */
+- stat_buffer[20] = buffer[55];
+- stat_buffer[21] = buffer[54];
+- stat_buffer[22] = buffer[53];
+- stat_buffer[23] = buffer[52];
+- /* st_spare1 4 */
+- stat_buffer[24] = 0;
+- stat_buffer[25] = 0;
+- stat_buffer[26] = 0;
+- stat_buffer[27] = 0;
+- /* st_mtime 4 */
+- stat_buffer[28] = buffer[59];
+- stat_buffer[29] = buffer[58];
+- stat_buffer[30] = buffer[57];
+- stat_buffer[31] = buffer[56];
+- /* st_spare2 4 */
+- stat_buffer[32] = 0;
+- stat_buffer[33] = 0;
+- stat_buffer[34] = 0;
+- stat_buffer[35] = 0;
+- /* st_ctime 4 */
+- stat_buffer[36] = buffer[63];
+- stat_buffer[37] = buffer[62];
+- stat_buffer[38] = buffer[61];
+- stat_buffer[39] = buffer[60];
+- /* st_spare3 4 */
+- stat_buffer[40] = 0;
+- stat_buffer[41] = 0;
+- stat_buffer[42] = 0;
+- stat_buffer[43] = 0;
+- /* st_blksize 4 */
+- stat_buffer[44] = buffer[43];
+- stat_buffer[45] = buffer[42];
+- stat_buffer[46] = buffer[41];
+- stat_buffer[47] = buffer[40];
+- /* st_blocks 4 */
+- stat_buffer[48] = buffer[51];
+- stat_buffer[49] = buffer[50];
+- stat_buffer[50] = buffer[49];
+- stat_buffer[51] = buffer[48];
+- /* st_spare4 8 */
+- stat_buffer[52] = 0;
+- stat_buffer[53] = 0;
+- stat_buffer[54] = 0;
+- stat_buffer[55] = 0;
+- stat_buffer[56] = 0;
+- stat_buffer[57] = 0;
+- stat_buffer[58] = 0;
+- stat_buffer[59] = 0;
+-
+- return nds32_write_buffer(nds32->target, address, NDS32_STRUCT_STAT_SIZE, stat_buffer);
+- } else if (nds32->active_syscall_id == NDS32_SYSCALL_GETTIMEOFDAY) {
+- /* If doing GDB file-I/O, target should convert 'struct timeval'
+- * from gdb-format to target-format */
+- uint8_t timeval_buffer[NDS32_STRUCT_TIMEVAL_SIZE];
+- timeval_buffer[0] = buffer[3];
+- timeval_buffer[1] = buffer[2];
+- timeval_buffer[2] = buffer[1];
+- timeval_buffer[3] = buffer[0];
+- timeval_buffer[4] = buffer[11];
+- timeval_buffer[5] = buffer[10];
+- timeval_buffer[6] = buffer[9];
+- timeval_buffer[7] = buffer[8];
+-
+- return nds32_write_buffer(nds32->target, address, NDS32_STRUCT_TIMEVAL_SIZE, timeval_buffer);
+- }
+-
+- return nds32_write_buffer(nds32->target, address, size, buffer);
+-}
+-
+-int nds32_reset_halt(struct nds32 *nds32)
+-{
+- LOG_INFO("reset halt as init");
+-
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+- aice_assert_srst(aice, AICE_RESET_HOLD);
+-
+- return ERROR_OK;
+-}
+diff --git a/src/target/nds32.h b/src/target/nds32.h
+deleted file mode 100644
+index d0b680a97..000000000
+--- a/src/target/nds32.h
++++ /dev/null
+@@ -1,447 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_H
+-#define OPENOCD_TARGET_NDS32_H
+-
+-#include <jtag/jtag.h>
+-#include "target.h"
+-#include "target_type.h"
+-#include "register.h"
+-#include "breakpoints.h"
+-#include "nds32_reg.h"
+-#include "nds32_insn.h"
+-#include "nds32_edm.h"
+-
+-#define NDS32_EDM_OPERATION_MAX_NUM 64
+-
+-#define CHECK_RETVAL(action) \
+- do { \
+- int __retval = (action); \
+- if (__retval != ERROR_OK) { \
+- LOG_DEBUG("error while calling \"%s\"", \
+- # action); \
+- return __retval; \
+- } \
+- } while (0)
+-
+-/**
+- * @file
+- * Holds the interface to Andes cores.
+- */
+-
+-extern const char *nds32_debug_type_name[11];
+-
+-enum nds32_debug_reason {
+- NDS32_DEBUG_BREAK = 0,
+- NDS32_DEBUG_BREAK_16,
+- NDS32_DEBUG_INST_BREAK,
+- NDS32_DEBUG_DATA_ADDR_WATCHPOINT_PRECISE,
+- NDS32_DEBUG_DATA_VALUE_WATCHPOINT_PRECISE,
+- NDS32_DEBUG_DATA_VALUE_WATCHPOINT_IMPRECISE,
+- NDS32_DEBUG_DEBUG_INTERRUPT,
+- NDS32_DEBUG_HARDWARE_SINGLE_STEP,
+- NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE,
+- NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE,
+- NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP,
+-};
+-
+-#define NDS32_STRUCT_STAT_SIZE 60
+-#define NDS32_STRUCT_TIMEVAL_SIZE 8
+-
+-enum nds32_syscall_id {
+- NDS32_SYSCALL_UNDEFINED = 0,
+- NDS32_SYSCALL_EXIT = 1,
+- NDS32_SYSCALL_OPEN = 2,
+- NDS32_SYSCALL_CLOSE = 3,
+- NDS32_SYSCALL_READ = 4,
+- NDS32_SYSCALL_WRITE = 5,
+- NDS32_SYSCALL_LSEEK = 6,
+- NDS32_SYSCALL_UNLINK = 7,
+- NDS32_SYSCALL_RENAME = 3001,
+- NDS32_SYSCALL_FSTAT = 10,
+- NDS32_SYSCALL_STAT = 15,
+- NDS32_SYSCALL_GETTIMEOFDAY = 19,
+- NDS32_SYSCALL_ISATTY = 3002,
+- NDS32_SYSCALL_SYSTEM = 3003,
+- NDS32_SYSCALL_ERRNO = 6001,
+-};
+-
+-#define NDS32_COMMON_MAGIC 0xADE5ADE5U
+-
+-struct nds32_edm {
+-
+- /** EDM_CFG.VER, indicate the EDM version */
+- int version;
+-
+- /** The number of hardware breakpoints */
+- int breakpoint_num;
+-
+- /** EDM_CFG.DALM, indicate if direct local memory access
+- * feature is supported or not */
+- bool direct_access_local_memory;
+-
+- /** Support ACC_CTL register */
+- bool access_control;
+-
+- /** */
+- bool support_max_stop;
+-};
+-
+-struct nds32_cache {
+-
+- /** enable cache or not */
+- bool enable;
+-
+- /** cache sets per way */
+- int set;
+-
+- /** cache ways */
+- int way;
+-
+- /** cache line size */
+- int line_size;
+-
+- /** cache locking support */
+- bool lock_support;
+-};
+-
+-struct nds32_memory {
+-
+- /** ICache */
+- struct nds32_cache icache;
+-
+- /** DCache */
+- struct nds32_cache dcache;
+-
+- /** On-chip instruction local memory base */
+- int ilm_base;
+-
+- /** On-chip instruction local memory size */
+- int ilm_size;
+-
+- /** ILM base register alignment version */
+- int ilm_align_ver;
+-
+- /** DLM is enabled or not */
+- bool ilm_enable;
+-
+- /** DLM start address */
+- int ilm_start;
+-
+- /** DLM end address */
+- int ilm_end;
+-
+- /** On-chip data local memory base */
+- int dlm_base;
+-
+- /** On-chip data local memory size */
+- int dlm_size;
+-
+- /** DLM base register alignment version */
+- int dlm_align_ver;
+-
+- /** DLM is enabled or not */
+- bool dlm_enable;
+-
+- /** DLM start address */
+- int dlm_start;
+-
+- /** DLM end address */
+- int dlm_end;
+-
+- /** Memory access method */
+- enum nds_memory_access access_channel;
+-
+- /** Memory access mode */
+- enum nds_memory_select mode;
+-
+- /** Address translation */
+- bool address_translation;
+-};
+-
+-struct nds32_cpu_version {
+- bool performance_extension;
+- bool _16bit_extension;
+- bool performance_extension_2;
+- bool cop_fpu_extension;
+- bool string_extension;
+-
+- int revision;
+- int cpu_id_family;
+- int cpu_id_version;
+-};
+-
+-struct nds32_mmu_config {
+- int memory_protection;
+- int memory_protection_version;
+- bool fully_associative_tlb;
+- int tlb_size;
+- int tlb_ways;
+- int tlb_sets;
+- bool _8k_page_support;
+- int extra_page_size_support;
+- bool tlb_lock;
+- bool hardware_page_table_walker;
+- bool default_endian;
+- int partition_num;
+- bool invisible_tlb;
+- bool vlpt;
+- bool ntme;
+- bool drde;
+- int default_min_page_size;
+- bool multiple_page_size_in_use;
+-};
+-
+-struct nds32_misc_config {
+- bool edm;
+- bool local_memory_dma;
+- bool performance_monitor;
+- bool high_speed_memory_port;
+- bool debug_tracer;
+- bool div_instruction;
+- bool mac_instruction;
+- int audio_isa;
+- bool l2_cache;
+- bool reduce_register;
+- bool addr_24;
+- bool interruption_level;
+- int baseline_instruction;
+- bool no_dx_register;
+- bool implement_dependant_register;
+- bool implement_dependant_sr_encoding;
+- bool ifc;
+- bool mcu;
+- bool ex9;
+- int shadow;
+-};
+-
+-/**
+- * Represents a generic Andes core.
+- */
+-struct nds32 {
+- unsigned int common_magic;
+-
+- struct reg_cache *core_cache;
+-
+- /** Handle for the debug module. */
+- struct nds32_edm edm;
+-
+- /** Memory information */
+- struct nds32_memory memory;
+-
+- /** cpu version */
+- struct nds32_cpu_version cpu_version;
+-
+- /** MMU configuration */
+- struct nds32_mmu_config mmu_config;
+-
+- /** Misc configuration */
+- struct nds32_misc_config misc_config;
+-
+- /** Retrieve all core registers, for display. */
+- int (*full_context)(struct nds32 *nds32);
+-
+- /** Register mappings */
+- int (*register_map)(struct nds32 *nds32, int reg_no);
+-
+- /** Get debug exception virtual address */
+- int (*get_debug_reason)(struct nds32 *nds32, uint32_t *reason);
+-
+- /** Restore target registers may be modified in debug state */
+- int (*leave_debug_state)(struct nds32 *nds32, bool enable_watchpoint);
+-
+- /** Backup target registers may be modified in debug state */
+- int (*enter_debug_state)(struct nds32 *nds32, bool enable_watchpoint);
+-
+- /** Get address hit watchpoint */
+- int (*get_watched_address)(struct nds32 *nds32, uint32_t *address, uint32_t reason);
+-
+- /** maximum interrupt level */
+- uint32_t max_interrupt_level;
+-
+- /** current interrupt level */
+- uint32_t current_interrupt_level;
+-
+- uint32_t watched_address;
+-
+- /** Flag reporting whether virtual hosting is active. */
+- bool virtual_hosting;
+-
+- /** Flag reporting whether continue/step hits syscall or not */
+- bool hit_syscall;
+-
+- /** Value to be returned by virtual hosting SYS_ERRNO request. */
+- int virtual_hosting_errno;
+-
+- /** Flag reporting whether syscall is aborted */
+- bool virtual_hosting_ctrl_c;
+-
+- /** Record syscall ID for other operations to do special processing for target */
+- int active_syscall_id;
+-
+- struct breakpoint syscall_break;
+-
+- /** Flag reporting whether global stop is active. */
+- bool global_stop;
+-
+- /** Flag reporting whether to use soft-reset-halt or not as issuing reset-halt. */
+- bool soft_reset_halt;
+-
+- /** reset-halt as target examine */
+- bool reset_halt_as_examine;
+-
+- /** backup/restore target EDM_CTL value. As debugging target debug
+- * handler, it should be true. */
+- bool keep_target_edm_ctl;
+-
+- /* Value of $EDM_CTL before target enters debug mode */
+- uint32_t backup_edm_ctl;
+-
+- /** always use word-aligned address to access memory */
+- bool word_access_mem;
+-
+- /** EDM passcode for debugging secure MCU */
+- char *edm_passcode;
+-
+- /** current privilege_level if using secure MCU. value 0 is the highest level. */
+- int privilege_level;
+-
+- /** Period to wait after SRST. */
+- uint32_t boot_time;
+-
+- /** Flag to indicate HSS steps into ISR or not */
+- bool step_isr_enable;
+-
+- /** Flag to indicate register table is ready or not */
+- bool init_arch_info_after_halted;
+-
+- /** Flag to indicate audio-extension is enabled or not */
+- bool audio_enable;
+-
+- /** Flag to indicate fpu-extension is enabled or not */
+- bool fpu_enable;
+-
+- /* Andes Core has mixed endian model. Instruction is always big-endian.
+- * Data may be big or little endian. Device registers may have different
+- * endian from data and instruction. */
+- /** Endian of data memory */
+- enum target_endianness data_endian;
+-
+- /** Endian of device registers */
+- enum target_endianness device_reg_endian;
+-
+- /** Flag to indicate if auto convert software breakpoints to
+- * hardware breakpoints or not in ROM */
+- bool auto_convert_hw_bp;
+-
+- /* Flag to indicate the target is attached by debugger or not */
+- bool attached;
+-
+- /** Backpointer to the target. */
+- struct target *target;
+-
+- void *arch_info;
+-};
+-
+-struct nds32_reg {
+- int32_t num;
+- uint8_t value[8];
+- struct target *target;
+- struct nds32 *nds32;
+- bool enable;
+-};
+-
+-struct nds32_edm_operation {
+- uint32_t reg_no;
+- uint32_t value;
+-};
+-
+-extern int nds32_config(struct nds32 *nds32);
+-extern int nds32_init_arch_info(struct target *target, struct nds32 *nds32);
+-extern int nds32_full_context(struct nds32 *nds32);
+-extern int nds32_arch_state(struct target *target);
+-extern int nds32_add_software_breakpoint(struct target *target,
+- struct breakpoint *breakpoint);
+-extern int nds32_remove_software_breakpoint(struct target *target,
+- struct breakpoint *breakpoint);
+-
+-extern int nds32_get_gdb_reg_list(struct target *target,
+- struct reg **reg_list[], int *reg_list_size,
+- enum target_register_class reg_class);
+-
+-extern int nds32_write_buffer(struct target *target, uint32_t address,
+- uint32_t size, const uint8_t *buffer);
+-extern int nds32_read_buffer(struct target *target, uint32_t address,
+- uint32_t size, uint8_t *buffer);
+-extern int nds32_read_memory(struct target *target, uint32_t address,
+- uint32_t size, uint32_t count, uint8_t *buffer);
+-extern int nds32_write_memory(struct target *target, uint32_t address,
+- uint32_t size, uint32_t count, const uint8_t *buffer);
+-
+-extern int nds32_init_register_table(struct nds32 *nds32);
+-extern int nds32_init_memory_info(struct nds32 *nds32);
+-extern int nds32_restore_context(struct target *target);
+-extern int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t *value);
+-extern int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value);
+-
+-extern int nds32_edm_config(struct nds32 *nds32);
+-extern int nds32_cache_sync(struct target *target, target_addr_t address, uint32_t length);
+-extern int nds32_mmu(struct target *target, int *enabled);
+-extern int nds32_virtual_to_physical(struct target *target, target_addr_t address,
+- target_addr_t *physical);
+-extern int nds32_read_phys_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, uint8_t *buffer);
+-extern int nds32_write_phys_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, const uint8_t *buffer);
+-extern uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address);
+-extern int nds32_examine_debug_reason(struct nds32 *nds32);
+-extern int nds32_step(struct target *target, int current,
+- target_addr_t address, int handle_breakpoints);
+-extern int nds32_target_state(struct nds32 *nds32, enum target_state *state);
+-extern int nds32_halt(struct target *target);
+-extern int nds32_poll(struct target *target);
+-extern int nds32_resume(struct target *target, int current,
+- target_addr_t address, int handle_breakpoints, int debug_execution);
+-extern int nds32_assert_reset(struct target *target);
+-extern int nds32_init(struct nds32 *nds32);
+-extern int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info);
+-extern int nds32_gdb_fileio_write_memory(struct nds32 *nds32, uint32_t address,
+- uint32_t size, const uint8_t *buffer);
+-extern int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c);
+-extern int nds32_reset_halt(struct nds32 *nds32);
+-extern int nds32_login(struct nds32 *nds32);
+-extern int nds32_profiling(struct target *target, uint32_t *samples,
+- uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
+-
+-/** Convert target handle to generic Andes target state handle. */
+-static inline struct nds32 *target_to_nds32(struct target *target)
+-{
+- assert(target);
+- return target->arch_info;
+-}
+-
+-/** */
+-static inline struct aice_port_s *target_to_aice(struct target *target)
+-{
+- assert(target);
+- return target->tap->priv;
+-}
+-
+-static inline bool is_nds32(struct nds32 *nds32)
+-{
+- assert(nds32);
+- return nds32->common_magic == NDS32_COMMON_MAGIC;
+-}
+-
+-static inline bool nds32_reach_max_interrupt_level(struct nds32 *nds32)
+-{
+- assert(nds32);
+- return nds32->max_interrupt_level == nds32->current_interrupt_level;
+-}
+-
+-#endif /* OPENOCD_TARGET_NDS32_H */
+diff --git a/src/target/nds32_aice.c b/src/target/nds32_aice.c
+deleted file mode 100644
+index 8dc4d7795..000000000
+--- a/src/target/nds32_aice.c
++++ /dev/null
+@@ -1,147 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes technology. *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <helper/log.h>
+-#include "nds32_aice.h"
+-
+-int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val)
+-{
+- if (!aice->port->api->read_reg_64) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->read_reg_64(aice->coreid, num, val);
+-}
+-
+-int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val)
+-{
+- if (!aice->port->api->write_reg_64) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->write_reg_64(aice->coreid, num, val);
+-}
+-
+-int aice_read_tlb(struct aice_port_s *aice, target_addr_t virtual_address,
+- target_addr_t *physical_address)
+-{
+- if (!aice->port->api->read_tlb) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->read_tlb(aice->coreid, virtual_address, physical_address);
+-}
+-
+-int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address)
+-{
+- if (!aice->port->api->cache_ctl) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->cache_ctl(aice->coreid, subtype, address);
+-}
+-
+-int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times)
+-{
+- if (!aice->port->api->set_retry_times) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->set_retry_times(a_retry_times);
+-}
+-
+-int aice_program_edm(struct aice_port_s *aice, char *command_sequence)
+-{
+- if (!aice->port->api->program_edm) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->program_edm(aice->coreid, command_sequence);
+-}
+-
+-int aice_set_command_mode(struct aice_port_s *aice,
+- enum aice_command_mode command_mode)
+-{
+- if (!aice->port->api->set_command_mode) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->set_command_mode(command_mode);
+-}
+-
+-int aice_execute(struct aice_port_s *aice, uint32_t *instructions,
+- uint32_t instruction_num)
+-{
+- if (!aice->port->api->execute) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->execute(aice->coreid, instructions, instruction_num);
+-}
+-
+-int aice_set_custom_srst_script(struct aice_port_s *aice, const char *script)
+-{
+- if (!aice->port->api->set_custom_srst_script) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->set_custom_srst_script(script);
+-}
+-
+-int aice_set_custom_trst_script(struct aice_port_s *aice, const char *script)
+-{
+- if (!aice->port->api->set_custom_trst_script) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->set_custom_trst_script(script);
+-}
+-
+-int aice_set_custom_restart_script(struct aice_port_s *aice, const char *script)
+-{
+- if (!aice->port->api->set_custom_restart_script) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->set_custom_restart_script(script);
+-}
+-
+-int aice_set_count_to_check_dbger(struct aice_port_s *aice, uint32_t count_to_check)
+-{
+- if (!aice->port->api->set_count_to_check_dbger) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->set_count_to_check_dbger(count_to_check);
+-}
+-
+-int aice_profiling(struct aice_port_s *aice, uint32_t interval, uint32_t iteration,
+- uint32_t reg_no, uint32_t *samples, uint32_t *num_samples)
+-{
+- if (!aice->port->api->profiling) {
+- LOG_WARNING("Not implemented: %s", __func__);
+- return ERROR_FAIL;
+- }
+-
+- return aice->port->api->profiling(aice->coreid, interval, iteration,
+- reg_no, samples, num_samples);
+-}
+diff --git a/src/target/nds32_aice.h b/src/target/nds32_aice.h
+deleted file mode 100644
+index 2a6c879ff..000000000
+--- a/src/target/nds32_aice.h
++++ /dev/null
+@@ -1,150 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes technology. *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_AICE_H
+-#define OPENOCD_TARGET_NDS32_AICE_H
+-
+-#include <jtag/aice/aice_port.h>
+-
+-int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val);
+-int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val);
+-int aice_read_tlb(struct aice_port_s *aice, target_addr_t virtual_address,
+- target_addr_t *physical_address);
+-int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address);
+-int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times);
+-int aice_program_edm(struct aice_port_s *aice, char *command_sequence);
+-int aice_set_command_mode(struct aice_port_s *aice,
+- enum aice_command_mode command_mode);
+-int aice_execute(struct aice_port_s *aice, uint32_t *instructions,
+- uint32_t instruction_num);
+-int aice_set_custom_srst_script(struct aice_port_s *aice, const char *script);
+-int aice_set_custom_trst_script(struct aice_port_s *aice, const char *script);
+-int aice_set_custom_restart_script(struct aice_port_s *aice, const char *script);
+-int aice_set_count_to_check_dbger(struct aice_port_s *aice, uint32_t count_to_check);
+-int aice_profiling(struct aice_port_s *aice, uint32_t interval, uint32_t iteration,
+- uint32_t reg_no, uint32_t *samples, uint32_t *num_samples);
+-
+-static inline int aice_open(struct aice_port_s *aice, struct aice_port_param_s *param)
+-{
+- return aice->port->api->open(param);
+-}
+-
+-static inline int aice_close(struct aice_port_s *aice)
+-{
+- return aice->port->api->close();
+-}
+-
+-static inline int aice_reset(struct aice_port_s *aice)
+-{
+- return aice->port->api->reset();
+-}
+-
+-static inline int aice_assert_srst(struct aice_port_s *aice,
+- enum aice_srst_type_s srst)
+-{
+- return aice->port->api->assert_srst(aice->coreid, srst);
+-}
+-
+-static inline int aice_run(struct aice_port_s *aice)
+-{
+- return aice->port->api->run(aice->coreid);
+-}
+-
+-static inline int aice_halt(struct aice_port_s *aice)
+-{
+- return aice->port->api->halt(aice->coreid);
+-}
+-
+-static inline int aice_step(struct aice_port_s *aice)
+-{
+- return aice->port->api->step(aice->coreid);
+-}
+-
+-static inline int aice_read_register(struct aice_port_s *aice, uint32_t num,
+- uint32_t *val)
+-{
+- return aice->port->api->read_reg(aice->coreid, num, val);
+-}
+-
+-static inline int aice_write_register(struct aice_port_s *aice, uint32_t num,
+- uint32_t val)
+-{
+- return aice->port->api->write_reg(aice->coreid, num, val);
+-}
+-
+-static inline int aice_read_debug_reg(struct aice_port_s *aice, uint32_t addr,
+- uint32_t *val)
+-{
+- return aice->port->api->read_debug_reg(aice->coreid, addr, val);
+-}
+-
+-static inline int aice_write_debug_reg(struct aice_port_s *aice, uint32_t addr,
+- const uint32_t val)
+-{
+- return aice->port->api->write_debug_reg(aice->coreid, addr, val);
+-}
+-
+-static inline int aice_read_mem_unit(struct aice_port_s *aice, uint32_t addr,
+- uint32_t size, uint32_t count, uint8_t *buffer)
+-{
+- return aice->port->api->read_mem_unit(aice->coreid, addr, size, count, buffer);
+-}
+-
+-static inline int aice_write_mem_unit(struct aice_port_s *aice, uint32_t addr,
+- uint32_t size, uint32_t count, const uint8_t *buffer)
+-{
+- return aice->port->api->write_mem_unit(aice->coreid, addr, size, count, buffer);
+-}
+-
+-static inline int aice_read_mem_bulk(struct aice_port_s *aice, uint32_t addr,
+- uint32_t length, uint8_t *buffer)
+-{
+- return aice->port->api->read_mem_bulk(aice->coreid, addr, length, buffer);
+-}
+-
+-static inline int aice_write_mem_bulk(struct aice_port_s *aice, uint32_t addr,
+- uint32_t length, const uint8_t *buffer)
+-{
+- return aice->port->api->write_mem_bulk(aice->coreid, addr, length, buffer);
+-}
+-
+-static inline int aice_idcode(struct aice_port_s *aice, uint32_t *idcode,
+- uint8_t *num_of_idcode)
+-{
+- return aice->port->api->idcode(idcode, num_of_idcode);
+-}
+-
+-static inline int aice_state(struct aice_port_s *aice,
+- enum aice_target_state_s *state)
+-{
+- return aice->port->api->state(aice->coreid, state);
+-}
+-
+-static inline int aice_set_jtag_clock(struct aice_port_s *aice, uint32_t a_clock)
+-{
+- return aice->port->api->set_jtag_clock(a_clock);
+-}
+-
+-static inline int aice_memory_access(struct aice_port_s *aice,
+- enum nds_memory_access a_access)
+-{
+- return aice->port->api->memory_access(aice->coreid, a_access);
+-}
+-
+-static inline int aice_memory_mode(struct aice_port_s *aice,
+- enum nds_memory_select mem_select)
+-{
+- return aice->port->api->memory_mode(aice->coreid, mem_select);
+-}
+-
+-static inline int aice_set_data_endian(struct aice_port_s *aice,
+- enum aice_target_endian target_data_endian)
+-{
+- return aice->port->api->set_data_endian(aice->coreid, target_data_endian);
+-}
+-
+-#endif /* OPENOCD_TARGET_NDS32_AICE_H */
+diff --git a/src/target/nds32_cmd.c b/src/target/nds32_cmd.c
+deleted file mode 100644
+index 37f7648c9..000000000
+--- a/src/target/nds32_cmd.c
++++ /dev/null
+@@ -1,1123 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <helper/command.h>
+-#include "nds32.h"
+-#include "nds32_aice.h"
+-#include "nds32_disassembler.h"
+-
+-extern struct nds32_edm_operation nds32_edm_ops[NDS32_EDM_OPERATION_MAX_NUM];
+-extern uint32_t nds32_edm_ops_num;
+-
+-static const char *const nds_memory_access_name[] = {
+- "BUS",
+- "CPU",
+-};
+-
+-static const char *const nds_memory_select_name[] = {
+- "AUTO",
+- "MEM",
+- "ILM",
+- "DLM",
+-};
+-
+-COMMAND_HANDLER(handle_nds32_dssim_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+- if (strcmp(CMD_ARGV[0], "on") == 0)
+- nds32->step_isr_enable = true;
+- if (strcmp(CMD_ARGV[0], "off") == 0)
+- nds32->step_isr_enable = false;
+- }
+-
+- command_print(CMD, "%s: $INT_MASK.DSSIM: %d", target_name(target),
+- nds32->step_isr_enable);
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_memory_access_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+- if (strcmp(CMD_ARGV[0], "bus") == 0)
+- memory->access_channel = NDS_MEMORY_ACC_BUS;
+- else if (strcmp(CMD_ARGV[0], "cpu") == 0)
+- memory->access_channel = NDS_MEMORY_ACC_CPU;
+- else /* default access channel is NDS_MEMORY_ACC_CPU */
+- memory->access_channel = NDS_MEMORY_ACC_CPU;
+-
+- LOG_DEBUG("memory access channel is changed to %s",
+- nds_memory_access_name[memory->access_channel]);
+-
+- aice_memory_access(aice, memory->access_channel);
+- } else {
+- command_print(CMD, "%s: memory access channel: %s",
+- target_name(target),
+- nds_memory_access_name[memory->access_channel]);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_memory_mode_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+-
+- if (nds32->edm.access_control == false) {
+- command_print(CMD, "%s does not support ACC_CTL. "
+- "Set memory mode to MEMORY", target_name(target));
+- nds32->memory.mode = NDS_MEMORY_SELECT_MEM;
+- } else if (nds32->edm.direct_access_local_memory == false) {
+- command_print(CMD, "%s does not support direct access "
+- "local memory. Set memory mode to MEMORY",
+- target_name(target));
+- nds32->memory.mode = NDS_MEMORY_SELECT_MEM;
+-
+- /* set to ACC_CTL */
+- aice_memory_mode(aice, nds32->memory.mode);
+- } else {
+- if (strcmp(CMD_ARGV[0], "auto") == 0) {
+- nds32->memory.mode = NDS_MEMORY_SELECT_AUTO;
+- } else if (strcmp(CMD_ARGV[0], "mem") == 0) {
+- nds32->memory.mode = NDS_MEMORY_SELECT_MEM;
+- } else if (strcmp(CMD_ARGV[0], "ilm") == 0) {
+- if (nds32->memory.ilm_base == 0)
+- command_print(CMD, "%s does not support ILM",
+- target_name(target));
+- else
+- nds32->memory.mode = NDS_MEMORY_SELECT_ILM;
+- } else if (strcmp(CMD_ARGV[0], "dlm") == 0) {
+- if (nds32->memory.dlm_base == 0)
+- command_print(CMD, "%s does not support DLM",
+- target_name(target));
+- else
+- nds32->memory.mode = NDS_MEMORY_SELECT_DLM;
+- }
+-
+- /* set to ACC_CTL */
+- aice_memory_mode(aice, nds32->memory.mode);
+- }
+- }
+-
+- command_print(CMD, "%s: memory mode: %s",
+- target_name(target),
+- nds_memory_select_name[nds32->memory.mode]);
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_cache_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_cache *icache = &(nds32->memory.icache);
+- struct nds32_cache *dcache = &(nds32->memory.dcache);
+- int result;
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+-
+- if (strcmp(CMD_ARGV[0], "invalidate") == 0) {
+- if ((dcache->line_size != 0) && (dcache->enable == true)) {
+- /* D$ write back */
+- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_WBALL, 0);
+- if (result != ERROR_OK) {
+- command_print(CMD, "%s: Write back data cache...failed",
+- target_name(target));
+- return result;
+- }
+-
+- command_print(CMD, "%s: Write back data cache...done",
+- target_name(target));
+-
+- /* D$ invalidate */
+- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_INVALALL, 0);
+- if (result != ERROR_OK) {
+- command_print(CMD, "%s: Invalidate data cache...failed",
+- target_name(target));
+- return result;
+- }
+-
+- command_print(CMD, "%s: Invalidate data cache...done",
+- target_name(target));
+- } else {
+- if (dcache->line_size == 0)
+- command_print(CMD, "%s: No data cache",
+- target_name(target));
+- else
+- command_print(CMD, "%s: Data cache disabled",
+- target_name(target));
+- }
+-
+- if ((icache->line_size != 0) && (icache->enable == true)) {
+- /* I$ invalidate */
+- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_INVALALL, 0);
+- if (result != ERROR_OK) {
+- command_print(CMD, "%s: Invalidate instruction cache...failed",
+- target_name(target));
+- return result;
+- }
+-
+- command_print(CMD, "%s: Invalidate instruction cache...done",
+- target_name(target));
+- } else {
+- if (icache->line_size == 0)
+- command_print(CMD, "%s: No instruction cache",
+- target_name(target));
+- else
+- command_print(CMD, "%s: Instruction cache disabled",
+- target_name(target));
+- }
+- } else
+- command_print(CMD, "No valid parameter");
+- }
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_icache_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_cache *icache = &(nds32->memory.icache);
+- int result;
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+-
+- if (icache->line_size == 0) {
+- command_print(CMD, "%s: No instruction cache",
+- target_name(target));
+- return ERROR_OK;
+- }
+-
+- if (strcmp(CMD_ARGV[0], "invalidate") == 0) {
+- if (icache->enable == true) {
+- /* I$ invalidate */
+- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_INVALALL, 0);
+- if (result != ERROR_OK) {
+- command_print(CMD, "%s: Invalidate instruction cache...failed",
+- target_name(target));
+- return result;
+- }
+-
+- command_print(CMD, "%s: Invalidate instruction cache...done",
+- target_name(target));
+- } else {
+- command_print(CMD, "%s: Instruction cache disabled",
+- target_name(target));
+- }
+- } else if (strcmp(CMD_ARGV[0], "enable") == 0) {
+- uint32_t value;
+- nds32_get_mapped_reg(nds32, IR8, &value);
+- nds32_set_mapped_reg(nds32, IR8, value | 0x1);
+- } else if (strcmp(CMD_ARGV[0], "disable") == 0) {
+- uint32_t value;
+- nds32_get_mapped_reg(nds32, IR8, &value);
+- nds32_set_mapped_reg(nds32, IR8, value & ~0x1);
+- } else if (strcmp(CMD_ARGV[0], "dump") == 0) {
+- /* TODO: dump cache content */
+- } else {
+- command_print(CMD, "%s: No valid parameter", target_name(target));
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_dcache_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_cache *dcache = &(nds32->memory.dcache);
+- int result;
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+-
+- if (dcache->line_size == 0) {
+- command_print(CMD, "%s: No data cache", target_name(target));
+- return ERROR_OK;
+- }
+-
+- if (strcmp(CMD_ARGV[0], "invalidate") == 0) {
+- if (dcache->enable == true) {
+- /* D$ write back */
+- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_WBALL, 0);
+- if (result != ERROR_OK) {
+- command_print(CMD, "%s: Write back data cache...failed",
+- target_name(target));
+- return result;
+- }
+-
+- command_print(CMD, "%s: Write back data cache...done",
+- target_name(target));
+-
+- /* D$ invalidate */
+- result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_INVALALL, 0);
+- if (result != ERROR_OK) {
+- command_print(CMD, "%s: Invalidate data cache...failed",
+- target_name(target));
+- return result;
+- }
+-
+- command_print(CMD, "%s: Invalidate data cache...done",
+- target_name(target));
+- } else {
+- command_print(CMD, "%s: Data cache disabled",
+- target_name(target));
+- }
+- } else if (strcmp(CMD_ARGV[0], "enable") == 0) {
+- uint32_t value;
+- nds32_get_mapped_reg(nds32, IR8, &value);
+- nds32_set_mapped_reg(nds32, IR8, value | 0x2);
+- } else if (strcmp(CMD_ARGV[0], "disable") == 0) {
+- uint32_t value;
+- nds32_get_mapped_reg(nds32, IR8, &value);
+- nds32_set_mapped_reg(nds32, IR8, value & ~0x2);
+- } else if (strcmp(CMD_ARGV[0], "dump") == 0) {
+- /* TODO: dump cache content */
+- } else {
+- command_print(CMD, "%s: No valid parameter", target_name(target));
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_auto_break_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+- if (strcmp(CMD_ARGV[0], "on") == 0)
+- nds32->auto_convert_hw_bp = true;
+- if (strcmp(CMD_ARGV[0], "off") == 0)
+- nds32->auto_convert_hw_bp = false;
+- }
+-
+- if (nds32->auto_convert_hw_bp)
+- command_print(CMD, "%s: convert sw break to hw break on ROM: on",
+- target_name(target));
+- else
+- command_print(CMD, "%s: convert sw break to hw break on ROM: off",
+- target_name(target));
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_virtual_hosting_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+- if (strcmp(CMD_ARGV[0], "on") == 0)
+- nds32->virtual_hosting = true;
+- if (strcmp(CMD_ARGV[0], "off") == 0)
+- nds32->virtual_hosting = false;
+- }
+-
+- if (nds32->virtual_hosting)
+- command_print(CMD, "%s: virtual hosting: on", target_name(target));
+- else
+- command_print(CMD, "%s: virtual hosting: off", target_name(target));
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_global_stop_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+- if (strcmp(CMD_ARGV[0], "on") == 0)
+- nds32->global_stop = true;
+- if (strcmp(CMD_ARGV[0], "off") == 0)
+- nds32->global_stop = false;
+- }
+-
+- if (nds32->global_stop)
+- LOG_INFO("%s: global stop: on", target_name(target));
+- else
+- LOG_INFO("%s: global stop: off", target_name(target));
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_soft_reset_halt_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+- if (strcmp(CMD_ARGV[0], "on") == 0)
+- nds32->soft_reset_halt = true;
+- if (strcmp(CMD_ARGV[0], "off") == 0)
+- nds32->soft_reset_halt = false;
+- }
+-
+- if (nds32->soft_reset_halt)
+- LOG_INFO("%s: soft-reset-halt: on", target_name(target));
+- else
+- LOG_INFO("%s: soft-reset-halt: off", target_name(target));
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_boot_time_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0)
+- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], nds32->boot_time);
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_login_edm_passcode_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- nds32->edm_passcode = strdup(CMD_ARGV[0]);
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_login_edm_operation_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 1) {
+-
+- uint32_t misc_reg_no;
+- uint32_t data;
+-
+- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], misc_reg_no);
+- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], data);
+-
+- if (nds32_edm_ops_num >= NDS32_EDM_OPERATION_MAX_NUM)
+- return ERROR_FAIL;
+-
+- /* Just save the operation. Execute it in nds32_login() */
+- nds32_edm_ops[nds32_edm_ops_num].reg_no = misc_reg_no;
+- nds32_edm_ops[nds32_edm_ops_num].value = data;
+- nds32_edm_ops_num++;
+- } else
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_reset_halt_as_init_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+- if (strcmp(CMD_ARGV[0], "on") == 0)
+- nds32->reset_halt_as_examine = true;
+- if (strcmp(CMD_ARGV[0], "off") == 0)
+- nds32->reset_halt_as_examine = false;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_keep_target_edm_ctl_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+- if (strcmp(CMD_ARGV[0], "on") == 0)
+- nds32->keep_target_edm_ctl = true;
+- if (strcmp(CMD_ARGV[0], "off") == 0)
+- nds32->keep_target_edm_ctl = false;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_decode_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 1) {
+-
+- uint32_t addr;
+- uint32_t insn_count;
+- uint32_t opcode;
+- uint32_t read_addr;
+- uint32_t i;
+- struct nds32_instruction instruction;
+-
+- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], insn_count);
+-
+- read_addr = addr;
+- i = 0;
+- while (i < insn_count) {
+- if (nds32_read_opcode(nds32, read_addr, &opcode) != ERROR_OK)
+- return ERROR_FAIL;
+- if (nds32_evaluate_opcode(nds32, opcode, read_addr, &instruction) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- command_print(CMD, "%s", instruction.text);
+-
+- read_addr += instruction.instruction_size;
+- i++;
+- }
+- } else if (CMD_ARGC == 1) {
+-
+- uint32_t addr;
+- uint32_t opcode;
+- struct nds32_instruction instruction;
+-
+- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+-
+- if (nds32_read_opcode(nds32, addr, &opcode) != ERROR_OK)
+- return ERROR_FAIL;
+- if (nds32_evaluate_opcode(nds32, opcode, addr, &instruction) != ERROR_OK)
+- return ERROR_FAIL;
+-
+- command_print(CMD, "%s", instruction.text);
+- } else
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_word_access_mem_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- if (CMD_ARGC > 0) {
+- if (strcmp(CMD_ARGV[0], "on") == 0)
+- nds32->word_access_mem = true;
+- if (strcmp(CMD_ARGV[0], "off") == 0)
+- nds32->word_access_mem = false;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_query_target_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- command_print(CMD, "OCD");
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_query_endian_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- uint32_t value_psw;
+- nds32_get_mapped_reg(nds32, IR0, &value_psw);
+-
+- if (value_psw & 0x20)
+- command_print(CMD, "%s: BE", target_name(target));
+- else
+- command_print(CMD, "%s: LE", target_name(target));
+-
+- return ERROR_OK;
+-}
+-
+-COMMAND_HANDLER(handle_nds32_query_cpuid_command)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- if (!is_nds32(nds32)) {
+- command_print(CMD, "current target isn't an Andes core");
+- return ERROR_FAIL;
+- }
+-
+- command_print(CMD, "CPUID: %s", target_name(target));
+-
+- return ERROR_OK;
+-}
+-
+-static int jim_nds32_bulk_write(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- const char *cmd_name = Jim_GetString(argv[0], NULL);
+-
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+-
+- if (goi.argc < 3) {
+- Jim_SetResultFormatted(goi.interp,
+- "usage: %s <address> <count> <data>", cmd_name);
+- return JIM_ERR;
+- }
+-
+- int e;
+- jim_wide address;
+- e = jim_getopt_wide(&goi, &address);
+- if (e != JIM_OK)
+- return e;
+-
+- jim_wide count;
+- e = jim_getopt_wide(&goi, &count);
+- if (e != JIM_OK)
+- return e;
+-
+- uint32_t *data = malloc(count * sizeof(uint32_t));
+- if (!data)
+- return JIM_ERR;
+-
+- jim_wide i;
+- for (i = 0; i < count; i++) {
+- jim_wide tmp;
+- e = jim_getopt_wide(&goi, &tmp);
+- if (e != JIM_OK) {
+- free(data);
+- return e;
+- }
+- data[i] = (uint32_t)tmp;
+- }
+-
+- /* all args must be consumed */
+- if (goi.argc != 0) {
+- free(data);
+- return JIM_ERR;
+- }
+-
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
+- struct target *target = get_current_target(cmd_ctx);
+- int result;
+-
+- result = target_write_buffer(target, address, count * 4, (const uint8_t *)data);
+-
+- free(data);
+-
+- return result;
+-}
+-
+-static int jim_nds32_multi_write(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- const char *cmd_name = Jim_GetString(argv[0], NULL);
+-
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+-
+- if (goi.argc < 3) {
+- Jim_SetResultFormatted(goi.interp,
+- "usage: %s # of pairs [<address> <data>]+", cmd_name);
+- return JIM_ERR;
+- }
+-
+- int e;
+- jim_wide num_of_pairs;
+- e = jim_getopt_wide(&goi, &num_of_pairs);
+- if (e != JIM_OK)
+- return e;
+-
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
+- struct target *target = get_current_target(cmd_ctx);
+- struct aice_port_s *aice = target_to_aice(target);
+- int result;
+- uint32_t address;
+- uint32_t data;
+- jim_wide i;
+-
+- aice_set_command_mode(aice, AICE_COMMAND_MODE_PACK);
+- for (i = 0; i < num_of_pairs; i++) {
+- jim_wide tmp;
+- e = jim_getopt_wide(&goi, &tmp);
+- if (e != JIM_OK)
+- break;
+- address = (uint32_t)tmp;
+-
+- e = jim_getopt_wide(&goi, &tmp);
+- if (e != JIM_OK)
+- break;
+- data = (uint32_t)tmp;
+-
+- result = target_write_buffer(target, address, 4, (const uint8_t *)&data);
+- if (result != ERROR_OK)
+- break;
+- }
+- aice_set_command_mode(aice, AICE_COMMAND_MODE_NORMAL);
+-
+- /* all args must be consumed */
+- if (goi.argc != 0)
+- return JIM_ERR;
+-
+- return ERROR_OK;
+-}
+-
+-static int jim_nds32_bulk_read(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- const char *cmd_name = Jim_GetString(argv[0], NULL);
+-
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+-
+- if (goi.argc < 2) {
+- Jim_SetResultFormatted(goi.interp,
+- "usage: %s <address> <count>", cmd_name);
+- return JIM_ERR;
+- }
+-
+- int e;
+- jim_wide address;
+- e = jim_getopt_wide(&goi, &address);
+- if (e != JIM_OK)
+- return e;
+-
+- jim_wide count;
+- e = jim_getopt_wide(&goi, &count);
+- if (e != JIM_OK)
+- return e;
+-
+- /* all args must be consumed */
+- if (goi.argc != 0)
+- return JIM_ERR;
+-
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
+- struct target *target = get_current_target(cmd_ctx);
+- uint32_t *data = malloc(count * sizeof(uint32_t));
+- int result;
+- result = target_read_buffer(target, address, count * 4, (uint8_t *)data);
+- char data_str[12];
+-
+- jim_wide i;
+- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+- for (i = 0; i < count; i++) {
+- sprintf(data_str, "0x%08" PRIx32 " ", data[i]);
+- Jim_AppendStrings(interp, Jim_GetResult(interp), data_str, NULL);
+- }
+-
+- free(data);
+-
+- return result;
+-}
+-
+-static int jim_nds32_read_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- const char *cmd_name = Jim_GetString(argv[0], NULL);
+-
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+-
+- if (goi.argc < 1) {
+- Jim_SetResultFormatted(goi.interp,
+- "usage: %s <edm_sr_name>", cmd_name);
+- return JIM_ERR;
+- }
+-
+- int e;
+- const char *edm_sr_name;
+- int edm_sr_name_len;
+- e = jim_getopt_string(&goi, &edm_sr_name, &edm_sr_name_len);
+- if (e != JIM_OK)
+- return e;
+-
+- /* all args must be consumed */
+- if (goi.argc != 0)
+- return JIM_ERR;
+-
+- uint32_t edm_sr_number;
+- uint32_t edm_sr_value;
+- if (strncmp(edm_sr_name, "edm_dtr", edm_sr_name_len) == 0)
+- edm_sr_number = NDS_EDM_SR_EDM_DTR;
+- else if (strncmp(edm_sr_name, "edmsw", edm_sr_name_len) == 0)
+- edm_sr_number = NDS_EDM_SR_EDMSW;
+- else
+- return ERROR_FAIL;
+-
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
+- struct target *target = get_current_target(cmd_ctx);
+- struct aice_port_s *aice = target_to_aice(target);
+- char data_str[11];
+-
+- aice_read_debug_reg(aice, edm_sr_number, &edm_sr_value);
+-
+- sprintf(data_str, "0x%08" PRIx32, edm_sr_value);
+- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+- Jim_AppendStrings(interp, Jim_GetResult(interp), data_str, NULL);
+-
+- return ERROR_OK;
+-}
+-
+-static int jim_nds32_write_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- const char *cmd_name = Jim_GetString(argv[0], NULL);
+-
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+-
+- if (goi.argc < 2) {
+- Jim_SetResultFormatted(goi.interp,
+- "usage: %s <edm_sr_name> <value>", cmd_name);
+- return JIM_ERR;
+- }
+-
+- int e;
+- const char *edm_sr_name;
+- int edm_sr_name_len;
+- e = jim_getopt_string(&goi, &edm_sr_name, &edm_sr_name_len);
+- if (e != JIM_OK)
+- return e;
+-
+- jim_wide value;
+- e = jim_getopt_wide(&goi, &value);
+- if (e != JIM_OK)
+- return e;
+-
+- /* all args must be consumed */
+- if (goi.argc != 0)
+- return JIM_ERR;
+-
+- uint32_t edm_sr_number;
+- if (strncmp(edm_sr_name, "edm_dtr", edm_sr_name_len) == 0)
+- edm_sr_number = NDS_EDM_SR_EDM_DTR;
+- else
+- return ERROR_FAIL;
+-
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
+- struct target *target = get_current_target(cmd_ctx);
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- aice_write_debug_reg(aice, edm_sr_number, value);
+-
+- return ERROR_OK;
+-}
+-
+-static const struct command_registration nds32_query_command_handlers[] = {
+- {
+- .name = "target",
+- .handler = handle_nds32_query_target_command,
+- .mode = COMMAND_EXEC,
+- .usage = "",
+- .help = "reply 'OCD' for gdb to identify server-side is OpenOCD",
+- },
+- {
+- .name = "endian",
+- .handler = handle_nds32_query_endian_command,
+- .mode = COMMAND_EXEC,
+- .usage = "",
+- .help = "query target endian",
+- },
+- {
+- .name = "cpuid",
+- .handler = handle_nds32_query_cpuid_command,
+- .mode = COMMAND_EXEC,
+- .usage = "",
+- .help = "query CPU ID",
+- },
+-
+- COMMAND_REGISTRATION_DONE
+-};
+-
+-static const struct command_registration nds32_exec_command_handlers[] = {
+- {
+- .name = "dssim",
+- .handler = handle_nds32_dssim_command,
+- .mode = COMMAND_EXEC,
+- .usage = "['on'|'off']",
+- .help = "display/change $INT_MASK.DSSIM status",
+- },
+- {
+- .name = "mem_access",
+- .handler = handle_nds32_memory_access_command,
+- .mode = COMMAND_EXEC,
+- .usage = "['bus'|'cpu']",
+- .help = "display/change memory access channel",
+- },
+- {
+- .name = "mem_mode",
+- .handler = handle_nds32_memory_mode_command,
+- .mode = COMMAND_EXEC,
+- .usage = "['auto'|'mem'|'ilm'|'dlm']",
+- .help = "display/change memory mode",
+- },
+- {
+- .name = "cache",
+- .handler = handle_nds32_cache_command,
+- .mode = COMMAND_EXEC,
+- .usage = "['invalidate']",
+- .help = "cache control",
+- },
+- {
+- .name = "icache",
+- .handler = handle_nds32_icache_command,
+- .mode = COMMAND_EXEC,
+- .usage = "['invalidate'|'enable'|'disable'|'dump']",
+- .help = "icache control",
+- },
+- {
+- .name = "dcache",
+- .handler = handle_nds32_dcache_command,
+- .mode = COMMAND_EXEC,
+- .usage = "['invalidate'|'enable'|'disable'|'dump']",
+- .help = "dcache control",
+- },
+- {
+- .name = "auto_break",
+- .handler = handle_nds32_auto_break_command,
+- .mode = COMMAND_EXEC,
+- .usage = "['on'|'off']",
+- .help = "convert software breakpoints to hardware breakpoints if needed",
+- },
+- {
+- .name = "virtual_hosting",
+- .handler = handle_nds32_virtual_hosting_command,
+- .mode = COMMAND_ANY,
+- .usage = "['on'|'off']",
+- .help = "turn on/off virtual hosting",
+- },
+- {
+- .name = "global_stop",
+- .handler = handle_nds32_global_stop_command,
+- .mode = COMMAND_ANY,
+- .usage = "['on'|'off']",
+- .help = "turn on/off global stop. After turning on, every load/store "
+- "instructions will be stopped to check memory access.",
+- },
+- {
+- .name = "soft_reset_halt",
+- .handler = handle_nds32_soft_reset_halt_command,
+- .mode = COMMAND_ANY,
+- .usage = "['on'|'off']",
+- .help = "as issuing rest-halt, to use soft-reset-halt or not."
+- "the feature is for backward-compatible.",
+- },
+- {
+- .name = "boot_time",
+- .handler = handle_nds32_boot_time_command,
+- .mode = COMMAND_CONFIG,
+- .usage = "milliseconds",
+- .help = "set the period to wait after srst.",
+- },
+- {
+- .name = "login_edm_passcode",
+- .handler = handle_nds32_login_edm_passcode_command,
+- .mode = COMMAND_CONFIG,
+- .usage = "passcode",
+- .help = "set EDM passcode for secure MCU debugging.",
+- },
+- {
+- .name = "login_edm_operation",
+- .handler = handle_nds32_login_edm_operation_command,
+- .mode = COMMAND_CONFIG,
+- .usage = "misc_reg_no value",
+- .help = "add EDM operations for secure MCU debugging.",
+- },
+- {
+- .name = "reset_halt_as_init",
+- .handler = handle_nds32_reset_halt_as_init_command,
+- .mode = COMMAND_CONFIG,
+- .usage = "['on'|'off']",
+- .help = "reset halt as openocd init.",
+- },
+- {
+- .name = "keep_target_edm_ctl",
+- .handler = handle_nds32_keep_target_edm_ctl_command,
+- .mode = COMMAND_CONFIG,
+- .usage = "['on'|'off']",
+- .help = "Backup/Restore target EDM_CTL register.",
+- },
+- {
+- .name = "decode",
+- .handler = handle_nds32_decode_command,
+- .mode = COMMAND_EXEC,
+- .usage = "address icount",
+- .help = "decode instruction.",
+- },
+- {
+- .name = "word_access_mem",
+- .handler = handle_nds32_word_access_mem_command,
+- .mode = COMMAND_ANY,
+- .usage = "['on'|'off']",
+- .help = "Always use word-aligned address to access memory.",
+- },
+- {
+- .name = "bulk_write",
+- .jim_handler = jim_nds32_bulk_write,
+- .mode = COMMAND_EXEC,
+- .help = "Write multiple 32-bit words to target memory",
+- .usage = "address count data",
+- },
+- {
+- .name = "multi_write",
+- .jim_handler = jim_nds32_multi_write,
+- .mode = COMMAND_EXEC,
+- .help = "Write multiple addresses/words to target memory",
+- .usage = "num_of_pairs [address data]+",
+- },
+- {
+- .name = "bulk_read",
+- .jim_handler = jim_nds32_bulk_read,
+- .mode = COMMAND_EXEC,
+- .help = "Read multiple 32-bit words from target memory",
+- .usage = "address count",
+- },
+- {
+- .name = "read_edmsr",
+- .jim_handler = jim_nds32_read_edm_sr,
+- .mode = COMMAND_EXEC,
+- .help = "Read EDM system register",
+- .usage = "['edmsw'|'edm_dtr']",
+- },
+- {
+- .name = "write_edmsr",
+- .jim_handler = jim_nds32_write_edm_sr,
+- .mode = COMMAND_EXEC,
+- .help = "Write EDM system register",
+- .usage = "['edm_dtr'] value",
+- },
+- {
+- .name = "query",
+- .mode = COMMAND_EXEC,
+- .help = "Andes query command group",
+- .usage = "",
+- .chain = nds32_query_command_handlers,
+- },
+-
+- COMMAND_REGISTRATION_DONE
+-};
+-
+-const struct command_registration nds32_command_handlers[] = {
+- {
+- .name = "nds",
+- .mode = COMMAND_ANY,
+- .help = "Andes command group",
+- .usage = "",
+- .chain = nds32_exec_command_handlers,
+- },
+- COMMAND_REGISTRATION_DONE
+-};
+diff --git a/src/target/nds32_cmd.h b/src/target/nds32_cmd.h
+deleted file mode 100644
+index 15932438c..000000000
+--- a/src/target/nds32_cmd.h
++++ /dev/null
+@@ -1,15 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_CMD_H
+-#define OPENOCD_TARGET_NDS32_CMD_H
+-
+-#include <helper/command.h>
+-
+-extern const struct command_registration nds32_command_handlers[];
+-
+-#endif /* OPENOCD_TARGET_NDS32_CMD_H */
+diff --git a/src/target/nds32_disassembler.c b/src/target/nds32_disassembler.c
+deleted file mode 100644
+index eebbfe109..000000000
+--- a/src/target/nds32_disassembler.c
++++ /dev/null
+@@ -1,3847 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <helper/log.h>
+-#include <target/target.h>
+-#include "nds32_disassembler.h"
+-
+-static const int enable4_bits[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
+-
+-int nds32_read_opcode(struct nds32 *nds32, uint32_t address, uint32_t *value)
+-{
+- struct target *target = nds32->target;
+- uint8_t value_buf[4];
+-
+- if (!target_was_examined(target)) {
+- LOG_ERROR("Target not examined yet");
+- return ERROR_FAIL;
+- }
+-
+- int retval = target_read_buffer(target, address, 4, value_buf);
+-
+- if (retval == ERROR_OK) {
+- /* instructions are always big-endian */
+- *value = be_to_h_u32(value_buf);
+-
+- LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "",
+- address,
+- *value);
+- } else {
+- *value = 0x0;
+- LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
+- address);
+- }
+-
+- return retval;
+-}
+-
+-static int nds32_parse_type_0(uint32_t opcode, int32_t *imm)
+-{
+- *imm = opcode & 0x1FFFFFF;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_type_1(uint32_t opcode, uint8_t *rt, int32_t *imm)
+-{
+- *rt = (opcode >> 20) & 0x1F;
+- *imm = opcode & 0xFFFFF;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_type_2(uint32_t opcode, uint8_t *rt, uint8_t *ra, int32_t *imm)
+-{
+- *rt = (opcode >> 20) & 0x1F;
+- *ra = (opcode >> 15) & 0x1F;
+- *imm = opcode & 0x7FFF;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_type_3(uint32_t opcode, uint8_t *rt, uint8_t *ra,
+- uint8_t *rb, int32_t *imm)
+-{
+- *rt = (opcode >> 20) & 0x1F;
+- *ra = (opcode >> 15) & 0x1F;
+- *rb = (opcode >> 10) & 0x1F;
+- *imm = opcode & 0x3FF;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_type_4(uint32_t opcode, uint8_t *rt, uint8_t *ra,
+- uint8_t *rb, uint8_t *rd, uint8_t *sub_opc)
+-{
+- *rt = (opcode >> 20) & 0x1F;
+- *ra = (opcode >> 15) & 0x1F;
+- *rb = (opcode >> 10) & 0x1F;
+- *rd = (opcode >> 5) & 0x1F;
+- *sub_opc = opcode & 0x1F;
+-
+- return ERROR_OK;
+-}
+-
+-/* LBI, LHI, LWI, LBI.bi, LHI.bi, LWI.bi */
+-static int nds32_parse_group_0_insn(struct nds32 *nds32, uint32_t opcode,
+- uint32_t address,
+- struct nds32_instruction *instruction)
+-{
+- uint8_t opc_6;
+-
+- opc_6 = instruction->info.opc_6;
+-
+- switch (opc_6 & 0x7) {
+- case 0: /* LBI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLBI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 1: /* LHI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLHI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 2: /* LWI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLWI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 4: /* LBI.bi */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLBI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 5: /* LHI.bi */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLHI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 6: /* LWI.bi */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLWI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32 "",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_group_1_insn(struct nds32 *nds32, uint32_t opcode,
+- uint32_t address, struct nds32_instruction *instruction)
+-{
+- uint8_t opc_6;
+-
+- opc_6 = instruction->info.opc_6;
+-
+- switch (opc_6 & 0x7) {
+- case 0: /* SBI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSBI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 1: /* SHI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSHI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 2: /* SWI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSWI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 4: /* SBI.bi */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSBI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 5: /* SHI.bi */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSHI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 6: /* SWI.bi */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSWI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_group_2_insn(struct nds32 *nds32, uint32_t opcode,
+- uint32_t address, struct nds32_instruction *instruction)
+-{
+- uint8_t opc_6;
+-
+- opc_6 = instruction->info.opc_6;
+-
+- switch (opc_6 & 0x7) {
+- case 0: /* LBSI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLBSI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 1: /* LHSI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLHSI\t$r%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 3: { /* DPREFI */
+- uint8_t sub_type;
+- nds32_parse_type_2(opcode, &sub_type, &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->info.sub_opc = sub_type & 0xF;
+- instruction->type = NDS32_INSN_MISC;
+- if (sub_type & 0x10) { /* DPREFI.d */
+- /* sign-extend */
+- instruction->info.imm = (instruction->info.imm << 17) >> 14;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tDPREFI.d\t%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.sub_opc,
+- instruction->info.ra, instruction->info.imm);
+- } else { /* DPREFI.w */
+- /* sign-extend */
+- instruction->info.imm = (instruction->info.imm << 17) >> 15;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tDPREFI.w\t%" PRIu8 ",[$r%" PRIu8 "+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.sub_opc,
+- instruction->info.ra, instruction->info.imm);
+- }
+- }
+- break;
+- case 4: /* LBSI.bi */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLBSI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 5: /* LHSI.bi */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLHSI.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 6: /* LBGP */
+- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- if ((instruction->info.imm >> 19) & 0x1) { /* LBSI.gp */
+- instruction->info.imm = (instruction->info.imm << 13) >> 13;
+- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLBSI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- } else { /* LBI.gp */
+- instruction->info.imm = (instruction->info.imm << 13) >> 13;
+- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLBI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- }
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_mem(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+- struct nds32_instruction *instruction)
+-{
+- uint32_t sub_opcode = opcode & 0x3F;
+- uint32_t val_ra, val_rb;
+- switch (sub_opcode >> 3) {
+- case 0:
+- switch (sub_opcode & 0x7) {
+- case 0: /* LB */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLB\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 1: /* LH */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLH\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 2: /* LW */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 4: /* LB.bi */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLB.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
+- address,
+- opcode, instruction->info.rt,
+- instruction->info.ra, instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 5: /* LH.bi */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLH.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 6: /* LW.bi */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLW.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- }
+- break;
+- case 1:
+- switch (sub_opcode & 0x7) {
+- case 0: /* SB */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSB\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt,
+- instruction->info.ra, instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 1: /* SH */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSH\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 2: /* SW */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt,
+- instruction->info.ra, instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 4: /* SB.bi */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSB.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 5: /* SH.bi */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSH.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 6: /* SW.bi */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSW.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- }
+- break;
+- case 2:
+- switch (sub_opcode & 0x7) {
+- case 0: /* LBS */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLBS\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt,
+- instruction->info.ra, instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 1: /* LHS */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLHS\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 3: /* DPREF */
+- nds32_parse_type_3(opcode, &(instruction->info.sub_opc),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tDPREF\t#%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<#%" PRId32 ")]",
+- address,
+- opcode, instruction->info.sub_opc,
+- instruction->info.ra, instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 4: /* LBS.bi */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLBS.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 5: /* LHS.bi */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLHS.bi\t$r%" PRIu8 ",[$r%" PRIu8 "],($r%" PRIu8 "<<%" PRId32 ")",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- }
+- break;
+- case 3:
+- switch (sub_opcode & 0x7) {
+- case 0: /* LLW */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLLW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 1: /* SCW */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSCW\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- }
+- break;
+- case 4:
+- switch (sub_opcode & 0x7) {
+- case 0: /* LBUP */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLBUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 2: /* LWUP */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLWUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- }
+- break;
+- case 5:
+- switch (sub_opcode & 0x7) {
+- case 0: /* SBUP */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSBUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- case 2: /* SWUP */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+- nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+- instruction->access_start = val_ra +
+- (val_rb << ((instruction->info.imm >> 8) & 0x3));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSWUP\t$r%" PRIu8 ",[$r%" PRIu8 "+($r%" PRIu8 "<<%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- (instruction->info.imm >> 8) & 0x3);
+- break;
+- }
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_calculate_lsmw_access_range(struct nds32 *nds32,
+- struct nds32_instruction *instruction)
+-{
+- uint8_t ba;
+- uint8_t id;
+- uint8_t enable4;
+-
+- enable4 = (instruction->info.imm >> 6) & 0xF;
+- ba = (instruction->info.imm >> 4) & 0x1;
+- id = (instruction->info.imm >> 3) & 0x1;
+-
+- if (ba) {
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start));
+- if (id) { /* decrease */
+- /* access_end is the (last_element+1), so no need to minus 4 */
+- /* instruction->access_end -= 4; */
+- instruction->access_end = instruction->access_start;
+- } else { /* increase */
+- instruction->access_start += 4;
+- }
+- } else {
+- nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start));
+- instruction->access_end = instruction->access_start - 4;
+- }
+-
+- if (id) { /* decrease */
+- instruction->access_start = instruction->access_end -
+- 4 * (instruction->info.rd - instruction->info.rb + 1);
+- instruction->access_start -= (4 * enable4_bits[enable4]);
+- } else { /* increase */
+- instruction->access_end = instruction->access_start +
+- 4 * (instruction->info.rd - instruction->info.rb + 1);
+- instruction->access_end += (4 * enable4_bits[enable4]);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_lsmw(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+- struct nds32_instruction *instruction)
+-{
+- if (opcode & 0x20) { /* SMW, SMWA, SMWZB */
+- switch (opcode & 0x3) {
+- /* TODO */
+- case 0: /* SMW */
+- /* use rd as re */
+- nds32_parse_type_3(opcode, &(instruction->info.rb),
+- &(instruction->info.ra),
+- &(instruction->info.rd), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_calculate_lsmw_access_range(nds32, instruction);
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSMW\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rb, instruction->info.ra,
+- instruction->info.rd,
+- (instruction->info.imm >> 6) & 0xF);
+- break;
+- case 1: /* SMWA */
+- nds32_parse_type_3(opcode, &(instruction->info.rb),
+- &(instruction->info.ra),
+- &(instruction->info.rd), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_calculate_lsmw_access_range(nds32, instruction);
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSMWA\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rb, instruction->info.ra,
+- instruction->info.rd,
+- (instruction->info.imm >> 6) & 0xF);
+- break;
+- case 2: /* SMWZB */
+- nds32_parse_type_3(opcode, &(instruction->info.rb),
+- &(instruction->info.ra),
+- &(instruction->info.rd), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- /* TODO: calculate access_start/access_end */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSMWZB\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rb, instruction->info.ra,
+- instruction->info.rd,
+- (instruction->info.imm >> 6) & 0xF);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+- } else { /* LMW, LMWA, LMWZB */
+- switch (opcode & 0x3) {
+- case 0: /* LMW */
+- nds32_parse_type_3(opcode, &(instruction->info.rb),
+- &(instruction->info.ra),
+- &(instruction->info.rd), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_calculate_lsmw_access_range(nds32, instruction);
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLMW\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rb, instruction->info.ra,
+- instruction->info.rd,
+- (instruction->info.imm >> 6) & 0xF);
+- break;
+- case 1: /* LMWA */
+- nds32_parse_type_3(opcode, &(instruction->info.rb),
+- &(instruction->info.ra),
+- &(instruction->info.rd), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_calculate_lsmw_access_range(nds32, instruction);
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLMWA\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rb, instruction->info.ra,
+- instruction->info.rd,
+- (instruction->info.imm >> 6) & 0xF);
+- break;
+- case 2: /* LMWZB */
+- nds32_parse_type_3(opcode, &(instruction->info.rb),
+- &(instruction->info.ra),
+- &(instruction->info.rd), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- /* TODO: calculate access_start/access_end */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLMWZB\t$r%" PRIu8 ",[$r%" PRIu8 "],$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rb, instruction->info.ra,
+- instruction->info.rd,
+- (instruction->info.imm >> 6) & 0xF);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_hwgp(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+- struct nds32_instruction *instruction)
+-{
+- switch ((opcode >> 18) & 0x3) {
+- case 0: /* LHI.gp */
+- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLHI.gp\t$r%" PRIu8 ",[#%" PRId32"]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 1: /* LHSI.gp */
+- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLHSI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 2: /* SHI.gp */
+- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSHI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 3:
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- if ((opcode >> 17) & 0x1) { /* SWI.gp */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- /* sign-extend */
+- instruction->info.imm = (instruction->info.imm << 15) >> 13;
+- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSWI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- } else { /* LWI.gp */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- /* sign-extend */
+- instruction->info.imm = (instruction->info.imm << 15) >> 13;
+- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tLWI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- }
+-
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_sbgp(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+- struct nds32_instruction *instruction)
+-{
+- switch ((opcode >> 19) & 0x1) {
+- case 0: /* SBI.gp */
+- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 13) >> 13; /* sign-extend */
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSBI.gp\t$r%" PRIu8 ",[#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 1: /* ADDI.gp */
+- nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 13) >> 13; /* sign-extend */
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tADDI.gp\t$r%" PRIu8 ",#%" PRId32 "",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_group_3_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+- struct nds32_instruction *instruction)
+-{
+- uint8_t opc_6;
+-
+- opc_6 = instruction->info.opc_6;
+-
+- switch (opc_6 & 0x7) {
+- case 4: /* MEM */
+- nds32_parse_mem(nds32, opcode, address, instruction);
+- break;
+- case 5: /* LSMW */
+- nds32_parse_lsmw(nds32, opcode, address, instruction);
+- break;
+- case 6: /* HWGP */
+- nds32_parse_hwgp(nds32, opcode, address, instruction);
+- break;
+- case 7: /* SBGP */
+- nds32_parse_sbgp(nds32, opcode, address, instruction);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_alu_1(uint32_t opcode, uint32_t address,
+- struct nds32_instruction *instruction)
+-{
+- switch (opcode & 0x1F) {
+- case 0: /* ADD */
+- nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tADD_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tADD\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 1: /* SUB */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSUB_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSUB\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 "",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 2: /* AND */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tAND_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tAND\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 "",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 3: /* XOR */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tXOR_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tXOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 4: /* OR */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tOR_SLLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 5: /* NOR */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tNOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 6: /* SLT */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSLT\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 7: /* SLTS */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSLTS\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 8: { /* SLLI */
+- uint8_t imm;
+- int32_t sub_op;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &sub_op);
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSLLI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 9: { /* SRLI */
+- uint8_t imm;
+- int32_t sub_op;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &sub_op);
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSRLI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 10: { /* SRAI */
+- uint8_t imm;
+- int32_t sub_op;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &sub_op);
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSRAI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 11: { /* ROTRI */
+- uint8_t imm;
+- int32_t sub_op;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &sub_op);
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tROTRI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 12: { /* SLL */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSLL\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 13: { /* SRL */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSRL\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 14: { /* SRA */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSRA\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 15: { /* ROTR */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tROTR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 16: { /* SEB */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSEB\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- }
+- break;
+- case 17: { /* SEH */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSEH\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- }
+- break;
+- case 18: /* BITC */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBITC\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 19: { /* ZEH */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tZEH\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- }
+- break;
+- case 20: { /* WSBH */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tWSBH\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- }
+- break;
+- case 21: /* OR_SRLI */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tOR_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 22: { /* DIVSR */
+- nds32_parse_type_4(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.rd),
+- &(instruction->info.sub_opc));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tDIVSR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.rd);
+- }
+- break;
+- case 23: { /* DIVR */
+- nds32_parse_type_4(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.rd),
+- &(instruction->info.sub_opc));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tDIVR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.rd);
+- }
+- break;
+- case 24: { /* SVA */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSVA\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 25: { /* SVS */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSVS\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 26: { /* CMOVZ */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tCMOVZ\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 27: { /* CMOVN */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tCMOVN\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 28: /* ADD_SRLI */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tADD_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tADD\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 29: /* SUB_SRLI */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSUB_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSUB\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 30: /* AND_SRLI */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tAND_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tAND\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 31: /* XOR_SRLI */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+- if (instruction->info.imm)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tXOR_SRLI\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8 ",%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb,
+- instruction->info.imm);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tXOR\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_alu_2(uint32_t opcode, uint32_t address,
+- struct nds32_instruction *instruction)
+-{
+- switch (opcode & 0x3F) {
+- case 0: /* MAX */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMAX\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 1: /* MIN */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMIN\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 2: /* AVE */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tAVE\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 3: /* ABS */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tAVE\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 4: { /* CLIPS */
+- uint8_t imm;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &(instruction->info.imm));
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tCLIPS\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 5: { /* CLIP */
+- uint8_t imm;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &(instruction->info.imm));
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tCLIP\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 6: /* CLO */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tCLO\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 7: /* CLZ */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tCLZ\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 8: { /* BSET */
+- uint8_t imm;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &(instruction->info.imm));
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBSET\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 9: { /* BCLR */
+- uint8_t imm;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &(instruction->info.imm));
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBCLR\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 10: { /* BTGL */
+- uint8_t imm;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &(instruction->info.imm));
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBTGL\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 11: { /* BTST */
+- uint8_t imm;
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &imm, &(instruction->info.imm));
+- instruction->info.imm = imm;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBTST\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- case 12: /* BSE */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBSE\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 13: /* BSP */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBSP\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 14: /* FFB */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tFFB\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 15: /* FFMISM */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tFFMISM\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 23: /* FFZMISM */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tFFZMISM\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 32: /* MFUSR */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMFUSR\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt,
+- (instruction->info.imm >> 10) & 0x3FF);
+- break;
+- case 33: /* MTUSR */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMTUSR\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt,
+- (instruction->info.imm >> 10) & 0x3FF);
+- break;
+- case 36: /* MUL */
+- nds32_parse_type_3(opcode, &(instruction->info.rt),
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMUL\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- break;
+- case 40: { /* MULTS64 */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val,
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMULTS64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 41: { /* MULT64 */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val,
+- &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMULT64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 42: { /* MADDS64 */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMADDS64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 43: { /* MADD64 */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMADD64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 44: { /* MSUBS64 */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMSUBS64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 45: { /* MSUB64 */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMSUB64\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 46: { /* DIVS */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tDIVS\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 47: { /* DIV */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tDIV\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 49: { /* MULT32 */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMULT32\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 51: { /* MADD32 */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMADD32\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 53: { /* MSUB32 */
+- uint8_t dt_val;
+- nds32_parse_type_3(opcode, &dt_val, &(instruction->info.ra),
+- &(instruction->info.rb), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMSUB32\t$D%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, (uint8_t)((dt_val >> 1) & 0x1), instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_group_4_insn(struct nds32 *nds32, uint32_t opcode,
+- uint32_t address, struct nds32_instruction *instruction)
+-{
+- uint8_t opc_6;
+-
+- opc_6 = instruction->info.opc_6;
+-
+- switch (opc_6 & 0x7) {
+- case 0: /* ALU_1 */
+- nds32_parse_alu_1(opcode, address, instruction);
+- break;
+- case 1: /* ALU_2 */
+- nds32_parse_alu_2(opcode, address, instruction);
+- break;
+- case 2: /* MOVI */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- /* sign-extend */
+- instruction->info.imm = (instruction->info.imm << 12) >> 12;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMOVI\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 3: /* SETHI */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSETHI\t$r%" PRIu8 ",0x%8.8" PRIx32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 4: /* JI */
+- nds32_parse_type_0(opcode, &(instruction->info.imm));
+- /* sign-extend */
+- instruction->info.imm = (instruction->info.imm << 8) >> 8;
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- if ((instruction->info.imm >> 24) & 0x1) { /* JAL */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tJAL\t#%" PRId32,
+- address,
+- opcode, instruction->info.imm);
+- } else { /* J */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tJ\t#%" PRId32,
+- address,
+- opcode, instruction->info.imm);
+- }
+- break;
+- case 5: { /* JREG */
+- int32_t imm;
+- nds32_parse_type_0(opcode, &imm);
+- instruction->info.rb = (imm >> 10) & 0x1F;
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- switch (imm & 0x1F) {
+- /* TODO */
+- case 0: /* JR */
+- if (imm & 0x20) { /* RET */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tRET\t$r%" PRIu8,
+- address,
+- opcode, instruction->info.rb);
+- } else { /* JR */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tJR\t$r%" PRIu8,
+- address,
+- opcode, instruction->info.rb);
+- }
+- break;
+- case 1: /* JRAL */
+- instruction->info.rt = (imm >> 20) & 0x1F;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tJRAL\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.rb);
+- break;
+- case 2: /* JRNEZ */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tJRNEZ\t$r%" PRIu8,
+- address,
+- opcode, instruction->info.rb);
+- break;
+- case 3: /* JRALNEZ */
+- instruction->info.rt = (imm >> 20) & 0x1F;
+- if (instruction->info.rt == R30)
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tJRALNEZ\t$r%" PRIu8,
+- address,
+- opcode, instruction->info.rb);
+- else
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tJRALNEZ\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode,
+- instruction->info.rt,
+- instruction->info.rb);
+- break;
+- }
+- }
+- break;
+- case 6: { /* BR1 */
+- int32_t imm;
+-
+- nds32_parse_type_0(opcode, &imm);
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- if ((imm >> 14) & 0x1) { /* BNE */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- /* sign-extend */
+- instruction->info.imm = (instruction->info.imm << 18) >> 18;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBNE\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- } else { /* BEQ */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- /* sign-extend */
+- instruction->info.imm = (instruction->info.imm << 18) >> 18;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBEQ\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt,
+- instruction->info.ra,
+- instruction->info.imm);
+- }
+- }
+- break;
+- case 7: { /* BR2 */
+- int32_t imm;
+-
+- nds32_parse_type_0(opcode, &imm);
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- switch ((imm >> 16) & 0xF) {
+- case 2: /* BEQZ */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 16) >> 16;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBEQZ\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 3: /* BNEZ */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 16) >> 16;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBNEZ\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 4: /* BGEZ */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 16) >> 16;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBGEZ\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 5: /* BLTZ */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 16) >> 16;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBLTZ\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 6: /* BGTZ */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 16) >> 16;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBGTZ\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 7: /* BLEZ */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 16) >> 16;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBLEZ\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 12: /* BGEZAL */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 16) >> 16;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBGEZAL\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 13: /* BLTZAL */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 16) >> 16;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBLTZAL\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- }
+- }
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_group_5_insn(struct nds32 *nds32, uint32_t opcode,
+- uint32_t address, struct nds32_instruction *instruction)
+-{
+- uint8_t opc_6;
+-
+- opc_6 = instruction->info.opc_6;
+-
+- switch (opc_6 & 0x7) {
+- case 0: /* ADDI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tADDI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 1: /* SUBRI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSUBRI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 2: /* ANDI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tANDI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 3: /* XORI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tXORI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 4: /* ORI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tORI\t$r%" PRIu8 ",$r%" PRIu8 ",0x%8.8" PRIx32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 6: /* SLTI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSLTI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 7: /* SLTSI */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSLTSI\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_group_6_insn(struct nds32 *nds32, uint32_t opcode,
+- uint32_t address, struct nds32_instruction *instruction)
+-{
+- uint8_t opc_6;
+-
+- opc_6 = instruction->info.opc_6;
+-
+- switch (opc_6 & 0x7) {
+- case 2: { /* MISC */
+- int32_t imm;
+- uint8_t sub_opc;
+-
+- nds32_parse_type_0(opcode, &imm);
+-
+- sub_opc = imm & 0x1F;
+- switch (sub_opc) {
+- case 0: /* STANDBY */
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSTANDBY\t#%" PRIu32,
+- address,
+- opcode, (opcode >> 5) & 0x3);
+- break;
+- case 1: /* CCTL */
+- /* TODO */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCCTL",
+- address,
+- opcode);
+- break;
+- case 2: /* MFSR */
+- nds32_parse_type_1(opcode, &(instruction->info.rt),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMFSR\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt,
+- (instruction->info.imm >> 10) & 0x3FF);
+- break;
+- case 3: /* MTSR */
+- nds32_parse_type_1(opcode, &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMTSR\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.ra,
+- (instruction->info.imm >> 10) & 0x3FF);
+- break;
+- case 4: /* IRET */
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tIRET",
+- address,
+- opcode);
+- break;
+- case 5: /* TRAP */
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tTRAP\t#%" PRId32,
+- address,
+- opcode, (imm >> 5) & 0x7FFF);
+- break;
+- case 6: /* TEQZ */
+- nds32_parse_type_1(opcode, &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tTEQZ\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.ra,
+- (instruction->info.imm >> 5) & 0x7FFF);
+- break;
+- case 7: /* TNEZ */
+- nds32_parse_type_1(opcode, &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tTNEZ\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.ra,
+- (instruction->info.imm >> 5) & 0x7FFF);
+- break;
+- case 8: /* DSB */
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB",
+- address,
+- opcode);
+- break;
+- case 9: /* ISB */
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB",
+- address,
+- opcode);
+- break;
+- case 10: /* BREAK */
+- instruction->type = NDS32_INSN_MISC;
+- instruction->info.sub_opc = imm & 0x1F;
+- instruction->info.imm = (imm >> 5) & 0x7FFF;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tBREAK\t#%" PRId32,
+- address,
+- opcode, instruction->info.imm);
+- break;
+- case 11: /* SYSCALL */
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tSYSCALL\t#%" PRId32,
+- address,
+- opcode, (imm >> 5) & 0x7FFF);
+- break;
+- case 12: /* MSYNC */
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tMSYNC\t#%" PRId32,
+- address,
+- opcode, (imm >> 5) & 0x7);
+- break;
+- case 13: /* ISYNC */
+- nds32_parse_type_1(opcode, &(instruction->info.ra),
+- &(instruction->info.imm));
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+- "\tISYNC\t$r%" PRIu8,
+- address,
+- opcode, instruction->info.ra);
+- break;
+- case 14: /* TLBOP */
+- /* TODO */
+- nds32_parse_type_2(opcode, &(instruction->info.rt),
+- &(instruction->info.ra), &(instruction->info.imm));
+- instruction->type = NDS32_INSN_RESOURCE_ACCESS;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tTLBOP",
+- address,
+- opcode);
+- break;
+- }
+-
+- break;
+- }
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static uint32_t field_mask[9] = {
+- 0x0,
+- 0x1,
+- 0x3,
+- 0x7,
+- 0xF,
+- 0x1F,
+- 0x3F,
+- 0x7F,
+- 0xFF,
+-};
+-
+-static uint8_t nds32_extract_field_8u(uint16_t opcode, uint32_t start, uint32_t length)
+-{
+- if (length > 0 && length < 9)
+- return (opcode >> start) & field_mask[length];
+-
+- return 0;
+-}
+-
+-static int nds32_parse_group_0_insn_16(struct nds32 *nds32, uint16_t opcode,
+- uint32_t address, struct nds32_instruction *instruction)
+-{
+- switch ((opcode >> 10) & 0x7) {
+- case 0: /* MOV55 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 5);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tMOV55\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 1: /* MOVI55 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 5);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->info.imm = (instruction->info.imm << 27) >> 27;
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tMOVI55\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 2: /* ADD45, SUB45 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADD45 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tADD45\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.rb);
+- } else { /* SUB45 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSUB45\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.rb);
+- }
+-
+- break;
+- case 3: /* ADDI45, SUBI45 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADDI45 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tADDI45\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- } else { /* SUBI45 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSUBI45\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- }
+- break;
+- case 4: /* SRAI45, SRLI45 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* SRAI45 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSRAI45\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- } else { /* SRLI45 */
+- if ((instruction->info.rt == 0) && (instruction->info.imm == 0)) {
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16 "\t\tNOP",
+- address,
+- opcode);
+- } else {
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSRLI45\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- }
+- }
+- break;
+- case 5:
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* SLLI333 */
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSLLI333\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- } else {
+- instruction->info.sub_opc = nds32_extract_field_8u(opcode, 0, 3);
+- switch (instruction->info.sub_opc) {
+- case 0: /* ZEB33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tZEB33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 1: /* ZEH33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tZEH33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 2: /* SEB33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSEB33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 3: /* SEH33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSEH33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 4: /* XLSB33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tXLSB33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 5: /* XLLB33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tXLLB33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 6: /* BMSKI33 */
+- instruction->info.ra = 0;
+- instruction->info.imm = nds32_extract_field_8u(opcode, 3, 3);
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tBMSKI33\t$r%" PRIu8 ",$r%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 7: /* FEXTI33 */
+- instruction->info.ra = 0;
+- instruction->info.imm = nds32_extract_field_8u(opcode, 3, 3);
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tFEXTI33\t$r%" PRIu8 ",$r%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16
+- "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+- }
+- break;
+- case 6: /* ADD333, SUB333 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 3);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADD333 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tADD333\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- } else { /* SUB333 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSUB333\t$r%" PRIu8 ",$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.rb);
+- }
+- break;
+- case 7: /* ADDI333, SUBI333 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- if (nds32_extract_field_8u(opcode, 9, 1) == 0) { /* ADDI333 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tADDI333\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- } else { /* SUBI333 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSUBI333\t$r%" PRIu8 ",$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- }
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_group_1_insn_16(struct nds32 *nds32, uint16_t opcode,
+- uint32_t address, struct nds32_instruction *instruction)
+-{
+- switch ((opcode >> 9) & 0xF) {
+- case 0: /* LWI333 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 2;
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tLWI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 1: /* LWI333.BI */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tLWI333.BI\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm << 2);
+- break;
+- case 2: /* LHI333 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 1;
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tLHI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 3: /* LBI333 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tLBI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 4: /* SWI333 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 2;
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSWI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 5: /* SWI333.BI */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 2;
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSWI333.BI\t$r%" PRIu8 ",[$r%" PRIu8 "],#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 6: /* SHI333 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3) << 1;
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 2;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSHI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 7: /* SBI333 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 3);
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 1;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSHI333\t$r%" PRIu8 ",[$r%" PRIu8 "+(#%" PRId32 ")]",
+- address,
+- opcode, instruction->info.rt, instruction->info.ra,
+- instruction->info.imm);
+- break;
+- case 8: /* ADDRI36.SP */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 6) << 2;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tADDRI36.SP\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 9: /* LWI45.FE */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->info.imm -= 32;
+- instruction->info.imm <<= 2;
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, R8, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tLWI45.FE\t$r%" PRIu8 ",[#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 10: /* LWI450 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tLWI450\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 11: /* SWI450 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.ra = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, instruction->info.ra,
+- &(instruction->access_start));
+- instruction->access_end = instruction->access_start + 4;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSWI450\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 12:
+- case 13:
+- case 14:
+- case 15: /* LWI37, SWI37 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 7) << 2;
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, R28, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 4;
+- if (nds32_extract_field_8u(opcode, 7, 1) == 0) { /* LWI37 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tLWI37\t$r%" PRIu8 ",[fp+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- } else { /* SWI37 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSWI37\t$r%" PRIu8 ",[fp+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- }
+- break;
+- default: /* ERROR */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_group_2_insn_16(struct nds32 *nds32, uint16_t opcode,
+- uint32_t address, struct nds32_instruction *instruction)
+-{
+- switch ((opcode >> 11) & 0x3) {
+- case 0: /* BEQZ38 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
+- instruction->info.imm = (instruction->info.imm << 24) >> 24;
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tBEQZ38\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 1: /* BNEZ38 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
+- instruction->info.imm = (instruction->info.imm << 24) >> 24;
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tBNEZ38\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 2: /* BEQS38,J8 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
+- instruction->info.imm = (instruction->info.imm << 24) >> 24;
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- if (instruction->info.rt == 5) { /* J8 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tJ8\t#%" PRId32,
+- address,
+- opcode, instruction->info.imm);
+- } else { /* BEQS38 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tBEQS38\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- }
+- break;
+- case 3: /* BNES38, JR5, RET5, JRAL5 */
+- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
+- instruction->info.imm = (instruction->info.imm << 24) >> 24;
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- if (instruction->info.rt == 5) {
+- instruction->info.imm = 0;
+- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5);
+- switch (nds32_extract_field_8u(opcode, 5, 3)) {
+- case 0: /* JR5 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tJR5\t$r%" PRIu8,
+- address,
+- opcode, instruction->info.rb);
+- break;
+- case 1: /* JRAL5 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tJRAL5\t$r%" PRIu8,
+- address,
+- opcode, instruction->info.rb);
+- break;
+- case 2: /* EX9.IT */
+- instruction->info.rb = 0;
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
+- /* TODO: implement real instruction semantics */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tEX9.IT\t#%" PRId32,
+- address,
+- opcode, instruction->info.imm);
+- break;
+- case 4: /* RET5 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tRET5\t$r%" PRIu8,
+- address,
+- opcode, instruction->info.rb);
+- break;
+- case 5: /* ADD5.PC */
+- instruction->info.rt = 0;
+- instruction->info.rt = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tADD5.PC\t$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16
+- "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+- } else { /* BNES38 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tBNES38\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- }
+- break;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_parse_group_3_insn_16(struct nds32 *nds32, uint16_t opcode,
+- uint32_t address, struct nds32_instruction *instruction)
+-{
+- switch ((opcode >> 11) & 0x3) {
+- case 0:
+- switch ((opcode >> 9) & 0x3) {
+- case 0: /* SLTS45 */
+- instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSLTS45\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.ra, instruction->info.rb);
+- break;
+- case 1: /* SLT45 */
+- instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.rb = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSLT45\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.ra, instruction->info.rb);
+- break;
+- case 2: /* SLTSI45 */
+- instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSLTSI45\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.ra, instruction->info.imm);
+- break;
+- case 3: /* SLTI45 */
+- instruction->info.ra = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSLTI45\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.ra, instruction->info.imm);
+- break;
+- }
+- break;
+- case 1:
+- switch ((opcode >> 9) & 0x3) {
+- case 0:
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 8);
+- instruction->info.imm = (instruction->info.imm << 24) >> 24;
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- if (nds32_extract_field_8u(opcode, 8, 1) == 0) { /* BEQZS8 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tBEQZS8\t#%" PRId32,
+- address,
+- opcode, instruction->info.imm);
+- } else { /* BNEZS8 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tBNEZS8\t#%" PRId32,
+- address,
+- opcode, instruction->info.imm);
+- }
+- break;
+- case 1: /* BREAK16 */
+- if (((opcode >> 5) & 0xF) == 0) {
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tBREAK16\t#%" PRId16,
+- address,
+- opcode, (int16_t)(opcode & 0x1F));
+- } else { /* EX9.IT */
+- instruction->type = NDS32_INSN_MISC;
+- /* TODO: implement real instruction semantics */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tEX9.IT\t#%" PRId16,
+- address,
+- opcode, (int16_t)(opcode & 0x1FF));
+- }
+- break;
+- case 2: /* ADDI10S */
+- case 3:
+- instruction->info.imm = opcode & 0x3FF;
+- instruction->info.imm = (instruction->info.imm << 22) >> 22;
+- instruction->type = NDS32_INSN_DATA_PROC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tADDI10.SP\t#%" PRId32,
+- address,
+- opcode, instruction->info.imm);
+- break;
+- }
+- break;
+- case 2:
+- instruction->info.rt = nds32_extract_field_8u(opcode, 8, 3);
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 7) << 2;
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- nds32_get_mapped_reg(nds32, R31, &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end = instruction->access_start + 4;
+- if (nds32_extract_field_8u(opcode, 7, 1) == 0) { /* LWI37.SP */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tLWI37.SP\t$r%" PRIu8 ",[+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- } else { /* SWI37.SP */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tSWI37.SP\t$r%" PRIu8 ",[+#%" PRId32 "]",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- }
+- break;
+- case 3:
+- switch ((opcode >> 9) & 0x3) {
+- case 0: /* IFCALL9 */
+- instruction->info.imm = opcode & 0x1FF;
+- instruction->type = NDS32_INSN_JUMP_BRANCH;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tIFCALL9\t#%" PRId32 "",
+- address,
+- opcode, instruction->info.imm);
+- break;
+- case 1: /* MOVPI45 */
+- instruction->info.imm = nds32_extract_field_8u(opcode, 0, 5) + 16;
+- instruction->info.rt = nds32_extract_field_8u(opcode, 5, 4);
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tMOVPI45\t$r%" PRIu8 ",#%" PRId32 "",
+- address,
+- opcode, instruction->info.rt, instruction->info.imm);
+- break;
+- case 2: /* PUSH25, POP25, MOVD44 */
+- switch ((opcode >> 7) & 0x3) {
+- case 0: /* PUSH25 */
+- {
+- uint8_t re;
+- uint8_t gpr_count;
+-
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- instruction->info.imm =
+- nds32_extract_field_8u(opcode, 0, 5) << 3;
+- re = nds32_extract_field_8u(opcode, 5, 2);
+-
+- if (re == 0)
+- re = 6;
+- else if (re == 1)
+- re = 8;
+- else if (re == 2)
+- re = 10;
+- else if (re == 3)
+- re = 14;
+-
+- instruction->info.rd = re;
+- /* GPRs list: R6 ~ Re and fp, gp, lp */
+- gpr_count = 3 + (re - 5);
+-
+- nds32_get_mapped_reg(nds32, R31,
+- &(instruction->access_end));
+- instruction->access_start =
+- instruction->access_end - (gpr_count * 4);
+-
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tPUSH25\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rd,
+- instruction->info.imm);
+- }
+- break;
+- case 1: /* POP25 */
+- {
+- uint8_t re;
+- uint8_t gpr_count;
+-
+- instruction->type = NDS32_INSN_LOAD_STORE;
+- instruction->info.imm =
+- nds32_extract_field_8u(opcode, 0, 5) << 3;
+- re = nds32_extract_field_8u(opcode, 5, 2);
+-
+- if (re == 0)
+- re = 6;
+- else if (re == 1)
+- re = 8;
+- else if (re == 2)
+- re = 10;
+- else if (re == 3)
+- re = 14;
+-
+- instruction->info.rd = re;
+- /* GPRs list: R6 ~ Re and fp, gp, lp */
+- gpr_count = 3 + (re - 5);
+-
+- nds32_get_mapped_reg(nds32, R31,
+- &(instruction->access_start));
+- instruction->access_start += instruction->info.imm;
+- instruction->access_end =
+- instruction->access_start + (gpr_count * 4);
+-
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tPOP25\t$r%" PRIu8 ",#%" PRId32,
+- address,
+- opcode, instruction->info.rd,
+- instruction->info.imm);
+- }
+- break;
+- case 2: /* MOVD44 */
+- case 3:
+- instruction->info.ra =
+- nds32_extract_field_8u(opcode, 0, 4) * 2;
+- instruction->info.rt =
+- nds32_extract_field_8u(opcode, 4, 4) * 2;
+- instruction->type = NDS32_INSN_MISC;
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tMOVD44\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- }
+- break;
+- case 3: /* NEG33, NOT33, MUL33, XOR33, AND33, OR33 */
+- instruction->info.ra = nds32_extract_field_8u(opcode, 3, 3);
+- instruction->info.rt = nds32_extract_field_8u(opcode, 6, 3);
+- instruction->type = NDS32_INSN_DATA_PROC;
+- switch (opcode & 0x7) {
+- case 2: /* NEG33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tNEG33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 3: /* NOT33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tNOT33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 4: /* MUL33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tMUL33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 5: /* XOR33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tXOR33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 6: /* AND33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tAND33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- case 7: /* OR33 */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%4.4" PRIx16
+- "\t\tOR33\t$r%" PRIu8 ",$r%" PRIu8,
+- address,
+- opcode, instruction->info.rt, instruction->info.ra);
+- break;
+- }
+- break;
+- }
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx16 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_evaluate_opcode(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+- struct nds32_instruction *instruction)
+-{
+- int retval = ERROR_OK;
+-
+- /* clear fields, to avoid confusion */
+- memset(instruction, 0, sizeof(struct nds32_instruction));
+-
+- if (opcode >> 31) {
+- /* 16 bits instruction */
+- instruction->instruction_size = 2;
+- opcode = (opcode >> 16) & 0xFFFF;
+- instruction->opcode = opcode;
+-
+- switch ((opcode >> 13) & 0x3) {
+- case 0:
+- retval = nds32_parse_group_0_insn_16(nds32, opcode, address, instruction);
+- break;
+- case 1:
+- retval = nds32_parse_group_1_insn_16(nds32, opcode, address, instruction);
+- break;
+- case 2:
+- retval = nds32_parse_group_2_insn_16(nds32, opcode, address, instruction);
+- break;
+- case 3:
+- retval = nds32_parse_group_3_insn_16(nds32, opcode, address, instruction);
+- break;
+- default:
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+- } else {
+- /* 32 bits instruction */
+- instruction->instruction_size = 4;
+- instruction->opcode = opcode;
+-
+- uint8_t opc_6;
+- opc_6 = opcode >> 25;
+- instruction->info.opc_6 = opc_6;
+-
+- switch ((opc_6 >> 3) & 0x7) {
+- case 0: /* LBI, LHI, LWI, LBI.bi, LHI.bi, LWI.bi */
+- retval = nds32_parse_group_0_insn(nds32, opcode, address, instruction);
+- break;
+- case 1: /* SBI, SHI, SWI, SBI.bi, SHI.bi, SWI.bi */
+- retval = nds32_parse_group_1_insn(nds32, opcode, address, instruction);
+- break;
+- case 2: /* LBSI, LHSI, DPREFI, LBSI.bi, LHSI.bi, LBGP */
+- retval = nds32_parse_group_2_insn(nds32, opcode, address, instruction);
+- break;
+- case 3: /* MEM, LSMW, HWGP, SBGP */
+- retval = nds32_parse_group_3_insn(nds32, opcode, address, instruction);
+- break;
+- case 4: /* ALU_1, ALU_2, MOVI, SETHI, JI, JREG, BR1, BR2 */
+- retval = nds32_parse_group_4_insn(nds32, opcode, address, instruction);
+- break;
+- case 5: /* ADDI, SUBRI, ANDI, XORI, ORI, SLTI, SLTSI */
+- retval = nds32_parse_group_5_insn(nds32, opcode, address, instruction);
+- break;
+- case 6: /* MISC */
+- retval = nds32_parse_group_6_insn(nds32, opcode, address, instruction);
+- break;
+- default: /* ERROR */
+- snprintf(instruction->text,
+- 128,
+- "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+- address,
+- opcode);
+- return ERROR_FAIL;
+- }
+- }
+-
+- return retval;
+-}
+diff --git a/src/target/nds32_disassembler.h b/src/target/nds32_disassembler.h
+deleted file mode 100644
+index f2c8e8596..000000000
+--- a/src/target/nds32_disassembler.h
++++ /dev/null
+@@ -1,45 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_DISASSEMBLER_H
+-#define OPENOCD_TARGET_NDS32_DISASSEMBLER_H
+-
+-#include <target/nds32.h>
+-
+-enum nds32_instruction_type {
+- NDS32_INSN_DATA_PROC = 0,
+- NDS32_INSN_LOAD_STORE,
+- NDS32_INSN_JUMP_BRANCH,
+- NDS32_INSN_RESOURCE_ACCESS,
+- NDS32_INSN_MISC,
+-};
+-
+-struct nds32_instruction {
+- enum nds32_instruction_type type;
+- char text[128];
+- uint32_t opcode;
+- uint8_t instruction_size;
+- uint32_t access_start;
+- uint32_t access_end;
+-
+- struct {
+- uint8_t opc_6;
+- uint8_t rt;
+- uint8_t ra;
+- uint8_t rb;
+- uint8_t rd;
+- uint8_t sub_opc;
+- int32_t imm;
+- } info;
+-
+-};
+-
+-int nds32_read_opcode(struct nds32 *nds32, uint32_t address, uint32_t *value);
+-int nds32_evaluate_opcode(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+- struct nds32_instruction *instruction);
+-
+-#endif /* OPENOCD_TARGET_NDS32_DISASSEMBLER_H */
+diff --git a/src/target/nds32_edm.h b/src/target/nds32_edm.h
+deleted file mode 100644
+index 3213604b9..000000000
+--- a/src/target/nds32_edm.h
++++ /dev/null
+@@ -1,106 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_EDM_H
+-#define OPENOCD_TARGET_NDS32_EDM_H
+-
+-#include "helper/types.h"
+-
+-/**
+- * @file
+- * This is the interface to the Embedded Debug Module for Andes cores.
+- */
+-
+-/* EDM misc registers */
+-enum nds_edm_misc_reg {
+- NDS_EDM_MISC_DIMIR = 0x0,
+- NDS_EDM_MISC_SBAR,
+- NDS_EDM_MISC_EDM_CMDR,
+- NDS_EDM_MISC_DBGER,
+- NDS_EDM_MISC_ACC_CTL,
+- NDS_EDM_MISC_EDM_PROBE,
+- NDS_EDM_MISC_GEN_PORT0,
+- NDS_EDM_MISC_GEN_PORT1,
+-};
+-
+-/* EDM system registers */
+-enum nds_edm_system_reg {
+- NDS_EDM_SR_BPC0 = 0x00,
+- NDS_EDM_SR_BPC1,
+- NDS_EDM_SR_BPC2,
+- NDS_EDM_SR_BPC3,
+- NDS_EDM_SR_BPC4,
+- NDS_EDM_SR_BPC5,
+- NDS_EDM_SR_BPC6,
+- NDS_EDM_SR_BPC7,
+- NDS_EDM_SR_BPA0 = 0x08,
+- NDS_EDM_SR_BPA1,
+- NDS_EDM_SR_BPA2,
+- NDS_EDM_SR_BPA3,
+- NDS_EDM_SR_BPA4,
+- NDS_EDM_SR_BPA5,
+- NDS_EDM_SR_BPA6,
+- NDS_EDM_SR_BPA7,
+- NDS_EDM_SR_BPAM0 = 0x10,
+- NDS_EDM_SR_BPAM1,
+- NDS_EDM_SR_BPAM2,
+- NDS_EDM_SR_BPAM3,
+- NDS_EDM_SR_BPAM4,
+- NDS_EDM_SR_BPAM5,
+- NDS_EDM_SR_BPAM6,
+- NDS_EDM_SR_BPAM7,
+- NDS_EDM_SR_BPV0 = 0x18,
+- NDS_EDM_SR_BPV1,
+- NDS_EDM_SR_BPV2,
+- NDS_EDM_SR_BPV3,
+- NDS_EDM_SR_BPV4,
+- NDS_EDM_SR_BPV5,
+- NDS_EDM_SR_BPV6,
+- NDS_EDM_SR_BPV7,
+- NDS_EDM_SR_BPCID0 = 0x20,
+- NDS_EDM_SR_BPCID1,
+- NDS_EDM_SR_BPCID2,
+- NDS_EDM_SR_BPCID3,
+- NDS_EDM_SR_BPCID4,
+- NDS_EDM_SR_BPCID5,
+- NDS_EDM_SR_BPCID6,
+- NDS_EDM_SR_BPCID7,
+- NDS_EDM_SR_EDM_CFG = 0x28,
+- NDS_EDM_SR_EDMSW = 0x30,
+- NDS_EDM_SR_EDM_CTL = 0x38,
+- NDS_EDM_SR_EDM_DTR = 0x40,
+- NDS_EDM_SR_BPMTV = 0x48,
+- NDS_EDM_SR_DIMBR = 0x50,
+- NDS_EDM_SR_TECR0 = 0x70,
+- NDS_EDM_SR_TECR1 = 0x71,
+-};
+-
+-enum nds_memory_access {
+- NDS_MEMORY_ACC_BUS = 0,
+- NDS_MEMORY_ACC_CPU,
+-};
+-
+-enum nds_memory_select {
+- NDS_MEMORY_SELECT_AUTO = 0,
+- NDS_MEMORY_SELECT_MEM = 1,
+- NDS_MEMORY_SELECT_ILM = 2,
+- NDS_MEMORY_SELECT_DLM = 3,
+-};
+-
+-#define NDS_DBGER_DEX (0x1)
+-#define NDS_DBGER_DPED (0x2)
+-#define NDS_DBGER_CRST (0x4)
+-#define NDS_DBGER_AT_MAX (0x8)
+-#define NDS_DBGER_ILL_SEC_ACC (0x10)
+-#define NDS_DBGER_ALL_SUPRS_EX (0x40000000)
+-#define NDS_DBGER_RESACC (0x80000000)
+-#define NDS_DBGER_CLEAR_ALL (0x1F)
+-
+-#define NDS_EDMSW_WDV (1 << 0)
+-#define NDS_EDMSW_RDV (1 << 1)
+-
+-#endif /* OPENOCD_TARGET_NDS32_EDM_H */
+diff --git a/src/target/nds32_insn.h b/src/target/nds32_insn.h
+deleted file mode 100644
+index 25eb9ab8c..000000000
+--- a/src/target/nds32_insn.h
++++ /dev/null
+@@ -1,67 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_INSN_H
+-#define OPENOCD_TARGET_NDS32_INSN_H
+-
+-#define NOP (0x40000009)
+-#define DSB (0x64000008)
+-#define ISB (0x64000009)
+-#define BEQ_MINUS_12 (0x4C000000 | 0x3FFA)
+-#define MTSR_DTR(a) (0x64000003 | (((0x03 << 7) | (0x08 << 3) | (0x00 << 0)) << 10) | (((a) & 0x1F) << 20))
+-#define MFSR_DTR(a) (0x64000002 | (((0x03 << 7) | (0x08 << 3) | (0x00 << 0)) << 10) | (((a) & 0x1F) << 20))
+-#define SETHI(a, b) (0x46000000 | ((a) << 20) | (b))
+-#define ORI(a, b, c) (0x58000000 | ((a) << 20) | ((b) << 15) | (c))
+-#define LWI_BI(a, b) (0x0C000001 | (a << 20) | (b << 15))
+-#define LHI_BI(a, b) (0x0A000001 | (a << 20) | (b << 15))
+-#define LBI_BI(a, b) (0x08000001 | (a << 20) | (b << 15))
+-#define SWI_BI(a, b) (0x1C000001 | (a << 20) | (b << 15))
+-#define SHI_BI(a, b) (0x1A000001 | (a << 20) | (b << 15))
+-#define SBI_BI(a, b) (0x18000001 | (a << 20) | (b << 15))
+-#define IRET (0x64000004)
+-#define L1D_IX_WB(a) (0x64000021 | ((a) << 15))
+-#define L1D_IX_INVAL(a) (0x64000001 | ((a) << 15))
+-#define L1D_VA_INVAL(a) (0x64000101 | ((a) << 15))
+-#define L1D_VA_WB(a) (0x64000121 | ((a) << 15))
+-#define L1D_IX_RTAG(a) (0x64000061 | ((a) << 15))
+-#define L1D_IX_RWD(a) (0x64000081 | ((a) << 15))
+-#define L1I_IX_INVAL(a) (0x64000201 | ((a) << 15))
+-#define L1I_VA_INVAL(a) (0x64000301 | ((a) << 15))
+-#define L1I_IX_RTAG(a) (0x64000261 | ((a) << 15))
+-#define L1I_IX_RWD(a) (0x64000281 | ((a) << 15))
+-#define L1I_VA_FILLCK(a) (0x64000361 | ((a) << 15))
+-#define ISYNC(a) (0x6400000d | ((a) << 20))
+-#define MSYNC_STORE (0x6400002c)
+-#define MSYNC_ALL (0x6400000c)
+-#define TLBOP_TARGET_READ(a) (0x6400000e | ((a) << 15))
+-#define TLBOP_TARGET_PROBE(a, b) (0x640000AE | ((a) << 20) | ((b) << 15))
+-#define MFCPD(a, b, c) (0x6A000041 | (a << 20) | (b << 8) | (c << 4))
+-#define MFCPW(a, b, c) (0x6A000001 | (a << 20) | (b << 8) | (c << 4))
+-#define MTCPD(a, b, c) (0x6A000049 | (a << 20) | (b << 8) | (c << 4))
+-#define MTCPW(a, b, c) (0x6A000009 | (a << 20) | (b << 8) | (c << 4))
+-#define MOVI_(a, b) (0x44000000 | (a << 20) | (b & 0xFFFFF))
+-#define MFUSR_G0(a, b) (0x42000020 | (a << 20) | (b << 15))
+-#define MTUSR_G0(a, b) (0x42000021 | (a << 20) | (b << 15))
+-#define MFSR(a, b) (0x64000002 | (b << 10) | (a << 20))
+-#define MTSR(a, b) (0x64000003 | (b << 10) | (a << 20))
+-#define AMFAR(a, b) (0x60300060 | (a << 15) | b)
+-#define AMTAR(a, b) (0x60300040 | (a << 15) | b)
+-#define AMFAR2(a, b) (0x60300260 | (a << 15) | b)
+-#define AMTAR2(a, b) (0x60300240 | (a << 15) | b)
+-#define FMFCSR (0x6A000701)
+-#define FMTCSR (0x6A000709)
+-#define FMFCFG (0x6A000301)
+-#define FMFSR(a, b) (0x6A000001 | ((a) << 20) | ((b) << 15))
+-#define FMTSR(a, b) (0x6A000009 | ((a) << 20) | ((b) << 15))
+-#define FMFDR(a, b) (0x6A000041 | ((a) << 20) | ((b) << 15))
+-#define FMTDR(a, b) (0x6A000049 | ((a) << 20) | ((b) << 15))
+-
+-/* break instructions */
+-#define NDS32_BREAK_16 (0x00EA)
+-#define NDS32_BREAK_32 (0x0A000064)
+-
+-#endif /* OPENOCD_TARGET_NDS32_INSN_H */
+diff --git a/src/target/nds32_reg.c b/src/target/nds32_reg.c
+deleted file mode 100644
+index 1687e69ce..000000000
+--- a/src/target/nds32_reg.c
++++ /dev/null
+@@ -1,369 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <helper/log.h>
+-#include "nds32_reg.h"
+-
+-static bool nds32_reg_init_done;
+-static struct nds32_reg_s nds32_regs[TOTAL_REG_NUM];
+-static const struct nds32_reg_exception_s nds32_ex_reg_values[] = {
+- {IR0, 3, 0x3, 2},
+- {IR0, 3, 0x3, 3},
+- {IR1, 3, 0x3, 2},
+- {IR1, 3, 0x3, 3},
+- {IR2, 3, 0x3, 2},
+- {IR2, 3, 0x3, 3},
+- {MR3, 1, 0x7, 0},
+- {MR3, 1, 0x7, 4},
+- {MR3, 1, 0x7, 6},
+- {MR3, 8, 0x7, 3},
+- {0, 0, 0, 0},
+-};
+-
+-static inline void nds32_reg_set(uint32_t number, const char *simple_mnemonic,
+- const char *symbolic_mnemonic, uint32_t sr_index,
+- enum nds32_reg_type_s type, uint8_t size)
+-{
+- nds32_regs[number].simple_mnemonic = simple_mnemonic;
+- nds32_regs[number].symbolic_mnemonic = symbolic_mnemonic;
+- nds32_regs[number].sr_index = sr_index;
+- nds32_regs[number].type = type;
+- nds32_regs[number].size = size;
+-}
+-
+-void nds32_reg_init(void)
+-{
+- if (nds32_reg_init_done == true)
+- return;
+-
+- nds32_reg_set(R0, "r0", "r0", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R1, "r1", "r1", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R2, "r2", "r2", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R3, "r3", "r3", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R4, "r4", "r4", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R5, "r5", "r5", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R6, "r6", "r6", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R7, "r7", "r7", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R8, "r8", "r8", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R9, "r9", "r9", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R10, "r10", "r10", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R11, "r11", "r11", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R12, "r12", "r12", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R13, "r13", "r13", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R14, "r14", "r14", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R15, "r15", "r15", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R16, "r16", "r16", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R17, "r17", "r17", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R18, "r18", "r18", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R19, "r19", "r19", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R20, "r20", "r20", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R21, "r21", "r21", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R22, "r22", "r22", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R23, "r23", "r23", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R24, "r24", "r24", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R25, "r25", "r25", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R26, "r26", "p0", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R27, "r27", "p1", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R28, "fp", "fp", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R29, "gp", "gp", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R30, "lp", "lp", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(R31, "sp", "sp", 0, NDS32_REG_TYPE_GPR, 32);
+- nds32_reg_set(PC, "pc", "pc", 31, NDS32_REG_TYPE_SPR, 32);
+-
+- nds32_reg_set(D0LO, "d0lo", "d0lo", 0, NDS32_REG_TYPE_SPR, 32);
+- nds32_reg_set(D0HI, "d0hi", "d0hi", 1, NDS32_REG_TYPE_SPR, 32);
+- nds32_reg_set(D1LO, "d1lo", "d1lo", 2, NDS32_REG_TYPE_SPR, 32);
+- nds32_reg_set(D1HI, "d1hi", "d1hi", 3, NDS32_REG_TYPE_SPR, 32);
+- nds32_reg_set(ITB, "itb", "itb", 28, NDS32_REG_TYPE_SPR, 32);
+- nds32_reg_set(IFC_LP, "ifc_lp", "ifc_lp", 29, NDS32_REG_TYPE_SPR, 32);
+-
+- nds32_reg_set(CR0, "cr0", "CPU_VER", SRIDX(0, 0, 0), NDS32_REG_TYPE_CR, 32);
+- nds32_reg_set(CR1, "cr1", "ICM_CFG", SRIDX(0, 1, 0), NDS32_REG_TYPE_CR, 32);
+- nds32_reg_set(CR2, "cr2", "DCM_CFG", SRIDX(0, 2, 0), NDS32_REG_TYPE_CR, 32);
+- nds32_reg_set(CR3, "cr3", "MMU_CFG", SRIDX(0, 3, 0), NDS32_REG_TYPE_CR, 32);
+- nds32_reg_set(CR4, "cr4", "MSC_CFG", SRIDX(0, 4, 0), NDS32_REG_TYPE_CR, 32);
+- nds32_reg_set(CR5, "cr5", "CORE_ID", SRIDX(0, 0, 1), NDS32_REG_TYPE_CR, 32);
+- nds32_reg_set(CR6, "cr6", "FUCOP_EXIST", SRIDX(0, 5, 0), NDS32_REG_TYPE_CR, 32);
+-
+- nds32_reg_set(IR0, "ir0", "PSW", SRIDX(1, 0, 0), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR1, "ir1", "IPSW", SRIDX(1, 0, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR2, "ir2", "P_IPSW", SRIDX(1, 0, 2), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR3, "ir3", "IVB", SRIDX(1, 1, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR4, "ir4", "EVA", SRIDX(1, 2, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR5, "ir5", "P_EVA", SRIDX(1, 2, 2), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR6, "ir6", "ITYPE", SRIDX(1, 3, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR7, "ir7", "P_ITYPE", SRIDX(1, 3, 2), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR8, "ir8", "MERR", SRIDX(1, 4, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR9, "ir9", "IPC", SRIDX(1, 5, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR10, "ir10", "P_IPC", SRIDX(1, 5, 2), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR11, "ir11", "OIPC", SRIDX(1, 5, 3), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR12, "ir12", "P_P0", SRIDX(1, 6, 2), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR13, "ir13", "P_P1", SRIDX(1, 7, 2), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR14, "ir14", "INT_MASK", SRIDX(1, 8, 0), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR15, "ir15", "INT_PEND", SRIDX(1, 9, 0), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR16, "ir16", "", SRIDX(1, 10, 0), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR17, "ir17", "", SRIDX(1, 10, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR18, "ir18", "", SRIDX(1, 11, 0), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR19, "ir19", "", SRIDX(1, 1, 2), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR20, "ir20", "", SRIDX(1, 10, 2), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR21, "ir21", "", SRIDX(1, 10, 3), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR22, "ir22", "", SRIDX(1, 10, 4), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR23, "ir23", "", SRIDX(1, 10, 5), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR24, "ir24", "", SRIDX(1, 10, 6), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR25, "ir25", "", SRIDX(1, 10, 7), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR26, "ir26", "", SRIDX(1, 8, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR27, "ir27", "", SRIDX(1, 9, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR28, "ir28", "", SRIDX(1, 11, 1), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR29, "ir29", "", SRIDX(1, 9, 4), NDS32_REG_TYPE_IR, 32);
+- nds32_reg_set(IR30, "ir30", "", SRIDX(1, 1, 3), NDS32_REG_TYPE_IR, 32);
+-
+- nds32_reg_set(MR0, "mr0", "MMU_CTL", SRIDX(2, 0, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR1, "mr1", "L1_PPTB", SRIDX(2, 1, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR2, "mr2", "TLB_VPN", SRIDX(2, 2, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR3, "mr3", "TLB_DATA", SRIDX(2, 3, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR4, "mr4", "TLB_MISC", SRIDX(2, 4, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR5, "mr5", "VLPT_IDX", SRIDX(2, 5, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR6, "mr6", "ILMB", SRIDX(2, 6, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR7, "mr7", "DLMB", SRIDX(2, 7, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR8, "mr8", "CACHE_CTL", SRIDX(2, 8, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR9, "mr9", "HSMP_SADDR", SRIDX(2, 9, 0), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR10, "mr10", "HSMP_EADDR", SRIDX(2, 9, 1), NDS32_REG_TYPE_MR, 32);
+- nds32_reg_set(MR11, "mr11", "", SRIDX(2, 0, 1), NDS32_REG_TYPE_MR, 32);
+-
+- nds32_reg_set(DR0, "dr0", "BPC0", SRIDX(3, 0, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR1, "dr1", "BPA0", SRIDX(3, 1, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR2, "dr2", "BPAM0", SRIDX(3, 2, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR3, "dr3", "BPV0", SRIDX(3, 3, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR4, "dr4", "BPCID0", SRIDX(3, 4, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR5, "dr5", "BPC1", SRIDX(3, 0, 1), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR6, "dr6", "BPA1", SRIDX(3, 1, 1), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR7, "dr7", "BPAM1", SRIDX(3, 2, 1), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR8, "dr8", "BPV1", SRIDX(3, 3, 1), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR9, "dr9", "BPCID1", SRIDX(3, 4, 1), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR10, "dr10", "BPC2", SRIDX(3, 0, 2), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR11, "dr11", "BPA2", SRIDX(3, 1, 2), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR12, "dr12", "BPAM2", SRIDX(3, 2, 2), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR13, "dr13", "BPV2", SRIDX(3, 3, 2), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR14, "dr14", "BPCID2", SRIDX(3, 4, 2), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR15, "dr15", "BPC3", SRIDX(3, 0, 3), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR16, "dr16", "BPA3", SRIDX(3, 1, 3), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR17, "dr17", "BPAM3", SRIDX(3, 2, 3), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR18, "dr18", "BPV3", SRIDX(3, 3, 3), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR19, "dr19", "BPCID3", SRIDX(3, 4, 3), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR20, "dr20", "BPC4", SRIDX(3, 0, 4), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR21, "dr21", "BPA4", SRIDX(3, 1, 4), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR22, "dr22", "BPAM4", SRIDX(3, 2, 4), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR23, "dr23", "BPV4", SRIDX(3, 3, 4), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR24, "dr24", "BPCID4", SRIDX(3, 4, 4), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR25, "dr25", "BPC5", SRIDX(3, 0, 5), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR26, "dr26", "BPA5", SRIDX(3, 1, 5), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR27, "dr27", "BPAM5", SRIDX(3, 2, 5), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR28, "dr28", "BPV5", SRIDX(3, 3, 5), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR29, "dr29", "BPCID5", SRIDX(3, 4, 5), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR30, "dr30", "BPC6", SRIDX(3, 0, 6), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR31, "dr31", "BPA6", SRIDX(3, 1, 6), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR32, "dr32", "BPAM6", SRIDX(3, 2, 6), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR33, "dr33", "BPV6", SRIDX(3, 3, 6), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR34, "dr34", "BPCID6", SRIDX(3, 4, 6), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR35, "dr35", "BPC7", SRIDX(3, 0, 7), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR36, "dr36", "BPA7", SRIDX(3, 1, 7), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR37, "dr37", "BPAM7", SRIDX(3, 2, 7), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR38, "dr38", "BPV7", SRIDX(3, 3, 7), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR39, "dr39", "BPCID7", SRIDX(3, 4, 7), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR40, "dr40", "EDM_CFG", SRIDX(3, 5, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR41, "dr41", "EDMSW", SRIDX(3, 6, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR42, "dr42", "EDM_CTL", SRIDX(3, 7, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR43, "dr43", "EDM_DTR", SRIDX(3, 8, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR44, "dr44", "BPMTC", SRIDX(3, 9, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR45, "dr45", "DIMBR", SRIDX(3, 10, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR46, "dr46", "TECR0", SRIDX(3, 14, 0), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR47, "dr47", "TECR1", SRIDX(3, 14, 1), NDS32_REG_TYPE_DR, 32);
+- nds32_reg_set(DR48, "dr48", "", SRIDX(3, 11, 0), NDS32_REG_TYPE_DR, 32);
+-
+- nds32_reg_set(PFR0, "pfr0", "PFMC0", SRIDX(4, 0, 0), NDS32_REG_TYPE_PFR, 32);
+- nds32_reg_set(PFR1, "pfr1", "PFMC1", SRIDX(4, 0, 1), NDS32_REG_TYPE_PFR, 32);
+- nds32_reg_set(PFR2, "pfr2", "PFMC2", SRIDX(4, 0, 2), NDS32_REG_TYPE_PFR, 32);
+- nds32_reg_set(PFR3, "pfr3", "PFM_CTL", SRIDX(4, 1, 0), NDS32_REG_TYPE_PFR, 32);
+-
+- nds32_reg_set(DMAR0, "dmar0", "DMA_CFG", SRIDX(5, 0, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR1, "dmar1", "DMA_GCSW", SRIDX(5, 1, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR2, "dmar2", "DMA_CHNSEL", SRIDX(5, 2, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR3, "dmar3", "DMA_ACT", SRIDX(5, 3, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR4, "dmar4", "DMA_SETUP", SRIDX(5, 4, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR5, "dmar5", "DMA_ISADDR", SRIDX(5, 5, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR6, "dmar6", "DMA_ESADDR", SRIDX(5, 6, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR7, "dmar7", "DMA_TCNT", SRIDX(5, 7, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR8, "dmar8", "DMA_STATUS", SRIDX(5, 8, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR9, "dmar9", "DMA_2DSET", SRIDX(5, 9, 0), NDS32_REG_TYPE_DMAR, 32);
+- nds32_reg_set(DMAR10, "dmar10", "DMA_2DSCTL", SRIDX(5, 9, 1), NDS32_REG_TYPE_DMAR, 32);
+-
+- nds32_reg_set(RACR, "racr", "PRUSR_ACC_CTL", SRIDX(4, 4, 0), NDS32_REG_TYPE_RACR, 32);
+- nds32_reg_set(FUCPR, "fucpr", "FUCOP_CTL", SRIDX(4, 5, 0), NDS32_REG_TYPE_RACR, 32);
+-
+- nds32_reg_set(IDR0, "idr0", "SDZ_CTL", SRIDX(2, 15, 0), NDS32_REG_TYPE_IDR, 32);
+- nds32_reg_set(IDR1, "idr1", "MISC_CTL", SRIDX(2, 15, 1), NDS32_REG_TYPE_IDR, 32);
+-
+- nds32_reg_set(SECUR0, "secur0", "", SRIDX(6, 0, 0), NDS32_REG_TYPE_SECURE, 32);
+-
+- nds32_reg_set(D0L24, "D0L24", "D0L24", 0x10, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(D1L24, "D1L24", "D1L24", 0x11, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(I0, "I0", "I0", 0x0, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(I1, "I1", "I1", 0x1, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(I2, "I2", "I2", 0x2, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(I3, "I3", "I3", 0x3, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(I4, "I4", "I4", 0x4, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(I5, "I5", "I5", 0x5, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(I6, "I6", "I6", 0x6, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(I7, "I7", "I7", 0x7, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(M1, "M1", "M1", 0x9, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(M2, "M2", "M2", 0xA, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(M3, "M3", "M3", 0xB, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(M5, "M5", "M5", 0xD, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(M6, "M6", "M6", 0xE, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(M7, "M7", "M7", 0xF, NDS32_REG_TYPE_AUMR, 32);
+-
+- nds32_reg_set(MOD, "MOD", "MOD", 0x8, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(LBE, "LBE", "LBE", 0x18, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(LE, "LE", "LE", 0x19, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(LC, "LC", "LC", 0x1A, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(ADM_VBASE, "ADM_VBASE", "ADM_VBASE", 0x1B, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(SHFT_CTL0, "SHFT_CTL0", "SHFT_CTL0", 0x12, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(SHFT_CTL1, "SHFT_CTL1", "SHFT_CTL1", 0x13, NDS32_REG_TYPE_AUMR, 32);
+-
+- nds32_reg_set(CB_CTL, "CB_CTL", "CB_CTL", 0x1F, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(CBB0, "CBB0", "CBB0", 0x0, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(CBB1, "CBB1", "CBB1", 0x1, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(CBB2, "CBB2", "CBB2", 0x2, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(CBB3, "CBB3", "CBB3", 0x3, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(CBE0, "CBE0", "CBE0", 0x4, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(CBE1, "CBE1", "CBE1", 0x5, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(CBE2, "CBE2", "CBE2", 0x6, NDS32_REG_TYPE_AUMR, 32);
+- nds32_reg_set(CBE3, "CBE3", "CBE3", 0x7, NDS32_REG_TYPE_AUMR, 32);
+-
+- nds32_reg_set(FPCSR, "fpcsr", "FPCSR", 0x7, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FPCFG, "fpcfg", "FPCFG", 0x7, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS0, "fs0", "FS0", 0, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS1, "fs1", "FS1", 1, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS2, "fs2", "FS2", 2, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS3, "fs3", "FS3", 3, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS4, "fs4", "FS4", 4, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS5, "fs5", "FS5", 5, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS6, "fs6", "FS6", 6, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS7, "fs7", "FS7", 7, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS8, "fs8", "FS8", 8, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS9, "fs9", "FS9", 9, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS10, "fs10", "FS10", 10, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS11, "fs11", "FS11", 11, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS12, "fs12", "FS12", 12, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS13, "fs13", "FS13", 13, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS14, "fs14", "FS14", 14, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS15, "fs15", "FS15", 15, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS16, "fs16", "FS16", 16, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS17, "fs17", "FS17", 17, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS18, "fs18", "FS18", 18, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS19, "fs19", "FS19", 19, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS20, "fs20", "FS20", 20, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS21, "fs21", "FS21", 21, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS22, "fs22", "FS22", 22, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS23, "fs23", "FS23", 23, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS24, "fs24", "FS24", 24, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS25, "fs25", "FS25", 25, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS26, "fs26", "FS26", 26, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS27, "fs27", "FS27", 27, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS28, "fs28", "FS28", 28, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS29, "fs29", "FS29", 29, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS30, "fs30", "FS30", 30, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FS31, "fs31", "FS31", 31, NDS32_REG_TYPE_FPU, 32);
+- nds32_reg_set(FD0, "fd0", "FD0", 0, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD1, "fd1", "FD1", 1, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD2, "fd2", "FD2", 2, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD3, "fd3", "FD3", 3, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD4, "fd4", "FD4", 4, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD5, "fd5", "FD5", 5, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD6, "fd6", "FD6", 6, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD7, "fd7", "FD7", 7, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD8, "fd8", "FD8", 8, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD9, "fd9", "FD9", 9, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD10, "fd10", "FD10", 10, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD11, "fd11", "FD11", 11, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD12, "fd12", "FD12", 12, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD13, "fd13", "FD13", 13, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD14, "fd14", "FD14", 14, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD15, "fd15", "FD15", 15, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD16, "fd16", "FD16", 16, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD17, "fd17", "FD17", 17, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD18, "fd18", "FD18", 18, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD19, "fd19", "FD19", 19, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD20, "fd20", "FD20", 20, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD21, "fd21", "FD21", 21, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD22, "fd22", "FD22", 22, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD23, "fd23", "FD23", 23, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD24, "fd24", "FD24", 24, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD25, "fd25", "FD25", 25, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD26, "fd26", "FD26", 26, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD27, "fd27", "FD27", 27, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD28, "fd28", "FD28", 28, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD29, "fd29", "FD29", 29, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD30, "fd30", "FD30", 30, NDS32_REG_TYPE_FPU, 64);
+- nds32_reg_set(FD31, "fd31", "FD31", 31, NDS32_REG_TYPE_FPU, 64);
+-
+- nds32_reg_init_done = true;
+-}
+-
+-uint32_t nds32_reg_sr_index(uint32_t number)
+-{
+- return nds32_regs[number].sr_index;
+-}
+-
+-enum nds32_reg_type_s nds32_reg_type(uint32_t number)
+-{
+- return nds32_regs[number].type;
+-}
+-
+-uint8_t nds32_reg_size(uint32_t number)
+-{
+- return nds32_regs[number].size;
+-}
+-
+-const char *nds32_reg_simple_name(uint32_t number)
+-{
+- return nds32_regs[number].simple_mnemonic;
+-}
+-
+-const char *nds32_reg_symbolic_name(uint32_t number)
+-{
+- return nds32_regs[number].symbolic_mnemonic;
+-}
+-
+-bool nds32_reg_exception(uint32_t number, uint32_t value)
+-{
+- int i;
+- const struct nds32_reg_exception_s *ex_reg_value;
+- uint32_t field_value;
+-
+- i = 0;
+- while (nds32_ex_reg_values[i].reg_num != 0) {
+- ex_reg_value = nds32_ex_reg_values + i;
+-
+- if (ex_reg_value->reg_num == number) {
+- field_value = (value >> ex_reg_value->ex_value_bit_pos) &
+- ex_reg_value->ex_value_mask;
+- if (field_value == ex_reg_value->ex_value) {
+- LOG_WARNING("It will generate exceptions as setting %" PRIu32 " to %s",
+- value, nds32_regs[number].simple_mnemonic);
+- return true;
+- }
+- }
+-
+- i++;
+- }
+-
+- return false;
+-}
+diff --git a/src/target/nds32_reg.h b/src/target/nds32_reg.h
+deleted file mode 100644
+index 30cd24172..000000000
+--- a/src/target/nds32_reg.h
++++ /dev/null
+@@ -1,314 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_REG_H
+-#define OPENOCD_TARGET_NDS32_REG_H
+-
+-#define SRIDX(a, b, c) ((a << 7) | (b << 3) | c)
+-#define NDS32_REGISTER_DISABLE (0x0)
+-
+-enum nds32_reg_number_s {
+- R0 = 0, /* general registers */
+- R1,
+- R2,
+- R3,
+- R4,
+- R5,
+- R6,
+- R7,
+- R8,
+- R9,
+- R10,
+- R11,
+- R12,
+- R13,
+- R14,
+- R15,
+- R16,
+- R17,
+- R18,
+- R19,
+- R20,
+- R21,
+- R22,
+- R23,
+- R24,
+- R25,
+- R26,
+- R27,
+- R28,
+- R29,
+- R30,
+- R31,
+- PC,
+- D0LO,
+- D0HI,
+- D1LO,
+- D1HI,
+- ITB,
+- IFC_LP,
+- CR0, /* system registers */
+- CR1,
+- CR2,
+- CR3,
+- CR4,
+- CR5,
+- CR6,
+- IR0,
+- IR1,
+- IR2,
+- IR3,
+- IR4,
+- IR5,
+- IR6,
+- IR7,
+- IR8,
+- IR9,
+- IR10,
+- IR11,
+- IR12,
+- IR13,
+- IR14,
+- IR15,
+- IR16,
+- IR17,
+- IR18,
+- IR19,
+- IR20,
+- IR21,
+- IR22,
+- IR23,
+- IR24,
+- IR25,
+- IR26,
+- IR27,
+- IR28,
+- IR29,
+- IR30,
+- MR0,
+- MR1,
+- MR2,
+- MR3,
+- MR4,
+- MR5,
+- MR6,
+- MR7,
+- MR8,
+- MR9,
+- MR10,
+- MR11,
+- DR0,
+- DR1,
+- DR2,
+- DR3,
+- DR4,
+- DR5,
+- DR6,
+- DR7,
+- DR8,
+- DR9,
+- DR10,
+- DR11,
+- DR12,
+- DR13,
+- DR14,
+- DR15,
+- DR16,
+- DR17,
+- DR18,
+- DR19,
+- DR20,
+- DR21,
+- DR22,
+- DR23,
+- DR24,
+- DR25,
+- DR26,
+- DR27,
+- DR28,
+- DR29,
+- DR30,
+- DR31,
+- DR32,
+- DR33,
+- DR34,
+- DR35,
+- DR36,
+- DR37,
+- DR38,
+- DR39,
+- DR40,
+- DR41,
+- DR42,
+- DR43,
+- DR44,
+- DR45,
+- DR46,
+- DR47,
+- DR48,
+- PFR0,
+- PFR1,
+- PFR2,
+- PFR3,
+- DMAR0,
+- DMAR1,
+- DMAR2,
+- DMAR3,
+- DMAR4,
+- DMAR5,
+- DMAR6,
+- DMAR7,
+- DMAR8,
+- DMAR9,
+- DMAR10,
+- RACR,
+- FUCPR,
+- IDR0,
+- IDR1,
+- SECUR0,
+- D0L24, /* audio registers */
+- D1L24,
+- I0,
+- I1,
+- I2,
+- I3,
+- I4,
+- I5,
+- I6,
+- I7,
+- M1,
+- M2,
+- M3,
+- M5,
+- M6,
+- M7,
+- MOD,
+- LBE,
+- LE,
+- LC,
+- ADM_VBASE,
+- SHFT_CTL0,
+- SHFT_CTL1,
+- CB_CTL,
+- CBB0,
+- CBB1,
+- CBB2,
+- CBB3,
+- CBE0,
+- CBE1,
+- CBE2,
+- CBE3,
+- FPCSR, /* fpu */
+- FPCFG,
+- FS0,
+- FS1,
+- FS2,
+- FS3,
+- FS4,
+- FS5,
+- FS6,
+- FS7,
+- FS8,
+- FS9,
+- FS10,
+- FS11,
+- FS12,
+- FS13,
+- FS14,
+- FS15,
+- FS16,
+- FS17,
+- FS18,
+- FS19,
+- FS20,
+- FS21,
+- FS22,
+- FS23,
+- FS24,
+- FS25,
+- FS26,
+- FS27,
+- FS28,
+- FS29,
+- FS30,
+- FS31,
+- FD0,
+- FD1,
+- FD2,
+- FD3,
+- FD4,
+- FD5,
+- FD6,
+- FD7,
+- FD8,
+- FD9,
+- FD10,
+- FD11,
+- FD12,
+- FD13,
+- FD14,
+- FD15,
+- FD16,
+- FD17,
+- FD18,
+- FD19,
+- FD20,
+- FD21,
+- FD22,
+- FD23,
+- FD24,
+- FD25,
+- FD26,
+- FD27,
+- FD28,
+- FD29,
+- FD30,
+- FD31,
+-
+- TOTAL_REG_NUM,
+-};
+-
+-enum nds32_reg_type_s {
+- NDS32_REG_TYPE_GPR = 0,
+- NDS32_REG_TYPE_SPR,
+- NDS32_REG_TYPE_CR,
+- NDS32_REG_TYPE_IR,
+- NDS32_REG_TYPE_MR,
+- NDS32_REG_TYPE_DR,
+- NDS32_REG_TYPE_PFR,
+- NDS32_REG_TYPE_DMAR,
+- NDS32_REG_TYPE_RACR,
+- NDS32_REG_TYPE_IDR,
+- NDS32_REG_TYPE_AUMR,
+- NDS32_REG_TYPE_SECURE,
+- NDS32_REG_TYPE_FPU,
+-};
+-
+-struct nds32_reg_s {
+- const char *simple_mnemonic;
+- const char *symbolic_mnemonic;
+- uint32_t sr_index;
+- enum nds32_reg_type_s type;
+- uint8_t size;
+-};
+-
+-struct nds32_reg_exception_s {
+- uint32_t reg_num;
+- uint32_t ex_value_bit_pos;
+- uint32_t ex_value_mask;
+- uint32_t ex_value;
+-};
+-
+-void nds32_reg_init(void);
+-uint32_t nds32_reg_sr_index(uint32_t number);
+-enum nds32_reg_type_s nds32_reg_type(uint32_t number);
+-uint8_t nds32_reg_size(uint32_t number);
+-const char *nds32_reg_simple_name(uint32_t number);
+-const char *nds32_reg_symbolic_name(uint32_t number);
+-bool nds32_reg_exception(uint32_t number, uint32_t value);
+-
+-#endif /* OPENOCD_TARGET_NDS32_REG_H */
+diff --git a/src/target/nds32_tlb.c b/src/target/nds32_tlb.c
+deleted file mode 100644
+index a533e593d..000000000
+--- a/src/target/nds32_tlb.c
++++ /dev/null
+@@ -1,67 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include "nds32_aice.h"
+-#include "nds32_tlb.h"
+-
+-int nds32_probe_tlb(struct nds32 *nds32, const target_addr_t virtual_address,
+- target_addr_t *physical_address)
+-{
+- struct target *target = nds32->target;
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- return aice_read_tlb(aice, virtual_address, physical_address);
+-}
+-
+-static struct page_table_walker_info_s page_table_info[PAGE_SIZE_NUM] = {
+- /* 4K page */
+- {0xFFC00000, 20, 0x003FF000, 10, 0x00000FFF, 0xFFFFF000, 0xFFFFF000, 0xFFFFF000},
+- /* 8K page */
+- {0xFF000000, 22, 0x00FFE000, 11, 0x00001FFF, 0xFFFFF000, 0xFFFFE000, 0xFFFFE000},
+-};
+-
+-int nds32_walk_page_table(struct nds32 *nds32, const target_addr_t virtual_address,
+- target_addr_t *physical_address)
+-{
+- struct target *target = nds32->target;
+- uint32_t value_mr1;
+- uint32_t load_address;
+- uint32_t l1_page_table_entry;
+- uint32_t l2_page_table_entry;
+- uint32_t page_size_index = nds32->mmu_config.default_min_page_size;
+- struct page_table_walker_info_s *page_table_info_p =
+- &(page_table_info[page_size_index]);
+-
+- /* Read L1 Physical Page Table */
+- nds32_get_mapped_reg(nds32, MR1, &value_mr1);
+- load_address = (value_mr1 & page_table_info_p->l1_base_mask) |
+- ((virtual_address & page_table_info_p->l1_offset_mask) >>
+- page_table_info_p->l1_offset_shift);
+- /* load_address is physical address */
+- nds32_read_buffer(target, load_address, 4, (uint8_t *)&l1_page_table_entry);
+-
+- /* Read L2 Physical Page Table */
+- if (l1_page_table_entry & 0x1) /* L1_PTE not present */
+- return ERROR_FAIL;
+-
+- load_address = (l1_page_table_entry & page_table_info_p->l2_base_mask) |
+- ((virtual_address & page_table_info_p->l2_offset_mask) >>
+- page_table_info_p->l2_offset_shift);
+- /* load_address is physical address */
+- nds32_read_buffer(target, load_address, 4, (uint8_t *)&l2_page_table_entry);
+-
+- if ((l2_page_table_entry & 0x1) != 0x1) /* L2_PTE not valid */
+- return ERROR_FAIL;
+-
+- *physical_address = (l2_page_table_entry & page_table_info_p->ppn_mask) |
+- (virtual_address & page_table_info_p->va_offset_mask);
+-
+- return ERROR_OK;
+-}
+diff --git a/src/target/nds32_tlb.h b/src/target/nds32_tlb.h
+deleted file mode 100644
+index 1edff294f..000000000
+--- a/src/target/nds32_tlb.h
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_TLB_H
+-#define OPENOCD_TARGET_NDS32_TLB_H
+-
+-#include "nds32.h"
+-
+-enum {
+- PAGE_SIZE_4K = 0,
+- PAGE_SIZE_8K,
+- PAGE_SIZE_NUM,
+-};
+-
+-struct page_table_walker_info_s {
+-
+- uint32_t l1_offset_mask;
+- uint32_t l1_offset_shift;
+- uint32_t l2_offset_mask;
+- uint32_t l2_offset_shift;
+- uint32_t va_offset_mask;
+- uint32_t l1_base_mask;
+- uint32_t l2_base_mask;
+- uint32_t ppn_mask;
+-};
+-
+-extern int nds32_probe_tlb(struct nds32 *nds32, const target_addr_t virtual_address,
+- target_addr_t *physical_address);
+-extern int nds32_walk_page_table(struct nds32 *nds32, const target_addr_t virtual_address,
+- target_addr_t *physical_address);
+-
+-#endif /* OPENOCD_TARGET_NDS32_TLB_H */
+diff --git a/src/target/nds32_v2.c b/src/target/nds32_v2.c
+deleted file mode 100644
+index 214929117..000000000
+--- a/src/target/nds32_v2.c
++++ /dev/null
+@@ -1,774 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <helper/time_support.h>
+-#include <helper/binarybuffer.h>
+-#include "breakpoints.h"
+-#include "nds32_insn.h"
+-#include "nds32_reg.h"
+-#include "nds32_edm.h"
+-#include "nds32_cmd.h"
+-#include "nds32_v2.h"
+-#include "nds32_aice.h"
+-#include "target_type.h"
+-
+-static int nds32_v2_register_mapping(struct nds32 *nds32, int reg_no)
+-{
+- uint32_t max_level = nds32->max_interrupt_level;
+- uint32_t cur_level = nds32->current_interrupt_level;
+-
+- if ((cur_level >= 1) && (cur_level < max_level)) {
+- if (reg_no == IR0) {
+- LOG_DEBUG("Map PSW to IPSW");
+- return IR1;
+- } else if (reg_no == PC) {
+- LOG_DEBUG("Map PC to IPC");
+- return IR9;
+- }
+- } else if ((cur_level >= 2) && (cur_level < max_level)) {
+- if (reg_no == R26) {
+- LOG_DEBUG("Mapping P0 to P_P0");
+- return IR12;
+- } else if (reg_no == R27) {
+- LOG_DEBUG("Mapping P1 to P_P1");
+- return IR13;
+- } else if (reg_no == IR1) {
+- LOG_DEBUG("Mapping IPSW to P_IPSW");
+- return IR2;
+- } else if (reg_no == IR4) {
+- LOG_DEBUG("Mapping EVA to P_EVA");
+- return IR5;
+- } else if (reg_no == IR6) {
+- LOG_DEBUG("Mapping ITYPE to P_ITYPE");
+- return IR7;
+- } else if (reg_no == IR9) {
+- LOG_DEBUG("Mapping IPC to P_IPC");
+- return IR10;
+- }
+- } else if (cur_level == max_level) {
+- if (reg_no == PC) {
+- LOG_DEBUG("Mapping PC to O_IPC");
+- return IR11;
+- }
+- }
+-
+- return reg_no;
+-}
+-
+-static int nds32_v2_get_debug_reason(struct nds32 *nds32, uint32_t *reason)
+-{
+- uint32_t val_itype;
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+-
+- aice_read_register(aice, IR6, &val_itype);
+-
+- *reason = val_itype & 0x0F;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_activate_hardware_breakpoint(struct target *target)
+-{
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct breakpoint *bp;
+- int32_t hbr_index = 0;
+-
+- for (bp = target->breakpoints; bp; bp = bp->next) {
+- if (bp->type == BKPT_SOFT) {
+- /* already set at nds32_v2_add_breakpoint() */
+- continue;
+- } else if (bp->type == BKPT_HARD) {
+- /* set address */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address);
+- /* set mask */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0);
+- /* set value */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0);
+-
+- if (nds32_v2->nds32.memory.address_translation)
+- /* enable breakpoint (virtual address) */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2);
+- else
+- /* enable breakpoint (physical address) */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA);
+-
+- LOG_DEBUG("Add hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index,
+- bp->address);
+-
+- hbr_index++;
+- } else {
+- return ERROR_FAIL;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_deactivate_hardware_breakpoint(struct target *target)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+- struct breakpoint *bp;
+- int32_t hbr_index = 0;
+-
+- for (bp = target->breakpoints; bp; bp = bp->next) {
+- if (bp->type == BKPT_SOFT)
+- continue;
+- else if (bp->type == BKPT_HARD)
+- /* disable breakpoint */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0);
+- else
+- return ERROR_FAIL;
+-
+- LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index,
+- bp->address);
+-
+- hbr_index++;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_activate_hardware_watchpoint(struct target *target)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
+- struct watchpoint *wp;
+- int32_t wp_num = nds32_v2->next_hbr_index;
+- uint32_t wp_config = 0;
+-
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+-
+- wp_num--;
+- wp->mask = wp->length - 1;
+- if ((wp->address % wp->length) != 0)
+- wp->mask = (wp->mask << 1) + 1;
+-
+- if (wp->rw == WPT_READ)
+- wp_config = 0x3;
+- else if (wp->rw == WPT_WRITE)
+- wp_config = 0x5;
+- else if (wp->rw == WPT_ACCESS)
+- wp_config = 0x7;
+-
+- /* set/unset physical address bit of BPCn according to PSW.DT */
+- if (nds32_v2->nds32.memory.address_translation == false)
+- wp_config |= 0x8;
+-
+- /* set address */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
+- wp->address - (wp->address % wp->length));
+- /* set mask */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
+- /* enable watchpoint */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
+- /* set value */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0);
+-
+- LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num,
+- wp->address, wp->mask);
+-
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_deactivate_hardware_watchpoint(struct target *target)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
+- int32_t wp_num = nds32_v2->next_hbr_index;
+- struct watchpoint *wp;
+-
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+- wp_num--;
+- /* disable watchpoint */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
+-
+- LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32,
+- wp_num, wp->address, wp->mask);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_check_interrupt_stack(struct nds32_v2_common *nds32_v2)
+-{
+- struct nds32 *nds32 = &(nds32_v2->nds32);
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+- uint32_t val_ir0;
+- uint32_t val_ir1;
+- uint32_t val_ir2;
+- uint32_t modified_psw;
+-
+- /* Save interrupt level */
+- aice_read_register(aice, IR0, &val_ir0); /* get $IR0 directly */
+-
+- /* backup $IR0 */
+- nds32_v2->backup_ir0 = val_ir0;
+-
+- nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
+-
+- if (nds32_reach_max_interrupt_level(nds32)) {
+- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->",
+- nds32->current_interrupt_level);
+-
+- /* decrease interrupt level */
+- modified_psw = val_ir0 - 0x2;
+-
+- /* disable GIE, IT, DT, HSS */
+- modified_psw &= (~0x8C1);
+-
+- aice_write_register(aice, IR0, modified_psw);
+-
+- return ERROR_OK;
+- }
+-
+- /* There is a case that single step also trigger another interrupt,
+- then HSS bit in psw(ir0) will push to ipsw(ir1).
+- Then hit debug interrupt HSS bit in ipsw(ir1) will push to (p_ipsw)ir2
+- Therefore, HSS bit in p_ipsw(ir2) also need clear.
+-
+- Only update $ir2 as current interrupt level is 2, because $ir2 will be random
+- value if the target never reaches interrupt level 2. */
+- if ((nds32->max_interrupt_level == 3) && (nds32->current_interrupt_level == 2)) {
+- aice_read_register(aice, IR2, &val_ir2); /* get $IR2 directly */
+- val_ir2 &= ~(0x01 << 11);
+- aice_write_register(aice, IR2, val_ir2);
+- }
+-
+- /* get original DT bit and set to current state let debugger has same memory view
+- PSW.IT MUST be turned off. Otherwise, DIM could not operate normally. */
+- aice_read_register(aice, IR1, &val_ir1);
+- modified_psw = val_ir0 | (val_ir1 & 0x80);
+- aice_write_register(aice, IR0, modified_psw);
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_restore_interrupt_stack(struct nds32_v2_common *nds32_v2)
+-{
+- struct nds32 *nds32 = &(nds32_v2->nds32);
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+-
+- /* restore origin $IR0 */
+- aice_write_register(aice, IR0, nds32_v2->backup_ir0);
+-
+- return ERROR_OK;
+-}
+-
+-/**
+- * Save processor state. This is called after a HALT instruction
+- * succeeds, and on other occasions the processor enters debug mode
+- * (breakpoint, watchpoint, etc).
+- */
+-static int nds32_v2_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
+-{
+- LOG_DEBUG("nds32_v2_debug_entry");
+-
+- if (nds32->virtual_hosting)
+- LOG_WARNING("<-- TARGET WARNING! Virtual hosting is not supported "
+- "under V1/V2 architecture. -->");
+-
+- enum target_state backup_state = nds32->target->state;
+- nds32->target->state = TARGET_HALTED;
+-
+- if (nds32->init_arch_info_after_halted == false) {
+- /* init architecture info according to config registers */
+- CHECK_RETVAL(nds32_config(nds32));
+-
+- nds32->init_arch_info_after_halted = true;
+- }
+-
+- /* REVISIT entire cache should already be invalid !!! */
+- register_cache_invalidate(nds32->core_cache);
+-
+- /* deactivate all hardware breakpoints */
+- CHECK_RETVAL(nds32_v2_deactivate_hardware_breakpoint(nds32->target));
+-
+- if (enable_watchpoint)
+- CHECK_RETVAL(nds32_v2_deactivate_hardware_watchpoint(nds32->target));
+-
+- if (nds32_examine_debug_reason(nds32) != ERROR_OK) {
+- nds32->target->state = backup_state;
+-
+- /* re-activate all hardware breakpoints & watchpoints */
+- CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
+-
+- if (enable_watchpoint) {
+- /* activate all watchpoints */
+- CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
+- }
+-
+- return ERROR_FAIL;
+- }
+-
+- /* check interrupt level before .full_context(), because
+- * get_mapped_reg() in nds32_full_context() needs current_interrupt_level
+- * information */
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
+- nds32_v2_check_interrupt_stack(nds32_v2);
+-
+- /* Save registers. */
+- nds32_full_context(nds32);
+-
+- return ERROR_OK;
+-}
+-
+-/* target request support */
+-static int nds32_v2_target_request_data(struct target *target,
+- uint32_t size, uint8_t *buffer)
+-{
+- /* AndesCore could use DTR register to communicate with OpenOCD
+- * to output messages
+- * Target data will be put in buffer
+- * The format of DTR is as follow
+- * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd
+- * target_req_cmd has three possible values:
+- * TARGET_REQ_TRACEMSG
+- * TARGET_REQ_DEBUGMSG
+- * TARGET_REQ_DEBUGCHAR
+- * if size == 0, target will call target_asciimsg(),
+- * else call target_hexmsg()
+- */
+- LOG_WARNING("Not implemented: %s", __func__);
+-
+- return ERROR_OK;
+-}
+-
+-/**
+- * Restore processor state.
+- */
+-static int nds32_v2_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint)
+-{
+- LOG_DEBUG("nds32_v2_leave_debug_state");
+-
+- struct target *target = nds32->target;
+-
+- /* activate all hardware breakpoints */
+- CHECK_RETVAL(nds32_v2_activate_hardware_breakpoint(nds32->target));
+-
+- if (enable_watchpoint) {
+- /* activate all watchpoints */
+- CHECK_RETVAL(nds32_v2_activate_hardware_watchpoint(nds32->target));
+- }
+-
+- /* restore interrupt stack */
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(nds32->target);
+- nds32_v2_restore_interrupt_stack(nds32_v2);
+-
+- /* restore PSW, PC, and R0 ... after flushing any modified
+- * registers.
+- */
+- CHECK_RETVAL(nds32_restore_context(target));
+-
+- register_cache_invalidate(nds32->core_cache);
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_deassert_reset(struct target *target)
+-{
+- int retval;
+-
+- CHECK_RETVAL(nds32_poll(target));
+-
+- if (target->state != TARGET_HALTED) {
+- /* reset only */
+- LOG_WARNING("%s: ran after reset and before halt ...",
+- target_name(target));
+- retval = target_halt(target);
+- if (retval != ERROR_OK)
+- return retval;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_checksum_memory(struct target *target,
+- target_addr_t address, uint32_t count, uint32_t *checksum)
+-{
+- LOG_WARNING("Not implemented: %s", __func__);
+-
+- return ERROR_FAIL;
+-}
+-
+-static int nds32_v2_add_breakpoint(struct target *target,
+- struct breakpoint *breakpoint)
+-{
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
+- struct nds32 *nds32 = &(nds32_v2->nds32);
+- int result;
+-
+- if (breakpoint->type == BKPT_HARD) {
+- /* check hardware resource */
+- if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
+- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
+- "breakpoints/watchpoints! The limit of "
+- "combined hardware breakpoints/watchpoints "
+- "is %" PRId32 ". -->", nds32_v2->n_hbr);
+- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+- }
+-
+- /* update next place to put hardware breakpoint */
+- nds32_v2->next_hbr_index++;
+-
+- /* hardware breakpoint insertion occurs before 'continue' actually */
+- return ERROR_OK;
+- } else if (breakpoint->type == BKPT_SOFT) {
+- result = nds32_add_software_breakpoint(target, breakpoint);
+- if (result != ERROR_OK) {
+- /* auto convert to hardware breakpoint if failed */
+- if (nds32->auto_convert_hw_bp) {
+- /* convert to hardware breakpoint */
+- breakpoint->type = BKPT_HARD;
+-
+- return nds32_v2_add_breakpoint(target, breakpoint);
+- }
+- }
+-
+- return result;
+- } else /* unrecognized breakpoint type */
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_remove_breakpoint(struct target *target,
+- struct breakpoint *breakpoint)
+-{
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
+-
+- if (breakpoint->type == BKPT_HARD) {
+- if (nds32_v2->next_hbr_index <= 0)
+- return ERROR_FAIL;
+-
+- /* update next place to put hardware breakpoint */
+- nds32_v2->next_hbr_index--;
+-
+- /* hardware breakpoint removal occurs after 'halted' actually */
+- return ERROR_OK;
+- } else if (breakpoint->type == BKPT_SOFT) {
+- return nds32_remove_software_breakpoint(target, breakpoint);
+- } else /* unrecognized breakpoint type */
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_add_watchpoint(struct target *target,
+- struct watchpoint *watchpoint)
+-{
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
+-
+- /* check hardware resource */
+- if (nds32_v2->n_hbr <= nds32_v2->next_hbr_index) {
+- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
+- "breakpoints/watchpoints! The limit of "
+- "combined hardware breakpoints/watchpoints is %" PRId32 ". -->", nds32_v2->n_hbr);
+- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+- }
+-
+- /* update next place to put hardware watchpoint */
+- nds32_v2->next_hbr_index++;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_remove_watchpoint(struct target *target,
+- struct watchpoint *watchpoint)
+-{
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
+-
+- if (nds32_v2->next_hbr_index <= 0)
+- return ERROR_FAIL;
+-
+- /* update next place to put hardware breakpoint */
+- nds32_v2->next_hbr_index--;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_get_exception_address(struct nds32 *nds32,
+- uint32_t *address, uint32_t reason)
+-{
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+-
+- aice_read_register(aice, IR4, address); /* read $EVA directly */
+-
+- /* TODO: hit multiple watchpoints */
+-
+- return ERROR_OK;
+-}
+-
+-/**
+- * find out which watchpoint hits
+- * get exception address and compare the address to watchpoints
+- */
+-static int nds32_v2_hit_watchpoint(struct target *target,
+- struct watchpoint **hit_watchpoint)
+-{
+- uint32_t exception_address;
+- struct watchpoint *wp;
+- static struct watchpoint scan_all_watchpoint;
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- scan_all_watchpoint.address = 0;
+- scan_all_watchpoint.rw = WPT_WRITE;
+- scan_all_watchpoint.next = 0;
+- scan_all_watchpoint.unique_id = 0x5CA8;
+-
+- exception_address = nds32->watched_address;
+-
+- if (exception_address == 0) {
+- /* send watch:0 to tell GDB to do software scan for hitting multiple watchpoints */
+- *hit_watchpoint = &scan_all_watchpoint;
+- return ERROR_OK;
+- }
+-
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+- if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
+- /* TODO: dispel false match */
+- *hit_watchpoint = wp;
+- return ERROR_OK;
+- }
+- }
+-
+- return ERROR_FAIL;
+-}
+-
+-static int nds32_v2_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,
+- int timeout_ms,
+- void *arch_info)
+-{
+- LOG_WARNING("Not implemented: %s", __func__);
+-
+- return ERROR_FAIL;
+-}
+-
+-static int nds32_v2_target_create(struct target *target, Jim_Interp *interp)
+-{
+- struct nds32_v2_common *nds32_v2;
+-
+- nds32_v2 = calloc(1, sizeof(*nds32_v2));
+- if (!nds32_v2)
+- return ERROR_FAIL;
+-
+- nds32_v2->nds32.register_map = nds32_v2_register_mapping;
+- nds32_v2->nds32.get_debug_reason = nds32_v2_get_debug_reason;
+- nds32_v2->nds32.enter_debug_state = nds32_v2_debug_entry;
+- nds32_v2->nds32.leave_debug_state = nds32_v2_leave_debug_state;
+- nds32_v2->nds32.get_watched_address = nds32_v2_get_exception_address;
+-
+- nds32_init_arch_info(target, &(nds32_v2->nds32));
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_init_target(struct command_context *cmd_ctx,
+- struct target *target)
+-{
+- /* Initialize anything we can set up without talking to the target */
+-
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- nds32_init(nds32);
+-
+- return ERROR_OK;
+-}
+-
+-/* talk to the target and set things up */
+-static int nds32_v2_examine(struct target *target)
+-{
+- struct nds32_v2_common *nds32_v2 = target_to_nds32_v2(target);
+- struct nds32 *nds32 = &(nds32_v2->nds32);
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- if (!target_was_examined(target)) {
+- CHECK_RETVAL(nds32_edm_config(nds32));
+-
+- if (nds32->reset_halt_as_examine)
+- CHECK_RETVAL(nds32_reset_halt(nds32));
+- }
+-
+- uint32_t edm_cfg;
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
+-
+- /* get the number of hardware breakpoints */
+- nds32_v2->n_hbr = (edm_cfg & 0x7) + 1;
+-
+- nds32_v2->next_hbr_index = 0;
+-
+- LOG_INFO("%s: total hardware breakpoint %" PRId32, target_name(target),
+- nds32_v2->n_hbr);
+-
+- nds32->target->state = TARGET_RUNNING;
+- nds32->target->debug_reason = DBG_REASON_NOTHALTED;
+-
+- target_set_examined(target);
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_translate_address(struct target *target, target_addr_t *address)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+- target_addr_t physical_address;
+-
+- /* Following conditions need to do address translation
+- * 1. BUS mode
+- * 2. CPU mode under maximum interrupt level */
+- if ((memory->access_channel == NDS_MEMORY_ACC_BUS) ||
+- ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- nds32_reach_max_interrupt_level(nds32))) {
+- if (target->type->virt2phys(target, *address, &physical_address) == ERROR_OK)
+- *address = physical_address;
+- else
+- return ERROR_FAIL;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v2_read_buffer(struct target *target, target_addr_t address,
+- uint32_t size, uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- /* BUG: If access range crosses multiple pages, the translation will not correct
+- * for second page or so. */
+-
+- nds32_v2_translate_address(target, &address);
+-
+- return nds32_read_buffer(target, address, size, buffer);
+-}
+-
+-static int nds32_v2_write_buffer(struct target *target, target_addr_t address,
+- uint32_t size, const uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- /* BUG: If access range crosses multiple pages, the translation will not correct
+- * for second page or so. */
+-
+- nds32_v2_translate_address(target, &address);
+-
+- return nds32_write_buffer(target, address, size, buffer);
+-}
+-
+-static int nds32_v2_read_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- /* BUG: If access range crosses multiple pages, the translation will not correct
+- * for second page or so. */
+-
+- nds32_v2_translate_address(target, &address);
+-
+- return nds32_read_memory(target, address, size, count, buffer);
+-}
+-
+-static int nds32_v2_write_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, const uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- /* BUG: If access range crosses multiple pages, the translation will not correct
+- * for second page or so. */
+-
+- nds32_v2_translate_address(target, &address);
+-
+- return nds32_write_memory(target, address, size, count, buffer);
+-}
+-
+-/** Holds methods for V2 targets. */
+-struct target_type nds32_v2_target = {
+- .name = "nds32_v2",
+-
+- .poll = nds32_poll,
+- .arch_state = nds32_arch_state,
+-
+- .target_request_data = nds32_v2_target_request_data,
+-
+- .halt = nds32_halt,
+- .resume = nds32_resume,
+- .step = nds32_step,
+-
+- .assert_reset = nds32_assert_reset,
+- .deassert_reset = nds32_v2_deassert_reset,
+-
+- /* register access */
+- .get_gdb_reg_list = nds32_get_gdb_reg_list,
+-
+- /* memory access */
+- .read_buffer = nds32_v2_read_buffer,
+- .write_buffer = nds32_v2_write_buffer,
+- .read_memory = nds32_v2_read_memory,
+- .write_memory = nds32_v2_write_memory,
+-
+- .checksum_memory = nds32_v2_checksum_memory,
+-
+- /* breakpoint/watchpoint */
+- .add_breakpoint = nds32_v2_add_breakpoint,
+- .remove_breakpoint = nds32_v2_remove_breakpoint,
+- .add_watchpoint = nds32_v2_add_watchpoint,
+- .remove_watchpoint = nds32_v2_remove_watchpoint,
+- .hit_watchpoint = nds32_v2_hit_watchpoint,
+-
+- /* MMU */
+- .mmu = nds32_mmu,
+- .virt2phys = nds32_virtual_to_physical,
+- .read_phys_memory = nds32_read_phys_memory,
+- .write_phys_memory = nds32_write_phys_memory,
+-
+- .run_algorithm = nds32_v2_run_algorithm,
+-
+- .commands = nds32_command_handlers,
+- .target_create = nds32_v2_target_create,
+- .init_target = nds32_v2_init_target,
+- .examine = nds32_v2_examine,
+-};
+diff --git a/src/target/nds32_v2.h b/src/target/nds32_v2.h
+deleted file mode 100644
+index 3c3010869..000000000
+--- a/src/target/nds32_v2.h
++++ /dev/null
+@@ -1,31 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_V2_H
+-#define OPENOCD_TARGET_NDS32_V2_H
+-
+-#include "nds32.h"
+-
+-struct nds32_v2_common {
+- struct nds32 nds32;
+-
+- uint32_t backup_ir0;
+-
+- /** number of hardware breakpoints */
+- int32_t n_hbr;
+-
+- /** next hardware breakpoint index */
+- /** increase from low index to high index */
+- int32_t next_hbr_index;
+-};
+-
+-static inline struct nds32_v2_common *target_to_nds32_v2(struct target *target)
+-{
+- return container_of(target->arch_info, struct nds32_v2_common, nds32);
+-}
+-
+-#endif /* OPENOCD_TARGET_NDS32_V2_H */
+diff --git a/src/target/nds32_v3.c b/src/target/nds32_v3.c
+deleted file mode 100644
+index 9d02e5ac9..000000000
+--- a/src/target/nds32_v3.c
++++ /dev/null
+@@ -1,510 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include "breakpoints.h"
+-#include "nds32_cmd.h"
+-#include "nds32_aice.h"
+-#include "nds32_v3.h"
+-#include "nds32_v3_common.h"
+-
+-static int nds32_v3_activate_hardware_breakpoint(struct target *target)
+-{
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct breakpoint *bp;
+- int32_t hbr_index = nds32_v3->next_hbr_index;
+-
+- for (bp = target->breakpoints; bp; bp = bp->next) {
+- if (bp->type == BKPT_SOFT) {
+- /* already set at nds32_v3_add_breakpoint() */
+- continue;
+- } else if (bp->type == BKPT_HARD) {
+- hbr_index--;
+- /* set address */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + hbr_index, bp->address);
+- /* set mask */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + hbr_index, 0);
+- /* set value */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + hbr_index, 0);
+-
+- if (nds32_v3->nds32.memory.address_translation)
+- /* enable breakpoint (virtual address) */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x2);
+- else
+- /* enable breakpoint (physical address) */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA);
+-
+- LOG_DEBUG("Add hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index,
+- bp->address);
+- } else {
+- return ERROR_FAIL;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_deactivate_hardware_breakpoint(struct target *target)
+-{
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct breakpoint *bp;
+- int32_t hbr_index = nds32_v3->next_hbr_index;
+-
+- for (bp = target->breakpoints; bp; bp = bp->next) {
+- if (bp->type == BKPT_SOFT) {
+- continue;
+- } else if (bp->type == BKPT_HARD) {
+- hbr_index--;
+- /* disable breakpoint */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0x0);
+- } else {
+- return ERROR_FAIL;
+- }
+-
+- LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index,
+- bp->address);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_activate_hardware_watchpoint(struct target *target)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+- struct watchpoint *wp;
+- int32_t wp_num = 0;
+- uint32_t wp_config = 0;
+- bool ld_stop, st_stop;
+-
+- if (nds32_v3->nds32.global_stop)
+- ld_stop = st_stop = false;
+-
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+-
+- if (wp_num < nds32_v3->used_n_wp) {
+- wp->mask = wp->length - 1;
+- if ((wp->address % wp->length) != 0)
+- wp->mask = (wp->mask << 1) + 1;
+-
+- if (wp->rw == WPT_READ)
+- wp_config = 0x3;
+- else if (wp->rw == WPT_WRITE)
+- wp_config = 0x5;
+- else if (wp->rw == WPT_ACCESS)
+- wp_config = 0x7;
+-
+- /* set/unset physical address bit of BPCn according to PSW.DT */
+- if (nds32_v3->nds32.memory.address_translation == false)
+- wp_config |= 0x8;
+-
+- /* set address */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
+- wp->address - (wp->address % wp->length));
+- /* set mask */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
+- /* enable watchpoint */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
+- /* set value */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0);
+-
+- LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32,
+- wp_num, wp->address, wp->mask);
+-
+- wp_num++;
+- } else if (nds32_v3->nds32.global_stop) {
+- if (wp->rw == WPT_READ)
+- ld_stop = true;
+- else if (wp->rw == WPT_WRITE)
+- st_stop = true;
+- else if (wp->rw == WPT_ACCESS)
+- ld_stop = st_stop = true;
+- }
+- }
+-
+- if (nds32_v3->nds32.global_stop) {
+- uint32_t edm_ctl;
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
+- if (ld_stop)
+- edm_ctl |= 0x10;
+- if (st_stop)
+- edm_ctl |= 0x20;
+- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_deactivate_hardware_watchpoint(struct target *target)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+- int32_t wp_num = 0;
+- struct watchpoint *wp;
+- bool clean_global_stop = false;
+-
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+-
+- if (wp_num < nds32_v3->used_n_wp) {
+- /* disable watchpoint */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
+-
+- LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR
+- " mask %08" PRIx32, wp_num,
+- wp->address, wp->mask);
+- wp_num++;
+- } else if (nds32_v3->nds32.global_stop) {
+- clean_global_stop = true;
+- }
+- }
+-
+- if (clean_global_stop) {
+- uint32_t edm_ctl;
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
+- edm_ctl = edm_ctl & (~0x30);
+- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_check_interrupt_stack(struct nds32 *nds32)
+-{
+- uint32_t val_ir0;
+- uint32_t value;
+-
+- /* Save interrupt level */
+- nds32_get_mapped_reg(nds32, IR0, &val_ir0);
+- nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
+-
+- if (nds32_reach_max_interrupt_level(nds32))
+- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->",
+- nds32->current_interrupt_level);
+-
+- /* backup $ir4 & $ir6 to avoid suppressed exception overwrite */
+- nds32_get_mapped_reg(nds32, IR4, &value);
+- nds32_get_mapped_reg(nds32, IR6, &value);
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_restore_interrupt_stack(struct nds32 *nds32)
+-{
+- uint32_t value;
+-
+- /* get backup value from cache */
+- /* then set back to make the register dirty */
+- nds32_get_mapped_reg(nds32, IR0, &value);
+- nds32_set_mapped_reg(nds32, IR0, value);
+-
+- nds32_get_mapped_reg(nds32, IR4, &value);
+- nds32_set_mapped_reg(nds32, IR4, value);
+-
+- nds32_get_mapped_reg(nds32, IR6, &value);
+- nds32_set_mapped_reg(nds32, IR6, value);
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_deassert_reset(struct target *target)
+-{
+- int retval;
+- struct aice_port_s *aice = target_to_aice(target);
+- bool switch_to_v3_stack = false;
+- uint32_t value_edm_ctl;
+-
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &value_edm_ctl);
+- if (((value_edm_ctl >> 6) & 0x1) == 0) { /* reset to V2 EDM mode */
+- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, value_edm_ctl | (0x1 << 6));
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &value_edm_ctl);
+- if (((value_edm_ctl >> 6) & 0x1) == 1)
+- switch_to_v3_stack = true;
+- } else
+- switch_to_v3_stack = false;
+-
+- CHECK_RETVAL(nds32_poll(target));
+-
+- if (target->state != TARGET_HALTED) {
+- /* reset only */
+- LOG_WARNING("%s: ran after reset and before halt ...",
+- target_name(target));
+- retval = target_halt(target);
+- if (retval != ERROR_OK)
+- return retval;
+-
+- } else {
+- /* reset-halt */
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+- struct nds32 *nds32 = &(nds32_v3->nds32);
+- uint32_t value;
+- uint32_t interrupt_level;
+-
+- if (switch_to_v3_stack == true) {
+- /* PSW.INTL-- */
+- nds32_get_mapped_reg(nds32, IR0, &value);
+- interrupt_level = (value >> 1) & 0x3;
+- interrupt_level--;
+- value &= ~(0x6);
+- value |= (interrupt_level << 1);
+- value |= 0x400; /* set PSW.DEX */
+- nds32_set_mapped_reg(nds32, IR0, value);
+-
+- /* copy IPC to OIPC */
+- if ((interrupt_level + 1) < nds32->max_interrupt_level) {
+- nds32_get_mapped_reg(nds32, IR9, &value);
+- nds32_set_mapped_reg(nds32, IR11, value);
+- }
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_add_breakpoint(struct target *target,
+- struct breakpoint *breakpoint)
+-{
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+- struct nds32 *nds32 = &(nds32_v3->nds32);
+- int result;
+-
+- if (breakpoint->type == BKPT_HARD) {
+- /* check hardware resource */
+- if (nds32_v3->n_hbr <= nds32_v3->next_hbr_index) {
+- LOG_WARNING("<-- TARGET WARNING! Insert too many "
+- "hardware breakpoints/watchpoints! "
+- "The limit of combined hardware "
+- "breakpoints/watchpoints is %" PRId32 ". -->",
+- nds32_v3->n_hbr);
+- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
+- "hardware breakpoint: %" PRId32 ", hardware "
+- "watchpoints: %" PRId32 ". -->",
+- nds32_v3->next_hbr_index - nds32_v3->used_n_wp,
+- nds32_v3->used_n_wp);
+- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+- }
+-
+- /* update next place to put hardware breakpoint */
+- nds32_v3->next_hbr_index++;
+-
+- /* hardware breakpoint insertion occurs before 'continue' actually */
+- return ERROR_OK;
+- } else if (breakpoint->type == BKPT_SOFT) {
+- result = nds32_add_software_breakpoint(target, breakpoint);
+- if (result != ERROR_OK) {
+- /* auto convert to hardware breakpoint if failed */
+- if (nds32->auto_convert_hw_bp) {
+- /* convert to hardware breakpoint */
+- breakpoint->type = BKPT_HARD;
+-
+- return nds32_v3_add_breakpoint(target, breakpoint);
+- }
+- }
+-
+- return result;
+- } else /* unrecognized breakpoint type */
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_remove_breakpoint(struct target *target,
+- struct breakpoint *breakpoint)
+-{
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+-
+- if (breakpoint->type == BKPT_HARD) {
+- if (nds32_v3->next_hbr_index <= 0)
+- return ERROR_FAIL;
+-
+- /* update next place to put hardware breakpoint */
+- nds32_v3->next_hbr_index--;
+-
+- /* hardware breakpoint removal occurs after 'halted' actually */
+- return ERROR_OK;
+- } else if (breakpoint->type == BKPT_SOFT) {
+- return nds32_remove_software_breakpoint(target, breakpoint);
+- } else /* unrecognized breakpoint type */
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_add_watchpoint(struct target *target,
+- struct watchpoint *watchpoint)
+-{
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+-
+- /* check hardware resource */
+- if (nds32_v3->n_hbr <= nds32_v3->next_hbr_index) {
+- /* No hardware resource */
+- if (nds32_v3->nds32.global_stop) {
+- LOG_WARNING("<-- TARGET WARNING! The number of "
+- "watchpoints exceeds the hardware "
+- "resources. Stop at every load/store "
+- "instruction to check for watchpoint matches. -->");
+- return ERROR_OK;
+- }
+-
+- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
+- "breakpoints/watchpoints! The limit of combined "
+- "hardware breakpoints/watchpoints is %" PRId32 ". -->",
+- nds32_v3->n_hbr);
+- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
+- "hardware breakpoint: %" PRId32 ", hardware "
+- "watchpoints: %" PRId32 ". -->",
+- nds32_v3->next_hbr_index - nds32_v3->used_n_wp,
+- nds32_v3->used_n_wp);
+-
+- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+- }
+-
+- /* update next place to put hardware watchpoint */
+- nds32_v3->next_hbr_index++;
+- nds32_v3->used_n_wp++;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_remove_watchpoint(struct target *target,
+- struct watchpoint *watchpoint)
+-{
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+-
+- if (nds32_v3->next_hbr_index <= 0) {
+- if (nds32_v3->nds32.global_stop)
+- return ERROR_OK;
+-
+- return ERROR_FAIL;
+- }
+-
+- /* update next place to put hardware breakpoint */
+- nds32_v3->next_hbr_index--;
+- nds32_v3->used_n_wp--;
+-
+- return ERROR_OK;
+-}
+-
+-static struct nds32_v3_common_callback nds32_v3_common_callback = {
+- .check_interrupt_stack = nds32_v3_check_interrupt_stack,
+- .restore_interrupt_stack = nds32_v3_restore_interrupt_stack,
+- .activate_hardware_breakpoint = nds32_v3_activate_hardware_breakpoint,
+- .activate_hardware_watchpoint = nds32_v3_activate_hardware_watchpoint,
+- .deactivate_hardware_breakpoint = nds32_v3_deactivate_hardware_breakpoint,
+- .deactivate_hardware_watchpoint = nds32_v3_deactivate_hardware_watchpoint,
+-};
+-
+-static int nds32_v3_target_create(struct target *target, Jim_Interp *interp)
+-{
+- struct nds32_v3_common *nds32_v3;
+-
+- nds32_v3 = calloc(1, sizeof(*nds32_v3));
+- if (!nds32_v3)
+- return ERROR_FAIL;
+-
+- nds32_v3_common_register_callback(&nds32_v3_common_callback);
+- nds32_v3_target_create_common(target, &(nds32_v3->nds32));
+-
+- return ERROR_OK;
+-}
+-
+-/* talk to the target and set things up */
+-static int nds32_v3_examine(struct target *target)
+-{
+- struct nds32_v3_common *nds32_v3 = target_to_nds32_v3(target);
+- struct nds32 *nds32 = &(nds32_v3->nds32);
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- if (!target_was_examined(target)) {
+- CHECK_RETVAL(nds32_edm_config(nds32));
+-
+- if (nds32->reset_halt_as_examine)
+- CHECK_RETVAL(nds32_reset_halt(nds32));
+- }
+-
+- uint32_t edm_cfg;
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
+-
+- /* get the number of hardware breakpoints */
+- nds32_v3->n_hbr = (edm_cfg & 0x7) + 1;
+-
+- /* low interference profiling */
+- if (edm_cfg & 0x100)
+- nds32_v3->low_interference_profile = true;
+- else
+- nds32_v3->low_interference_profile = false;
+-
+- nds32_v3->next_hbr_index = 0;
+- nds32_v3->used_n_wp = 0;
+-
+- LOG_INFO("%s: total hardware breakpoint %" PRId32, target_name(target),
+- nds32_v3->n_hbr);
+-
+- nds32->target->state = TARGET_RUNNING;
+- nds32->target->debug_reason = DBG_REASON_NOTHALTED;
+-
+- target_set_examined(target);
+-
+- return ERROR_OK;
+-}
+-
+-/** Holds methods for Andes1337 targets. */
+-struct target_type nds32_v3_target = {
+- .name = "nds32_v3",
+-
+- .poll = nds32_poll,
+- .arch_state = nds32_arch_state,
+-
+- .target_request_data = nds32_v3_target_request_data,
+-
+- .halt = nds32_halt,
+- .resume = nds32_resume,
+- .step = nds32_step,
+-
+- .assert_reset = nds32_assert_reset,
+- .deassert_reset = nds32_v3_deassert_reset,
+-
+- /* register access */
+- .get_gdb_reg_list = nds32_get_gdb_reg_list,
+-
+- /* memory access */
+- .read_buffer = nds32_v3_read_buffer,
+- .write_buffer = nds32_v3_write_buffer,
+- .read_memory = nds32_v3_read_memory,
+- .write_memory = nds32_v3_write_memory,
+-
+- .checksum_memory = nds32_v3_checksum_memory,
+-
+- /* breakpoint/watchpoint */
+- .add_breakpoint = nds32_v3_add_breakpoint,
+- .remove_breakpoint = nds32_v3_remove_breakpoint,
+- .add_watchpoint = nds32_v3_add_watchpoint,
+- .remove_watchpoint = nds32_v3_remove_watchpoint,
+- .hit_watchpoint = nds32_v3_hit_watchpoint,
+-
+- /* MMU */
+- .mmu = nds32_mmu,
+- .virt2phys = nds32_virtual_to_physical,
+- .read_phys_memory = nds32_read_phys_memory,
+- .write_phys_memory = nds32_write_phys_memory,
+-
+- .run_algorithm = nds32_v3_run_algorithm,
+-
+- .commands = nds32_command_handlers,
+- .target_create = nds32_v3_target_create,
+- .init_target = nds32_v3_init_target,
+- .examine = nds32_v3_examine,
+-
+- .get_gdb_fileio_info = nds32_get_gdb_fileio_info,
+- .gdb_fileio_end = nds32_gdb_fileio_end,
+-
+- .profiling = nds32_profiling,
+-};
+diff --git a/src/target/nds32_v3.h b/src/target/nds32_v3.h
+deleted file mode 100644
+index 389838d8f..000000000
+--- a/src/target/nds32_v3.h
++++ /dev/null
+@@ -1,34 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_V3_H
+-#define OPENOCD_TARGET_NDS32_V3_H
+-
+-#include "nds32.h"
+-
+-struct nds32_v3_common {
+- struct nds32 nds32;
+-
+- /** number of hardware breakpoints */
+- int32_t n_hbr;
+-
+- /** number of used hardware watchpoints */
+- int32_t used_n_wp;
+-
+- /** next hardware breakpoint index */
+- int32_t next_hbr_index;
+-
+- /** low interference profiling */
+- bool low_interference_profile;
+-};
+-
+-static inline struct nds32_v3_common *target_to_nds32_v3(struct target *target)
+-{
+- return container_of(target->arch_info, struct nds32_v3_common, nds32);
+-}
+-
+-#endif /* OPENOCD_TARGET_NDS32_V3_H */
+diff --git a/src/target/nds32_v3_common.c b/src/target/nds32_v3_common.c
+deleted file mode 100644
+index f2efab441..000000000
+--- a/src/target/nds32_v3_common.c
++++ /dev/null
+@@ -1,664 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include "breakpoints.h"
+-#include "nds32_reg.h"
+-#include "nds32_disassembler.h"
+-#include "nds32.h"
+-#include "nds32_aice.h"
+-#include "nds32_v3_common.h"
+-
+-static struct nds32_v3_common_callback *v3_common_callback;
+-
+-static int nds32_v3_register_mapping(struct nds32 *nds32, int reg_no)
+-{
+- if (reg_no == PC)
+- return IR11;
+-
+- return reg_no;
+-}
+-
+-static int nds32_v3_get_debug_reason(struct nds32 *nds32, uint32_t *reason)
+-{
+- uint32_t edmsw;
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &edmsw);
+-
+- *reason = (edmsw >> 12) & 0x0F;
+-
+- return ERROR_OK;
+-}
+-
+-/**
+- * Save processor state. This is called after a HALT instruction
+- * succeeds, and on other occasions the processor enters debug mode
+- * (breakpoint, watchpoint, etc).
+- */
+-static int nds32_v3_debug_entry(struct nds32 *nds32, bool enable_watchpoint)
+-{
+- LOG_DEBUG("nds32_v3_debug_entry");
+-
+- enum target_state backup_state = nds32->target->state;
+- nds32->target->state = TARGET_HALTED;
+-
+- if (nds32->init_arch_info_after_halted == false) {
+- /* init architecture info according to config registers */
+- CHECK_RETVAL(nds32_config(nds32));
+-
+- nds32->init_arch_info_after_halted = true;
+- }
+-
+- /* REVISIT entire cache should already be invalid !!! */
+- register_cache_invalidate(nds32->core_cache);
+-
+- /* deactivate all hardware breakpoints */
+- CHECK_RETVAL(v3_common_callback->deactivate_hardware_breakpoint(nds32->target));
+-
+- if (enable_watchpoint)
+- CHECK_RETVAL(v3_common_callback->deactivate_hardware_watchpoint(nds32->target));
+-
+- struct breakpoint *syscall_break = &(nds32->syscall_break);
+- if (nds32->virtual_hosting) {
+- if (syscall_break->is_set) {
+- /** disable virtual hosting */
+-
+- /* remove breakpoint at syscall entry */
+- target_remove_breakpoint(nds32->target, syscall_break);
+- syscall_break->is_set = false;
+-
+- uint32_t value_pc;
+- nds32_get_mapped_reg(nds32, PC, &value_pc);
+- if (value_pc == syscall_break->address)
+- /** process syscall for virtual hosting */
+- nds32->hit_syscall = true;
+- }
+- }
+-
+- if (nds32_examine_debug_reason(nds32) != ERROR_OK) {
+- nds32->target->state = backup_state;
+-
+- /* re-activate all hardware breakpoints & watchpoints */
+- CHECK_RETVAL(v3_common_callback->activate_hardware_breakpoint(nds32->target));
+-
+- if (enable_watchpoint)
+- CHECK_RETVAL(v3_common_callback->activate_hardware_watchpoint(nds32->target));
+-
+- return ERROR_FAIL;
+- }
+-
+- /* Save registers. */
+- nds32_full_context(nds32);
+-
+- /* check interrupt level */
+- v3_common_callback->check_interrupt_stack(nds32);
+-
+- return ERROR_OK;
+-}
+-
+-/**
+- * Restore processor state.
+- */
+-static int nds32_v3_leave_debug_state(struct nds32 *nds32, bool enable_watchpoint)
+-{
+- LOG_DEBUG("nds32_v3_leave_debug_state");
+-
+- struct target *target = nds32->target;
+-
+- /* activate all hardware breakpoints */
+- CHECK_RETVAL(v3_common_callback->activate_hardware_breakpoint(target));
+-
+- if (enable_watchpoint) {
+- /* activate all watchpoints */
+- CHECK_RETVAL(v3_common_callback->activate_hardware_watchpoint(target));
+- }
+-
+- /* restore interrupt stack */
+- v3_common_callback->restore_interrupt_stack(nds32);
+-
+- /* REVISIT once we start caring about MMU and cache state,
+- * address it here ...
+- */
+-
+- /* restore PSW, PC, and R0 ... after flushing any modified
+- * registers.
+- */
+- CHECK_RETVAL(nds32_restore_context(target));
+-
+- if (nds32->virtual_hosting) {
+- /** enable virtual hosting */
+- uint32_t value_ir3;
+- uint32_t entry_size;
+- uint32_t syscall_address;
+-
+- /* get syscall entry address */
+- nds32_get_mapped_reg(nds32, IR3, &value_ir3);
+- entry_size = 0x4 << (((value_ir3 >> 14) & 0x3) << 1);
+- syscall_address = (value_ir3 & 0xFFFF0000) + entry_size * 8; /* The index of SYSCALL is 8 */
+-
+- if (nds32->hit_syscall) {
+- /* single step to skip syscall entry */
+- /* use IRET to skip syscall */
+- struct aice_port_s *aice = target_to_aice(target);
+- uint32_t value_ir9;
+- uint32_t value_ir6;
+- uint32_t syscall_id;
+-
+- nds32_get_mapped_reg(nds32, IR6, &value_ir6);
+- syscall_id = (value_ir6 >> 16) & 0x7FFF;
+-
+- if (syscall_id == NDS32_SYSCALL_EXIT) {
+- /* If target hits exit syscall, do not use IRET to skip handler. */
+- aice_step(aice);
+- } else {
+- /* use api->read/write_reg to skip nds32 register cache */
+- uint32_t value_dimbr;
+- aice_read_debug_reg(aice, NDS_EDM_SR_DIMBR, &value_dimbr);
+- aice_write_register(aice, IR11, value_dimbr + 0xC);
+-
+- aice_read_register(aice, IR9, &value_ir9);
+- value_ir9 += 4; /* syscall is always 4 bytes */
+- aice_write_register(aice, IR9, value_ir9);
+-
+- /* backup hardware breakpoint 0 */
+- uint32_t backup_bpa, backup_bpam, backup_bpc;
+- aice_read_debug_reg(aice, NDS_EDM_SR_BPA0, &backup_bpa);
+- aice_read_debug_reg(aice, NDS_EDM_SR_BPAM0, &backup_bpam);
+- aice_read_debug_reg(aice, NDS_EDM_SR_BPC0, &backup_bpc);
+-
+- /* use hardware breakpoint 0 to stop cpu after skipping syscall */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, value_ir9);
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, 0);
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, 0xA);
+-
+- /* Execute two IRET.
+- * First IRET is used to quit debug mode.
+- * Second IRET is used to quit current syscall. */
+- uint32_t dim_inst[4] = {NOP, NOP, IRET, IRET};
+- aice_execute(aice, dim_inst, 4);
+-
+- /* restore origin hardware breakpoint 0 */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0, backup_bpa);
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0, backup_bpam);
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0, backup_bpc);
+- }
+-
+- nds32->hit_syscall = false;
+- }
+-
+- /* insert breakpoint at syscall entry */
+- struct breakpoint *syscall_break = &(nds32->syscall_break);
+-
+- syscall_break->address = syscall_address;
+- syscall_break->type = BKPT_SOFT;
+- syscall_break->is_set = true;
+- target_add_breakpoint(target, syscall_break);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3_get_exception_address(struct nds32 *nds32,
+- uint32_t *address, uint32_t reason)
+-{
+- LOG_DEBUG("nds32_v3_get_exception_address");
+-
+- struct aice_port_s *aice = target_to_aice(nds32->target);
+- struct target *target = nds32->target;
+- uint32_t edmsw;
+- uint32_t edm_cfg;
+- uint32_t match_bits;
+- uint32_t match_count;
+- int32_t i;
+- static int32_t number_of_hard_break;
+- uint32_t bp_control;
+-
+- if (number_of_hard_break == 0) {
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
+- number_of_hard_break = (edm_cfg & 0x7) + 1;
+- }
+-
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &edmsw);
+- /* clear matching bits (write-one-clear) */
+- aice_write_debug_reg(aice, NDS_EDM_SR_EDMSW, edmsw);
+- match_bits = (edmsw >> 4) & 0xFF;
+- match_count = 0;
+- for (i = 0 ; i < number_of_hard_break ; i++) {
+- if (match_bits & (1 << i)) {
+- aice_read_debug_reg(aice, NDS_EDM_SR_BPA0 + i, address);
+- match_count++;
+-
+- /* If target hits multiple read/access watchpoint,
+- * select the first one. */
+- aice_read_debug_reg(aice, NDS_EDM_SR_BPC0 + i, &bp_control);
+- if (0x3 == (bp_control & 0x3)) {
+- match_count = 1;
+- break;
+- }
+- }
+- }
+-
+- if (match_count > 1) { /* multiple hits */
+- *address = 0;
+- return ERROR_OK;
+- } else if (match_count == 1) {
+- uint32_t val_pc;
+- uint32_t opcode;
+- struct nds32_instruction instruction;
+- struct watchpoint *wp;
+- bool hit;
+-
+- nds32_get_mapped_reg(nds32, PC, &val_pc);
+-
+- if ((reason == NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE) ||
+- (reason == NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE)) {
+- if (edmsw & 0x4) /* check EDMSW.IS_16BIT */
+- val_pc -= 2;
+- else
+- val_pc -= 4;
+- }
+-
+- nds32_read_opcode(nds32, val_pc, &opcode);
+- nds32_evaluate_opcode(nds32, opcode, val_pc, &instruction);
+-
+- LOG_DEBUG("PC: 0x%08" PRIx32 ", access start: 0x%08" PRIx32 ", end: 0x%08" PRIx32,
+- val_pc, instruction.access_start, instruction.access_end);
+-
+- /* check if multiple hits in the access range */
+- uint32_t in_range_watch_count = 0;
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+- if ((instruction.access_start <= wp->address) &&
+- (wp->address < instruction.access_end))
+- in_range_watch_count++;
+- }
+- if (in_range_watch_count > 1) {
+- /* Hit LSMW instruction. */
+- *address = 0;
+- return ERROR_OK;
+- }
+-
+- /* dispel false match */
+- hit = false;
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+- if (((*address ^ wp->address) & (~wp->mask)) == 0) {
+- uint32_t watch_start;
+- uint32_t watch_end;
+-
+- watch_start = wp->address;
+- watch_end = wp->address + wp->length;
+-
+- if ((watch_end <= instruction.access_start) ||
+- (instruction.access_end <= watch_start))
+- continue;
+-
+- hit = true;
+- break;
+- }
+- }
+-
+- if (hit)
+- return ERROR_OK;
+- else
+- return ERROR_FAIL;
+- } else if (match_count == 0) {
+- /* global stop is precise exception */
+- if ((reason == NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP) && nds32->global_stop) {
+- /* parse instruction to get correct access address */
+- uint32_t val_pc;
+- uint32_t opcode;
+- struct nds32_instruction instruction;
+-
+- nds32_get_mapped_reg(nds32, PC, &val_pc);
+- nds32_read_opcode(nds32, val_pc, &opcode);
+- nds32_evaluate_opcode(nds32, opcode, val_pc, &instruction);
+-
+- *address = instruction.access_start;
+-
+- return ERROR_OK;
+- }
+- }
+-
+- *address = 0xFFFFFFFF;
+- return ERROR_FAIL;
+-}
+-
+-void nds32_v3_common_register_callback(struct nds32_v3_common_callback *callback)
+-{
+- v3_common_callback = callback;
+-}
+-
+-/** target_type functions: */
+-/* target request support */
+-int nds32_v3_target_request_data(struct target *target,
+- uint32_t size, uint8_t *buffer)
+-{
+- /* AndesCore could use DTR register to communicate with OpenOCD
+- * to output messages
+- * Target data will be put in buffer
+- * The format of DTR is as follow
+- * DTR[31:16] => length, DTR[15:8] => size, DTR[7:0] => target_req_cmd
+- * target_req_cmd has three possible values:
+- * TARGET_REQ_TRACEMSG
+- * TARGET_REQ_DEBUGMSG
+- * TARGET_REQ_DEBUGCHAR
+- * if size == 0, target will call target_asciimsg(),
+- * else call target_hexmsg()
+- */
+- LOG_WARNING("Not implemented: %s", __func__);
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_v3_checksum_memory(struct target *target,
+- target_addr_t address, uint32_t count, uint32_t *checksum)
+-{
+- LOG_WARNING("Not implemented: %s", __func__);
+-
+- return ERROR_FAIL;
+-}
+-
+-/**
+- * find out which watchpoint hits
+- * get exception address and compare the address to watchpoints
+- */
+-int nds32_v3_hit_watchpoint(struct target *target,
+- struct watchpoint **hit_watchpoint)
+-{
+- static struct watchpoint scan_all_watchpoint;
+-
+- uint32_t exception_address;
+- struct watchpoint *wp;
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- exception_address = nds32->watched_address;
+-
+- if (exception_address == 0xFFFFFFFF)
+- return ERROR_FAIL;
+-
+- if (exception_address == 0) {
+- scan_all_watchpoint.address = 0;
+- scan_all_watchpoint.rw = WPT_WRITE;
+- scan_all_watchpoint.next = 0;
+- scan_all_watchpoint.unique_id = 0x5CA8;
+-
+- *hit_watchpoint = &scan_all_watchpoint;
+- return ERROR_OK;
+- }
+-
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+- if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
+- *hit_watchpoint = wp;
+-
+- return ERROR_OK;
+- }
+- }
+-
+- return ERROR_FAIL;
+-}
+-
+-int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32)
+-{
+- nds32->register_map = nds32_v3_register_mapping;
+- nds32->get_debug_reason = nds32_v3_get_debug_reason;
+- nds32->enter_debug_state = nds32_v3_debug_entry;
+- nds32->leave_debug_state = nds32_v3_leave_debug_state;
+- nds32->get_watched_address = nds32_v3_get_exception_address;
+-
+- /* Init target->arch_info in nds32_init_arch_info().
+- * After this, user could use target_to_nds32() to get nds32 object */
+- nds32_init_arch_info(target, nds32);
+-
+- return ERROR_OK;
+-}
+-
+-int nds32_v3_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,
+- int timeout_ms,
+- void *arch_info)
+-{
+- LOG_WARNING("Not implemented: %s", __func__);
+-
+- return ERROR_FAIL;
+-}
+-
+-int nds32_v3_read_buffer(struct target *target, target_addr_t address,
+- uint32_t size, uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- target_addr_t physical_address;
+- /* BUG: If access range crosses multiple pages, the translation will not correct
+- * for second page or so. */
+-
+- /* When DEX is set to one, hardware will enforce the following behavior without
+- * modifying the corresponding control bits in PSW.
+- *
+- * Disable all interrupts
+- * Become superuser mode
+- * Turn off IT/DT
+- * Use MMU_CFG.DE as the data access endian
+- * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
+- * Disable audio special features
+- * Disable inline function call
+- *
+- * Because hardware will turn off IT/DT by default, it MUST translate virtual address
+- * to physical address.
+- */
+- if (target->type->virt2phys(target, address, &physical_address) == ERROR_OK)
+- address = physical_address;
+- else
+- return ERROR_FAIL;
+-
+- int result;
+- struct aice_port_s *aice = target_to_aice(target);
+- /* give arbitrary initial value to avoid warning messages */
+- enum nds_memory_access origin_access_channel = NDS_MEMORY_ACC_CPU;
+-
+- if (nds32->hit_syscall) {
+- /* Use bus mode to access memory during virtual hosting */
+- origin_access_channel = memory->access_channel;
+- memory->access_channel = NDS_MEMORY_ACC_BUS;
+- aice_memory_access(aice, NDS_MEMORY_ACC_BUS);
+- }
+-
+- result = nds32_read_buffer(target, address, size, buffer);
+-
+- if (nds32->hit_syscall) {
+- /* Restore access_channel after virtual hosting */
+- memory->access_channel = origin_access_channel;
+- aice_memory_access(aice, origin_access_channel);
+- }
+-
+- return result;
+-}
+-
+-int nds32_v3_write_buffer(struct target *target, target_addr_t address,
+- uint32_t size, const uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- target_addr_t physical_address;
+- /* BUG: If access range crosses multiple pages, the translation will not correct
+- * for second page or so. */
+-
+- /* When DEX is set to one, hardware will enforce the following behavior without
+- * modifying the corresponding control bits in PSW.
+- *
+- * Disable all interrupts
+- * Become superuser mode
+- * Turn off IT/DT
+- * Use MMU_CFG.DE as the data access endian
+- * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
+- * Disable audio special features
+- * Disable inline function call
+- *
+- * Because hardware will turn off IT/DT by default, it MUST translate virtual address
+- * to physical address.
+- */
+- if (target->type->virt2phys(target, address, &physical_address) == ERROR_OK)
+- address = physical_address;
+- else
+- return ERROR_FAIL;
+-
+- if (nds32->hit_syscall) {
+- struct aice_port_s *aice = target_to_aice(target);
+- enum nds_memory_access origin_access_channel;
+- origin_access_channel = memory->access_channel;
+-
+- /* If target has no cache, use BUS mode to access memory. */
+- if ((memory->dcache.line_size == 0)
+- || (memory->dcache.enable == false)) {
+- /* There is no Dcache or Dcache is disabled. */
+- memory->access_channel = NDS_MEMORY_ACC_BUS;
+- aice_memory_access(aice, NDS_MEMORY_ACC_BUS);
+- }
+-
+- int result;
+- result = nds32_gdb_fileio_write_memory(nds32, address, size, buffer);
+-
+- if (origin_access_channel == NDS_MEMORY_ACC_CPU) {
+- memory->access_channel = NDS_MEMORY_ACC_CPU;
+- aice_memory_access(aice, NDS_MEMORY_ACC_CPU);
+- }
+-
+- return result;
+- }
+-
+- return nds32_write_buffer(target, address, size, buffer);
+-}
+-
+-int nds32_v3_read_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- target_addr_t physical_address;
+- /* BUG: If access range crosses multiple pages, the translation will not correct
+- * for second page or so. */
+-
+- /* When DEX is set to one, hardware will enforce the following behavior without
+- * modifying the corresponding control bits in PSW.
+- *
+- * Disable all interrupts
+- * Become superuser mode
+- * Turn off IT/DT
+- * Use MMU_CFG.DE as the data access endian
+- * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
+- * Disable audio special features
+- * Disable inline function call
+- *
+- * Because hardware will turn off IT/DT by default, it MUST translate virtual address
+- * to physical address.
+- */
+- if (target->type->virt2phys(target, address, &physical_address) == ERROR_OK)
+- address = physical_address;
+- else
+- return ERROR_FAIL;
+-
+- struct aice_port_s *aice = target_to_aice(target);
+- /* give arbitrary initial value to avoid warning messages */
+- enum nds_memory_access origin_access_channel = NDS_MEMORY_ACC_CPU;
+- int result;
+-
+- if (nds32->hit_syscall) {
+- /* Use bus mode to access memory during virtual hosting */
+- origin_access_channel = memory->access_channel;
+- memory->access_channel = NDS_MEMORY_ACC_BUS;
+- aice_memory_access(aice, NDS_MEMORY_ACC_BUS);
+- }
+-
+- result = nds32_read_memory(target, address, size, count, buffer);
+-
+- if (nds32->hit_syscall) {
+- /* Restore access_channel after virtual hosting */
+- memory->access_channel = origin_access_channel;
+- aice_memory_access(aice, origin_access_channel);
+- }
+-
+- return result;
+-}
+-
+-int nds32_v3_write_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, const uint8_t *buffer)
+-{
+- struct nds32 *nds32 = target_to_nds32(target);
+- struct nds32_memory *memory = &(nds32->memory);
+-
+- if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
+- (target->state != TARGET_HALTED)) {
+- LOG_WARNING("target was not halted");
+- return ERROR_TARGET_NOT_HALTED;
+- }
+-
+- target_addr_t physical_address;
+- /* BUG: If access range crosses multiple pages, the translation will not correct
+- * for second page or so. */
+-
+- /* When DEX is set to one, hardware will enforce the following behavior without
+- * modifying the corresponding control bits in PSW.
+- *
+- * Disable all interrupts
+- * Become superuser mode
+- * Turn off IT/DT
+- * Use MMU_CFG.DE as the data access endian
+- * Use MMU_CFG.DRDE as the device register access endian if MMU_CTL.DREE is asserted
+- * Disable audio special features
+- * Disable inline function call
+- *
+- * Because hardware will turn off IT/DT by default, it MUST translate virtual address
+- * to physical address.
+- */
+- if (target->type->virt2phys(target, address, &physical_address) == ERROR_OK)
+- address = physical_address;
+- else
+- return ERROR_FAIL;
+-
+- return nds32_write_memory(target, address, size, count, buffer);
+-}
+-
+-int nds32_v3_init_target(struct command_context *cmd_ctx,
+- struct target *target)
+-{
+- /* Initialize anything we can set up without talking to the target */
+- struct nds32 *nds32 = target_to_nds32(target);
+-
+- nds32_init(nds32);
+-
+- target->fileio_info = malloc(sizeof(struct gdb_fileio_info));
+- target->fileio_info->identifier = NULL;
+-
+- return ERROR_OK;
+-}
+diff --git a/src/target/nds32_v3_common.h b/src/target/nds32_v3_common.h
+deleted file mode 100644
+index a98988e5a..000000000
+--- a/src/target/nds32_v3_common.h
++++ /dev/null
+@@ -1,50 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_V3_COMMON_H
+-#define OPENOCD_TARGET_NDS32_V3_COMMON_H
+-
+-#include "target.h"
+-
+-struct nds32_v3_common_callback {
+- int (*check_interrupt_stack)(struct nds32 *nds32);
+- int (*restore_interrupt_stack)(struct nds32 *nds32);
+- int (*activate_hardware_breakpoint)(struct target *target);
+- int (*activate_hardware_watchpoint)(struct target *target);
+- int (*deactivate_hardware_breakpoint)(struct target *target);
+- int (*deactivate_hardware_watchpoint)(struct target *target);
+-};
+-
+-void nds32_v3_common_register_callback(struct nds32_v3_common_callback *callback);
+-int nds32_v3_target_request_data(struct target *target,
+- uint32_t size, uint8_t *buffer);
+-int nds32_v3_checksum_memory(struct target *target,
+- target_addr_t address, uint32_t count, uint32_t *checksum);
+-int nds32_v3_hit_watchpoint(struct target *target,
+- struct watchpoint **hit_watchpoint);
+-int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32);
+-int nds32_v3_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,
+- int timeout_ms,
+- void *arch_info);
+-int nds32_v3_read_buffer(struct target *target, target_addr_t address,
+- uint32_t size, uint8_t *buffer);
+-int nds32_v3_write_buffer(struct target *target, target_addr_t address,
+- uint32_t size, const uint8_t *buffer);
+-int nds32_v3_read_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, uint8_t *buffer);
+-int nds32_v3_write_memory(struct target *target, target_addr_t address,
+- uint32_t size, uint32_t count, const uint8_t *buffer);
+-int nds32_v3_init_target(struct command_context *cmd_ctx,
+- struct target *target);
+-
+-#endif /* OPENOCD_TARGET_NDS32_V3_COMMON_H */
+diff --git a/src/target/nds32_v3m.c b/src/target/nds32_v3m.c
+deleted file mode 100644
+index 6bc549f46..000000000
+--- a/src/target/nds32_v3m.c
++++ /dev/null
+@@ -1,495 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include "breakpoints.h"
+-#include "nds32_cmd.h"
+-#include "nds32_aice.h"
+-#include "nds32_v3m.h"
+-#include "nds32_v3_common.h"
+-
+-static int nds32_v3m_activate_hardware_breakpoint(struct target *target)
+-{
+- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct breakpoint *bp;
+- unsigned brp_num = nds32_v3m->n_hbr - 1;
+-
+- for (bp = target->breakpoints; bp; bp = bp->next) {
+- if (bp->type == BKPT_SOFT) {
+- /* already set at nds32_v3m_add_breakpoint() */
+- continue;
+- } else if (bp->type == BKPT_HARD) {
+- /* set address */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + brp_num, bp->address);
+- /* set mask */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + brp_num, 0);
+-
+- if (nds32_v3m->nds32.memory.address_translation)
+- /* enable breakpoint (virtual address) */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0x2);
+- else
+- /* enable breakpoint (physical address) */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0xA);
+-
+- LOG_DEBUG("Add hardware BP %u at %08" TARGET_PRIxADDR, brp_num,
+- bp->address);
+-
+- brp_num--;
+- } else {
+- return ERROR_FAIL;
+- }
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_deactivate_hardware_breakpoint(struct target *target)
+-{
+- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct breakpoint *bp;
+- unsigned brp_num = nds32_v3m->n_hbr - 1;
+-
+- for (bp = target->breakpoints; bp; bp = bp->next) {
+- if (bp->type == BKPT_SOFT)
+- continue;
+- else if (bp->type == BKPT_HARD)
+- /* disable breakpoint */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0x0);
+- else
+- return ERROR_FAIL;
+-
+- LOG_DEBUG("Remove hardware BP %u at %08" TARGET_PRIxADDR, brp_num,
+- bp->address);
+-
+- brp_num--;
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_activate_hardware_watchpoint(struct target *target)
+-{
+- struct aice_port_s *aice = target_to_aice(target);
+- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
+- struct watchpoint *wp;
+- int32_t wp_num = 0;
+- uint32_t wp_config = 0;
+- bool ld_stop, st_stop;
+-
+- if (nds32_v3m->nds32.global_stop)
+- ld_stop = st_stop = false;
+-
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+-
+- if (wp_num < nds32_v3m->used_n_wp) {
+- wp->mask = wp->length - 1;
+- if ((wp->address % wp->length) != 0)
+- wp->mask = (wp->mask << 1) + 1;
+-
+- if (wp->rw == WPT_READ)
+- wp_config = 0x3;
+- else if (wp->rw == WPT_WRITE)
+- wp_config = 0x5;
+- else if (wp->rw == WPT_ACCESS)
+- wp_config = 0x7;
+-
+- /* set/unset physical address bit of BPCn according to PSW.DT */
+- if (nds32_v3m->nds32.memory.address_translation == false)
+- wp_config |= 0x8;
+-
+- /* set address */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPA0 + wp_num,
+- wp->address - (wp->address % wp->length));
+- /* set mask */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPAM0 + wp_num, wp->mask);
+- /* enable watchpoint */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config);
+-
+- LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR
+- " mask %08" PRIx32, wp_num, wp->address, wp->mask);
+-
+- wp_num++;
+- } else if (nds32_v3m->nds32.global_stop) {
+- if (wp->rw == WPT_READ)
+- ld_stop = true;
+- else if (wp->rw == WPT_WRITE)
+- st_stop = true;
+- else if (wp->rw == WPT_ACCESS)
+- ld_stop = st_stop = true;
+- }
+- }
+-
+- if (nds32_v3m->nds32.global_stop) {
+- uint32_t edm_ctl;
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
+- if (ld_stop)
+- edm_ctl |= 0x10;
+- if (st_stop)
+- edm_ctl |= 0x20;
+- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_deactivate_hardware_watchpoint(struct target *target)
+-{
+- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
+- struct aice_port_s *aice = target_to_aice(target);
+- struct watchpoint *wp;
+- int32_t wp_num = 0;
+- bool clean_global_stop = false;
+-
+- for (wp = target->watchpoints; wp; wp = wp->next) {
+-
+- if (wp_num < nds32_v3m->used_n_wp) {
+- /* disable watchpoint */
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0);
+-
+- LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR
+- " mask %08" PRIx32, wp_num, wp->address, wp->mask);
+- wp_num++;
+- } else if (nds32_v3m->nds32.global_stop) {
+- clean_global_stop = true;
+- }
+- }
+-
+- if (clean_global_stop) {
+- uint32_t edm_ctl;
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
+- edm_ctl = edm_ctl & (~0x30);
+- aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, edm_ctl);
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_check_interrupt_stack(struct nds32 *nds32)
+-{
+- uint32_t val_ir0;
+- uint32_t value;
+-
+- /* Save interrupt level */
+- nds32_get_mapped_reg(nds32, IR0, &val_ir0);
+- nds32->current_interrupt_level = (val_ir0 >> 1) & 0x3;
+-
+- if (nds32_reach_max_interrupt_level(nds32))
+- LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level %" PRIu32 ". -->",
+- nds32->current_interrupt_level);
+-
+- /* backup $ir6 to avoid suppressed exception overwrite */
+- nds32_get_mapped_reg(nds32, IR6, &value);
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_restore_interrupt_stack(struct nds32 *nds32)
+-{
+- uint32_t value;
+-
+- /* get backup value from cache */
+- /* then set back to make the register dirty */
+- nds32_get_mapped_reg(nds32, IR0, &value);
+- nds32_set_mapped_reg(nds32, IR0, value);
+-
+- nds32_get_mapped_reg(nds32, IR6, &value);
+- nds32_set_mapped_reg(nds32, IR6, value);
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_deassert_reset(struct target *target)
+-{
+- int retval;
+-
+- CHECK_RETVAL(nds32_poll(target));
+-
+- if (target->state != TARGET_HALTED) {
+- /* reset only */
+- LOG_WARNING("%s: ran after reset and before halt ...",
+- target_name(target));
+- retval = target_halt(target);
+- if (retval != ERROR_OK)
+- return retval;
+-
+- }
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_add_breakpoint(struct target *target,
+- struct breakpoint *breakpoint)
+-{
+- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
+- struct nds32 *nds32 = &(nds32_v3m->nds32);
+- int result;
+-
+- if (breakpoint->type == BKPT_HARD) {
+- /* check hardware resource */
+- if (nds32_v3m->next_hbr_index < nds32_v3m->next_hwp_index) {
+- LOG_WARNING("<-- TARGET WARNING! Insert too many "
+- "hardware breakpoints/watchpoints! "
+- "The limit of combined hardware "
+- "breakpoints/watchpoints is %" PRId32 ". -->",
+- nds32_v3m->n_hbr);
+- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
+- "hardware breakpoint: %" PRId32 ", hardware "
+- "watchpoints: %" PRId32 ". -->",
+- nds32_v3m->n_hbr - nds32_v3m->next_hbr_index - 1,
+- nds32_v3m->used_n_wp);
+- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+- }
+-
+- /* update next place to put hardware breakpoint */
+- nds32_v3m->next_hbr_index--;
+-
+- /* hardware breakpoint insertion occurs before 'continue' actually */
+- return ERROR_OK;
+- } else if (breakpoint->type == BKPT_SOFT) {
+- result = nds32_add_software_breakpoint(target, breakpoint);
+- if (result != ERROR_OK) {
+- /* auto convert to hardware breakpoint if failed */
+- if (nds32->auto_convert_hw_bp) {
+- /* convert to hardware breakpoint */
+- breakpoint->type = BKPT_HARD;
+-
+- return nds32_v3m_add_breakpoint(target, breakpoint);
+- }
+- }
+-
+- return result;
+- } else /* unrecognized breakpoint type */
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_remove_breakpoint(struct target *target,
+- struct breakpoint *breakpoint)
+-{
+- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
+-
+- if (breakpoint->type == BKPT_HARD) {
+- if (nds32_v3m->next_hbr_index >= nds32_v3m->n_hbr - 1)
+- return ERROR_FAIL;
+-
+- /* update next place to put hardware breakpoint */
+- nds32_v3m->next_hbr_index++;
+-
+- /* hardware breakpoint removal occurs after 'halted' actually */
+- return ERROR_OK;
+- } else if (breakpoint->type == BKPT_SOFT) {
+- return nds32_remove_software_breakpoint(target, breakpoint);
+- } else /* unrecognized breakpoint type */
+- return ERROR_FAIL;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_add_watchpoint(struct target *target,
+- struct watchpoint *watchpoint)
+-{
+- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
+-
+- /* check hardware resource */
+- if (nds32_v3m->next_hwp_index >= nds32_v3m->n_hwp) {
+- /* No hardware resource */
+- if (nds32_v3m->nds32.global_stop) {
+- LOG_WARNING("<-- TARGET WARNING! The number of "
+- "watchpoints exceeds the hardware "
+- "resources. Stop at every load/store "
+- "instruction to check for watchpoint matches. -->");
+- return ERROR_OK;
+- }
+-
+- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
+- "watchpoints! The limit of hardware watchpoints "
+- "is %" PRId32 ". -->", nds32_v3m->n_hwp);
+- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
+- "hardware watchpoint: %" PRId32 ". -->",
+- nds32_v3m->used_n_wp);
+- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+- }
+-
+- if (nds32_v3m->next_hwp_index > nds32_v3m->next_hbr_index) {
+- /* No hardware resource */
+- if (nds32_v3m->nds32.global_stop) {
+- LOG_WARNING("<-- TARGET WARNING! The number of "
+- "watchpoints exceeds the hardware "
+- "resources. Stop at every load/store "
+- "instruction to check for watchpoint matches. -->");
+- return ERROR_OK;
+- }
+-
+- LOG_WARNING("<-- TARGET WARNING! Insert too many hardware "
+- "breakpoints/watchpoints! The limit of combined "
+- "hardware breakpoints/watchpoints is %" PRId32 ". -->",
+- nds32_v3m->n_hbr);
+- LOG_WARNING("<-- TARGET STATUS: Inserted number of "
+- "hardware breakpoint: %" PRId32 ", hardware "
+- "watchpoints: %" PRId32 ". -->",
+- nds32_v3m->n_hbr - nds32_v3m->next_hbr_index - 1,
+- nds32_v3m->used_n_wp);
+- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+- }
+-
+- /* update next place to put hardware watchpoint */
+- nds32_v3m->next_hwp_index++;
+- nds32_v3m->used_n_wp++;
+-
+- return ERROR_OK;
+-}
+-
+-static int nds32_v3m_remove_watchpoint(struct target *target,
+- struct watchpoint *watchpoint)
+-{
+- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
+-
+- if (nds32_v3m->next_hwp_index <= 0) {
+- if (nds32_v3m->nds32.global_stop)
+- return ERROR_OK;
+-
+- return ERROR_FAIL;
+- }
+-
+- /* update next place to put hardware watchpoint */
+- nds32_v3m->next_hwp_index--;
+- nds32_v3m->used_n_wp--;
+-
+- return ERROR_OK;
+-}
+-
+-static struct nds32_v3_common_callback nds32_v3m_common_callback = {
+- .check_interrupt_stack = nds32_v3m_check_interrupt_stack,
+- .restore_interrupt_stack = nds32_v3m_restore_interrupt_stack,
+- .activate_hardware_breakpoint = nds32_v3m_activate_hardware_breakpoint,
+- .activate_hardware_watchpoint = nds32_v3m_activate_hardware_watchpoint,
+- .deactivate_hardware_breakpoint = nds32_v3m_deactivate_hardware_breakpoint,
+- .deactivate_hardware_watchpoint = nds32_v3m_deactivate_hardware_watchpoint,
+-};
+-
+-static int nds32_v3m_target_create(struct target *target, Jim_Interp *interp)
+-{
+- struct nds32_v3m_common *nds32_v3m;
+-
+- nds32_v3m = calloc(1, sizeof(*nds32_v3m));
+- if (!nds32_v3m)
+- return ERROR_FAIL;
+-
+- nds32_v3_common_register_callback(&nds32_v3m_common_callback);
+- nds32_v3_target_create_common(target, &(nds32_v3m->nds32));
+-
+- return ERROR_OK;
+-}
+-
+-/* talk to the target and set things up */
+-static int nds32_v3m_examine(struct target *target)
+-{
+- struct nds32_v3m_common *nds32_v3m = target_to_nds32_v3m(target);
+- struct nds32 *nds32 = &(nds32_v3m->nds32);
+- struct aice_port_s *aice = target_to_aice(target);
+-
+- if (!target_was_examined(target)) {
+- CHECK_RETVAL(nds32_edm_config(nds32));
+-
+- if (nds32->reset_halt_as_examine)
+- CHECK_RETVAL(nds32_reset_halt(nds32));
+- }
+-
+- uint32_t edm_cfg;
+- aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
+-
+- /* get the number of hardware breakpoints */
+- nds32_v3m->n_hbr = (edm_cfg & 0x7) + 1;
+- nds32_v3m->used_n_wp = 0;
+-
+- /* get the number of hardware watchpoints */
+- /* If the WP field is hardwired to zero, it means this is a
+- * simple breakpoint. Otherwise, if the WP field is writable
+- * then it means this is a regular watchpoints. */
+- nds32_v3m->n_hwp = 0;
+- for (int32_t i = 0 ; i < nds32_v3m->n_hbr ; i++) {
+- /** check the hardware breakpoint is simple or not */
+- uint32_t tmp_value;
+- aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + i, 0x1);
+- aice_read_debug_reg(aice, NDS_EDM_SR_BPC0 + i, &tmp_value);
+-
+- if (tmp_value)
+- nds32_v3m->n_hwp++;
+- }
+- /* hardware breakpoint is inserted from high index to low index */
+- nds32_v3m->next_hbr_index = nds32_v3m->n_hbr - 1;
+- /* hardware watchpoint is inserted from low index to high index */
+- nds32_v3m->next_hwp_index = 0;
+-
+- LOG_INFO("%s: total hardware breakpoint %" PRId32 " (simple breakpoint %" PRId32 ")",
+- target_name(target), nds32_v3m->n_hbr, nds32_v3m->n_hbr - nds32_v3m->n_hwp);
+- LOG_INFO("%s: total hardware watchpoint %" PRId32, target_name(target), nds32_v3m->n_hwp);
+-
+- nds32->target->state = TARGET_RUNNING;
+- nds32->target->debug_reason = DBG_REASON_NOTHALTED;
+-
+- target_set_examined(target);
+-
+- return ERROR_OK;
+-}
+-
+-/** Holds methods for NDS32 V3m targets. */
+-struct target_type nds32_v3m_target = {
+- .name = "nds32_v3m",
+-
+- .poll = nds32_poll,
+- .arch_state = nds32_arch_state,
+-
+- .target_request_data = nds32_v3_target_request_data,
+-
+- .halt = nds32_halt,
+- .resume = nds32_resume,
+- .step = nds32_step,
+-
+- .assert_reset = nds32_assert_reset,
+- .deassert_reset = nds32_v3m_deassert_reset,
+-
+- /* register access */
+- .get_gdb_reg_list = nds32_get_gdb_reg_list,
+-
+- /* memory access */
+- .read_buffer = nds32_v3_read_buffer,
+- .write_buffer = nds32_v3_write_buffer,
+- .read_memory = nds32_v3_read_memory,
+- .write_memory = nds32_v3_write_memory,
+-
+- .checksum_memory = nds32_v3_checksum_memory,
+-
+- /* breakpoint/watchpoint */
+- .add_breakpoint = nds32_v3m_add_breakpoint,
+- .remove_breakpoint = nds32_v3m_remove_breakpoint,
+- .add_watchpoint = nds32_v3m_add_watchpoint,
+- .remove_watchpoint = nds32_v3m_remove_watchpoint,
+- .hit_watchpoint = nds32_v3_hit_watchpoint,
+-
+- /* MMU */
+- .mmu = nds32_mmu,
+- .virt2phys = nds32_virtual_to_physical,
+- .read_phys_memory = nds32_read_phys_memory,
+- .write_phys_memory = nds32_write_phys_memory,
+-
+- .run_algorithm = nds32_v3_run_algorithm,
+-
+- .commands = nds32_command_handlers,
+- .target_create = nds32_v3m_target_create,
+- .init_target = nds32_v3_init_target,
+- .examine = nds32_v3m_examine,
+-
+- .get_gdb_fileio_info = nds32_get_gdb_fileio_info,
+- .gdb_fileio_end = nds32_gdb_fileio_end,
+-};
+diff --git a/src/target/nds32_v3m.h b/src/target/nds32_v3m.h
+deleted file mode 100644
+index f21dd62c5..000000000
+--- a/src/target/nds32_v3m.h
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2013 Andes Technology *
+- * Hsiangkai Wang <hkwang@andestech.com> *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_TARGET_NDS32_V3M_H
+-#define OPENOCD_TARGET_NDS32_V3M_H
+-
+-#include "nds32.h"
+-
+-struct nds32_v3m_common {
+- struct nds32 nds32;
+-
+- /** number of hardware breakpoints */
+- int32_t n_hbr;
+-
+- /** number of hardware watchpoints */
+- int32_t n_hwp;
+-
+- /** number of used hardware watchpoints */
+- int32_t used_n_wp;
+-
+- /** next hardware breakpoint index */
+- /** for simple breakpoints, hardware breakpoints are inserted
+- * from high index to low index */
+- int32_t next_hbr_index;
+-
+- /** next hardware watchpoint index */
+- /** increase from low index to high index */
+- int32_t next_hwp_index;
+-};
+-
+-static inline struct nds32_v3m_common *target_to_nds32_v3m(struct target *target)
+-{
+- return container_of(target->arch_info, struct nds32_v3m_common, nds32);
+-}
+-
+-#endif /* OPENOCD_TARGET_NDS32_V3M_H */
+diff --git a/src/target/target.c b/src/target/target.c
+index e3a6f955e..ae419ac8b 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -92,9 +92,6 @@ extern struct target_type dsp5680xx_target;
+ extern struct target_type testee_target;
+ extern struct target_type avr32_ap7k_target;
+ extern struct target_type hla_target;
+-extern struct target_type nds32_v2_target;
+-extern struct target_type nds32_v3_target;
+-extern struct target_type nds32_v3m_target;
+ extern struct target_type esp32_target;
+ extern struct target_type esp32s2_target;
+ extern struct target_type esp32s3_target;
+@@ -132,9 +129,6 @@ static struct target_type *target_types[] = {
+ &testee_target,
+ &avr32_ap7k_target,
+ &hla_target,
+- &nds32_v2_target,
+- &nds32_v3_target,
+- &nds32_v3m_target,
+ &esp32_target,
+ &esp32s2_target,
+ &esp32s3_target,
+diff --git a/tcl/board/nds32_xc5.cfg b/tcl/board/nds32_xc5.cfg
+deleted file mode 100644
+index 82a117e71..000000000
+--- a/tcl/board/nds32_xc5.cfg
++++ /dev/null
+@@ -1,7 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-set _CPUTAPID 0x1000063d
+-set _CHIPNAME nds32
+-source [find target/nds32v3.cfg]
+-
+-jtag init
+diff --git a/tcl/interface/nds32-aice.cfg b/tcl/interface/nds32-aice.cfg
+deleted file mode 100644
+index 1d9717c4c..000000000
+--- a/tcl/interface/nds32-aice.cfg
++++ /dev/null
+@@ -1,17 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-#
+-# Andes AICE
+-#
+-# http://www.andestech.com
+-#
+-
+-adapter driver aice
+-aice desc "Andes AICE adapter"
+-# adapter serial "C001-42163"
+-aice vid_pid 0x1CFC 0x0000
+-aice port aice_usb
+-reset_config trst_and_srst
+-adapter speed 24000
+-aice retry_times 50
+-aice count_to_check_dbger 30
+diff --git a/tcl/target/nds32v2.cfg b/tcl/target/nds32v2.cfg
+deleted file mode 100644
+index 07814b7f3..000000000
+--- a/tcl/target/nds32v2.cfg
++++ /dev/null
+@@ -1,12 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-#
+-# Andes Core
+-#
+-# http://www.andestech.com
+-#
+-
+-jtag newtap $_CHIPNAME cpu -expected-id $_CPUTAPID
+-
+-set _TARGETNAME $_CHIPNAME.cpu
+-target create $_TARGETNAME nds32_v2 -endian little -chain-position $_TARGETNAME
+diff --git a/tcl/target/nds32v3.cfg b/tcl/target/nds32v3.cfg
+deleted file mode 100644
+index 0fd136910..000000000
+--- a/tcl/target/nds32v3.cfg
++++ /dev/null
+@@ -1,12 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-#
+-# Andes Core
+-#
+-# http://www.andestech.com
+-#
+-
+-jtag newtap $_CHIPNAME cpu -expected-id $_CPUTAPID
+-
+-set _TARGETNAME $_CHIPNAME.cpu
+-target create $_TARGETNAME nds32_v3 -endian little -chain-position $_TARGETNAME
+diff --git a/tcl/target/nds32v3m.cfg b/tcl/target/nds32v3m.cfg
+deleted file mode 100644
+index 29a247805..000000000
+--- a/tcl/target/nds32v3m.cfg
++++ /dev/null
+@@ -1,12 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-#
+-# Andes Core
+-#
+-# http://www.andestech.com
+-#
+-
+-jtag newtap $_CHIPNAME cpu -expected-id $_CPUTAPID
+-
+-set _TARGETNAME $_CHIPNAME.cpu
+-target create $_TARGETNAME nds32_v3m -endian little -chain-position $_TARGETNAME
+diff --git a/tools/scripts/camelcase.txt b/tools/scripts/camelcase.txt
+index 59fe5cae0..2caa81caa 100644
+--- a/tools/scripts/camelcase.txt
++++ b/tools/scripts/camelcase.txt
+@@ -175,10 +175,7 @@ __FreeBSD_kernel__
+ # for Windows
+ CreateFile
+ CloseHandle
+-CreatePipe
+-CreateProcess
+ FormatMessage
+-GetLastError
+ GetModuleFileName
+ GetSystemTimeAsFileTime
+ GetTickCount
+@@ -189,29 +186,16 @@ MsgWaitForMultipleObjects
+ PeekMessage
+ PeekNamedPipe
+ QuadPart
+-ReadFile
+ SetConsoleCtrlHandler
+-SetHandleInformation
+ Sleep
+ WaitForSingleObject
+-WriteFile
+ WSACleanup
+ WSAGetLastError
+ WSAStartup
+-ZeroMemory
+-bInheritHandle
+-dwFlags
+ dwHighDateTime
+ dwLowDateTime
+ dwPlatformId
+ dwOSVersionInfoSize
+-hProcess
+-hThread
+-hStdError
+-hStdInput
+-hStdOutput
+-lpSecurityDescriptor
+-nLength
+
+ # OpenOCD exceptions that should be removed
+ KiB
new file mode 100644
@@ -0,0 +1,127 @@
+From 95603fae18f81eebdafc5b318e70f9e2cdefab9e Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 18 Dec 2022 19:15:57 +0100
+Subject: [PATCH] openocd: revert workarounds for 'expr' syntax change
+
+With OpenOCD v0.12.0 released, drop the workarounds for 'expr'
+syntax change by reverting:
+- commit 320043c054dc ("openocd: fix for polling during "expr"
+ computation");
+- commit c7eaaf620488 ("openocd: prepare for jimtcl 0.81 'expr'
+ syntax change").
+
+Replace the call to target_call_timer_callbacks_now() with call
+to target_call_timer_callbacks().
+
+Change-Id: Iae5afc50e3f688e11176a52648efc9a6577a9a11
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7405
+Tested-by: jenkins
+---
+ src/helper/command.c | 14 +----------
+ src/openocd.c | 60 --------------------------------------------
+ 2 files changed, 1 insertion(+), 73 deletions(-)
+
+diff --git a/src/helper/command.c b/src/helper/command.c
+index 6898e2d7c..ca66cf7dd 100644
+--- a/src/helper/command.c
++++ b/src/helper/command.c
+@@ -936,19 +936,7 @@ static int jim_command_dispatch(Jim_Interp *interp, int argc, Jim_Obj * const *a
+ if (!command_can_run(cmd_ctx, c, Jim_GetString(argv[0], NULL)))
+ return JIM_ERR;
+
+- /*
+- * TODO: to be removed after v0.12.0
+- * workaround for https://sourceforge.net/p/openocd/tickets/362/
+- * After syntax change of "expr" in jimtcl 0.81
+- * the replacement of jimtcl "expr" with openocd version in
+- * https://review.openocd.org/6510/
+- * introduces too many target polling during math expressions with
+- * "expr" commands.
+- * After v0.12.0 replace the following two lines with
+- * target_call_timer_callbacks();
+- */
+- if (strcmp(c->name, "expr"))
+- target_call_timer_callbacks_now();
++ target_call_timer_callbacks();
+
+ /*
+ * Black magic of overridden current target:
+diff --git a/src/openocd.c b/src/openocd.c
+index bef084f98..875da5a62 100644
+--- a/src/openocd.c
++++ b/src/openocd.c
+@@ -230,65 +230,6 @@ static int openocd_register_commands(struct command_context *cmd_ctx)
+ return register_commands(cmd_ctx, NULL, openocd_command_handlers);
+ }
+
+-/*
+- * TODO: to be removed after v0.12.0
+- * workaround for syntax change of "expr" in jimtcl 0.81
+- * replace "expr" with openocd version that prints the deprecated msg
+- */
+-struct jim_scriptobj {
+- void *token;
+- Jim_Obj *filename_obj;
+- int len;
+- int subst_flags;
+- int in_use;
+- int firstline;
+- int linenr;
+- int missing;
+-};
+-
+-static int jim_expr_command(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- if (argc == 2)
+- return Jim_EvalExpression(interp, argv[1]);
+-
+- if (argc > 2) {
+- Jim_Obj *obj = Jim_ConcatObj(interp, argc - 1, argv + 1);
+- Jim_IncrRefCount(obj);
+- const char *s = Jim_String(obj);
+- struct jim_scriptobj *script = Jim_GetIntRepPtr(interp->currentScriptObj);
+- if (interp->currentScriptObj == interp->emptyObj ||
+- strcmp(interp->currentScriptObj->typePtr->name, "script") ||
+- script->subst_flags ||
+- script->filename_obj == interp->emptyObj)
+- LOG_WARNING("DEPRECATED! use 'expr { %s }' not 'expr %s'", s, s);
+- else
+- LOG_WARNING("DEPRECATED! (%s:%d) use 'expr { %s }' not 'expr %s'",
+- Jim_String(script->filename_obj), script->linenr, s, s);
+- int retcode = Jim_EvalExpression(interp, obj);
+- Jim_DecrRefCount(interp, obj);
+- return retcode;
+- }
+-
+- Jim_WrongNumArgs(interp, 1, argv, "expression ?...?");
+- return JIM_ERR;
+-}
+-
+-static const struct command_registration expr_handler[] = {
+- {
+- .name = "expr",
+- .jim_handler = jim_expr_command,
+- .mode = COMMAND_ANY,
+- .help = "",
+- .usage = "",
+- },
+- COMMAND_REGISTRATION_DONE
+-};
+-
+-static int workaround_for_jimtcl_expr(struct command_context *cmd_ctx)
+-{
+- return register_commands(cmd_ctx, NULL, expr_handler);
+-}
+-
+ struct command_context *global_cmd_ctx;
+
+ static struct command_context *setup_command_handler(Jim_Interp *interp)
+@@ -301,7 +242,6 @@ static struct command_context *setup_command_handler(Jim_Interp *interp)
+ /* register subsystem commands */
+ typedef int (*command_registrant_t)(struct command_context *cmd_ctx_value);
+ static const command_registrant_t command_registrants[] = {
+- &workaround_for_jimtcl_expr,
+ &openocd_register_commands,
+ &server_register_commands,
+ &gdb_register_commands,
new file mode 100644
@@ -0,0 +1,66 @@
+From 0c28006cf2cf2d98ba2d73a73bf629e781f4ffb8 Mon Sep 17 00:00:00 2001
+From: Kyle Schwarz <zeranoe@gmail.com>
+Date: Sun, 10 Jul 2022 15:58:14 -0400
+Subject: [PATCH] flash/nor/avrf: add ATmega32U4 support
+
+Add new chip info and tcl target
+
+Change-Id: Ib9d33d1b145a8659857b7a6cc9c5acba047f41d1
+Signed-off-by: Kyle Schwarz <zeranoe@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7081
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/avrf.c | 1 +
+ tcl/target/atmega32u4.cfg | 30 ++++++++++++++++++++++++++++++
+ 2 files changed, 31 insertions(+)
+ create mode 100644 tcl/target/atmega32u4.cfg
+
+diff --git a/src/flash/nor/avrf.c b/src/flash/nor/avrf.c
+index 0e2e263ce..1d317a10c 100644
+--- a/src/flash/nor/avrf.c
++++ b/src/flash/nor/avrf.c
+@@ -64,6 +64,7 @@ static const struct avrf_type avft_chips_info[] = {
+ {"atmega324pa", 0x9511, 128, 256, 4, 256},
+ {"atmega644p", 0x960a, 256, 256, 8, 256},
+ {"atmega1284p", 0x9705, 256, 512, 8, 512},
++ {"atmega32u4", 0x9587, 128, 256, 4, 256},
+ };
+
+ /* avr program functions */
+diff --git a/tcl/target/atmega32u4.cfg b/tcl/target/atmega32u4.cfg
+new file mode 100644
+index 000000000..9199c741e
+--- /dev/null
++++ b/tcl/target/atmega32u4.cfg
+@@ -0,0 +1,30 @@
++# SPDX-License-Identifier: GPL-2.0-or-later
++# ATmega32U4
++
++if { [info exists CHIPNAME] } {
++ set _CHIPNAME $CHIPNAME
++} else {
++ set _CHIPNAME avr
++}
++
++if { [info exists ENDIAN] } {
++ set _ENDIAN $ENDIAN
++} else {
++ set _ENDIAN little
++}
++
++if { [info exists CPUTAPID] } {
++ set _CPUTAPID $CPUTAPID
++} else {
++ set _CPUTAPID 0x4958703f
++}
++
++adapter speed 4500
++
++jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
++
++set _TARGETNAME $_CHIPNAME.cpu
++target create $_TARGETNAME avr -endian $_ENDIAN -chain-position $_TARGETNAME
++
++set _FLASHNAME $_CHIPNAME.flash
++flash bank $_FLASHNAME avr 0 0 0 0 $_TARGETNAME
new file mode 100644
@@ -0,0 +1,31 @@
+From 0708ccead4fbce07e3d78bb7380aca0aae8cb14d Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Thu, 29 Sep 2022 00:22:00 +0200
+Subject: [PATCH] target/xtensa: remove needless target_was_examined check
+
+In any case flag will be set as examined.
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: I5177ee656f726a807269e2f4725223f50e49e855
+Reviewed-on: https://review.openocd.org/c/openocd/+/7231
+Tested-by: jenkins
+Reviewed-by: Ian Thompson <ianst@cadence.com>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/xtensa/xtensa.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c
+index c2c047edb..b57e2d660 100644
+--- a/src/target/xtensa/xtensa.c
++++ b/src/target/xtensa/xtensa.c
+@@ -801,8 +801,7 @@ int xtensa_examine(struct target *target)
+ return ERROR_TARGET_FAILURE;
+ }
+ LOG_DEBUG("OCD_ID = %08" PRIx32, xtensa->dbg_mod.device_id);
+- if (!target_was_examined(target))
+- target_set_examined(target);
++ target_set_examined(target);
+ xtensa_smpbreak_write(xtensa, xtensa->smp_break);
+ return ERROR_OK;
+ }
new file mode 100644
@@ -0,0 +1,30 @@
+From 9a7781ff8c9dea6ef5998238b1932094b8a226da Mon Sep 17 00:00:00 2001
+From: Fawaz Tirmizi <fawaz@rivosinc.com>
+Date: Fri, 19 Aug 2022 14:22:06 -0700
+Subject: [PATCH] flash/nor/spi: Add issi is25lq040b to device list
+
+The HiFive Inventor uses this flash chip, so adding it will allow for
+openocd to be used to program it. These values were taken from the
+chip's documentation.
+
+Signed-off-by: Fawaz Tirmizi <fawaz@rivosinc.com>
+Change-Id: I15c9d35f99d4500f73134cdc2d1b9ab6279b491c
+Reviewed-on: https://review.openocd.org/c/openocd/+/7135
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/spi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c
+index eed747b58..373a9a144 100644
+--- a/src/flash/nor/spi.c
++++ b/src/flash/nor/spi.c
+@@ -112,6 +112,7 @@ const struct flash_device flash_devices[] = {
+ FLASH_ID("gd gd25q128c", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
+ FLASH_ID("gd gd25q256c", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x001940c8, 0x100, 0x10000, 0x2000000),
+ FLASH_ID("gd gd25q512mc", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x002040c8, 0x100, 0x10000, 0x4000000),
++ FLASH_ID("issi is25lq040b", 0x03, 0xeb, 0x02, 0x20, 0xc7, 0x0013409d, 0x100, 0x1000, 0x80000),
+ FLASH_ID("issi is25lp032", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0016609d, 0x100, 0x10000, 0x400000),
+ FLASH_ID("issi is25lp064", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0017609d, 0x100, 0x10000, 0x800000),
+ FLASH_ID("issi is25lp128d", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018609d, 0x100, 0x10000, 0x1000000),
new file mode 100644
@@ -0,0 +1,1295 @@
+From d96dc47ef67e427cd64a07d9825fd297e3a81633 Mon Sep 17 00:00:00 2001
+From: "James G. Smith" <jsmith@rallysmith.co.uk>
+Date: Wed, 26 May 2021 10:08:26 +0100
+Subject: [PATCH] src/rtos/eCos : Support per-build configuration specific
+ structure layouts
+
+Extended feature. This is a large patch, but is self-contained to the
+eCos support and does not affect any other openocd functionality. It
+does NOT affect existing eCos RTOS plugin users where their
+applications do not provide the extended symbolic helper
+information. If the helper symbols are not available the rtos support
+code will behave as before. This "dynamic" functionality is *required*
+because eCos does NOT have a fixed/hardwired, known, layout for the
+thread descriptor structure. The per-application build eCos
+configuration can affect the shape of the thread descriptor structure
+(field presence, and hence offsets of subsequent fields) such that
+constant values cannot be used to consistently interpret all possible
+eCos application configurations. For historical reasons, there is not
+yet a consistent namespace for the helper symbols across eCos HALs
+hence the support is currently limited to specific architectures
+(Cortex-M and ARM/Cortex-A). No new Clang analyser warnings are raised
+by this changeset.
+
+Change-Id: Ib3a36877326eeb56595cbca55e21b9e59a59c98a
+Signed-off-by: James G. Smith <jsmith@rallysmith.co.uk>
+Reviewed-on: https://review.openocd.org/c/openocd/+/6275
+Reviewed-by: Alex Schuilenburg <alex.schuilenburg@gmail.com>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+Tested-by: jenkins
+---
+ src/rtos/eCos.c | 1033 +++++++++++++++++++++++++++++---
+ src/rtos/rtos_ecos_stackings.c | 7 +
+ 2 files changed, 950 insertions(+), 90 deletions(-)
+
+diff --git a/src/rtos/eCos.c b/src/rtos/eCos.c
+index 3f813ac38..963bb61cf 100644
+--- a/src/rtos/eCos.c
++++ b/src/rtos/eCos.c
+@@ -11,66 +11,446 @@
+ #include <jtag/jtag.h>
+ #include "target/target.h"
+ #include "target/target_type.h"
++#include "target/armv7m.h"
+ #include "rtos.h"
+ #include "helper/log.h"
+ #include "helper/types.h"
++#include "helper/bits.h"
++#include "rtos_standard_stackings.h"
+ #include "rtos_ecos_stackings.h"
++#include "server/gdb_server.h"
++
++/* Unfortunately for the moment we are limited to returning the hardwired
++ * register count (ARMV7M_NUM_CORE_REGS for Cortex-M) since the openocd RTOS
++ * support does not yet support accessing all per-thread "stacked"
++ * registers. e.g. For Cortex-M under eCos we have a per-thread BASEPRI, and for
++ * all eCos targets we may have per-thread VFP/FPU register state.
++ *
++ * So, for the moment, we continue to use the hardwired limit for the depth of
++ * the returned register description vector. The current openocd
++ * rtos_standard_stackings.c just provides the main core regs for the Cortex_M*
++ * targets regardless of whether FPU is present/enabled.
++ *
++ * However, this code is written with the expectation that we may eventually be
++ * able to provide more register information ("m-system" and "vfp" for example)
++ * and also with the expectation of supporting different register sets being
++ * returned depending on the per-thread Cortex-M eCos contex_m for
++ * example. Hence the fact that the eCos_stack_layout_*() functions below allow
++ * for the stack context descriptor vector to be returned by those calls
++ * allowing for eventual support where this code will potentially cache
++ * different sets of register descriptors for the different shapes of contexts
++ * in a *single* application/binary run-time.
++ *
++ * TODO: Extend openocd generic RTOS support to allow thread-specific system and
++ * FPU register state to be returned. */
++
++struct ecos_params;
+
+ static bool ecos_detect_rtos(struct target *target);
+ static int ecos_create(struct target *target);
+ static int ecos_update_threads(struct rtos *rtos);
+ static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs);
+ static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
++static int ecos_stack_layout_cortexm(struct rtos *rtos, struct ecos_params *param,
++ int64_t stack_ptr, const struct rtos_register_stacking **si);
++static int ecos_stack_layout_arm(struct rtos *rtos, struct ecos_params *param,
++ int64_t stack_ptr, const struct rtos_register_stacking **si);
++
++/* The current eCos thread IDentifier uses 0 as an unused (not a valid thread
++ * ID) value. Currently the unique_id field is 16-bits, but the eCos SMP support
++ * convention is that only 12-bits of the ID will be used. This
++ * ECOS_MAX_THREAD_COUNT manifest is provided to limit the potential for
++ * interpreting stale/inconsistent thread list state when the debug host scans
++ * the thread list before the target RTOS has completed its initialisation. This
++ * support will need to revisited when eCos is re-engineered to support more
++ * than 16 CPU SMP setups. */
++#define ECOS_MAX_THREAD_COUNT (4095)
+
+ struct ecos_thread_state {
+ int value;
+ const char *desc;
+ };
+
+-static const struct ecos_thread_state ecos_thread_states[] = {
+- { 0, "Ready" },
+- { 1, "Sleeping" },
+- { 2, "Countsleep" },
+- { 4, "Suspended" },
+- { 8, "Creating" },
+- { 16, "Exited" }
++/* The status is actually a logical-OR bitmask of states: */
++enum ecos_thread_state_flags {
++ RUNNING = 0, /* explicit no-bits-set value */
++ SLEEPING = BIT(0),
++ COUNTSLEEP = BIT(1),
++ SUSPENDED = BIT(2),
++ CREATING = BIT(3),
++ EXITED = BIT(4),
++ SLEEPSET = (SLEEPING | COUNTSLEEP)
++};
++
++/* Cyg_Thread:: reason codes for wake and sleep fields: */
++static const struct ecos_thread_state ecos_thread_reasons[] = {
++ { 0, "NONE" }, /* normally indicates "not yet started" */
++ { 1, "WAIT" }, /* wait with no timeout */
++ { 2, "DELAY" }, /* simple time delay */
++ { 3, "TIMEOUT" }, /* wait with timeout *or* timeout expired */
++ { 4, "BREAK" }, /* forced break out of sleep */
++ { 5, "DESTRUCT" }, /* wait on object being destroyed */
++ { 6, "EXIT" }, /* forced termination */
++ { 7, "DONE" } /* wait/delay completed */
++};
++
++static const char * const target_cortex_m[] = {
++ "cortex_m",
++ "hla_target",
++ NULL
++};
++
++static const char * const target_arm[] = {
++ "cortex_a",
++ "arm7tdmi",
++ "arm720t",
++ "arm9tdmi",
++ "arm920t",
++ "arm926ejs",
++ "arm946e",
++ "arm966e",
++ "arm11",
++ NULL
+ };
+
+-#define ECOS_NUM_STATES ARRAY_SIZE(ecos_thread_states)
++/* Since individual eCos application configurations may have different thread
++ * object structure layouts depending on the actual build-time enabled features
++ * we provide support for applications built containing the relevant symbolic
++ * support to match the actual application binary being debugged, rather than
++ * relying on a set of default/fixed (and potentially incorrect)
++ * offsets. However, for backwards compatibility, we do *NOT* enforce the
++ * requirement for the common extra helper symbols to be present to allow the
++ * fallback to the simple fixed CM3 model to avoid affecting existing users of
++ * older eCos worlds. Similarly we need to provide support for per-thread
++ * register context offsets, as well as for per-application-configurations,
++ * since some targets can have different stacked state on a per-thread basis
++ * (e.g. "cortex_m"). This is why the stacking_info is now set at run-time
++ * rather than being fixed. */
+
+ struct ecos_params {
+- const char *target_name;
++ const char * const *target_names; /* NULL terminated list of targets */
++ int (*target_stack_layout)(struct rtos *rtos, struct ecos_params *param,
++ int64_t stack_ptr, const struct rtos_register_stacking **si);
++ bool flush_common;
+ unsigned char pointer_width;
+- unsigned char thread_stack_offset;
+- unsigned char thread_name_offset;
+- unsigned char thread_state_offset;
+- unsigned char thread_next_offset;
+- unsigned char thread_uniqueid_offset;
++ unsigned char uid_width;
++ unsigned char state_width;
++ unsigned int thread_stack_offset;
++ unsigned int thread_name_offset;
++ unsigned int thread_state_offset;
++ unsigned int thread_next_offset;
++ unsigned int thread_uniqueid_offset;
+ const struct rtos_register_stacking *stacking_info;
+ };
+
+-static const struct ecos_params ecos_params_list[] = {
++/* As mentioned above we provide default offset values for the "cortex_m"
++ * targets for backwards compatibility with older eCos application builds and
++ * previous users of this RTOS specific support that do not have the
++ * configuration specific offsets provided in the symbol table. The support for
++ * other targets (e.g. "cortex_a") we do expect the application to provide the
++ * required symbolic information. We do not populate the stacking_info reference
++ * until we have had a chance to interrogate the symbol table. */
++
++static struct ecos_params ecos_params_list[] = {
++ {
++ .target_names = target_cortex_m,
++ .pointer_width = 4,
++ .uid_width = 2,
++ .state_width = 4,
++ .thread_stack_offset = 0x0c,
++ .thread_name_offset = 0x9c,
++ .thread_state_offset = 0x3c,
++ .thread_next_offset = 0xa0,
++ .thread_uniqueid_offset = 0x4c,
++ .target_stack_layout = ecos_stack_layout_cortexm,
++ .stacking_info = NULL
++ },
+ {
+- "cortex_m", /* target_name */
+- 4, /* pointer_width; */
+- 0x0c, /* thread_stack_offset; */
+- 0x9c, /* thread_name_offset; */
+- 0x3c, /* thread_state_offset; */
+- 0xa0, /* thread_next_offset */
+- 0x4c, /* thread_uniqueid_offset */
+- &rtos_ecos_cortex_m3_stacking /* stacking_info */
++ .target_names = target_arm,
++ .pointer_width = 0,
++ .uid_width = 0,
++ .state_width = 0,
++ .thread_stack_offset = 0,
++ .thread_name_offset = 0,
++ .thread_state_offset = 0,
++ .thread_next_offset = 0,
++ .thread_uniqueid_offset = 0,
++ .target_stack_layout = ecos_stack_layout_arm,
++ .stacking_info = NULL
+ }
+ };
+
++#define ECOS_NUM_PARAMS ARRAY_SIZE(ecos_params_list)
++
++/* To eventually allow for more than just the ARMV7M_NUM_CORE_REGS to be
++ * returned by the Cortex-M support, and to avoid run-time lookups we manually
++ * maintain our own mapping for the supplied stack register vector entries. This
++ * enum needs to match the rtos_ecos_regoff_cortexm[] vector. Admittedly the
++ * initial indices just match the corresponding ARMV7M_R* definitions, but after
++ * the base registers the ARMV7M_* number space does not match the vector we
++ * wish to populate in this eCos support code. */
++enum ecos_reglist_cortexm {
++ ECOS_REGLIST_R0 = 0,
++ ECOS_REGLIST_R1,
++ ECOS_REGLIST_R2,
++ ECOS_REGLIST_R3,
++ ECOS_REGLIST_R4,
++ ECOS_REGLIST_R5,
++ ECOS_REGLIST_R6,
++ ECOS_REGLIST_R7,
++ ECOS_REGLIST_R8,
++ ECOS_REGLIST_R9,
++ ECOS_REGLIST_R10,
++ ECOS_REGLIST_R11,
++ ECOS_REGLIST_R12,
++ ECOS_REGLIST_R13,
++ ECOS_REGLIST_R14,
++ ECOS_REGLIST_PC,
++ ECOS_REGLIST_XPSR, /* ARMV7M_NUM_CORE_REGS */
++ ECOS_REGLIST_BASEPRI,
++ ECOS_REGLIST_FPSCR, /* Following for FPU contexts */
++ ECOS_REGLIST_D0,
++ ECOS_REGLIST_D1,
++ ECOS_REGLIST_D2,
++ ECOS_REGLIST_D3,
++ ECOS_REGLIST_D4,
++ ECOS_REGLIST_D5,
++ ECOS_REGLIST_D6,
++ ECOS_REGLIST_D7,
++ ECOS_REGLIST_D8,
++ ECOS_REGLIST_D9,
++ ECOS_REGLIST_D10,
++ ECOS_REGLIST_D11,
++ ECOS_REGLIST_D12,
++ ECOS_REGLIST_D13,
++ ECOS_REGLIST_D14,
++ ECOS_REGLIST_D15
++};
++
++#define ECOS_CORTEXM_BASE_NUMREGS (ARMV7M_NUM_CORE_REGS)
++
++/* NOTE: The offsets in this vector are overwritten by the architecture specific
++ * layout functions depending on the specific application configuration. The
++ * ordering of this vector MUST match eCos_reglist. */
++static struct stack_register_offset rtos_ecos_regoff_cortexm[] = {
++ { ARMV7M_R0, -1, 32 }, /* r0 */
++ { ARMV7M_R1, -1, 32 }, /* r1 */
++ { ARMV7M_R2, -1, 32 }, /* r2 */
++ { ARMV7M_R3, -1, 32 }, /* r3 */
++ { ARMV7M_R4, -1, 32 }, /* r4 */
++ { ARMV7M_R5, -1, 32 }, /* r5 */
++ { ARMV7M_R6, -1, 32 }, /* r6 */
++ { ARMV7M_R7, -1, 32 }, /* r7 */
++ { ARMV7M_R8, -1, 32 }, /* r8 */
++ { ARMV7M_R9, -1, 32 }, /* r9 */
++ { ARMV7M_R10, -1, 32 }, /* r10 */
++ { ARMV7M_R11, -1, 32 }, /* r11 */
++ { ARMV7M_R12, -1, 32 }, /* r12 */
++ { ARMV7M_R13, -1, 32 }, /* sp */
++ { ARMV7M_R14, -1, 32 }, /* lr */
++ { ARMV7M_PC, -1, 32 }, /* pc */
++ { ARMV7M_XPSR, -1, 32 }, /* xPSR */
++ { ARMV7M_BASEPRI, -1, 32 }, /* BASEPRI */
++ { ARMV7M_FPSCR, -1, 32 }, /* FPSCR */
++ { ARMV7M_D0, -1, 64 }, /* D0 (S0/S1) */
++ { ARMV7M_D1, -1, 64 }, /* D1 (S2/S3) */
++ { ARMV7M_D2, -1, 64 }, /* D2 (S4/S5) */
++ { ARMV7M_D3, -1, 64 }, /* D3 (S6/S7) */
++ { ARMV7M_D4, -1, 64 }, /* D4 (S8/S9) */
++ { ARMV7M_D5, -1, 64 }, /* D5 (S10/S11) */
++ { ARMV7M_D6, -1, 64 }, /* D6 (S12/S13) */
++ { ARMV7M_D7, -1, 64 }, /* D7 (S14/S15) */
++ { ARMV7M_D8, -1, 64 }, /* D8 (S16/S17) */
++ { ARMV7M_D9, -1, 64 }, /* D9 (S18/S19) */
++ { ARMV7M_D10, -1, 64 }, /* D10 (S20/S21) */
++ { ARMV7M_D11, -1, 64 }, /* D11 (S22/S23) */
++ { ARMV7M_D12, -1, 64 }, /* D12 (S24/S25) */
++ { ARMV7M_D13, -1, 64 }, /* D13 (S26/S27) */
++ { ARMV7M_D14, -1, 64 }, /* D14 (S28/S29) */
++ { ARMV7M_D15, -1, 64 }, /* D15 (S30/S31) */
++};
++
++static struct stack_register_offset rtos_ecos_regoff_arm[] = {
++ { 0, -1, 32 }, /* r0 */
++ { 1, -1, 32 }, /* r1 */
++ { 2, -1, 32 }, /* r2 */
++ { 3, -1, 32 }, /* r3 */
++ { 4, -1, 32 }, /* r4 */
++ { 5, -1, 32 }, /* r5 */
++ { 6, -1, 32 }, /* r6 */
++ { 7, -1, 32 }, /* r7 */
++ { 8, -1, 32 }, /* r8 */
++ { 9, -1, 32 }, /* r9 */
++ { 10, -1, 32 }, /* r10 */
++ { 11, -1, 32 }, /* r11 (fp) */
++ { 12, -1, 32 }, /* r12 (ip) */
++ { 13, -1, 32 }, /* sp (r13) */
++ { 14, -1, 32 }, /* lr (r14) */
++ { 15, -1, 32 }, /* pc (r15) */
++ { 16, -1, 32 }, /* xPSR */
++};
++
++static struct rtos_register_stacking rtos_ecos_stacking = {
++ .stack_registers_size = 0,
++ .stack_growth_direction = -1,
++ .num_output_registers = 0,
++ .calculate_process_stack = NULL, /* stack_alignment */
++ .register_offsets = NULL
++};
++
++/* To avoid the run-time cost of matching explicit symbol names we push the
++ * lookup offsets to this *manually* maintained enumeration which must match the
++ * ecos_symbol_list[] order below. */
+ enum ecos_symbol_values {
+ ECOS_VAL_THREAD_LIST = 0,
+- ECOS_VAL_CURRENT_THREAD_PTR = 1
++ ECOS_VAL_CURRENT_THREAD_PTR,
++ ECOS_VAL_COMMON_THREAD_NEXT_OFF,
++ ECOS_VAL_COMMON_THREAD_NEXT_SIZE,
++ ECOS_VAL_COMMON_THREAD_STATE_OFF,
++ ECOS_VAL_COMMON_THREAD_STATE_SIZE,
++ ECOS_VAL_COMMON_THREAD_SLEEP_OFF,
++ ECOS_VAL_COMMON_THREAD_SLEEP_SIZE,
++ ECOS_VAL_COMMON_THREAD_WAKE_OFF,
++ ECOS_VAL_COMMON_THREAD_WAKE_SIZE,
++ ECOS_VAL_COMMON_THREAD_ID_OFF,
++ ECOS_VAL_COMMON_THREAD_ID_SIZE,
++ ECOS_VAL_COMMON_THREAD_NAME_OFF,
++ ECOS_VAL_COMMON_THREAD_NAME_SIZE,
++ ECOS_VAL_COMMON_THREAD_PRI_OFF,
++ ECOS_VAL_COMMON_THREAD_PRI_SIZE,
++ ECOS_VAL_COMMON_THREAD_STACK_OFF,
++ ECOS_VAL_COMMON_THREAD_STACK_SIZE,
++ ECOS_VAL_CORTEXM_THREAD_SAVED,
++ ECOS_VAL_CORTEXM_CTX_THREAD_SIZE,
++ ECOS_VAL_CORTEXM_CTX_TYPE_OFF,
++ ECOS_VAL_CORTEXM_CTX_TYPE_SIZE,
++ ECOS_VAL_CORTEXM_CTX_BASEPRI_OFF,
++ ECOS_VAL_CORTEXM_CTX_BASEPRI_SIZE,
++ ECOS_VAL_CORTEXM_CTX_SP_OFF,
++ ECOS_VAL_CORTEXM_CTX_SP_SIZE,
++ ECOS_VAL_CORTEXM_CTX_REG_OFF,
++ ECOS_VAL_CORTEXM_CTX_REG_SIZE,
++ ECOS_VAL_CORTEXM_CTX_PC_OFF,
++ ECOS_VAL_CORTEXM_CTX_PC_SIZE,
++ ECOS_VAL_CORTEXM_VAL_EXCEPTION,
++ ECOS_VAL_CORTEXM_VAL_THREAD,
++ ECOS_VAL_CORTEXM_VAL_INTERRUPT,
++ ECOS_VAL_CORTEXM_VAL_FPU,
++ ECOS_VAL_CORTEXM_CTX_FPSCR_OFF,
++ ECOS_VAL_CORTEXM_CTX_FPSCR_SIZE,
++ ECOS_VAL_CORTEXM_CTX_S_OFF,
++ ECOS_VAL_CORTEXM_CTX_S_SIZE,
++ ECOS_VAL_ARM_REGSIZE,
++ ECOS_VAL_ARM_CTX_R0_OFF,
++ ECOS_VAL_ARM_CTX_R1_OFF,
++ ECOS_VAL_ARM_CTX_R2_OFF,
++ ECOS_VAL_ARM_CTX_R3_OFF,
++ ECOS_VAL_ARM_CTX_R4_OFF,
++ ECOS_VAL_ARM_CTX_R5_OFF,
++ ECOS_VAL_ARM_CTX_R6_OFF,
++ ECOS_VAL_ARM_CTX_R7_OFF,
++ ECOS_VAL_ARM_CTX_R8_OFF,
++ ECOS_VAL_ARM_CTX_R9_OFF,
++ ECOS_VAL_ARM_CTX_R10_OFF,
++ ECOS_VAL_ARM_CTX_FP_OFF,
++ ECOS_VAL_ARM_CTX_IP_OFF,
++ ECOS_VAL_ARM_CTX_SP_OFF,
++ ECOS_VAL_ARM_CTX_LR_OFF,
++ ECOS_VAL_ARM_CTX_PC_OFF,
++ ECOS_VAL_ARM_CTX_CPSR_OFF,
++ ECOS_VAL_ARM_FPUSIZE,
++ ECOS_VAL_ARM_CTX_FPSCR_OFF,
++ ECOS_VAL_ARM_SCOUNT,
++ ECOS_VAL_ARM_CTX_SVEC_OFF,
++ ECOS_VAL_ARM_VFPCOUNT,
++ ECOS_VAL_ARM_CTX_VFPVEC_OFF
+ };
+
+-static const char * const ecos_symbol_list[] = {
+- "Cyg_Thread::thread_list",
+- "Cyg_Scheduler_Base::current_thread",
+- NULL
++struct symbols {
++ const char *name;
++ const char * const *target_names; /* non-NULL when for a specific architecture */
++ bool optional;
++};
++
++#define ECOSSYM(_n, _o, _t) { .name = _n, .optional = (_o), .target_names = _t }
++
++/* Some of offset/size helper symbols are common to all eCos
++ * targets. Unfortunately, for historical reasons, some information is in
++ * architecture specific namespaces leading to some duplication and a larger
++ * vector below. */
++static const struct symbols ecos_symbol_list[] = {
++ ECOSSYM("Cyg_Thread::thread_list", false, NULL),
++ ECOSSYM("Cyg_Scheduler_Base::current_thread", false, NULL),
++ /* Following symbols *are* required for generic application-specific
++ * configuration support, but we mark as optional for backwards
++ * compatibility with the previous fixed Cortex-M3 only RTOS plugin
++ * implementation. */
++ ECOSSYM("__ecospro_syminfo.off.cyg_thread.list_next", true, NULL),
++ ECOSSYM("__ecospro_syminfo.size.cyg_thread.list_next", true, NULL),
++ ECOSSYM("__ecospro_syminfo.off.cyg_thread.state", true, NULL),
++ ECOSSYM("__ecospro_syminfo.size.cyg_thread.state", true, NULL),
++ ECOSSYM("__ecospro_syminfo.off.cyg_thread.sleep_reason", true, NULL),
++ ECOSSYM("__ecospro_syminfo.size.cyg_thread.sleep_reason", true, NULL),
++ ECOSSYM("__ecospro_syminfo.off.cyg_thread.wake_reason", true, NULL),
++ ECOSSYM("__ecospro_syminfo.size.cyg_thread.wake_reason", true, NULL),
++ ECOSSYM("__ecospro_syminfo.off.cyg_thread.unique_id", true, NULL),
++ ECOSSYM("__ecospro_syminfo.size.cyg_thread.unique_id", true, NULL),
++ ECOSSYM("__ecospro_syminfo.off.cyg_thread.name", true, NULL),
++ ECOSSYM("__ecospro_syminfo.size.cyg_thread.name", true, NULL),
++ ECOSSYM("__ecospro_syminfo.off.cyg_thread.priority", true, NULL),
++ ECOSSYM("__ecospro_syminfo.size.cyg_thread.priority", true, NULL),
++ ECOSSYM("__ecospro_syminfo.off.cyg_thread.stack_ptr", true, NULL),
++ ECOSSYM("__ecospro_syminfo.size.cyg_thread.stack_ptr", true, NULL),
++ /* optional Cortex-M: */
++ ECOSSYM("__ecospro_syminfo.cortexm.thread.saved", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.Thread", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.type", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.type", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.basepri", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.basepri", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.sp", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.sp", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.r", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.r", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.pc", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.pc", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.value.HAL_SAVEDREGISTERS.EXCEPTION", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.value.HAL_SAVEDREGISTERS.THREAD", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.value.HAL_SAVEDREGISTERS.INTERRUPT", true, target_cortex_m),
++ /* optional Cortex-M with H/W FPU configured: */
++ ECOSSYM("__ecospro_syminfo.value.HAL_SAVEDREGISTERS.WITH_FPU", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.fpscr", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.fpscr", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.off.HAL_SavedRegisters.u.thread.s", true, target_cortex_m),
++ ECOSSYM("__ecospro_syminfo.size.HAL_SavedRegisters.u.thread.s", true, target_cortex_m),
++ /* optional ARM: */
++ ECOSSYM("ARMREG_SIZE", true, target_arm),
++ ECOSSYM("armreg_r0", true, target_arm),
++ ECOSSYM("armreg_r1", true, target_arm),
++ ECOSSYM("armreg_r2", true, target_arm),
++ ECOSSYM("armreg_r3", true, target_arm),
++ ECOSSYM("armreg_r4", true, target_arm),
++ ECOSSYM("armreg_r5", true, target_arm),
++ ECOSSYM("armreg_r6", true, target_arm),
++ ECOSSYM("armreg_r7", true, target_arm),
++ ECOSSYM("armreg_r8", true, target_arm),
++ ECOSSYM("armreg_r9", true, target_arm),
++ ECOSSYM("armreg_r10", true, target_arm),
++ ECOSSYM("armreg_fp", true, target_arm),
++ ECOSSYM("armreg_ip", true, target_arm),
++ ECOSSYM("armreg_sp", true, target_arm),
++ ECOSSYM("armreg_lr", true, target_arm),
++ ECOSSYM("armreg_pc", true, target_arm),
++ ECOSSYM("armreg_cpsr", true, target_arm),
++ /* optional ARM FPU common: */
++ ECOSSYM("ARMREG_FPUCONTEXT_SIZE", true, target_arm),
++ ECOSSYM("armreg_fpscr", true, target_arm),
++ /* optional ARM FPU single-precision: */
++ ECOSSYM("ARMREG_S_COUNT", true, target_arm),
++ ECOSSYM("armreg_s_vec", true, target_arm),
++ /* optional ARM FPU double-precision: */
++ ECOSSYM("ARMREG_VFP_COUNT", true, target_arm),
++ ECOSSYM("armreg_vfp_vec", true, target_arm),
+ };
+
+ const struct rtos_type ecos_rtos = {
+@@ -84,34 +464,280 @@ const struct rtos_type ecos_rtos = {
+
+ };
+
++static symbol_address_t ecos_value(struct rtos *rtos, unsigned int idx)
++{
++ if (idx < ARRAY_SIZE(ecos_symbol_list))
++ return rtos->symbols[idx].address;
++
++ /* We do not terminate, just return 0 in this case. */
++ LOG_ERROR("eCos: Invalid symbol index %u", idx);
++ return 0;
++}
++
++#define XMLENTRY(_c, _s) { .xc = (_c), .rs = (_s), .rlen = (sizeof(_s) - 1) }
++
++static const struct {
++ char xc;
++ const char *rs;
++ size_t rlen;
++} xmlchars[] = {
++ XMLENTRY('<', "<"),
++ XMLENTRY('&', "&"),
++ XMLENTRY('>', ">"),
++ XMLENTRY('\'', "'"),
++ XMLENTRY('"', """)
++};
++
++/** Escape any XML reserved characters in a string. */
++static bool ecos_escape_string(const char *raw, char *out, size_t limit)
++{
++ static const char *tokens = "<&>\'\"";
++ bool escaped = false;
++
++ if (!out || !limit)
++ return false;
++
++ (void)memset(out, '\0', limit);
++
++ while (raw && *raw && limit) {
++ size_t lok = strcspn(raw, tokens);
++ if (lok) {
++ size_t tocopy;
++ tocopy = ((limit < lok) ? limit : lok);
++ (void)memcpy(out, raw, tocopy);
++ limit -= tocopy;
++ out += tocopy;
++ raw += lok;
++ continue;
++ }
++
++ char *fidx = strchr(tokens, *raw);
++ if (!fidx) {
++ /* Should never happen assuming xmlchars
++ * vector and tokens string match. */
++ LOG_ERROR("eCos: Unexpected XML char %c", *raw);
++ continue;
++ }
++
++ uint32_t cidx = (fidx - tokens);
++ size_t tocopy = xmlchars[cidx].rlen;
++ if (limit < tocopy)
++ break;
++
++ escaped = true;
++ (void)memcpy(out, xmlchars[cidx].rs, tocopy);
++ limit -= tocopy;
++ out += tocopy;
++ raw++;
++ }
++
++ return escaped;
++}
++
++static int ecos_check_app_info(struct rtos *rtos, struct ecos_params *param)
++{
++ if (!rtos || !param)
++ return -1;
++
++ if (param->flush_common) {
++ if (debug_level >= LOG_LVL_DEBUG) {
++ for (unsigned int idx = 0; idx < ARRAY_SIZE(ecos_symbol_list); idx++) {
++ LOG_DEBUG("eCos: %s 0x%016" PRIX64 " %s",
++ rtos->symbols[idx].optional ? "OPTIONAL" : " ",
++ rtos->symbols[idx].address, rtos->symbols[idx].symbol_name);
++ }
++ }
++
++ /* If "__ecospro_syminfo.size.cyg_thread.list_next" is non-zero then we
++ * expect all of the generic thread structure symbols to have been
++ * provided. */
++ symbol_address_t thread_next_size = ecos_value(rtos, ECOS_VAL_COMMON_THREAD_NEXT_SIZE);
++ if (thread_next_size != 0) {
++ param->pointer_width = thread_next_size;
++ param->uid_width = ecos_value(rtos, ECOS_VAL_COMMON_THREAD_ID_SIZE);
++ param->state_width = ecos_value(rtos, ECOS_VAL_COMMON_THREAD_STATE_SIZE);
++ param->thread_stack_offset = ecos_value(rtos, ECOS_VAL_COMMON_THREAD_STACK_OFF);
++ param->thread_name_offset = ecos_value(rtos, ECOS_VAL_COMMON_THREAD_NAME_OFF);
++ param->thread_state_offset = ecos_value(rtos, ECOS_VAL_COMMON_THREAD_STATE_OFF);
++ param->thread_next_offset = ecos_value(rtos, ECOS_VAL_COMMON_THREAD_NEXT_OFF);
++ param->thread_uniqueid_offset = ecos_value(rtos, ECOS_VAL_COMMON_THREAD_ID_OFF);
++ }
++
++ if (param->uid_width != sizeof(uint16_t)) {
++ /* Currently all eCos configurations use a 16-bit field to hold the
++ * unique thread ID. */
++ LOG_WARNING("eCos: Unexpected unique_id width %" PRIu8, param->uid_width);
++ param->uid_width = (unsigned char)sizeof(uint16_t);
++ }
++
++ param->stacking_info = NULL;
++ param->flush_common = false;
++ }
++
++ return ERROR_OK;
++}
++
++/* The Cortex-M eCosPro "thread" contexts have a "type" indicator, which tracks
++ * the context state of (THREAD | EXCEPTION | INTERRUPT) and whether FPU
++ * registers are saved.
++ *
++ * For thread-aware debugging from GDB we are only interested in THREAD states
++ * and so do not need to implement support for INTERRUPT or EXCEPTION thread
++ * contexts since this code does not expose those stack contexts via the
++ * constructed thread list support. */
++static int ecos_stack_layout_cortexm(struct rtos *rtos,
++ struct ecos_params *param, int64_t stack_ptr,
++ const struct rtos_register_stacking **si)
++{
++ int retval = ERROR_OK;
++
++ /* CONSIDER: We could return
++ * ecos_value(rtos, ECOS_VAL_CORTEXM_THREAD_SAVED) as the actual PC
++ * address of a context switch, with the LR being set to the context PC
++ * field to give a true representation of where the thread switch
++ * occurs. However that would require extending the common
++ * rtos_generic_stack_read() code with suitable support for applying a
++ * supplied value, or just implementing our own version of that code that
++ * can inject data into what is passed onwards to GDB. */
++
++ /* UPDATE: When we can return VFP register state then we will NOT be
++ * basing the cached state on the single param->stacking_info value,
++ * since we will need a different stacking_info structure returned for
++ * each thread type when FPU support is enabled. The use of the single
++ * param->stacking_info is a holder whilst we are limited to the fixed
++ * ARMV7M_NUM_CORE_REGS set of descriptors. */
++
++ if (!param->stacking_info &&
++ ecos_value(rtos, ECOS_VAL_CORTEXM_THREAD_SAVED) &&
++ ecos_value(rtos, ECOS_VAL_CORTEXM_VAL_THREAD)) {
++ unsigned char numoutreg = ECOS_CORTEXM_BASE_NUMREGS;
++
++ rtos_ecos_stacking.stack_registers_size = ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_THREAD_SIZE);
++ rtos_ecos_stacking.calculate_process_stack = rtos_generic_stack_align8;
++ rtos_ecos_stacking.register_offsets = rtos_ecos_regoff_cortexm;
++
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R0].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x00);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R1].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x04);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R2].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x08);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R3].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x0C);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R4].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x10);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R5].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x14);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R6].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x18);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R7].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x1C);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R8].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x20);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R9].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x24);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R10].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x28);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R11].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x2C);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R12].offset = (ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_REG_OFF) + 0x30);
++ /* Rather than using the stacked ECOS_VAL_CORTEXM_CTX_SP_OFF
++ * value we force the reported sp to be after the stacked
++ * register context. */
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R13].offset = -2;
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_R14].offset = -1;
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_PC].offset = ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_PC_OFF);
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_XPSR].offset = -1;
++
++ param->stacking_info = &rtos_ecos_stacking;
++
++ /* Common Cortex-M thread register offsets for the current
++ * symbol table: */
++ if (retval == ERROR_OK && param->stacking_info) {
++ if (numoutreg > ECOS_REGLIST_BASEPRI) {
++ rtos_ecos_regoff_cortexm[ECOS_REGLIST_BASEPRI].offset =
++ ecos_value(rtos, ECOS_VAL_CORTEXM_CTX_BASEPRI_OFF);
++ }
++
++ rtos_ecos_stacking.num_output_registers = numoutreg;
++ }
++ }
++
++ if (si)
++ *si = param->stacking_info;
++
++ return retval;
++}
++
++static int ecos_stack_layout_arm(struct rtos *rtos, struct ecos_params *param,
++ int64_t stack_ptr, const struct rtos_register_stacking **si)
++{
++ int retval = ERROR_OK;
++
++ if (!param->stacking_info && ecos_value(rtos, ECOS_VAL_ARM_REGSIZE)) {
++ /* When OpenOCD is extended to allow FPU registers to be returned from a
++ * stacked thread context we can check:
++ * if (0 != ecos_value(rtos, ECOS_VAL_ARM_FPUSIZE)) { FPU }
++ * for presence of FPU registers in the context. */
++
++ rtos_ecos_stacking.stack_registers_size = ecos_value(rtos, ECOS_VAL_ARM_REGSIZE);
++ rtos_ecos_stacking.num_output_registers = ARRAY_SIZE(rtos_ecos_regoff_arm);
++ rtos_ecos_stacking.register_offsets = rtos_ecos_regoff_arm;
++
++ rtos_ecos_regoff_arm[0].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R0_OFF);
++ rtos_ecos_regoff_arm[1].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R1_OFF);
++ rtos_ecos_regoff_arm[2].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R2_OFF);
++ rtos_ecos_regoff_arm[3].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R3_OFF);
++ rtos_ecos_regoff_arm[4].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R4_OFF);
++ rtos_ecos_regoff_arm[5].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R5_OFF);
++ rtos_ecos_regoff_arm[6].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R6_OFF);
++ rtos_ecos_regoff_arm[7].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R7_OFF);
++ rtos_ecos_regoff_arm[8].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R8_OFF);
++ rtos_ecos_regoff_arm[9].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R9_OFF);
++ rtos_ecos_regoff_arm[10].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_R10_OFF);
++ rtos_ecos_regoff_arm[11].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_FP_OFF);
++ rtos_ecos_regoff_arm[12].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_IP_OFF);
++ rtos_ecos_regoff_arm[13].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_SP_OFF);
++ rtos_ecos_regoff_arm[14].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_LR_OFF);
++ rtos_ecos_regoff_arm[15].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_PC_OFF);
++ rtos_ecos_regoff_arm[16].offset = ecos_value(rtos, ECOS_VAL_ARM_CTX_CPSR_OFF);
++
++ param->stacking_info = &rtos_ecos_stacking;
++ }
++
++ if (si)
++ *si = param->stacking_info;
++
++ return retval;
++}
++
++/* We see this function called on a new connection, it looks like before and
++ * after the "tar rem"/"tar extended-remote". It might be the only point we can
++ * decide to cache information (to check if the symbol table has changed). */
+ static int ecos_update_threads(struct rtos *rtos)
+ {
+ int retval;
+ int tasks_found = 0;
+ int thread_list_size = 0;
+- const struct ecos_params *param;
++ struct ecos_params *param;
+
+ if (!rtos)
+ return -1;
+
++ /* wipe out previous thread details if any */
++ rtos_free_threadlist(rtos);
++
+ if (!rtos->rtos_specific_params)
+ return -3;
+
+- param = (const struct ecos_params *) rtos->rtos_specific_params;
++ param = rtos->rtos_specific_params;
+
+ if (!rtos->symbols) {
++ /* NOTE: We only see this when connecting from GDB the first
++ * time before the application image is loaded. So it is not a
++ * hook for detecting an application change. */
++ param->flush_common = true;
+ LOG_ERROR("No symbols for eCos");
+ return -4;
+ }
+
++ retval = ecos_check_app_info(rtos, param);
++ if (retval != ERROR_OK)
++ return retval;
++
+ if (rtos->symbols[ECOS_VAL_THREAD_LIST].address == 0) {
+ LOG_ERROR("Don't have the thread list head");
+ return -2;
+ }
+
+- /* wipe out previous thread details if any */
+- rtos_free_threadlist(rtos);
+-
+ /* determine the number of current threads */
+ uint32_t thread_list_head = rtos->symbols[ECOS_VAL_THREAD_LIST].address;
+ uint32_t thread_index;
+@@ -120,50 +746,82 @@ static int ecos_update_threads(struct rtos *rtos)
+ param->pointer_width,
+ (uint8_t *) &thread_index);
+ uint32_t first_thread = thread_index;
+- do {
+- thread_list_size++;
+- retval = target_read_buffer(rtos->target,
+- thread_index + param->thread_next_offset,
+- param->pointer_width,
+- (uint8_t *) &thread_index);
+- if (retval != ERROR_OK)
+- return retval;
+- } while (thread_index != first_thread);
++
++ /* Even if 0==first_thread indicates a system with no defined eCos
++ * threads, instead of early exiting here we fall through the code to
++ * allow the creation of a faked "Current Execution" descriptor as
++ * needed. */
++
++ if (first_thread) {
++ /* Since the OpenOCD RTOS support can attempt to obtain thread
++ * information on initial connection when the system *may* have
++ * undefined memory state it is possible for a simple thread count scan
++ * to produce invalid results. To avoid blocking indefinitely when
++ * encountering an invalid closed loop we limit the number of threads to
++ * the maximum possible, and if we pass that limit then something is
++ * wrong so treat the system as having no threads defined. */
++ do {
++ thread_list_size++;
++ if (thread_list_size > ECOS_MAX_THREAD_COUNT) {
++ /* Treat as "no threads" case: */
++ first_thread = 0;
++ thread_list_size = 0;
++ break;
++ }
++ retval = target_read_buffer(rtos->target,
++ thread_index + param->thread_next_offset,
++ param->pointer_width,
++ (uint8_t *)&thread_index);
++ if (retval != ERROR_OK)
++ return retval;
++ } while (thread_index != first_thread);
++ }
+
+ /* read the current thread id */
++ rtos->current_thread = 0;
++
+ uint32_t current_thread_addr;
+ retval = target_read_buffer(rtos->target,
+ rtos->symbols[ECOS_VAL_CURRENT_THREAD_PTR].address,
+- 4,
++ param->pointer_width,
+ (uint8_t *)¤t_thread_addr);
+- if (retval != ERROR_OK)
+- return retval;
+- rtos->current_thread = 0;
+- retval = target_read_buffer(rtos->target,
+- current_thread_addr + param->thread_uniqueid_offset,
+- 2,
+- (uint8_t *)&rtos->current_thread);
+ if (retval != ERROR_OK) {
+- LOG_ERROR("Could not read eCos current thread from target");
++ LOG_ERROR("Reading active thread address");
+ return retval;
+ }
+
+- if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
++ if (current_thread_addr) {
++ uint16_t id = 0;
++ retval = target_read_buffer(rtos->target,
++ current_thread_addr + param->thread_uniqueid_offset,
++ param->uid_width,
++ (uint8_t *)&id);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Could not read eCos current thread from target");
++ return retval;
++ }
++ rtos->current_thread = (threadid_t)id;
++ }
++
++ if (thread_list_size == 0 || rtos->current_thread == 0) {
+ /* Either : No RTOS threads - there is always at least the current execution though */
+ /* OR : No current thread - all threads suspended - show the current execution
+ * of idling */
+- char tmp_str[] = "Current Execution";
++ static const char tmp_str[] = "Current Execution";
+ thread_list_size++;
+ tasks_found++;
+ rtos->thread_details = malloc(
+ sizeof(struct thread_detail) * thread_list_size);
+- rtos->thread_details->threadid = 1;
++ /* 1 is a valid eCos thread id, so we return 0 for this faked
++ * "current" CPU state: */
++ rtos->thread_details->threadid = 0;
+ rtos->thread_details->exists = true;
+ rtos->thread_details->extra_info_str = NULL;
+ rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
+ strcpy(rtos->thread_details->thread_name_str, tmp_str);
+
+- if (thread_list_size == 0) {
++ /* Early exit if current CPU state our only "thread": */
++ if (thread_list_size == 1) {
+ rtos->thread_count = 1;
+ return ERROR_OK;
+ }
+@@ -176,18 +834,18 @@ static int ecos_update_threads(struct rtos *rtos)
+ /* loop over all threads */
+ thread_index = first_thread;
+ do {
+-
+ #define ECOS_THREAD_NAME_STR_SIZE (200)
+ char tmp_str[ECOS_THREAD_NAME_STR_SIZE];
+- unsigned int i = 0;
+ uint32_t name_ptr = 0;
+ uint32_t prev_thread_ptr;
+
+- /* Save the thread pointer */
+- uint16_t thread_id;
++ /* Save the thread ID. For eCos the thread has a unique ID distinct from
++ * the thread_index descriptor pointer. We present this scheduler ID
++ * instead of the descriptor memory address. */
++ uint16_t thread_id = 0;
+ retval = target_read_buffer(rtos->target,
+ thread_index + param->thread_uniqueid_offset,
+- 2,
++ param->uid_width,
+ (uint8_t *)&thread_id);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Could not read eCos thread id from target");
+@@ -195,7 +853,7 @@ static int ecos_update_threads(struct rtos *rtos)
+ }
+ rtos->thread_details[tasks_found].threadid = thread_id;
+
+- /* read the name pointer */
++ /* Read the name pointer */
+ retval = target_read_buffer(rtos->target,
+ thread_index + param->thread_name_offset,
+ param->pointer_width,
+@@ -217,8 +875,26 @@ static int ecos_update_threads(struct rtos *rtos)
+ }
+ tmp_str[ECOS_THREAD_NAME_STR_SIZE-1] = '\x00';
+
+- if (tmp_str[0] == '\x00')
+- strcpy(tmp_str, "No Name");
++ /* Since eCos can have arbitrary C string names we can sometimes
++ * get an internal warning from GDB about "not well-formed
++ * (invalid token)" since the XML post-processing done by GDB on
++ * the OpenOCD returned response containing the thread strings
++ * is not escaped. For example the eCos kernel testsuite
++ * application tm_basic uses the thread name "<<NULL>>" which
++ * will trigger this failure unless escaped. */
++ if (tmp_str[0] == '\x00') {
++ snprintf(tmp_str, ECOS_THREAD_NAME_STR_SIZE, "NoName:[0x%08" PRIX32 "]", thread_index);
++ } else {
++ /* The following is a workaround to avoid any issues
++ * from arbitrary eCos thread names causing GDB/OpenOCD
++ * issues. We limit the escaped thread name passed to
++ * GDB to the same length as the un-escaped just to
++ * avoid overly long strings. */
++ char esc_str[ECOS_THREAD_NAME_STR_SIZE];
++ bool escaped = ecos_escape_string(tmp_str, esc_str, sizeof(esc_str));
++ if (escaped)
++ strcpy(tmp_str, esc_str);
++ }
+
+ rtos->thread_details[tasks_found].thread_name_str =
+ malloc(strlen(tmp_str)+1);
+@@ -228,28 +904,109 @@ static int ecos_update_threads(struct rtos *rtos)
+ int64_t thread_status = 0;
+ retval = target_read_buffer(rtos->target,
+ thread_index + param->thread_state_offset,
+- 4,
++ param->state_width,
+ (uint8_t *)&thread_status);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("Error reading thread state from eCos target");
+ return retval;
+ }
+
+- for (i = 0; (i < ECOS_NUM_STATES) && (ecos_thread_states[i].value != thread_status); i++) {
+- /*
+- * empty
+- */
+- }
++ /* The thread_status is a BITMASK */
++ char state_desc[21]; /* Enough for "suspended+countsleep\0" maximum */
+
+- const char *state_desc;
+- if (i < ECOS_NUM_STATES)
+- state_desc = ecos_thread_states[i].desc;
++ if (thread_status & SUSPENDED)
++ strcpy(state_desc, "suspended+");
+ else
+- state_desc = "Unknown state";
++ state_desc[0] = '\0';
++
++ switch (thread_status & ~SUSPENDED) {
++ case RUNNING:
++ if (thread_index == current_thread_addr)
++ strcat(state_desc, "running");
++ else if (thread_status & SUSPENDED)
++ state_desc[9] = '\0'; /* Drop '+' from "suspended+" */
++ else
++ strcat(state_desc, "ready");
++ break;
++ case SLEEPING:
++ strcat(state_desc, "sleeping");
++ break;
++ case SLEEPSET:
++ case COUNTSLEEP:
++ strcat(state_desc, "counted sleep");
++ break;
++ case CREATING:
++ strcpy(state_desc, "creating");
++ break;
++ case EXITED:
++ strcpy(state_desc, "exited");
++ break;
++ default:
++ strcpy(state_desc, "unknown state");
++ break;
++ }
++
++ /* For the moment we do not bother decoding the wake reason for the
++ * active "running" thread, but it is useful providing the sleep reason
++ * for stacked threads. */
++ int64_t sleep_reason = 0; /* sleep reason */
++
++ if (thread_index != current_thread_addr &&
++ ecos_value(rtos, ECOS_VAL_COMMON_THREAD_SLEEP_SIZE)) {
++ retval = target_read_buffer(rtos->target,
++ (thread_index + ecos_value(rtos, ECOS_VAL_COMMON_THREAD_SLEEP_OFF)),
++ ecos_value(rtos, ECOS_VAL_COMMON_THREAD_SLEEP_SIZE),
++ (uint8_t *)&sleep_reason);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Error reading thread sleep reason from eCos target");
++ return retval;
++ }
++ if (sleep_reason < 0 ||
++ sleep_reason > (int64_t)ARRAY_SIZE(ecos_thread_reasons)) {
++ sleep_reason = 0;
++ }
++ }
++
++ /* We do not display anything for the Cyg_Thread::NONE reason */
++ size_t tr_extra = 0;
++ const char *reason_desc = NULL;
++ if (sleep_reason)
++ reason_desc = ecos_thread_reasons[sleep_reason].desc;
++ if (reason_desc)
++ tr_extra = 2 + strlen(reason_desc) + 1;
+
+- rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
+- state_desc)+8);
+- sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc);
++ /* Display thread priority if available: */
++ int64_t priority = 0;
++ size_t pri_extra = 0;
++ if (ecos_value(rtos, ECOS_VAL_COMMON_THREAD_PRI_SIZE)) {
++ retval = target_read_buffer(rtos->target,
++ (thread_index + ecos_value(rtos, ECOS_VAL_COMMON_THREAD_PRI_OFF)),
++ ecos_value(rtos, ECOS_VAL_COMMON_THREAD_PRI_SIZE),
++ (uint8_t *)&priority);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Error reading thread priority from eCos target");
++ return retval;
++ }
++ pri_extra = (12 + 20); /* worst-case ", Priority: " */
++ }
++
++ size_t eilen = (8 + strlen(state_desc) + tr_extra + pri_extra);
++ char *eistr = malloc(eilen);
++ /* We do not need to treat a malloc failure as a fatal error here since
++ * the code below will just not report extra thread information if NULL,
++ * thus allowing all of the threads to be enumerated even with reduced
++ * information when the host is low on memory. However... */
++ if (!eistr) {
++ LOG_ERROR("OOM allocating extra information buffer");
++ return ERROR_FAIL;
++ }
++
++ int soff = snprintf(eistr, eilen, "State: %s", state_desc);
++ if (tr_extra && reason_desc)
++ soff += snprintf(&eistr[soff], (eilen - soff), " (%s)", reason_desc);
++ if (pri_extra)
++ (void)snprintf(&eistr[soff], (eilen - soff), ", Priority: %" PRId64 "", priority);
++ rtos->thread_details[tasks_found].extra_info_str = eistr;
+
+ rtos->thread_details[tasks_found].exists = true;
+
+@@ -269,14 +1026,14 @@ static int ecos_update_threads(struct rtos *rtos)
+ } while (thread_index != first_thread);
+
+ rtos->thread_count = tasks_found;
+- return 0;
++ return ERROR_OK;
+ }
+
+ static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ struct rtos_reg **reg_list, int *num_regs)
+ {
+ int retval;
+- const struct ecos_params *param;
++ struct ecos_params *param;
+
+ if (!rtos)
+ return -1;
+@@ -287,7 +1044,22 @@ static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ if (!rtos->rtos_specific_params)
+ return -3;
+
+- param = (const struct ecos_params *) rtos->rtos_specific_params;
++ param = rtos->rtos_specific_params;
++
++ retval = ecos_check_app_info(rtos, param);
++ if (retval != ERROR_OK)
++ return retval;
++
++ /* We can get memory access errors reported by this function on
++ * re-connecting to a board with stale thread information in memory. The
++ * initial ecos_update_threads() is called twice and may read
++ * stale/invalid information depending on the memory state. This happens
++ * as part of the "target remote" connection so cannot be avoided by GDB
++ * scripting. It is not critical and allowing the application to run and
++ * initialise its BSS etc. will allow correct thread and register
++ * information to be obtained. This really only affects debug sessions
++ * where "info thr" is used before the initial run-time initialisation
++ * has occurred. */
+
+ /* Find the thread with that thread id */
+ uint16_t id = 0;
+@@ -299,10 +1071,10 @@ static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ while (!done) {
+ retval = target_read_buffer(rtos->target,
+ thread_index + param->thread_uniqueid_offset,
+- 2,
++ param->uid_width,
+ (uint8_t *)&id);
+ if (retval != ERROR_OK) {
+- LOG_ERROR("Error reading unique id from eCos thread");
++ LOG_ERROR("Error reading unique id from eCos thread 0x%08" PRIX32 "", thread_index);
+ return retval;
+ }
+
+@@ -328,8 +1100,24 @@ static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ return retval;
+ }
+
++ if (!stack_ptr) {
++ LOG_ERROR("NULL stack pointer in thread %" PRIu64, thread_id);
++ return -5;
++ }
++
++ const struct rtos_register_stacking *stacking_info = NULL;
++ if (param->target_stack_layout) {
++ retval = param->target_stack_layout(rtos, param, stack_ptr, &stacking_info);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Error reading stack layout for eCos thread");
++ return retval;
++ }
++ }
++ if (!stacking_info)
++ stacking_info = &rtos_ecos_cortex_m3_stacking;
++
+ return rtos_generic_stack_read(rtos->target,
+- param->stacking_info,
++ stacking_info,
+ stack_ptr,
+ reg_list,
+ num_regs);
+@@ -338,18 +1126,31 @@ static int ecos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ return -1;
+ }
+
++/* NOTE: This is only called once when the first GDB connection is made to
++ * OpenOCD and not on subsequent connections (when the application symbol table
++ * may have changed, affecting the offsets of critical fields and the stacked
++ * context shape). */
+ static int ecos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
+ {
+ unsigned int i;
+ *symbol_list = calloc(
+ ARRAY_SIZE(ecos_symbol_list), sizeof(struct symbol_table_elem));
+
+- for (i = 0; i < ARRAY_SIZE(ecos_symbol_list); i++)
+- (*symbol_list)[i].symbol_name = ecos_symbol_list[i];
++ /* If the target reference was passed into this function we could limit
++ * the symbols we need to lookup to the target->type->name based
++ * range. For the moment we need to provide a single vector with all of
++ * the symbols across all of the supported architectures. */
++ for (i = 0; i < ARRAY_SIZE(ecos_symbol_list); i++) {
++ (*symbol_list)[i].symbol_name = ecos_symbol_list[i].name;
++ (*symbol_list)[i].optional = ecos_symbol_list[i].optional;
++ }
+
+ return 0;
+ }
+
++/* NOTE: Only called by rtos.c:rtos_qsymbol() when auto-detecting the RTOS. If
++ * the target configuration uses the explicit "-rtos" config option then this
++ * detection routine is NOT called. */
+ static bool ecos_detect_rtos(struct target *target)
+ {
+ if ((target->rtos->symbols) &&
+@@ -360,15 +1161,67 @@ static bool ecos_detect_rtos(struct target *target)
+ return false;
+ }
+
++extern int rtos_thread_packet(struct connection *connection,
++ const char *packet, int packet_size);
++
++/* Since we should never have 0 as a valid eCos thread ID we use $Hg0 as the
++ * indicator of a new session as regards flushing any cached state. */
++static int ecos_packet_hook(struct connection *connection,
++ const char *packet, int packet_size)
++{
++ int64_t current_threadid;
++
++ if (packet[0] == 'H' && packet[1] == 'g') {
++ int numscan = sscanf(packet, "Hg%16" SCNx64, ¤t_threadid);
++ if (numscan == 1 && current_threadid == 0) {
++ struct target *target = get_target_from_connection(connection);
++ if (target && target->rtos && target->rtos->rtos_specific_params) {
++ struct ecos_params *param;
++ param = target->rtos->rtos_specific_params;
++ param->flush_common = true;
++ }
++ }
++ }
++
++ return rtos_thread_packet(connection, packet, packet_size);
++}
++
++/* Called at start of day when eCos detected or specified in config file. */
+ static int ecos_create(struct target *target)
+ {
+- for (unsigned int i = 0; i < ARRAY_SIZE(ecos_params_list); i++)
+- if (strcmp(ecos_params_list[i].target_name, target->type->name) == 0) {
+- target->rtos->rtos_specific_params = (void *)&ecos_params_list[i];
+- target->rtos->current_thread = 0;
+- target->rtos->thread_details = NULL;
+- return 0;
++ for (unsigned int i = 0; i < ARRAY_SIZE(ecos_params_list); i++) {
++ const char * const *tnames = ecos_params_list[i].target_names;
++ while (*tnames) {
++ if (strcmp(*tnames, target->type->name) == 0) {
++ /* LOG_DEBUG("eCos: matched target \"%s\"", target->type->name); */
++ target->rtos->rtos_specific_params = (void *)&ecos_params_list[i];
++ ecos_params_list[i].flush_common = true;
++ ecos_params_list[i].stacking_info = NULL;
++ target->rtos->current_thread = 0;
++ target->rtos->thread_details = NULL;
++
++ /* We use the $Hg0 packet as a new GDB connection "start-of-day" hook to
++ * force a re-cache of information. It is possible for a single OpenOCD
++ * session to be connected to a target with multiple GDB debug sessions
++ * started/stopped. With eCos it is possible for those GDB sessions to
++ * present applications with different offsets within a thread
++ * descriptor for fields used by this module, and for the stacked
++ * context within the connected target architecture to differ between
++ * applications and even between threads in a single application. So we
++ * need to ensure any information we cache is flushed on an application
++ * change, and GDB referencing an invalid eCos thread ID (0) is a good
++ * enough point, since we can accept the re-cache hit if that packet
++ * appears during an established session, whilst benefiting from not
++ * re-loading information on every update_threads or get_thread_reg_list
++ * call. */
++ target->rtos->gdb_thread_packet = ecos_packet_hook;
++ /* We do not currently use the target->rtos->gdb_target_for_threadid
++ * hook. */
++ return 0;
++ }
++ tnames++;
+ }
++ }
+
+ LOG_ERROR("Could not find target in eCos compatibility list");
+ return -1;
+diff --git a/src/rtos/rtos_ecos_stackings.c b/src/rtos/rtos_ecos_stackings.c
+index 0f54e86f7..86e176507 100644
+--- a/src/rtos/rtos_ecos_stackings.c
++++ b/src/rtos/rtos_ecos_stackings.c
+@@ -8,6 +8,13 @@
+ #include "rtos_standard_stackings.h"
+ #include "target/armv7m.h"
+
++/* For Cortex-M eCos applications the actual thread context register layout can
++ * be different between active threads of an application depending on whether
++ * the FPU is in use, configured for lazy FPU context saving, etc. */
++
++/* Default fixed thread register context description used for older eCos
++ * application builds without the necessary symbolic information describing the
++ * actual configuration-dependent offsets. */
+ static const struct stack_register_offset rtos_ecos_cortex_m3_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
+ { ARMV7M_R0, 0x0c, 32 }, /* r0 */
+ { ARMV7M_R1, 0x10, 32 }, /* r1 */
new file mode 100644
@@ -0,0 +1,460 @@
+From d0436b0cdabb2106701222628d78932c973a1e62 Mon Sep 17 00:00:00 2001
+From: Koudai Iwahori <koudai@google.com>
+Date: Tue, 4 Oct 2022 04:21:35 -0700
+Subject: [PATCH] armv8: Add support of pointer authentication
+
+When pointer authentication is enabled, some upper bits of the link
+register (LR[63:VA_SIZE]) are used to store a signature. Therefore, GDB
+need to remove the signature to get backtraces.
+GDB has support of pointer authentication. When pointer authenticaion is
+enabled, GDB requests 8-bytes mask to the target to remove the
+signature. mask[63:VA_SIZE] should be all set and mask[VA_SIZE-1:0]
+should be all cleared. GDB removes the signature by addr&~mask or
+addr|mask.
+I added a feature to provide the mask for pointer authentication.
+
+Signed-off-by: Koudai Iwahori <koudai@google.com>
+Change-Id: I56fbbf9cc23619b6536ecd326f350c8bf137f322
+Reviewed-on: https://review.openocd.org/c/openocd/+/7248
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ doc/openocd.texi | 10 ++
+ src/target/armv8.c | 335 +++++++++++++++++++++++++--------------------
+ src/target/armv8.h | 7 +
+ 3 files changed, 206 insertions(+), 146 deletions(-)
+
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index c7fee3e71..aa1707b7d 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -10297,6 +10297,16 @@ the target, the exception catch must be disabled again with @command{$target_nam
+ Issuing the command without options prints the current configuration.
+ @end deffn
+
++@deffn {Command} {$target_name pauth} [@option{off}|@option{on}]
++Enable or disable pointer authentication features.
++When pointer authentication is used on ARM cores, GDB asks GDB servers for an 8-bytes mask to remove signature bits added by pointer authentication.
++If this feature is enabled, OpenOCD provides GDB with an 8-bytes mask.
++Pointer authentication feature is broken until gdb 12.1, going to be fixed.
++Consider using a newer version of gdb if you want to enable pauth feature.
++The default configuration is @option{off}.
++@end deffn
++
++
+ @section EnSilica eSi-RISC Architecture
+
+ eSi-RISC is a highly configurable microprocessor architecture for embedded systems
+diff --git a/src/target/armv8.c b/src/target/armv8.c
+index de0bddb3e..ff71a8e63 100644
+--- a/src/target/armv8.c
++++ b/src/target/armv8.c
+@@ -114,6 +114,166 @@ const char *armv8_mode_name(unsigned psr_mode)
+ return "UNRECOGNIZED";
+ }
+
++static uint8_t armv8_pa_size(uint32_t ps)
++{
++ uint8_t ret = 0;
++ switch (ps) {
++ case 0:
++ ret = 32;
++ break;
++ case 1:
++ ret = 36;
++ break;
++ case 2:
++ ret = 40;
++ break;
++ case 3:
++ ret = 42;
++ break;
++ case 4:
++ ret = 44;
++ break;
++ case 5:
++ ret = 48;
++ break;
++ default:
++ LOG_INFO("Unknown physical address size");
++ break;
++ }
++ return ret;
++}
++
++static __attribute__((unused)) int armv8_read_ttbcr32(struct target *target)
++{
++ struct armv8_common *armv8 = target_to_armv8(target);
++ struct arm_dpm *dpm = armv8->arm.dpm;
++ uint32_t ttbcr, ttbcr_n;
++ int retval = dpm->prepare(dpm);
++ if (retval != ERROR_OK)
++ goto done;
++ /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
++ retval = dpm->instr_read_data_r0(dpm,
++ ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
++ &ttbcr);
++ if (retval != ERROR_OK)
++ goto done;
++
++ LOG_DEBUG("ttbcr %" PRIx32, ttbcr);
++
++ ttbcr_n = ttbcr & 0x7;
++ armv8->armv8_mmu.ttbcr = ttbcr;
++
++ /*
++ * ARM Architecture Reference Manual (ARMv7-A and ARMv7-R edition),
++ * document # ARM DDI 0406C
++ */
++ armv8->armv8_mmu.ttbr_range[0] = 0xffffffff >> ttbcr_n;
++ armv8->armv8_mmu.ttbr_range[1] = 0xffffffff;
++ armv8->armv8_mmu.ttbr_mask[0] = 0xffffffff << (14 - ttbcr_n);
++ armv8->armv8_mmu.ttbr_mask[1] = 0xffffffff << 14;
++
++ LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32 " ttbr1_mask %" PRIx32,
++ (ttbcr_n != 0) ? "used" : "not used",
++ armv8->armv8_mmu.ttbr_mask[0],
++ armv8->armv8_mmu.ttbr_mask[1]);
++
++done:
++ dpm->finish(dpm);
++ return retval;
++}
++
++static int armv8_read_ttbcr(struct target *target)
++{
++ struct armv8_common *armv8 = target_to_armv8(target);
++ struct arm_dpm *dpm = armv8->arm.dpm;
++ struct arm *arm = &armv8->arm;
++ uint32_t ttbcr;
++ uint64_t ttbcr_64;
++
++ int retval = dpm->prepare(dpm);
++ if (retval != ERROR_OK)
++ goto done;
++
++ /* clear ttrr1_used and ttbr0_mask */
++ memset(&armv8->armv8_mmu.ttbr1_used, 0, sizeof(armv8->armv8_mmu.ttbr1_used));
++ memset(&armv8->armv8_mmu.ttbr0_mask, 0, sizeof(armv8->armv8_mmu.ttbr0_mask));
++
++ switch (armv8_curel_from_core_mode(arm->core_mode)) {
++ case SYSTEM_CUREL_EL3:
++ retval = dpm->instr_read_data_r0(dpm,
++ ARMV8_MRS(SYSTEM_TCR_EL3, 0),
++ &ttbcr);
++ retval += dpm->instr_read_data_r0_64(dpm,
++ ARMV8_MRS(SYSTEM_TTBR0_EL3, 0),
++ &armv8->ttbr_base);
++ if (retval != ERROR_OK)
++ goto done;
++ armv8->va_size = 64 - (ttbcr & 0x3F);
++ armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
++ armv8->page_size = (ttbcr >> 14) & 3;
++ break;
++ case SYSTEM_CUREL_EL2:
++ retval = dpm->instr_read_data_r0(dpm,
++ ARMV8_MRS(SYSTEM_TCR_EL2, 0),
++ &ttbcr);
++ retval += dpm->instr_read_data_r0_64(dpm,
++ ARMV8_MRS(SYSTEM_TTBR0_EL2, 0),
++ &armv8->ttbr_base);
++ if (retval != ERROR_OK)
++ goto done;
++ armv8->va_size = 64 - (ttbcr & 0x3F);
++ armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
++ armv8->page_size = (ttbcr >> 14) & 3;
++ break;
++ case SYSTEM_CUREL_EL0:
++ armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H);
++ /* fall through */
++ case SYSTEM_CUREL_EL1:
++ retval = dpm->instr_read_data_r0_64(dpm,
++ ARMV8_MRS(SYSTEM_TCR_EL1, 0),
++ &ttbcr_64);
++ armv8->va_size = 64 - (ttbcr_64 & 0x3F);
++ armv8->pa_size = armv8_pa_size((ttbcr_64 >> 32) & 7);
++ armv8->page_size = (ttbcr_64 >> 14) & 3;
++ armv8->armv8_mmu.ttbr1_used = (((ttbcr_64 >> 16) & 0x3F) != 0) ? 1 : 0;
++ armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFF;
++ retval += dpm->instr_read_data_r0_64(dpm,
++ ARMV8_MRS(SYSTEM_TTBR0_EL1 | (armv8->armv8_mmu.ttbr1_used), 0),
++ &armv8->ttbr_base);
++ if (retval != ERROR_OK)
++ goto done;
++ break;
++ default:
++ LOG_ERROR("unknown core state");
++ retval = ERROR_FAIL;
++ break;
++ }
++ if (retval != ERROR_OK)
++ goto done;
++
++ if (armv8->armv8_mmu.ttbr1_used == 1)
++ LOG_INFO("TTBR0 access above %" PRIx64, (uint64_t)(armv8->armv8_mmu.ttbr0_mask));
++
++done:
++ armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
++ dpm->finish(dpm);
++ return retval;
++}
++
++static int armv8_get_pauth_mask(struct armv8_common *armv8, uint64_t *mask)
++{
++ struct arm *arm = &armv8->arm;
++ int retval = ERROR_OK;
++ if (armv8->va_size == 0)
++ retval = armv8_read_ttbcr(arm->target);
++ if (retval != ERROR_OK)
++ return retval;
++
++ *mask = ~(((uint64_t)1 << armv8->va_size) - 1);
++
++ return retval;
++}
++
+ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regval)
+ {
+ struct arm_dpm *dpm = &armv8->dpm;
+@@ -191,6 +351,10 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv
+ ARMV8_MRS(SYSTEM_SPSR_EL3, 0), &value);
+ value_64 = value;
+ break;
++ case ARMV8_PAUTH_CMASK:
++ case ARMV8_PAUTH_DMASK:
++ retval = armv8_get_pauth_mask(armv8, &value_64);
++ break;
+ default:
+ retval = ERROR_FAIL;
+ break;
+@@ -772,152 +936,6 @@ static __attribute__((unused)) void armv8_show_fault_registers(struct target *ta
+ armv8_show_fault_registers32(armv8);
+ }
+
+-static uint8_t armv8_pa_size(uint32_t ps)
+-{
+- uint8_t ret = 0;
+- switch (ps) {
+- case 0:
+- ret = 32;
+- break;
+- case 1:
+- ret = 36;
+- break;
+- case 2:
+- ret = 40;
+- break;
+- case 3:
+- ret = 42;
+- break;
+- case 4:
+- ret = 44;
+- break;
+- case 5:
+- ret = 48;
+- break;
+- default:
+- LOG_INFO("Unknown physical address size");
+- break;
+- }
+- return ret;
+-}
+-
+-static __attribute__((unused)) int armv8_read_ttbcr32(struct target *target)
+-{
+- struct armv8_common *armv8 = target_to_armv8(target);
+- struct arm_dpm *dpm = armv8->arm.dpm;
+- uint32_t ttbcr, ttbcr_n;
+- int retval = dpm->prepare(dpm);
+- if (retval != ERROR_OK)
+- goto done;
+- /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
+- retval = dpm->instr_read_data_r0(dpm,
+- ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
+- &ttbcr);
+- if (retval != ERROR_OK)
+- goto done;
+-
+- LOG_DEBUG("ttbcr %" PRIx32, ttbcr);
+-
+- ttbcr_n = ttbcr & 0x7;
+- armv8->armv8_mmu.ttbcr = ttbcr;
+-
+- /*
+- * ARM Architecture Reference Manual (ARMv7-A and ARMv7-R edition),
+- * document # ARM DDI 0406C
+- */
+- armv8->armv8_mmu.ttbr_range[0] = 0xffffffff >> ttbcr_n;
+- armv8->armv8_mmu.ttbr_range[1] = 0xffffffff;
+- armv8->armv8_mmu.ttbr_mask[0] = 0xffffffff << (14 - ttbcr_n);
+- armv8->armv8_mmu.ttbr_mask[1] = 0xffffffff << 14;
+-
+- LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32 " ttbr1_mask %" PRIx32,
+- (ttbcr_n != 0) ? "used" : "not used",
+- armv8->armv8_mmu.ttbr_mask[0],
+- armv8->armv8_mmu.ttbr_mask[1]);
+-
+-done:
+- dpm->finish(dpm);
+- return retval;
+-}
+-
+-static __attribute__((unused)) int armv8_read_ttbcr(struct target *target)
+-{
+- struct armv8_common *armv8 = target_to_armv8(target);
+- struct arm_dpm *dpm = armv8->arm.dpm;
+- struct arm *arm = &armv8->arm;
+- uint32_t ttbcr;
+- uint64_t ttbcr_64;
+-
+- int retval = dpm->prepare(dpm);
+- if (retval != ERROR_OK)
+- goto done;
+-
+- /* clear ttrr1_used and ttbr0_mask */
+- memset(&armv8->armv8_mmu.ttbr1_used, 0, sizeof(armv8->armv8_mmu.ttbr1_used));
+- memset(&armv8->armv8_mmu.ttbr0_mask, 0, sizeof(armv8->armv8_mmu.ttbr0_mask));
+-
+- switch (armv8_curel_from_core_mode(arm->core_mode)) {
+- case SYSTEM_CUREL_EL3:
+- retval = dpm->instr_read_data_r0(dpm,
+- ARMV8_MRS(SYSTEM_TCR_EL3, 0),
+- &ttbcr);
+- retval += dpm->instr_read_data_r0_64(dpm,
+- ARMV8_MRS(SYSTEM_TTBR0_EL3, 0),
+- &armv8->ttbr_base);
+- if (retval != ERROR_OK)
+- goto done;
+- armv8->va_size = 64 - (ttbcr & 0x3F);
+- armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
+- armv8->page_size = (ttbcr >> 14) & 3;
+- break;
+- case SYSTEM_CUREL_EL2:
+- retval = dpm->instr_read_data_r0(dpm,
+- ARMV8_MRS(SYSTEM_TCR_EL2, 0),
+- &ttbcr);
+- retval += dpm->instr_read_data_r0_64(dpm,
+- ARMV8_MRS(SYSTEM_TTBR0_EL2, 0),
+- &armv8->ttbr_base);
+- if (retval != ERROR_OK)
+- goto done;
+- armv8->va_size = 64 - (ttbcr & 0x3F);
+- armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
+- armv8->page_size = (ttbcr >> 14) & 3;
+- break;
+- case SYSTEM_CUREL_EL0:
+- armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H);
+- /* fall through */
+- case SYSTEM_CUREL_EL1:
+- retval = dpm->instr_read_data_r0_64(dpm,
+- ARMV8_MRS(SYSTEM_TCR_EL1, 0),
+- &ttbcr_64);
+- armv8->va_size = 64 - (ttbcr_64 & 0x3F);
+- armv8->pa_size = armv8_pa_size((ttbcr_64 >> 32) & 7);
+- armv8->page_size = (ttbcr_64 >> 14) & 3;
+- armv8->armv8_mmu.ttbr1_used = (((ttbcr_64 >> 16) & 0x3F) != 0) ? 1 : 0;
+- armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFF;
+- retval += dpm->instr_read_data_r0_64(dpm,
+- ARMV8_MRS(SYSTEM_TTBR0_EL1 | (armv8->armv8_mmu.ttbr1_used), 0),
+- &armv8->ttbr_base);
+- if (retval != ERROR_OK)
+- goto done;
+- break;
+- default:
+- LOG_ERROR("unknown core state");
+- retval = ERROR_FAIL;
+- break;
+- }
+- if (retval != ERROR_OK)
+- goto done;
+-
+- if (armv8->armv8_mmu.ttbr1_used == 1)
+- LOG_INFO("TTBR0 access above %" PRIx64, (uint64_t)(armv8->armv8_mmu.ttbr0_mask));
+-
+-done:
+- armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
+- dpm->finish(dpm);
+- return retval;
+-}
+-
+ /* method adapted to cortex A : reused arm v4 v5 method*/
+ int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr_t *val)
+ {
+@@ -1083,6 +1101,15 @@ COMMAND_HANDLER(armv8_handle_exception_catch_command)
+ return ERROR_OK;
+ }
+
++COMMAND_HANDLER(armv8_pauth_command)
++{
++ struct target *target = get_current_target(CMD_CTX);
++ struct armv8_common *armv8 = target_to_armv8(target);
++ return CALL_COMMAND_HANDLER(handle_command_parse_bool,
++ &armv8->enable_pauth,
++ "pauth feature");
++}
++
+ int armv8_handle_cache_info_command(struct command_invocation *cmd,
+ struct armv8_cache_common *armv8_cache)
+ {
+@@ -1421,6 +1448,8 @@ static const struct {
+ NULL},
+ { ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked",
+ NULL},
++ { ARMV8_PAUTH_DMASK, "pauth_dmask", 64, ARM_MODE_ANY, REG_TYPE_UINT64, NULL, "org.gnu.gdb.aarch64.pauth", NULL},
++ { ARMV8_PAUTH_CMASK, "pauth_cmask", 64, ARM_MODE_ANY, REG_TYPE_UINT64, NULL, "org.gnu.gdb.aarch64.pauth", NULL},
+ };
+
+ static const struct {
+@@ -1650,6 +1679,9 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
+ *reg_list[i].reg_data_type = *armv8_regs[i].data_type;
+ } else
+ LOG_ERROR("unable to allocate reg type list");
++
++ if (i == ARMV8_PAUTH_CMASK || i == ARMV8_PAUTH_DMASK)
++ reg_list[i].hidden = !armv8->enable_pauth;
+ }
+
+ arm->cpsr = reg_list + ARMV8_XPSR;
+@@ -1745,6 +1777,17 @@ const struct command_registration armv8_command_handlers[] = {
+ .help = "configure exception catch",
+ .usage = "[(nsec_el1,nsec_el2,sec_el1,sec_el3)+,off]",
+ },
++ {
++ .name = "pauth",
++ .handler = armv8_pauth_command,
++ .mode = COMMAND_CONFIG,
++ .help = "enable or disable providing GDB with an 8-bytes mask to "
++ "remove signature bits added by pointer authentication."
++ "Pointer authentication feature is broken until gdb 12.1, going to be fixed. "
++ "Consider using a newer version of gdb if you want enable "
++ "pauth feature.",
++ .usage = "[on|off]",
++ },
+ COMMAND_REGISTRATION_DONE
+ };
+
+diff --git a/src/target/armv8.h b/src/target/armv8.h
+index 2ed3a65ac..54aa08634 100644
+--- a/src/target/armv8.h
++++ b/src/target/armv8.h
+@@ -98,6 +98,10 @@ enum {
+ ARMV8_ESR_EL3 = 75,
+ ARMV8_SPSR_EL3 = 76,
+
++ /* Pseudo registers defined by GDB to remove the pauth signature. */
++ ARMV8_PAUTH_DMASK = 77,
++ ARMV8_PAUTH_CMASK = 78,
++
+ ARMV8_LAST_REG,
+ };
+
+@@ -205,6 +209,9 @@ struct armv8_common {
+
+ struct arm_cti *cti;
+
++ /* True if OpenOCD provides pointer auth related info to GDB */
++ bool enable_pauth;
++
+ /* last run-control command issued to this target (resume, halt, step) */
+ enum run_control_op last_run_control_op;
+
new file mode 100644
@@ -0,0 +1,34 @@
+From 083100fca3c5fd019517e38028d26a6c8e33a364 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sat, 1 Oct 2022 17:00:51 +0200
+Subject: [PATCH] target/armv7m: check error in armv7m_restore_context()
+
+Return error if arm.write_core_reg() fails.
+
+Change-Id: Ide8f5aa5958532b202dc9f5e13d3250a706d832d
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7238
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/armv7m.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/target/armv7m.c b/src/target/armv7m.c
+index 93df5877e..1b85315de 100644
+--- a/src/target/armv7m.c
++++ b/src/target/armv7m.c
+@@ -182,8 +182,11 @@ int armv7m_restore_context(struct target *target)
+ for (i = cache->num_regs - 1; i >= 0; i--) {
+ struct reg *r = &cache->reg_list[i];
+
+- if (r->exist && r->dirty)
+- armv7m->arm.write_core_reg(target, r, i, ARM_MODE_ANY, r->value);
++ if (r->exist && r->dirty) {
++ int retval = armv7m->arm.write_core_reg(target, r, i, ARM_MODE_ANY, r->value);
++ if (retval != ERROR_OK)
++ return retval;
++ }
+ }
+
+ return ERROR_OK;
new file mode 100644
@@ -0,0 +1,400 @@
+From 59763653c631625f195bf652f226f8537fe66832 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sat, 1 Oct 2022 17:10:31 +0200
+Subject: [PATCH] target/cortex_m: add SMP support for Cortex-M
+
+Cortex-M support for SMP multicore targets.
+
+This SMP implementation unlike older ones does not act
+on the first halted target found. It polls targets
+until a SMP group is finished and stores eventual
+'halted' events instead of emitting them. As soon as polling
+of a group is done, poll proceeds with SMP related tasks.
+This approach improves detection of a reason why debug
+stopped - a correct reason is detected for all targets,
+not only for the first found.
+Drawback: SMP target group should be defined in the same
+order as the targets were defined.
+
+Obsolete gdb 'J' packet/smp_gdb command core switching is not implemented,
+use with rtos hwthread.
+
+Only one core is resumed if debug_execution is requested.
+
+Some ideas taken from Graham Sanderson's [4936]
+and src/target/aarch64.c
+
+Added error checking of armv7m_restore_context().
+
+Change-Id: I60f5b79e74b624dc2b5835ff10e38ac2ccb23792
+Link: [4936]: target/cortex_m: Add smp support for Cortex M | https://review.openocd.org/c/openocd/+/4936
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7239
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/cortex_m.c | 226 ++++++++++++++++++++++++++++++++++++++----
+ src/target/target.h | 4 +
+ 2 files changed, 211 insertions(+), 19 deletions(-)
+
+diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
+index 017a6d3a1..88e9bb299 100644
+--- a/src/target/cortex_m.c
++++ b/src/target/cortex_m.c
+@@ -28,6 +28,7 @@
+ #include "register.h"
+ #include "arm_opcodes.h"
+ #include "arm_semihosting.h"
++#include "smp.h"
+ #include <helper/time_support.h>
+ #include <rtt/rtt.h>
+
+@@ -871,7 +872,7 @@ static int cortex_m_debug_entry(struct target *target)
+ return ERROR_OK;
+ }
+
+-static int cortex_m_poll(struct target *target)
++static int cortex_m_poll_one(struct target *target)
+ {
+ int detected_failure = ERROR_OK;
+ int retval = ERROR_OK;
+@@ -934,21 +935,26 @@ static int cortex_m_poll(struct target *target)
+
+ if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) {
+ retval = cortex_m_debug_entry(target);
+- if (retval != ERROR_OK)
+- return retval;
+
+- if (arm_semihosting(target, &retval) != 0)
++ /* arm_semihosting needs to know registers, don't run if debug entry returned error */
++ if (retval == ERROR_OK && arm_semihosting(target, &retval) != 0)
+ return retval;
+
+- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
++ if (target->smp) {
++ LOG_TARGET_DEBUG(target, "postpone target event 'halted'");
++ target->smp_halt_event_postponed = true;
++ } else {
++ /* regardless of errors returned in previous code update state */
++ target_call_event_callbacks(target, TARGET_EVENT_HALTED);
++ }
+ }
+ if (prev_target_state == TARGET_DEBUG_RUNNING) {
+ retval = cortex_m_debug_entry(target);
+- if (retval != ERROR_OK)
+- return retval;
+
+ target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+ }
++ if (retval != ERROR_OK)
++ return retval;
+ }
+
+ if (target->state == TARGET_UNKNOWN) {
+@@ -981,7 +987,104 @@ static int cortex_m_poll(struct target *target)
+ return retval;
+ }
+
+-static int cortex_m_halt(struct target *target)
++static int cortex_m_halt_one(struct target *target);
++
++static int cortex_m_smp_halt_all(struct list_head *smp_targets)
++{
++ int retval = ERROR_OK;
++ struct target_list *head;
++
++ foreach_smp_target(head, smp_targets) {
++ struct target *curr = head->target;
++ if (!target_was_examined(curr))
++ continue;
++ if (curr->state == TARGET_HALTED)
++ continue;
++
++ int ret2 = cortex_m_halt_one(curr);
++ if (retval == ERROR_OK)
++ retval = ret2; /* store the first error code ignore others */
++ }
++ return retval;
++}
++
++static int cortex_m_smp_post_halt_poll(struct list_head *smp_targets)
++{
++ int retval = ERROR_OK;
++ struct target_list *head;
++
++ foreach_smp_target(head, smp_targets) {
++ struct target *curr = head->target;
++ if (!target_was_examined(curr))
++ continue;
++ /* skip targets that were already halted */
++ if (curr->state == TARGET_HALTED)
++ continue;
++
++ int ret2 = cortex_m_poll_one(curr);
++ if (retval == ERROR_OK)
++ retval = ret2; /* store the first error code ignore others */
++ }
++ return retval;
++}
++
++static int cortex_m_poll_smp(struct list_head *smp_targets)
++{
++ int retval = ERROR_OK;
++ struct target_list *head;
++ bool halted = false;
++
++ foreach_smp_target(head, smp_targets) {
++ struct target *curr = head->target;
++ if (curr->smp_halt_event_postponed) {
++ halted = true;
++ break;
++ }
++ }
++
++ if (halted) {
++ retval = cortex_m_smp_halt_all(smp_targets);
++
++ int ret2 = cortex_m_smp_post_halt_poll(smp_targets);
++ if (retval == ERROR_OK)
++ retval = ret2; /* store the first error code ignore others */
++
++ foreach_smp_target(head, smp_targets) {
++ struct target *curr = head->target;
++ if (!curr->smp_halt_event_postponed)
++ continue;
++
++ curr->smp_halt_event_postponed = false;
++ if (curr->state == TARGET_HALTED) {
++ LOG_TARGET_DEBUG(curr, "sending postponed target event 'halted'");
++ target_call_event_callbacks(curr, TARGET_EVENT_HALTED);
++ }
++ }
++ /* There is no need to set gdb_service->target
++ * as hwthread_update_threads() selects an interesting thread
++ * by its own
++ */
++ }
++ return retval;
++}
++
++static int cortex_m_poll(struct target *target)
++{
++ int retval = cortex_m_poll_one(target);
++
++ if (target->smp) {
++ struct target_list *last;
++ last = list_last_entry(target->smp_targets, struct target_list, lh);
++ if (target == last->target)
++ /* After the last target in SMP group has been polled
++ * check for postponed halted events and eventually halt and re-poll
++ * other targets */
++ cortex_m_poll_smp(target->smp_targets);
++ }
++ return retval;
++}
++
++static int cortex_m_halt_one(struct target *target)
+ {
+ LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target));
+
+@@ -1019,6 +1122,14 @@ static int cortex_m_halt(struct target *target)
+ return ERROR_OK;
+ }
+
++static int cortex_m_halt(struct target *target)
++{
++ if (target->smp)
++ return cortex_m_smp_halt_all(target->smp_targets);
++ else
++ return cortex_m_halt_one(target);
++}
++
+ static int cortex_m_soft_reset_halt(struct target *target)
+ {
+ struct cortex_m_common *cortex_m = target_to_cm(target);
+@@ -1096,8 +1207,8 @@ void cortex_m_enable_breakpoints(struct target *target)
+ }
+ }
+
+-static int cortex_m_resume(struct target *target, int current,
+- target_addr_t address, int handle_breakpoints, int debug_execution)
++static int cortex_m_restore_one(struct target *target, bool current,
++ target_addr_t *address, bool handle_breakpoints, bool debug_execution)
+ {
+ struct armv7m_common *armv7m = target_to_armv7m(target);
+ struct breakpoint *breakpoint = NULL;
+@@ -1105,7 +1216,7 @@ static int cortex_m_resume(struct target *target, int current,
+ struct reg *r;
+
+ if (target->state != TARGET_HALTED) {
+- LOG_TARGET_WARNING(target, "target not halted");
++ LOG_TARGET_ERROR(target, "target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+@@ -1147,7 +1258,7 @@ static int cortex_m_resume(struct target *target, int current,
+ /* current = 1: continue on current pc, otherwise continue at <address> */
+ r = armv7m->arm.pc;
+ if (!current) {
+- buf_set_u32(r->value, 0, 32, address);
++ buf_set_u32(r->value, 0, 32, *address);
+ r->dirty = true;
+ r->valid = true;
+ }
+@@ -1161,8 +1272,12 @@ static int cortex_m_resume(struct target *target, int current,
+ armv7m_maybe_skip_bkpt_inst(target, NULL);
+
+ resume_pc = buf_get_u32(r->value, 0, 32);
++ if (current)
++ *address = resume_pc;
+
+- armv7m_restore_context(target);
++ int retval = armv7m_restore_context(target);
++ if (retval != ERROR_OK)
++ return retval;
+
+ /* the front-end may request us not to handle breakpoints */
+ if (handle_breakpoints) {
+@@ -1172,34 +1287,99 @@ static int cortex_m_resume(struct target *target, int current,
+ LOG_TARGET_DEBUG(target, "unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")",
+ breakpoint->address,
+ breakpoint->unique_id);
+- cortex_m_unset_breakpoint(target, breakpoint);
+- cortex_m_single_step_core(target);
+- cortex_m_set_breakpoint(target, breakpoint);
++ retval = cortex_m_unset_breakpoint(target, breakpoint);
++ if (retval == ERROR_OK)
++ retval = cortex_m_single_step_core(target);
++ int ret2 = cortex_m_set_breakpoint(target, breakpoint);
++ if (retval != ERROR_OK)
++ return retval;
++ if (ret2 != ERROR_OK)
++ return ret2;
+ }
+ }
+
++ return ERROR_OK;
++}
++
++static int cortex_m_restart_one(struct target *target, bool debug_execution)
++{
++ struct armv7m_common *armv7m = target_to_armv7m(target);
++
+ /* Restart core */
+ cortex_m_set_maskints_for_run(target);
+ cortex_m_write_debug_halt_mask(target, 0, C_HALT);
+
+ target->debug_reason = DBG_REASON_NOTHALTED;
+-
+ /* registers are now invalid */
+ register_cache_invalidate(armv7m->arm.core_cache);
+
+ if (!debug_execution) {
+ target->state = TARGET_RUNNING;
+ target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+- LOG_TARGET_DEBUG(target, "target resumed at 0x%" PRIx32 "", resume_pc);
+ } else {
+ target->state = TARGET_DEBUG_RUNNING;
+ target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
+- LOG_TARGET_DEBUG(target, "target debug resumed at 0x%" PRIx32 "", resume_pc);
+ }
+
+ return ERROR_OK;
+ }
+
++static int cortex_m_restore_smp(struct target *target, bool handle_breakpoints)
++{
++ struct target_list *head;
++ target_addr_t address;
++ foreach_smp_target(head, target->smp_targets) {
++ struct target *curr = head->target;
++ /* skip calling target */
++ if (curr == target)
++ continue;
++ if (!target_was_examined(curr))
++ continue;
++ /* skip running targets */
++ if (curr->state == TARGET_RUNNING)
++ continue;
++
++ int retval = cortex_m_restore_one(curr, true, &address,
++ handle_breakpoints, false);
++ if (retval != ERROR_OK)
++ return retval;
++
++ retval = cortex_m_restart_one(curr, false);
++ if (retval != ERROR_OK)
++ return retval;
++
++ LOG_TARGET_DEBUG(curr, "SMP resumed at " TARGET_ADDR_FMT, address);
++ }
++ return ERROR_OK;
++}
++
++static int cortex_m_resume(struct target *target, int current,
++ target_addr_t address, int handle_breakpoints, int debug_execution)
++{
++ int retval = cortex_m_restore_one(target, !!current, &address, !!handle_breakpoints, !!debug_execution);
++ if (retval != ERROR_OK) {
++ LOG_TARGET_ERROR(target, "context restore failed, aborting resume");
++ return retval;
++ }
++
++ if (target->smp && !debug_execution) {
++ retval = cortex_m_restore_smp(target, !!handle_breakpoints);
++ if (retval != ERROR_OK)
++ LOG_WARNING("resume of a SMP target failed, trying to resume current one");
++ }
++
++ cortex_m_restart_one(target, !!debug_execution);
++ if (retval != ERROR_OK) {
++ LOG_TARGET_ERROR(target, "resume failed");
++ return retval;
++ }
++
++ LOG_TARGET_DEBUG(target, "%sresumed at " TARGET_ADDR_FMT,
++ debug_execution ? "debug " : "", address);
++
++ return ERROR_OK;
++}
++
+ /* int irqstepcount = 0; */
+ static int cortex_m_step(struct target *target, int current,
+ target_addr_t address, int handle_breakpoints)
+@@ -1217,6 +1397,11 @@ static int cortex_m_step(struct target *target, int current,
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
++ /* Just one of SMP cores will step. Set the gdb control
++ * target to current one or gdb miss gdb-end event */
++ if (target->smp && target->gdb_service)
++ target->gdb_service->target = target;
++
+ /* current = 1: continue on current pc, otherwise continue at <address> */
+ if (!current) {
+ buf_set_u32(pc->value, 0, 32, address);
+@@ -2850,6 +3035,9 @@ static const struct command_registration cortex_m_exec_command_handlers[] = {
+ .help = "configure software reset handling",
+ .usage = "['sysresetreq'|'vectreset']",
+ },
++ {
++ .chain = smp_command_handlers,
++ },
+ COMMAND_REGISTRATION_DONE
+ };
+ static const struct command_registration cortex_m_command_handlers[] = {
+diff --git a/src/target/target.h b/src/target/target.h
+index d445c2975..ef9ba1062 100644
+--- a/src/target/target.h
++++ b/src/target/target.h
+@@ -193,6 +193,10 @@ struct target {
+ struct list_head *smp_targets; /* list all targets in this smp group/cluster
+ * The head of the list is shared between the
+ * cluster, thus here there is a pointer */
++ bool smp_halt_event_postponed; /* Some SMP implementations (currently Cortex-M) stores
++ * 'halted' events and emits them after all targets of
++ * the SMP group has been polled */
++
+ /* the gdb service is there in case of smp, we have only one gdb server
+ * for all smp target
+ * the target attached to the gdb is changing dynamically by changing
new file mode 100644
@@ -0,0 +1,103 @@
+From 0979cbc5bcf0688d10815aaa1b938a6086e75f0e Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sun, 2 Oct 2022 11:21:42 +0200
+Subject: [PATCH] flash/nor/rp2040: make SPI flash ID detection optional
+
+Do not read ID from SPI flash and suppress autodetection
+if non-zero flash bank size is configured.
+
+Change-Id: Idcf9ee6ca17f9fa89964a60da7bf11e47b4af5e7
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7241
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/rp2040.c | 55 +++++++++++++++++++++++++-----------------
+ 1 file changed, 33 insertions(+), 22 deletions(-)
+
+diff --git a/src/flash/nor/rp2040.c b/src/flash/nor/rp2040.c
+index feff9a6f9..b0d118bdb 100644
+--- a/src/flash/nor/rp2040.c
++++ b/src/flash/nor/rp2040.c
+@@ -50,6 +50,10 @@ struct rp2040_flash_bank {
+ const struct flash_device *dev;
+ };
+
++/* guessed SPI flash description if autodetection disabled (same as win w25q16jv) */
++static const struct flash_device rp2040_default_spi_device =
++ FLASH_ID("autodetect disabled", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0, 0x100, 0x10000, 0);
++
+ static uint32_t rp2040_lookup_symbol(struct target *target, uint32_t tag, uint16_t *symbol)
+ {
+ uint32_t magic;
+@@ -432,41 +436,48 @@ static int rp2040_flash_probe(struct flash_bank *bank)
+ return err;
+ }
+
+- err = rp2040_stack_grab_and_prep(bank);
++ if (bank->size) {
++ /* size overridden, suppress reading SPI flash ID */
++ priv->dev = &rp2040_default_spi_device;
++ LOG_DEBUG("SPI flash autodetection disabled, using configured size");
+
+- uint32_t device_id = 0;
+- if (err == ERROR_OK)
+- err = rp2040_spi_read_flash_id(target, &device_id);
++ } else {
++ /* zero bank size in cfg, read SPI flash ID and autodetect */
++ err = rp2040_stack_grab_and_prep(bank);
+
+- rp2040_finalize_stack_free(bank);
++ uint32_t device_id = 0;
++ if (err == ERROR_OK)
++ err = rp2040_spi_read_flash_id(target, &device_id);
+
+- if (err != ERROR_OK)
+- return err;
++ rp2040_finalize_stack_free(bank);
+
+- /* search for a SPI flash Device ID match */
+- priv->dev = NULL;
+- for (const struct flash_device *p = flash_devices; p->name ; p++)
+- if (p->device_id == device_id) {
+- priv->dev = p;
+- break;
++ if (err != ERROR_OK)
++ return err;
++
++ /* search for a SPI flash Device ID match */
++ priv->dev = NULL;
++ for (const struct flash_device *p = flash_devices; p->name ; p++)
++ if (p->device_id == device_id) {
++ priv->dev = p;
++ break;
++ }
++
++ if (!priv->dev) {
++ LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", device_id);
++ return ERROR_FAIL;
+ }
++ LOG_INFO("Found flash device '%s' (ID 0x%08" PRIx32 ")",
++ priv->dev->name, priv->dev->device_id);
+
+- if (!priv->dev) {
+- LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", device_id);
+- return ERROR_FAIL;
++ bank->size = priv->dev->size_in_bytes;
+ }
+
+- LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
+- priv->dev->name, priv->dev->device_id);
+-
+ /* the Boot ROM flash_range_program() routine requires page alignment */
+ bank->write_start_alignment = priv->dev->pagesize;
+ bank->write_end_alignment = priv->dev->pagesize;
+
+- bank->size = priv->dev->size_in_bytes;
+-
+ bank->num_sectors = bank->size / priv->dev->sectorsize;
+- LOG_INFO("RP2040 B0 Flash Probe: %d bytes @" TARGET_ADDR_FMT ", in %d sectors\n",
++ LOG_INFO("RP2040 B0 Flash Probe: %" PRIu32 " bytes @" TARGET_ADDR_FMT ", in %u sectors\n",
+ bank->size, bank->base, bank->num_sectors);
+ bank->sectors = alloc_block_array(0, priv->dev->sectorsize, bank->num_sectors);
+ if (!bank->sectors)
new file mode 100644
@@ -0,0 +1,51 @@
+From 8af4d4462fb1954ab4f5d97bc0513e3082a6bb52 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sun, 2 Oct 2022 14:46:11 +0200
+Subject: [PATCH] tcl/target: add SMP mode to rp2040.cfg
+
+Add the variable selected configuration for SMP debug with rtos hwthread.
+
+Use SMP by default.
+
+Change-Id: I1c37d91688a3ab58d65c15686737892965711adc
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7242
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ tcl/target/rp2040.cfg | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/tcl/target/rp2040.cfg b/tcl/target/rp2040.cfg
+index ee455420b..0593e03ba 100644
+--- a/tcl/target/rp2040.cfg
++++ b/tcl/target/rp2040.cfg
+@@ -26,12 +26,12 @@ if { [info exists CPUTAPID] } {
+ set _CPUTAPID 0x01002927
+ }
+
+-# Set to '0' or '1' for single core configuration,
+-# anything else for isolated debugging of both cores
++# Set to '0' or '1' for single core configuration, 'SMP' for -rtos hwthread
++# handling of both cores, anything else for isolated debugging of both cores
+ if { [info exists USE_CORE] } {
+ set _USE_CORE $USE_CORE
+ } else {
+- set _USE_CORE { 0 1 }
++ set _USE_CORE SMP
+ }
+ set _BOTH_CORES [expr { $_USE_CORE != 0 && $_USE_CORE != 1 }]
+
+@@ -54,6 +54,12 @@ if { $_USE_CORE != 0 } {
+ $_TARGETNAME_1 cortex_m reset_config sysresetreq
+ }
+
++if {[string compare $_USE_CORE SMP] == 0} {
++ $_TARGETNAME_0 configure -rtos hwthread
++ $_TARGETNAME_1 configure -rtos hwthread
++ target smp $_TARGETNAME_0 $_TARGETNAME_1
++}
++
+ if { $_USE_CORE == 1 } {
+ set _FLASH_TARGET $_TARGETNAME_1
+ } else {
new file mode 100644
@@ -0,0 +1,83 @@
+From 228fe7300c7df7aa05ba2c0bc19edde6d0156401 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Thu, 3 Nov 2022 10:32:36 +0100
+Subject: [PATCH] tcl/target: remove rp2040-core0.cfg
+
+rp2040-core0.cfg configuration file was intended for a special adapter
+which selects a SWD multidrop target on its own. This means
+that rp2040-core0.cfg is totally unusable with a standard SWD
+adapter. The file was marked as deprecated in 0.12 release.
+
+The reworked rp2040.cfg can be restricted to use just one core:
+ openocd ... -c 'set USE_CORE 0' -f target/rp2040.cfg
+
+Remove the obsoleted config.
+
+Change-Id: Id886471622bb4a8cb83f5c4c3660657407aaaf74
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7326
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ tcl/target/rp2040-core0.cfg | 52 -------------------------------------
+ 1 file changed, 52 deletions(-)
+ delete mode 100644 tcl/target/rp2040-core0.cfg
+
+diff --git a/tcl/target/rp2040-core0.cfg b/tcl/target/rp2040-core0.cfg
+deleted file mode 100644
+index 8a111bcbc..000000000
+--- a/tcl/target/rp2040-core0.cfg
++++ /dev/null
+@@ -1,52 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-# RP2040 is a microcontroller with dual Cortex-M0+ core.
+-# https://www.raspberrypi.com/documentation/microcontrollers/rp2040.html
+-
+-# The device requires multidrop SWD for debug.
+-# This configuration file is intended for a special adapter
+-# which selects a multidrop target on its own.
+-# Cannot be used with a standard SWD adapter!
+-
+-echo "Warn : rp2040-core0.cfg configuration file is deprecated and will be"
+-echo " removed in the next release. Use following parameters instead:"
+-echo " -c 'set USE_CORE 0' -f target/rp2040.cfg"
+-
+-transport select swd
+-
+-source [find target/swj-dp.tcl]
+-
+-if { [info exists CHIPNAME] } {
+- set _CHIPNAME $CHIPNAME
+-} else {
+- set _CHIPNAME rp2040
+-}
+-
+-if { [info exists WORKAREASIZE] } {
+- set _WORKAREASIZE $WORKAREASIZE
+-} else {
+- set _WORKAREASIZE 0x10000
+-}
+-
+-if { [info exists CPUTAPID] } {
+- set _CPUTAPID $CPUTAPID
+-} else {
+- set _CPUTAPID 0x01002927
+-}
+-
+-swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
+-dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
+-set _TARGETNAME $_CHIPNAME.cpu
+-target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap
+-
+-# Backup the work area. The flash probe runs an algorithm on the target CPU.
+-# The flash is probed during gdb connect if gdb_memory_map is enabled (by default).
+-$_TARGETNAME configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE -work-area-backup 1
+-
+-set _FLASHNAME $_CHIPNAME.flash
+-set _FLASHSIZE 0x200000
+-set _FLASHBASE 0x10000000
+-flash bank $_FLASHNAME rp2040_flash $_FLASHBASE $_FLASHSIZE 1 32 $_TARGETNAME
+-
+-# srst does not exist; use SYSRESETREQ to perform a soft reset
+-cortex_m reset_config sysresetreq
new file mode 100644
@@ -0,0 +1,71 @@
+From 27edeb775791a598a1e7997fd74078164e771ca6 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 17 Oct 2022 12:28:57 +0200
+Subject: [PATCH] riscv: drop deprecated command 'riscv set_prefer_sba'
+
+Change-Id: I546efe4e1a6b673b26cfb4a74b5c3809fecda49c
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7271
+Tested-by: jenkins
+Reviewed-by: Jan Matyas <matyas@codasip.com>
+---
+ src/target/riscv/riscv.c | 39 ---------------------------------------
+ 1 file changed, 39 deletions(-)
+
+diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
+index 4f24fb41e..dcd25fa08 100644
+--- a/src/target/riscv/riscv.c
++++ b/src/target/riscv/riscv.c
+@@ -2367,37 +2367,6 @@ COMMAND_HANDLER(riscv_set_reset_timeout_sec)
+ return ERROR_OK;
+ }
+
+-COMMAND_HANDLER(riscv_set_prefer_sba)
+-{
+- struct target *target = get_current_target(CMD_CTX);
+- RISCV_INFO(r);
+- bool prefer_sba;
+- LOG_WARNING("`riscv set_prefer_sba` is deprecated. Please use `riscv set_mem_access` instead.");
+- if (CMD_ARGC != 1) {
+- LOG_ERROR("Command takes exactly 1 parameter");
+- return ERROR_COMMAND_SYNTAX_ERROR;
+- }
+- COMMAND_PARSE_ON_OFF(CMD_ARGV[0], prefer_sba);
+- if (prefer_sba) {
+- /* Use system bus with highest priority */
+- r->mem_access_methods[0] = RISCV_MEM_ACCESS_SYSBUS;
+- r->mem_access_methods[1] = RISCV_MEM_ACCESS_PROGBUF;
+- r->mem_access_methods[2] = RISCV_MEM_ACCESS_ABSTRACT;
+- } else {
+- /* Use progbuf with highest priority */
+- r->mem_access_methods[0] = RISCV_MEM_ACCESS_PROGBUF;
+- r->mem_access_methods[1] = RISCV_MEM_ACCESS_SYSBUS;
+- r->mem_access_methods[2] = RISCV_MEM_ACCESS_ABSTRACT;
+- }
+-
+- /* Reset warning flags */
+- r->mem_access_progbuf_warn = true;
+- r->mem_access_sysbus_warn = true;
+- r->mem_access_abstract_warn = true;
+-
+- return ERROR_OK;
+-}
+-
+ COMMAND_HANDLER(riscv_set_mem_access)
+ {
+ struct target *target = get_current_target(CMD_CTX);
+@@ -2948,14 +2917,6 @@ static const struct command_registration riscv_exec_command_handlers[] = {
+ .usage = "[sec]",
+ .help = "Set the wall-clock timeout (in seconds) after reset is deasserted"
+ },
+- {
+- .name = "set_prefer_sba",
+- .handler = riscv_set_prefer_sba,
+- .mode = COMMAND_ANY,
+- .usage = "on|off",
+- .help = "When on, prefer to use System Bus Access to access memory. "
+- "When off (default), prefer to use the Program Buffer to access memory."
+- },
+ {
+ .name = "set_mem_access",
+ .handler = riscv_set_mem_access,
new file mode 100644
@@ -0,0 +1,480 @@
+From f2fc23e16b648c3d5600b5cc44bee69a1e697a3a Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 17 Oct 2022 12:34:23 +0200
+Subject: [PATCH] riscv: drop deprecated command 'riscv test_sba_config_reg'
+
+Change-Id: I51c1b1cb3de8cb86ee38280fa3f035f6f7a63dbc
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7272
+Reviewed-by: Jan Matyas <matyas@codasip.com>
+Reviewed-by: Tim Newsome <tim@sifive.com>
+Tested-by: jenkins
+---
+ src/target/riscv/riscv-013.c | 361 -----------------------------------
+ src/target/riscv/riscv.c | 45 -----
+ src/target/riscv/riscv.h | 3 -
+ 3 files changed, 409 deletions(-)
+
+diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
+index 99d3873de..4e6c8dc36 100644
+--- a/src/target/riscv/riscv-013.c
++++ b/src/target/riscv/riscv-013.c
+@@ -65,12 +65,6 @@ static int read_memory(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment);
+ static int write_memory(struct target *target, target_addr_t address,
+ uint32_t size, uint32_t count, const uint8_t *buffer);
+-static int riscv013_test_sba_config_reg(struct target *target, target_addr_t legal_address,
+- uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test);
+-static void write_memory_sba_simple(struct target *target, target_addr_t addr, uint32_t *write_data,
+- uint32_t write_size, uint32_t sbcs);
+-static void read_memory_sba_simple(struct target *target, target_addr_t addr,
+- uint32_t *rd_buf, uint32_t read_size, uint32_t sbcs);
+
+ /**
+ * Since almost everything can be accomplish by scanning the dbus register, all
+@@ -2307,7 +2301,6 @@ static int init_target(struct command_context *cmd_ctx,
+ generic_info->dmi_read = &dmi_read;
+ generic_info->dmi_write = &dmi_write;
+ generic_info->read_memory = read_memory;
+- generic_info->test_sba_config_reg = &riscv013_test_sba_config_reg;
+ generic_info->hart_count = &riscv013_hart_count;
+ generic_info->data_bits = &riscv013_data_bits;
+ generic_info->print_info = &riscv013_print_info;
+@@ -4408,360 +4401,6 @@ void riscv013_fill_dmi_nop_u64(struct target *target, char *buf)
+ buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, 0);
+ }
+
+-/* Helper function for riscv013_test_sba_config_reg */
+-static int get_max_sbaccess(struct target *target)
+-{
+- RISCV013_INFO(info);
+-
+- uint32_t sbaccess128 = get_field(info->sbcs, DM_SBCS_SBACCESS128);
+- uint32_t sbaccess64 = get_field(info->sbcs, DM_SBCS_SBACCESS64);
+- uint32_t sbaccess32 = get_field(info->sbcs, DM_SBCS_SBACCESS32);
+- uint32_t sbaccess16 = get_field(info->sbcs, DM_SBCS_SBACCESS16);
+- uint32_t sbaccess8 = get_field(info->sbcs, DM_SBCS_SBACCESS8);
+-
+- if (sbaccess128)
+- return 4;
+- else if (sbaccess64)
+- return 3;
+- else if (sbaccess32)
+- return 2;
+- else if (sbaccess16)
+- return 1;
+- else if (sbaccess8)
+- return 0;
+- else
+- return -1;
+-}
+-
+-static uint32_t get_num_sbdata_regs(struct target *target)
+-{
+- RISCV013_INFO(info);
+-
+- uint32_t sbaccess128 = get_field(info->sbcs, DM_SBCS_SBACCESS128);
+- uint32_t sbaccess64 = get_field(info->sbcs, DM_SBCS_SBACCESS64);
+- uint32_t sbaccess32 = get_field(info->sbcs, DM_SBCS_SBACCESS32);
+-
+- if (sbaccess128)
+- return 4;
+- else if (sbaccess64)
+- return 2;
+- else if (sbaccess32)
+- return 1;
+- else
+- return 0;
+-}
+-
+-static int riscv013_test_sba_config_reg(struct target *target,
+- target_addr_t legal_address, uint32_t num_words,
+- target_addr_t illegal_address, bool run_sbbusyerror_test)
+-{
+- LOG_INFO("Testing System Bus Access as defined by RISC-V Debug Spec v0.13");
+-
+- uint32_t tests_failed = 0;
+-
+- uint32_t rd_val;
+- uint32_t sbcs_orig;
+- int retval = dmi_read(target, &sbcs_orig, DM_SBCS);
+- if (retval != ERROR_OK)
+- return retval;
+-
+- uint32_t sbcs = sbcs_orig;
+- bool test_passed;
+-
+- int max_sbaccess = get_max_sbaccess(target);
+-
+- if (max_sbaccess == -1) {
+- LOG_ERROR("System Bus Access not supported in this config.");
+- return ERROR_FAIL;
+- }
+-
+- if (get_field(sbcs, DM_SBCS_SBVERSION) != 1) {
+- LOG_ERROR("System Bus Access unsupported SBVERSION (%d). Only version 1 is supported.",
+- get_field(sbcs, DM_SBCS_SBVERSION));
+- return ERROR_FAIL;
+- }
+-
+- uint32_t num_sbdata_regs = get_num_sbdata_regs(target);
+- assert(num_sbdata_regs);
+-
+- uint32_t rd_buf[num_sbdata_regs];
+-
+- /* Test 1: Simple write/read test */
+- test_passed = true;
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBAUTOINCREMENT, 0);
+- dmi_write(target, DM_SBCS, sbcs);
+-
+- uint32_t test_patterns[4] = {0xdeadbeef, 0xfeedbabe, 0x12345678, 0x08675309};
+- for (uint32_t sbaccess = 0; sbaccess <= (uint32_t)max_sbaccess; sbaccess++) {
+- sbcs = set_field(sbcs, DM_SBCS_SBACCESS, sbaccess);
+- dmi_write(target, DM_SBCS, sbcs);
+-
+- uint32_t compare_mask = (sbaccess == 0) ? 0xff : (sbaccess == 1) ? 0xffff : 0xffffffff;
+-
+- for (uint32_t i = 0; i < num_words; i++) {
+- uint32_t addr = legal_address + (i << sbaccess);
+- uint32_t wr_data[num_sbdata_regs];
+- for (uint32_t j = 0; j < num_sbdata_regs; j++)
+- wr_data[j] = test_patterns[j] + i;
+- write_memory_sba_simple(target, addr, wr_data, num_sbdata_regs, sbcs);
+- }
+-
+- for (uint32_t i = 0; i < num_words; i++) {
+- uint32_t addr = legal_address + (i << sbaccess);
+- read_memory_sba_simple(target, addr, rd_buf, num_sbdata_regs, sbcs);
+- for (uint32_t j = 0; j < num_sbdata_regs; j++) {
+- if (((test_patterns[j]+i)&compare_mask) != (rd_buf[j]&compare_mask)) {
+- LOG_ERROR("System Bus Access Test 1: Error reading non-autoincremented address %x,"
+- "expected val = %x, read val = %x", addr, test_patterns[j]+i, rd_buf[j]);
+- test_passed = false;
+- tests_failed++;
+- }
+- }
+- }
+- }
+- if (test_passed)
+- LOG_INFO("System Bus Access Test 1: Simple write/read test PASSED.");
+-
+- /* Test 2: Address autoincrement test */
+- target_addr_t curr_addr;
+- target_addr_t prev_addr;
+- test_passed = true;
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBAUTOINCREMENT, 1);
+- dmi_write(target, DM_SBCS, sbcs);
+-
+- for (uint32_t sbaccess = 0; sbaccess <= (uint32_t)max_sbaccess; sbaccess++) {
+- sbcs = set_field(sbcs, DM_SBCS_SBACCESS, sbaccess);
+- dmi_write(target, DM_SBCS, sbcs);
+-
+- dmi_write(target, DM_SBADDRESS0, legal_address);
+- read_sbcs_nonbusy(target, &sbcs);
+- curr_addr = legal_address;
+- for (uint32_t i = 0; i < num_words; i++) {
+- prev_addr = curr_addr;
+- read_sbcs_nonbusy(target, &sbcs);
+- curr_addr = sb_read_address(target);
+- if ((curr_addr - prev_addr != (uint32_t)(1 << sbaccess)) && (i != 0)) {
+- LOG_ERROR("System Bus Access Test 2: Error with address auto-increment, sbaccess = %x.", sbaccess);
+- test_passed = false;
+- tests_failed++;
+- }
+- dmi_write(target, DM_SBDATA0, i);
+- }
+-
+- read_sbcs_nonbusy(target, &sbcs);
+-
+- dmi_write(target, DM_SBADDRESS0, legal_address);
+-
+- uint32_t val;
+- sbcs = set_field(sbcs, DM_SBCS_SBREADONDATA, 1);
+- dmi_write(target, DM_SBCS, sbcs);
+- dmi_read(target, &val, DM_SBDATA0); /* Dummy read to trigger first system bus read */
+- curr_addr = legal_address;
+- for (uint32_t i = 0; i < num_words; i++) {
+- prev_addr = curr_addr;
+- read_sbcs_nonbusy(target, &sbcs);
+- curr_addr = sb_read_address(target);
+- if ((curr_addr - prev_addr != (uint32_t)(1 << sbaccess)) && (i != 0)) {
+- LOG_ERROR("System Bus Access Test 2: Error with address auto-increment, sbaccess = %x", sbaccess);
+- test_passed = false;
+- tests_failed++;
+- }
+- dmi_read(target, &val, DM_SBDATA0);
+- read_sbcs_nonbusy(target, &sbcs);
+- if (i != val) {
+- LOG_ERROR("System Bus Access Test 2: Error reading auto-incremented address,"
+- "expected val = %x, read val = %x.", i, val);
+- test_passed = false;
+- tests_failed++;
+- }
+- }
+- }
+- if (test_passed)
+- LOG_INFO("System Bus Access Test 2: Address auto-increment test PASSED.");
+-
+- /* Test 3: Read from illegal address */
+- read_memory_sba_simple(target, illegal_address, rd_buf, 1, sbcs_orig);
+-
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBERROR) == 2) {
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBERROR, 2);
+- dmi_write(target, DM_SBCS, sbcs);
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBERROR) == 0)
+- LOG_INFO("System Bus Access Test 3: Illegal address read test PASSED.");
+- else
+- LOG_ERROR("System Bus Access Test 3: Illegal address read test FAILED, unable to clear to 0.");
+- } else {
+- LOG_ERROR("System Bus Access Test 3: Illegal address read test FAILED, unable to set error code.");
+- }
+-
+- /* Test 4: Write to illegal address */
+- write_memory_sba_simple(target, illegal_address, test_patterns, 1, sbcs_orig);
+-
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBERROR) == 2) {
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBERROR, 2);
+- dmi_write(target, DM_SBCS, sbcs);
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBERROR) == 0)
+- LOG_INFO("System Bus Access Test 4: Illegal address write test PASSED.");
+- else {
+- LOG_ERROR("System Bus Access Test 4: Illegal address write test FAILED, unable to clear to 0.");
+- tests_failed++;
+- }
+- } else {
+- LOG_ERROR("System Bus Access Test 4: Illegal address write test FAILED, unable to set error code.");
+- tests_failed++;
+- }
+-
+- /* Test 5: Write with unsupported sbaccess size */
+- uint32_t sbaccess128 = get_field(sbcs_orig, DM_SBCS_SBACCESS128);
+-
+- if (sbaccess128) {
+- LOG_INFO("System Bus Access Test 5: SBCS sbaccess error test PASSED, all sbaccess sizes supported.");
+- } else {
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBACCESS, 4);
+-
+- write_memory_sba_simple(target, legal_address, test_patterns, 1, sbcs);
+-
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBERROR) == 4) {
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBERROR, 4);
+- dmi_write(target, DM_SBCS, sbcs);
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBERROR) == 0)
+- LOG_INFO("System Bus Access Test 5: SBCS sbaccess error test PASSED.");
+- else {
+- LOG_ERROR("System Bus Access Test 5: SBCS sbaccess error test FAILED, unable to clear to 0.");
+- tests_failed++;
+- }
+- } else {
+- LOG_ERROR("System Bus Access Test 5: SBCS sbaccess error test FAILED, unable to set error code.");
+- tests_failed++;
+- }
+- }
+-
+- /* Test 6: Write to misaligned address */
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBACCESS, 1);
+-
+- write_memory_sba_simple(target, legal_address+1, test_patterns, 1, sbcs);
+-
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBERROR) == 3) {
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBERROR, 3);
+- dmi_write(target, DM_SBCS, sbcs);
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBERROR) == 0)
+- LOG_INFO("System Bus Access Test 6: SBCS address alignment error test PASSED");
+- else {
+- LOG_ERROR("System Bus Access Test 6: SBCS address alignment error test FAILED, unable to clear to 0.");
+- tests_failed++;
+- }
+- } else {
+- LOG_ERROR("System Bus Access Test 6: SBCS address alignment error test FAILED, unable to set error code.");
+- tests_failed++;
+- }
+-
+- /* Test 7: Set sbbusyerror, only run this case in simulation as it is likely
+- * impossible to hit otherwise */
+- if (run_sbbusyerror_test) {
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBREADONADDR, 1);
+- dmi_write(target, DM_SBCS, sbcs);
+-
+- for (int i = 0; i < 16; i++)
+- dmi_write(target, DM_SBDATA0, 0xdeadbeef);
+-
+- for (int i = 0; i < 16; i++)
+- dmi_write(target, DM_SBADDRESS0, legal_address);
+-
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBBUSYERROR)) {
+- sbcs = set_field(sbcs_orig, DM_SBCS_SBBUSYERROR, 1);
+- dmi_write(target, DM_SBCS, sbcs);
+- dmi_read(target, &rd_val, DM_SBCS);
+- if (get_field(rd_val, DM_SBCS_SBBUSYERROR) == 0)
+- LOG_INFO("System Bus Access Test 7: SBCS sbbusyerror test PASSED.");
+- else {
+- LOG_ERROR("System Bus Access Test 7: SBCS sbbusyerror test FAILED, unable to clear to 0.");
+- tests_failed++;
+- }
+- } else {
+- LOG_ERROR("System Bus Access Test 7: SBCS sbbusyerror test FAILED, unable to set error code.");
+- tests_failed++;
+- }
+- }
+-
+- if (tests_failed == 0) {
+- LOG_INFO("ALL TESTS PASSED");
+- return ERROR_OK;
+- } else {
+- LOG_ERROR("%d TESTS FAILED", tests_failed);
+- return ERROR_FAIL;
+- }
+-
+-}
+-
+-static void write_memory_sba_simple(struct target *target, target_addr_t addr,
+- uint32_t *write_data, uint32_t write_size, uint32_t sbcs)
+-{
+- RISCV013_INFO(info);
+-
+- uint32_t rd_sbcs;
+- uint32_t masked_addr;
+-
+- uint32_t sba_size = get_field(info->sbcs, DM_SBCS_SBASIZE);
+-
+- read_sbcs_nonbusy(target, &rd_sbcs);
+-
+- uint32_t sbcs_no_readonaddr = set_field(sbcs, DM_SBCS_SBREADONADDR, 0);
+- dmi_write(target, DM_SBCS, sbcs_no_readonaddr);
+-
+- for (uint32_t i = 0; i < sba_size/32; i++) {
+- masked_addr = (addr >> 32*i) & 0xffffffff;
+-
+- if (i != 3)
+- dmi_write(target, DM_SBADDRESS0+i, masked_addr);
+- else
+- dmi_write(target, DM_SBADDRESS3, masked_addr);
+- }
+-
+- /* Write SBDATA registers starting with highest address, since write to
+- * SBDATA0 triggers write */
+- for (int i = write_size-1; i >= 0; i--)
+- dmi_write(target, DM_SBDATA0+i, write_data[i]);
+-}
+-
+-static void read_memory_sba_simple(struct target *target, target_addr_t addr,
+- uint32_t *rd_buf, uint32_t read_size, uint32_t sbcs)
+-{
+- RISCV013_INFO(info);
+-
+- uint32_t rd_sbcs;
+- uint32_t masked_addr;
+-
+- uint32_t sba_size = get_field(info->sbcs, DM_SBCS_SBASIZE);
+-
+- read_sbcs_nonbusy(target, &rd_sbcs);
+-
+- uint32_t sbcs_readonaddr = set_field(sbcs, DM_SBCS_SBREADONADDR, 1);
+- dmi_write(target, DM_SBCS, sbcs_readonaddr);
+-
+- /* Write addresses starting with highest address register */
+- for (int i = sba_size/32-1; i >= 0; i--) {
+- masked_addr = (addr >> 32*i) & 0xffffffff;
+-
+- if (i != 3)
+- dmi_write(target, DM_SBADDRESS0+i, masked_addr);
+- else
+- dmi_write(target, DM_SBADDRESS3, masked_addr);
+- }
+-
+- read_sbcs_nonbusy(target, &rd_sbcs);
+-
+- for (uint32_t i = 0; i < read_size; i++)
+- dmi_read(target, &(rd_buf[i]), DM_SBDATA0+i);
+-}
+-
+ int riscv013_dmi_write_u64_bits(struct target *target)
+ {
+ RISCV013_INFO(info);
+diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
+index dcd25fa08..8dafa02b4 100644
+--- a/src/target/riscv/riscv.c
++++ b/src/target/riscv/riscv.c
+@@ -2711,38 +2711,6 @@ COMMAND_HANDLER(riscv_dmi_write)
+ }
+ }
+
+-COMMAND_HANDLER(riscv_test_sba_config_reg)
+-{
+- LOG_WARNING("Command \"riscv test_sba_config_reg\" is deprecated. "
+- "It will be removed in a future OpenOCD version.");
+-
+- if (CMD_ARGC != 4) {
+- LOG_ERROR("Command takes exactly 4 arguments");
+- return ERROR_COMMAND_SYNTAX_ERROR;
+- }
+-
+- struct target *target = get_current_target(CMD_CTX);
+- RISCV_INFO(r);
+-
+- target_addr_t legal_address;
+- uint32_t num_words;
+- target_addr_t illegal_address;
+- bool run_sbbusyerror_test;
+-
+- COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[0], legal_address);
+- COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], num_words);
+- COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[2], illegal_address);
+- COMMAND_PARSE_ON_OFF(CMD_ARGV[3], run_sbbusyerror_test);
+-
+- if (r->test_sba_config_reg) {
+- return r->test_sba_config_reg(target, legal_address, num_words,
+- illegal_address, run_sbbusyerror_test);
+- } else {
+- LOG_ERROR("test_sba_config_reg is not implemented for this target.");
+- return ERROR_FAIL;
+- }
+-}
+-
+ COMMAND_HANDLER(riscv_reset_delays)
+ {
+ int wait = 0;
+@@ -2982,19 +2950,6 @@ static const struct command_registration riscv_exec_command_handlers[] = {
+ .usage = "address value",
+ .help = "Perform a 32-bit DMI write of value at address."
+ },
+- {
+- .name = "test_sba_config_reg",
+- .handler = riscv_test_sba_config_reg,
+- .mode = COMMAND_ANY,
+- .usage = "legal_address num_words "
+- "illegal_address run_sbbusyerror_test[on/off]",
+- .help = "Perform a series of tests on the SBCS register. "
+- "Inputs are a legal, 128-byte aligned address and a number of words to "
+- "read/write starting at that address (i.e., address range [legal address, "
+- "legal_address+word_size*num_words) must be legally readable/writable), "
+- "an illegal, 128-byte aligned address for error flag/handling cases, "
+- "and whether sbbusyerror test should be run."
+- },
+ {
+ .name = "reset_delays",
+ .handler = riscv_reset_delays,
+diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
+index e7e4c650b..aba0864e6 100644
+--- a/src/target/riscv/riscv.h
++++ b/src/target/riscv/riscv.h
+@@ -174,9 +174,6 @@ struct riscv_info {
+ int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address);
+ int (*dmi_write)(struct target *target, uint32_t address, uint32_t value);
+
+- int (*test_sba_config_reg)(struct target *target, target_addr_t legal_address,
+- uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test);
+-
+ int (*sample_memory)(struct target *target,
+ struct riscv_sample_buf *buf,
+ riscv_sample_config_t *config,
new file mode 100644
@@ -0,0 +1,66 @@
+From 30631224da59608d93f56bac0f68acd6c8fd32ac Mon Sep 17 00:00:00 2001
+From: Jan Matyas <matyas@codasip.com>
+Date: Mon, 17 Oct 2022 08:24:05 +0200
+Subject: [PATCH] adapter: Improve three adapter-related prints
+
+- Do not warn the user about adapter speed not being set
+ if the selected adapter does not support configurable speed.
+ This would be confusing to users.
+
+- Minor reword in the "adapter speed is not selected" warning.
+
+- Print the adapter name in the "adapter doesn't support
+ configurable speed" log entry
+
+- Another minor reword: autoselect --> autoselecting
+
+Signed-off-by: Jan Matyas <matyas@codasip.com>
+Change-Id: I4c198b547544fd8199921f092153562c5f159134
+Reviewed-on: https://review.openocd.org/c/openocd/+/7269
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/adapter.c | 8 +++++---
+ src/transport/transport.c | 2 +-
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
+index b7feac575..eb73fcb9a 100644
+--- a/src/jtag/adapter.c
++++ b/src/jtag/adapter.c
+@@ -136,9 +136,11 @@ int adapter_init(struct command_context *cmd_ctx)
+
+ int retval;
+
+- if (adapter_config.clock_mode == CLOCK_MODE_UNSELECTED) {
++ /* If the adapter supports configurable speed but the speed is not configured,
++ * provide a hint to the user. */
++ if (adapter_driver->speed && adapter_config.clock_mode == CLOCK_MODE_UNSELECTED) {
+ LOG_WARNING("An adapter speed is not selected in the init scripts."
+- " OpenOCD will try to run the adapter at the low speed (%d kHz)",
++ " OpenOCD will try to run the adapter at very low speed (%d kHz).",
+ DEFAULT_CLOCK_SPEED_KHZ);
+ LOG_WARNING("To remove this warnings and achieve reasonable communication speed with the target,"
+ " set \"adapter speed\" or \"jtag_rclk\" in the init scripts.");
+@@ -153,7 +155,7 @@ int adapter_init(struct command_context *cmd_ctx)
+ adapter_config.adapter_initialized = true;
+
+ if (!adapter_driver->speed) {
+- LOG_INFO("This adapter doesn't support configurable speed");
++ LOG_INFO("Note: The adapter \"%s\" doesn't support configurable speed", adapter_driver->name);
+ return ERROR_OK;
+ }
+
+diff --git a/src/transport/transport.c b/src/transport/transport.c
+index d72a48baa..c05db3f00 100644
+--- a/src/transport/transport.c
++++ b/src/transport/transport.c
+@@ -104,7 +104,7 @@ int allow_transports(struct command_context *ctx, const char * const *vector)
+
+ /* autoselect if there's no choice ... */
+ if (!vector[1]) {
+- LOG_INFO("only one transport option; autoselect '%s'", vector[0]);
++ LOG_INFO("only one transport option; autoselecting '%s'", vector[0]);
+ return transport_select(ctx, vector[0]);
+ }
+
new file mode 100644
@@ -0,0 +1,29 @@
+From 66da6f20e4df20511828424d835dfade7dd9d535 Mon Sep 17 00:00:00 2001
+From: Tarek BOCHKATI <tarek.bouchkati@st.com>
+Date: Thu, 20 Oct 2022 20:48:48 +0100
+Subject: [PATCH] flash/stm32l4x: avoid multiple assignments
+
+Change-Id: I6d8e0fbfa7e05f26295fc22733c65c11f7460b51
+Signed-off-by: Tarek BOCHKATI <tarek.bouchkati@st.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7282
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Tested-by: jenkins
+---
+ src/flash/nor/stm32l4x.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
+index 7a6ec3fd2..92d511c17 100644
+--- a/src/flash/nor/stm32l4x.c
++++ b/src/flash/nor/stm32l4x.c
+@@ -1740,7 +1740,8 @@ static int stm32l4_probe(struct flash_bank *bank)
+
+ /* Set flash write alignment boundaries.
+ * Ask the flash infrastructure to ensure required alignment */
+- bank->write_start_alignment = bank->write_end_alignment = stm32l4_info->data_width;
++ bank->write_start_alignment = stm32l4_info->data_width;
++ bank->write_end_alignment = stm32l4_info->data_width;
+
+ /* Initialize the flash registers layout */
+ if (part_info->flags & F_HAS_L5_FLASH_REGS)
new file mode 100644
@@ -0,0 +1,34 @@
+From 11ee500bffe488eba95cea37c99cee6b196e04ff Mon Sep 17 00:00:00 2001
+From: Boris-Chengbiao Zhou <bobo1239@web.de>
+Date: Wed, 26 Oct 2022 03:10:17 +0200
+Subject: [PATCH] target/armv7m: Rename xPSR to xpsr
+
+The org.gnu.gdb.arm.m-system GDB feature defines the name in lowercase
+letters.[1] Not adhering to the definition can cause issues with tools
+interacting with the GDB which expect the correct casing.
+
+[1]: https://sourceware.org/gdb/onlinedocs/gdb/ARM-Features.html
+
+Change-Id: I0b6584a78f86b053947d79686baad5dac3ec4a00
+Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7292
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/armv7m.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/target/armv7m.c b/src/target/armv7m.c
+index 1b85315de..5745681d4 100644
+--- a/src/target/armv7m.c
++++ b/src/target/armv7m.c
+@@ -97,7 +97,7 @@ static const struct {
+ { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile" },
+- { ARMV7M_XPSR, "xPSR", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
++ { ARMV7M_XPSR, "xpsr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+
+ { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
+ { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
new file mode 100644
@@ -0,0 +1,1395 @@
+From 776e045de0a2ce6644ae19de99820f02628dfbcc Mon Sep 17 00:00:00 2001
+From: Zale Yu <cyyu@nuvoton.com>
+Date: Sun, 6 Nov 2022 22:54:37 +0800
+Subject: [PATCH] flash/nor/numicro: reorder the parts list
+
+This patch is picked from the flash part of OpenOCD-Nuvoton's commit
+("flash: supported Nuvoton M4 series. jtag: Used HW reset instead of
+auto reset. tcl: added a configuration file for Nuvoton M4 series.") [1]
+It reorders Nuvoton MCU part list and spreads out the way to define the
+banks' base address & size of the parts.
+
+The code comes from the commit basically. Jian-Hong Pan tweaked for the
+compatibility with current OpenOCD. So, leave the author as Zale Yu.
+
+[1]: https://github.com/OpenNuvoton/OpenOCD-Nuvoton/commit/c2d5b8bfc705
+
+Signed-off-by: Zale Yu <cyyu@nuvoton.com>
+Signed-off-by: Jian-Hong Pan <chienhung.pan@gmail.com>
+Change-Id: I1f21f54dfdf53e5b8ea04d803347d1dbc8c321a0
+Reviewed-on: https://review.openocd.org/c/openocd/+/7339
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/numicro.c | 1347 ++++++++++-----------------------------
+ 1 file changed, 349 insertions(+), 998 deletions(-)
+
+diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c
+index 1a73eb26d..bafad80ce 100644
+--- a/src/flash/nor/numicro.c
++++ b/src/flash/nor/numicro.c
+@@ -12,6 +12,12 @@
+ * *
+ * Copyright (C) 2015 Nemui Trinomius *
+ * nemuisan_kawausogasuki@live.jp *
++ * *
++ * Copyright (C) 2017 Zale Yu *
++ * CYYU@nuvoton.com *
++ * *
++ * Copyright (C) 2022 Jian-Hong Pan *
++ * chienhung.pan@gmail.com *
+ ***************************************************************************/
+
+ #ifdef HAVE_CONFIG_H
+@@ -114,1008 +120,353 @@ struct numicro_cpu_type {
+ struct numicro_flash_bank_type bank[NUMICRO_MAX_FLASH_BANKS];
+ };
+
+-/* TODO : Support variable DataFlash region for 128kB Flash model */
+-#define NUMICRO_BANKS_NUC100(aprom_size) \
+- .n_banks = 4, \
+- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 4*1024}, \
+- {NUMICRO_CONFIG_BASE, 1024} }
+-
+-#define NUMICRO_BANKS_M051(aprom_size) \
+- .n_banks = 4, \
+- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 4*1024}, \
+- {NUMICRO_CONFIG_BASE, 1024} }
+-
+-#define NUMICRO_BANKS_MINI51(aprom_size) \
+- .n_banks = 3, \
+- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_LDROM_BASE, 2*1024}, {NUMICRO_CONFIG_BASE, 512} }
+-
+-#define NUMICRO_BANKS_NANO(aprom_size) \
++/* If DataFlash size equals zero, it means the actual size depends on config settings. */
++#define NUMICRO_BANKS_GENERAL(aprom_size, data_size, ldrom_size, config_size) \
+ .n_banks = 4, \
+- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 4*1024}, \
+- {NUMICRO_CONFIG_BASE, 1024} }
+-
+-#define NUMICRO_BANKS_NUC400(aprom_size) \
+- .n_banks = 4, \
+- { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 16*1024}, \
+- {NUMICRO_CONFIG_BASE, 1024} }
+-
++ {{NUMICRO_APROM_BASE, (aprom_size)}, \
++ {NUMICRO_DATA_BASE, (data_size)}, \
++ {NUMICRO_LDROM_BASE, (ldrom_size)}, \
++ {NUMICRO_CONFIG_BASE, (config_size)}}
+
+ static const struct numicro_cpu_type numicro_parts[] = {
+ /*PART NO*/ /*PART ID*/ /*Banks*/
+- /* NUC100 Version B */
+- {"NUC100LD2BN", 0x10010004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LD1BN", 0x10010005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LD0BN", 0x10010027, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LC2BN", 0x10010007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100LC1BN", 0x10010008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100LC0BN", 0x10010028, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100LB2BN", 0x10010029, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC100LB1BN", 0x10010030, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC100LB0BN", 0x10010031, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC100LA2BN", 0x10010032, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC100LA1BN", 0x10010033, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC100LA0BN", 0x10010034, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- {"NUC100RD2BN", 0x10010013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RD1BN", 0x10010014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RD0BN", 0x10010035, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RC2BN", 0x10010016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RC1BN", 0x10010017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RC0BN", 0x10010036, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RB2BN", 0x10010037, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC100RB1BN", 0x10010038, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC100RB0BN", 0x10010039, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC100RA2BN", 0x10010040, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC100RA1BN", 0x10010041, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC100RA0BN", 0x10010042, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- /* NUC100 Version C */
+- {"NUC100LE3CN", 0x20010000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100LE2CN", 0x20010001, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100LE1CN", 0x20010002, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100LD3CN", 0x20010003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LD2CN", 0x20010004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LD1CN", 0x20010005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LC3CN", 0x20010006, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100LC2CN", 0x20010007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100LC1CN", 0x20010008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RE3CN", 0x20010009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100RE2CN", 0x20010010, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100RE1CN", 0x20010011, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100RD3CN", 0x20010012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RD2CN", 0x20010013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RD1CN", 0x20010014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RC3CN", 0x20010015, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RC2CN", 0x20010016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RC1CN", 0x20010017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100VE3CN", 0x20010018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100VE2CN", 0x20010019, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100VE1CN", 0x20010020, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100VD3CN", 0x20010021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100VD2CN", 0x20010022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100VD1CN", 0x20010023, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100VC3CN", 0x20010024, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100VC2CN", 0x20010025, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100VC1CN", 0x20010026, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- /* NUC100 Version B */
+- {"NUC101YD2BN", 0x10010143, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101YD1BN", 0x10010144, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101YD0BN", 0x10010145, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101YC2BN", 0x10010146, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101YC1BN", 0x10010147, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101YC0BN", 0x10010148, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101YB2BN", 0x10010149, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC101YB1BN", 0x10010150, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC101YB0BN", 0x10010151, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC101YA2BN", 0x10010152, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC101YA1BN", 0x10010153, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC101YA0BN", 0x10010154, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- {"NUC101LD2BN", 0x10010104, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101LD1BN", 0x10010105, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101LD0BN", 0x10010127, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101LC2BN", 0x10010107, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101LC1BN", 0x10010108, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101LC0BN", 0x10010128, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101LB2BN", 0x10010129, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC101LB1BN", 0x10010130, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC101LB0BN", 0x10010131, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC101LA2BN", 0x10010132, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC101LA1BN", 0x10010133, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC101LA0BN", 0x10010134, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- {"NUC101RD2BN", 0x10010113, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101RD1BN", 0x10010114, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101RD0BN", 0x10010135, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101RC2BN", 0x10010116, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101RC1BN", 0x10010117, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101RC0BN", 0x10010136, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101RB2BN", 0x10010137, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC101RB1BN", 0x10010138, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC101RB0BN", 0x10010139, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC101RA2BN", 0x10010140, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC101RA1BN", 0x10010141, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC101RA0BN", 0x10010142, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- /* NUC101 Version C */
+- {"NUC101LE3CN", 0x20010100, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101LE2CN", 0x20010101, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101LE1CN", 0x20010102, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101LD3CN", 0x20010103, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101LD2CN", 0x20010104, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101LD1CN", 0x20010105, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101LC3CN", 0x20010106, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101LC2CN", 0x20010107, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101LC1CN", 0x20010108, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101RE3CN", 0x20010109, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101RE2CN", 0x20010110, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101RE1CN", 0x20010111, NUMICRO_BANKS_NUC100(128*1024)},
+-
+- {"NUC101RD3CN", 0x20010112, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101RD2CN", 0x20010113, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101RD1CN", 0x20010114, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101RC3CN", 0x20010115, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101RC2CN", 0x20010116, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101RC1CN", 0x20010117, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101VE3CN", 0x20010118, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101VE2CN", 0x20010119, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101VE1CN", 0x20010120, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101VD3CN", 0x20010121, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101VD2CN", 0x20010122, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101VD1CN", 0x20010123, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101VC3CN", 0x20010124, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101VC2CN", 0x20010125, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101VC1CN", 0x20010126, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- /* NUC102 Version A */
+- {"NUC102ZD2AN", 0x00010231, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC102ZC1AN", 0x00010235, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC102LD2AN", 0x00010204, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC102LC1AN", 0x00010208, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- {"NUC102RB3AN", 0x00010248, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102RB2AN", 0x00010249, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102RB1AN", 0x00010250, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102RA3AN", 0x00010251, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102RA2AN", 0x00010252, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102RA1AN", 0x00010253, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102VB3AN", 0x00010254, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102VB2AN", 0x00010255, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102VB1AN", 0x00010256, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102VA3AN", 0x00010257, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102VA2AN", 0x00010258, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102VA1AN", 0x00010259, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102LA0AN", 0x00010260, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102LB0AN", 0x00010261, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102LC0AN", 0x00010262, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC102LD0AN", 0x00010263, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC102RA0AN", 0x00010264, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102RB0AN", 0x00010265, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102RC0AN", 0x00010266, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC102RD0AN", 0x00010267, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC102VA0AN", 0x00010268, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102VB0AN", 0x00010269, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102VC0AN", 0x00010270, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC102VD0AN", 0x00010271, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC102ZA0AN", 0x00010272, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC102ZB0AN", 0x00010273, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC102ZC0AN", 0x00010274, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC102ZD0AN", 0x00010275, NUMICRO_BANKS_NUC100(64*1024)},
+-
+- /* NUC102 Version A */
+- {"NUC122LD2AN", 0x00012204, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122LD1AN", 0x00012205, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122LC2AN", 0x00012207, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122LC1AN", 0x00012208, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122RD2AN", 0x00012213, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122RD1AN", 0x00012214, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122RC2AN", 0x00012216, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122RC1AN", 0x00012217, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122SD2AN", 0x00012222, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122SD1AN", 0x00012223, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122SC2AN", 0x00012225, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122SC1AN", 0x00012226, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122ZD2AN", 0x00012231, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122ZD1AN", 0x00012232, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122ZC2AN", 0x00012234, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122ZC1AN", 0x00012235, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122ZB2AN", 0x00012237, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122ZB1AN", 0x00012238, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122ZA2AN", 0x00012240, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122ZA1AN", 0x00012241, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122LB2AN", 0x00012243, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122LB1AN", 0x00012244, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122LA2AN", 0x00012246, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122LA1AN", 0x00012247, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122RB2AN", 0x00012249, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122RB1AN", 0x00012250, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122RA2AN", 0x00012252, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122RA1AN", 0x00012253, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122SB2AN", 0x00012255, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122SB1AN", 0x00012256, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122SA2AN", 0x00012258, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122SA1AN", 0x00012259, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122LA0AN", 0x00012260, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122LB0AN", 0x00012261, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122LC0AN", 0x00012262, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122LD0AN", 0x00012263, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122RA0AN", 0x00012264, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122RB0AN", 0x00012265, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122RC0AN", 0x00012266, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122RD0AN", 0x00012267, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122SA0AN", 0x00012268, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122SB0AN", 0x00012269, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122SC0AN", 0x00012270, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122SD0AN", 0x00012271, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122ZA0AN", 0x00012272, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122ZB0AN", 0x00012273, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122ZC0AN", 0x00012274, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122ZD0AN", 0x00012275, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122YD2AN", 0x00012277, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122YD1AN", 0x00012278, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122YD0AN", 0x00012279, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC122YC2AN", 0x00012281, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122YC1AN", 0x00012282, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122YC0AN", 0x00012283, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC122YB2AN", 0x00012285, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122YB1AN", 0x00012286, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122YB0AN", 0x00012287, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC122YA2AN", 0x00012289, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122YA1AN", 0x00012290, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC122YA0AN", 0x00012291, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- /* NUC120 Version C */
+- {"NUC120LD2BN", 0x10012004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LD1BN", 0x10012005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LD0BN", 0x10012027, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LC2BN", 0x10012007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120LC1BN", 0x10012008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120LC0BN", 0x10012028, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120LB2BN", 0x10012029, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC120LB1BN", 0x10012030, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC120LB0BN", 0x10012031, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC120LA2BN", 0x10012032, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC120LA1BN", 0x10012033, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC120LA0BN", 0x10012034, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- {"NUC120RD2BN", 0x10012013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RD1BN", 0x10012014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RD0BN", 0x10012035, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RC2BN", 0x10012016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RC1BN", 0x10012017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RC0BN", 0x10012036, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RB2BN", 0x10012037, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC120RB1BN", 0x10012038, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC120RB0BN", 0x10012039, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC120RA2BN", 0x10012040, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC120RA1BN", 0x10012041, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC120RA0BN", 0x10012042, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- /* NUC120 Version C */
+- {"NUC120LE3CN", 0x20012000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120LE2CN", 0x20012001, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120LE1CN", 0x20012002, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120LD3CN", 0x20012003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LD2CN", 0x20012004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LD1CN", 0x20012005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LC3CN", 0x20012006, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120LC2CN", 0x20012007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120LC1CN", 0x20012008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RE3CN", 0x20012009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120RE2CN", 0x20012010, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120RE1CN", 0x20012011, NUMICRO_BANKS_NUC100(128*1024)},
+-
+- {"NUC120RD3CN", 0x20012012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RD2CN", 0x20012013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RD1CN", 0x20012014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RC3CN", 0x20012015, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RC2CN", 0x20012016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RC1CN", 0x20012017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120VE3CN", 0x20012018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120VE2CN", 0x20012019, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120VE1CN", 0x20012020, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120VD3CN", 0x20012021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120VD2CN", 0x20012022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120VD1CN", 0x20012023, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120VC3CN", 0x20012024, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120VC2CN", 0x20012025, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120VC1CN", 0x20012026, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- /* NUC120 Version B */
+- {"NUC130LD2BN", 0x10013004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130LD1BN", 0x10013005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130LD0BN", 0x10013027, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130LC2BN", 0x10013007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130LC1BN", 0x10013008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130LC0BN", 0x10013028, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130LB2BN", 0x10013029, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC130LB1BN", 0x10013030, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC130LB0BN", 0x10013031, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC130LA2BN", 0x10013032, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC130LA1BN", 0x10013033, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC130LA0BN", 0x10013034, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- {"NUC130RD2BN", 0x10013013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130RD1BN", 0x10013014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130RD0BN", 0x10013035, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130RC2BN", 0x10013016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130RC1BN", 0x10013017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130RC0BN", 0x10013036, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130RB2BN", 0x10013037, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC130RB1BN", 0x10013038, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC130RB0BN", 0x10013039, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC130RA2BN", 0x10013040, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC130RA1BN", 0x10013041, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC130RA0BN", 0x10013042, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- /* NUC130 Version C */
+- {"NUC130LE3CN", 0x20013000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130LE2CN", 0x20013001, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130LE1CN", 0x20013002, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130LD3CN", 0x20013003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130LD2CN", 0x20013004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130LD1CN", 0x20013005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130LC3CN", 0x20013006, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130LC2CN", 0x20013007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130LC1CN", 0x20013008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130RE3CN", 0x20013009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130RE2CN", 0x20013010, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130RE1CN", 0x20013011, NUMICRO_BANKS_NUC100(128*1024)},
+-
+- {"NUC130RD3CN", 0x20013012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130RD2CN", 0x20013013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130RD1CN", 0x20013014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130RC3CN", 0x20013015, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130RC2CN", 0x20013016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130RC1CN", 0x20013017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130VE3CN", 0x20013018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130VE2CN", 0x20013019, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130VE1CN", 0x20013020, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130VD3CN", 0x20013021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130VD2CN", 0x20013022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130VD1CN", 0x20013023, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130VC3CN", 0x20013024, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130VC2CN", 0x20013025, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130VC1CN", 0x20013026, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- /* NUC140 Version B */
+- {"NUC140LD2BN", 0x10014004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140LD1BN", 0x10014005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140LD0BN", 0x10014027, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140LC2BN", 0x10014007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140LC1BN", 0x10014008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140LC0BN", 0x10014028, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140LB2BN", 0x10014029, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC140LB1BN", 0x10014030, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC140LB0BN", 0x10014031, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC140LA2BN", 0x10014032, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC140LA1BN", 0x10014033, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC140LA0BN", 0x10014034, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- {"NUC140RD2BN", 0x10014013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140RD1BN", 0x10014014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140RD0BN", 0x10014035, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140RC2BN", 0x10014016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140RC1BN", 0x10014017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140RC0BN", 0x10014036, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140RB2BN", 0x10014037, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC140RB1BN", 0x10014038, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC140RB0BN", 0x10014039, NUMICRO_BANKS_NUC100(16*1024)},
+- {"NUC140RA2BN", 0x10014040, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC140RA1BN", 0x10014041, NUMICRO_BANKS_NUC100(8*1024)},
+- {"NUC140RA0BN", 0x10014042, NUMICRO_BANKS_NUC100(8*1024)},
+-
+- /* NUC140 Version C */
+- {"NUC140LE3CN", 0x20014000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140LE2CN", 0x20014001, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140LE1CN", 0x20014002, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140LD3CN", 0x20014003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140LD2CN", 0x20014004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140LD1CN", 0x20014005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140LC3CN", 0x20014006, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140LC2CN", 0x20014007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140LC1CN", 0x20014008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140RE3CN", 0x20014009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140RE2CN", 0x20014010, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140RE1CN", 0x20014011, NUMICRO_BANKS_NUC100(128*1024)},
+-
+- {"NUC140RD3CN", 0x20014012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140RD2CN", 0x20014013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140RD1CN", 0x20014014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140RC3CN", 0x20014015, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140RC2CN", 0x20014016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140RC1CN", 0x20014017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140VE3CN", 0x20014018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140VE2CN", 0x20014019, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140VE1CN", 0x20014020, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140VD3CN", 0x20014021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140VD2CN", 0x20014022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140VD1CN", 0x20014023, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140VC3CN", 0x20014024, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140VC2CN", 0x20014025, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140VC1CN", 0x20014026, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- /* NUC100 Version A */
+- {"NUC100LE3AN", 0x00010000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100LE2AN", 0x00010001, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100LE1AN", 0x00010002, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100LD3AN", 0x00010003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LD2AN", 0x00010004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LD1AN", 0x00010005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LC3AN", 0x00010006, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100LC2AN", 0x00010007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100LC1AN", 0x00010008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RE3AN", 0x00010009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100RE2AN", 0x00010010, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100RE1AN", 0x00010011, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100RD3AN", 0x00010012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RD2AN", 0x00010013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RD1AN", 0x00010014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RC3AN", 0x00010015, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RC2AN", 0x00010016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RC1AN", 0x00010017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100VE3AN", 0x00010018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100VE2AN", 0x00010019, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100VE1AN", 0x00010020, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100VD3AN", 0x00010021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100VD2AN", 0x00010022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100VD1AN", 0x00010023, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100VC3AN", 0x00010024, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100VC2AN", 0x00010025, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100VC1AN", 0x00010026, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- /* NUC100 Version A */
+- {"NUC101LE3AN", 0x00010100, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101LE2AN", 0x00010101, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101LE1AN", 0x00010102, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101LD3AN", 0x00010103, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101LD2AN", 0x00010104, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101LD1AN", 0x00010105, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101LC3AN", 0x00010106, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101LC2AN", 0x00010107, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101LC1AN", 0x00010108, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101RE3AN", 0x00010109, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101RE2AN", 0x00010110, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101RE1AN", 0x00010111, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101RD3AN", 0x00010112, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101RD2AN", 0x00010113, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101RD1AN", 0x00010114, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101RC3AN", 0x00010115, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101RC2AN", 0x00010116, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101RC1AN", 0x00010117, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101VE3AN", 0x00010118, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101VE2AN", 0x00010119, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101VE1AN", 0x00010120, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC101VD3AN", 0x00010121, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101VD2AN", 0x00010122, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101VD1AN", 0x00010123, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC101VC3AN", 0x00010124, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101VC2AN", 0x00010125, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC101VC1AN", 0x00010126, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- /* NUC120 Version A */
+- {"NUC120LE3AN", 0x00012000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120LE2AN", 0x00012001, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120LE1AN", 0x00012002, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120LD3AN", 0x00012003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LD2AN", 0x00012004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LD1AN", 0x00012005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LC3AN", 0x00012006, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120LC2AN", 0x00012007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120LC1AN", 0x00012008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RE3AN", 0x00012009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120RE2AN", 0x00012010, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120RE1AN", 0x00012011, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120RD3AN", 0x00012012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RD2AN", 0x00012013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RD1AN", 0x00012014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RC3AN", 0x00012015, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RC2AN", 0x00012016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RC1AN", 0x00012017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120VE3AN", 0x00012018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120VE2AN", 0x00012019, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120VE1AN", 0x00012020, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120VD3AN", 0x00012021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120VD2AN", 0x00012022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120VD1AN", 0x00012023, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120VC3AN", 0x00012024, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120VC2AN", 0x00012025, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120VC1AN", 0x00012026, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- /* NUC120 Version A */
+- {"NUC130LE3AN", 0x00013000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130LE2AN", 0x00013001, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130LE1AN", 0x00013002, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130LD3AN", 0x00013003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130LD2AN", 0x00013004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130LD1AN", 0x00013005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130LC3AN", 0x00013006, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130LC2AN", 0x00013007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130LC1AN", 0x00013008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130RE3AN", 0x00013009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130RE2AN", 0x00013010, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130RE1AN", 0x00013011, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130RD3AN", 0x00013012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130RD2AN", 0x00013013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130RD1AN", 0x00013014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130RC3AN", 0x00013015, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130RC2AN", 0x00013016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130RC1AN", 0x00013017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130VE3AN", 0x00013018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130VE2AN", 0x00013019, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130VE1AN", 0x00013020, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130VD3AN", 0x00013021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130VD2AN", 0x00013022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130VD1AN", 0x00013023, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC130VC3AN", 0x00013024, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130VC2AN", 0x00013025, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC130VC1AN", 0x00013026, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- /* NUC140 Version A */
+- {"NUC140LE3AN", 0x00014000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140LE2AN", 0x00014001, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140LE1AN", 0x00014002, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140LD3AN", 0x00014003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140LD2AN", 0x00014004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140LD1AN", 0x00014005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140LC3AN", 0x00014006, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140LC2AN", 0x00014007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140LC1AN", 0x00014008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140RE3AN", 0x00014009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140RE2AN", 0x00014010, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140RE1AN", 0x00014011, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140RD3AN", 0x00014012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140RD2AN", 0x00014013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140RD1AN", 0x00014014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140RC3AN", 0x00014015, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140RC2AN", 0x00014016, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140RC1AN", 0x00014017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140VE3AN", 0x00014018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140VE2AN", 0x00014019, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140VE1AN", 0x00014020, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC140VD3AN", 0x00014021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140VD2AN", 0x00014022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140VD1AN", 0x00014023, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC140VC3AN", 0x00014024, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140VC2AN", 0x00014025, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC140VC1AN", 0x00014026, NUMICRO_BANKS_NUC100(32*1024)},
+-
+-
+- /* M052 */
+- {"M052LAN" , 0x00005200, NUMICRO_BANKS_M051(8*1024)},
+- {"M052PAN" , 0x00005201, NUMICRO_BANKS_M051(8*1024)},
+- {"M052YAN" , 0x00005202, NUMICRO_BANKS_M051(8*1024)},
+- {"M052ZAN" , 0x00005203, NUMICRO_BANKS_M051(8*1024)},
+-
+- /* M054 */
+- {"M054LAN" , 0x00005400, NUMICRO_BANKS_M051(16*1024)},
+- {"M054PAN" , 0x00005401, NUMICRO_BANKS_M051(16*1024)},
+- {"M054YAN" , 0x00005402, NUMICRO_BANKS_M051(16*1024)},
+- {"M054ZAN" , 0x00005403, NUMICRO_BANKS_M051(16*1024)},
+-
+- /* M058 */
+- {"M058LAN" , 0x00005800, NUMICRO_BANKS_M051(32*1024)},
+- {"M058PAN" , 0x00005801, NUMICRO_BANKS_M051(32*1024)},
+- {"M058YAN" , 0x00005802, NUMICRO_BANKS_M051(32*1024)},
+- {"M058ZAN" , 0x00005803, NUMICRO_BANKS_M051(32*1024)},
+-
+- /* M0516 */
+- {"M0516LAN" , 0x00005A00, NUMICRO_BANKS_M051(64*1024)},
+- {"M0516PAN" , 0x00005A01, NUMICRO_BANKS_M051(64*1024)},
+- {"M0516YAN" , 0x00005A02, NUMICRO_BANKS_M051(64*1024)},
+- {"M0516ZAN" , 0x00005A03, NUMICRO_BANKS_M051(64*1024)},
+- {"M051LBN" , 0x10005100, NUMICRO_BANKS_M051(4*1024)},
+- {"M051PBN" , 0x10005101, NUMICRO_BANKS_M051(4*1024)},
+- {"M051YBN" , 0x10005102, NUMICRO_BANKS_M051(4*1024)},
+- {"M051ZBN" , 0x10005103, NUMICRO_BANKS_M051(4*1024)},
+- {"M052LBN" , 0x10005200, NUMICRO_BANKS_M051(8*1024)},
+- {"M052PBN" , 0x10005201, NUMICRO_BANKS_M051(8*1024)},
+- {"M052YBN" , 0x10005202, NUMICRO_BANKS_M051(8*1024)},
+- {"M052ZBN" , 0x10005203, NUMICRO_BANKS_M051(8*1024)},
+- {"M054LBN" , 0x10005400, NUMICRO_BANKS_M051(16*1024)},
+- {"M054PBN" , 0x10005401, NUMICRO_BANKS_M051(16*1024)},
+- {"M054YBN" , 0x10005402, NUMICRO_BANKS_M051(16*1024)},
+- {"M054ZBN" , 0x10005403, NUMICRO_BANKS_M051(16*1024)},
+- {"M058LBN" , 0x10005800, NUMICRO_BANKS_M051(32*1024)},
+- {"M058PBN" , 0x10005801, NUMICRO_BANKS_M051(32*1024)},
+- {"M058YBN" , 0x10005802, NUMICRO_BANKS_M051(32*1024)},
+- {"M058ZBN" , 0x10005803, NUMICRO_BANKS_M051(32*1024)},
+- {"M0516LBN" , 0x10005A00, NUMICRO_BANKS_M051(64*1024)},
+- {"M0516PBN" , 0x10005A01, NUMICRO_BANKS_M051(64*1024)},
+- {"M0516YBN" , 0x10005A02, NUMICRO_BANKS_M051(64*1024)},
+- {"M0516ZBN" , 0x10005A03, NUMICRO_BANKS_M051(64*1024)},
+- {"M052LDN" , 0x20005200, NUMICRO_BANKS_M051(8*1024)},
+- {"M054LDN" , 0x20005400, NUMICRO_BANKS_M051(16*1024)},
+- {"M058LDN" , 0x20005800, NUMICRO_BANKS_M051(32*1024)},
+- {"M0516LDN" , 0x20005A00, NUMICRO_BANKS_M051(64*1024)},
+- {"M052ZDN" , 0x20005203, NUMICRO_BANKS_M051(8*1024)},
+- {"M054ZDN" , 0x20005403, NUMICRO_BANKS_M051(16*1024)},
+- {"M058ZDN" , 0x20005803, NUMICRO_BANKS_M051(32*1024)},
+- {"M0516ZDN" , 0x20005A03, NUMICRO_BANKS_M051(64*1024)},
+- {"M052TDN" , 0x20005204, NUMICRO_BANKS_M051(8*1024)},
+- {"M054TDN" , 0x20005404, NUMICRO_BANKS_M051(16*1024)},
+- {"M058TDN" , 0x20005804, NUMICRO_BANKS_M051(32*1024)},
+- {"M0516TDN" , 0x20005A04, NUMICRO_BANKS_M051(64*1024)},
+- {"M052XDN" , 0x20005205, NUMICRO_BANKS_M051(8*1024)},
+- {"M054XDN" , 0x20005405, NUMICRO_BANKS_M051(16*1024)},
+- {"M058XDN" , 0x20005805, NUMICRO_BANKS_M051(32*1024)},
+- {"M0516XDN" , 0x20005A05, NUMICRO_BANKS_M051(64*1024)},
+- {"M052LDE" , 0x30005200, NUMICRO_BANKS_M051(8*1024)},
+- {"M054LDE" , 0x30005400, NUMICRO_BANKS_M051(16*1024)},
+- {"M058LDE" , 0x30005800, NUMICRO_BANKS_M051(32*1024)},
+- {"M0516LDE" , 0x30005A00, NUMICRO_BANKS_M051(64*1024)},
+- {"M052ZDE" , 0x30005203, NUMICRO_BANKS_M051(8*1024)},
+- {"M054ZDE" , 0x30005403, NUMICRO_BANKS_M051(16*1024)},
+- {"M058ZDE" , 0x30005803, NUMICRO_BANKS_M051(32*1024)},
+- {"M0516ZDE" , 0x30005A03, NUMICRO_BANKS_M051(64*1024)},
+- {"M052TDE" , 0x30005204, NUMICRO_BANKS_M051(8*1024)},
+- {"M054TDE" , 0x30005404, NUMICRO_BANKS_M051(16*1024)},
+- {"M058TDE" , 0x30005804, NUMICRO_BANKS_M051(32*1024)},
+- {"M0516TDE" , 0x30005A04, NUMICRO_BANKS_M051(64*1024)},
+- {"M052XDE" , 0x30005205, NUMICRO_BANKS_M051(8*1024)},
+- {"M054XDE" , 0x30005405, NUMICRO_BANKS_M051(16*1024)},
+- {"M058XDE" , 0x30005805, NUMICRO_BANKS_M051(32*1024)},
+- {"M0516XDE" , 0x30005A05, NUMICRO_BANKS_M051(64*1024)},
+-
+- /* Mini51 */
+- {"MINI51LAN", 0x00205100, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51QAN", 0x00205101, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51 ", 0x00205102, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51ZAN", 0x00205103, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51TAN", 0x00205104, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI52LAN", 0x00205200, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52QAN", 0x00205201, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52 ", 0x00205202, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52ZAN", 0x00205203, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52TAN", 0x00205204, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI54LAN", 0x00205400, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54QAN", 0x00205401, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54 ", 0x00205402, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54ZAN", 0x00205403, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54TAN", 0x00205404, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI51LBN", 0x10205100, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51QBN", 0x10205101, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51 ", 0x10205102, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51ZBN", 0x10205103, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51TBN", 0x10205104, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI52LBN", 0x10205200, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52QBN", 0x10205201, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52 ", 0x10205202, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52ZBN", 0x10205203, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52TBN", 0x10205204, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI54LBN", 0x10205400, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54QBN", 0x10205401, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54 ", 0x10205402, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54ZBN" , 0x10205403, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54TBN" , 0x10205404, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI51LDE" , 0x20205100, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51QDE" , 0x20205101, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51 " , 0x20205102, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51ZDE" , 0x20205103, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51TDE" , 0x20205104, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI51FDE" , 0x20205105, NUMICRO_BANKS_MINI51(4*1024)},
+- {"MINI52LDE" , 0x20205200, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52QDE" , 0x20205201, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52 " , 0x20205202, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52ZDE" , 0x20205203, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52TDE" , 0x20205204, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI52FDE" , 0x20205205, NUMICRO_BANKS_MINI51(8*1024)},
+- {"MINI54LDE" , 0x20205400, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54QDE" , 0x20205401, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54 " , 0x20205402, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54ZDE" , 0x20205403, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54TDE" , 0x20205404, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI54FDE" , 0x20205405, NUMICRO_BANKS_MINI51(16*1024)},
+- {"MINI55LDE" , 0x20205500, NUMICRO_BANKS_MINI51(16*1024)},
+-
+- /* NANO100 */
+- {"NANO100VF3AN" , 0x00110000, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO100VF2AN" , 0x00110001, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO100RF3AN" , 0x00110002, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO100RF2AN" , 0x00110003, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO100LF3AN" , 0x00110004, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO100LF2AN" , 0x00110005, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO100VE3AN" , 0x00110006, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100VE2AN" , 0x00110007, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100RE3AN" , 0x00110008, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100RE2AN" , 0x00110009, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100LE3AN" , 0x00110010, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100LE2AN" , 0x00110011, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100VD3AN" , 0x00110012, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100VD2AN" , 0x00110013, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100VD1AN" , 0x00110014, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100RD3AN" , 0x00110015, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100RD2AN" , 0x00110016, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100RD1AN" , 0x00110017, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100LD3AN" , 0x00110018, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100LD2AN" , 0x00110019, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100LD1AN" , 0x00110020, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100VC2AN" , 0x00110021, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100VC1AN" , 0x00110022, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100RC2AN" , 0x00110023, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100RC1AN" , 0x00110024, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100LC2AN" , 0x00110025, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100LC1AN" , 0x00110026, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100VB1AN" , 0x00110027, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO100VB0AN" , 0x00110028, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO100RB1AN" , 0x00110029, NUMICRO_BANKS_NANO(16*1024)},
+-
+- {"NANO110VF3AN" , 0x00111000, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO110VF2AN" , 0x00111001, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO110RF3AN" , 0x00111002, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO110RF2AN" , 0x00111003, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO110VE3AN" , 0x00111006, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110VE2AN" , 0x00111007, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110RE3AN" , 0x00111008, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110RE2AN" , 0x00111009, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110VD3AN" , 0x00111012, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110VD2AN" , 0x00111013, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110VD1AN" , 0x00111014, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110RD3AN" , 0x00111015, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110RD2AN" , 0x00111016, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110RD1AN" , 0x00111017, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110VC2AN" , 0x00111021, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO110VC1AN" , 0x00111022, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO110SC2AN" , 0x00111023, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO110SC1AN" , 0x00111024, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120VF3AN" , 0x00112000, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO120VF2AN" , 0x00112001, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO120RF3AN" , 0x00112002, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO120RF2AN" , 0x00112003, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO120LF3AN" , 0x00112004, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO120LF2AN" , 0x00112005, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO120VE3AN" , 0x00112006, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120VE2AN" , 0x00112007, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120RE3AN" , 0x00112008, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120RE2AN" , 0x00112009, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120LE3AN" , 0x00112010, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120LE2AN" , 0x00112011, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120VD3AN" , 0x00112012, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120VD2AN" , 0x00112013, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120VD1AN" , 0x00112014, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120SD3AN" , 0x00112015, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120SD2AN" , 0x00112016, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120SD1AN" , 0x00112017, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120LD3AN" , 0x00112018, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120LD2AN" , 0x00112019, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120LD1AN" , 0x00112020, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120VC2AN" , 0x00112021, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120VC1AN" , 0x00112022, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120SC2AN" , 0x00112023, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120SC1AN" , 0x00112024, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120LC2AN" , 0x00112025, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120LC1AN" , 0x00112026, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO130VF3AN" , 0x00113000, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO130VF2AN" , 0x00113001, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO130SF3AN" , 0x00113002, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO130SF2AN" , 0x00113003, NUMICRO_BANKS_NANO(256*1024)},
+- {"NANO130VE3AN" , 0x00113006, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO130VE2AN" , 0x00113007, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO130SE3AN" , 0x00113008, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO130SE2AN" , 0x00113009, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO130VD3AN" , 0x00113012, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130VD2AN" , 0x00113013, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130VD1AN" , 0x00113014, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130SD3AN" , 0x00113015, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130SD2AN" , 0x00113016, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130SD1AN" , 0x00113017, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130VC2AN" , 0x00113021, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO130VC1AN" , 0x00113022, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO130SC2AN" , 0x00113023, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO130SC1AN" , 0x00113024, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100KE3BN" , 0x00110030, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100KE2BN" , 0x00110031, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100VE3BN" , 0x00110032, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100VE2BN" , 0x00110033, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100SE3BN" , 0x00110034, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100SE2BN" , 0x00110035, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100LE3BN" , 0x00110036, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100LE2BN" , 0x00110037, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO100KD3BN" , 0x00110038, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100KD2BN" , 0x00110039, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100VD3BN" , 0x0011003A, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100VD2BN" , 0x0011003B, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100SD3BN" , 0x0011003C, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100SD2BN" , 0x0011003D, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100LD3BN" , 0x0011003E, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100LD2BN" , 0x0011003F, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO100KC2BN" , 0x00110040, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100VC2BN" , 0x00110041, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100SC2BN" , 0x00110042, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO100LC2BN" , 0x00110043, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO110KE3BN" , 0x00111030, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110KE2BN" , 0x00111031, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110VE3BN" , 0x00111032, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110VE2BN" , 0x00111033, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110SE3BN" , 0x00111034, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110SE2BN" , 0x00111035, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110KD3BN" , 0x00111038, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110KD2BN" , 0x00111039, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110VD3BN" , 0x0011103A, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110VD2BN" , 0x0011103B, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110SD3BN" , 0x0011103C, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110SD2BN" , 0x0011103D, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO110KC2BN" , 0x00111040, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO110VC2BN" , 0x00111041, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO110SC2BN" , 0x00111042, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120KE3BN" , 0x00112030, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120KE2BN" , 0x00112031, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120VE3BN" , 0x00112032, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120VE2BN" , 0x00112033, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120SE3BN" , 0x00112034, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120SE2BN" , 0x00112035, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120LE3BN" , 0x00112036, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120LE2BN" , 0x00112037, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO120KD3BN" , 0x00112038, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120KD2BN" , 0x00112039, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120VD3BN" , 0x0011203A, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120VD2BN" , 0x0011203B, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120SD3BN" , 0x0011203C, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120SD2BN" , 0x0011203D, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120LD3BN" , 0x0011203E, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120LD2BN" , 0x0011203F, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO120KC2BN" , 0x00112040, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120VC2BN" , 0x00112041, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120SC2BN" , 0x00112042, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO120LC2BN" , 0x00112043, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO130KE3BN" , 0x00113030, NUMICRO_BANKS_NANO(123*1024)},
+- {"NANO130KE2BN" , 0x00113031, NUMICRO_BANKS_NANO(123*1024)},
+- {"NANO130VE3BN" , 0x00113032, NUMICRO_BANKS_NANO(123*1024)},
+- {"NANO130VE2BN" , 0x00113033, NUMICRO_BANKS_NANO(123*1024)},
+- {"NANO130SE3BN" , 0x00113034, NUMICRO_BANKS_NANO(123*1024)},
+- {"NANO130SE2BN" , 0x00113035, NUMICRO_BANKS_NANO(123*1024)},
+- {"NANO130KD3BN" , 0x00113038, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130KD2BN" , 0x00113039, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130VD3BN" , 0x0011303A, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130VD2BN" , 0x0011303B, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130SD3BN" , 0x0011303C, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130SD2BN" , 0x0011303D, NUMICRO_BANKS_NANO(64*1024)},
+- {"NANO130KC2BN" , 0x00113040, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO130VC2BN" , 0x00113041, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO130SC2BN" , 0x00113042, NUMICRO_BANKS_NANO(32*1024)},
+- {"N512DC4" , 0x00100000, NUMICRO_BANKS_NANO(64*1024)},
+- {"N512LC4" , 0x00100001, NUMICRO_BANKS_NANO(64*1024)},
+- {"N512MC4" , 0x00100003, NUMICRO_BANKS_NANO(64*1024)},
+-
+- {"N512SC4" , 0x00100005, NUMICRO_BANKS_NANO(64*1024)},
+- {"N512VD4" , 0x00100008, NUMICRO_BANKS_NANO(128*1024)},
+- {"N512MD4" , 0x00100009, NUMICRO_BANKS_NANO(128*1024)},
+- {"N512SD4" , 0x00100010, NUMICRO_BANKS_NANO(128*1024)},
+- {"NANO110RC2BN" , 0x00111043, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO110RD3BN" , 0x00111045, NUMICRO_BANKS_NANO(64*1024)},
+- {"TX110VE3BN" , 0x00111036, NUMICRO_BANKS_NANO(128*1024)},
+-
+- /* NANO102/NANO112 */
+- {"NANO112LB0AN" , 0x00111201, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO112LB1AN" , 0x00111202, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO112LC1AN" , 0x00111203, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO112LC2AN" , 0x00111204, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO112SB0AN" , 0x00111205, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO112SB1AN" , 0x00111206, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO112SC1AN" , 0x00111207, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO112SC2AN" , 0x00111208, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO112RB0AN" , 0x00111209, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO112RB1AN" , 0x00111210, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO112RC1AN" , 0x00111211, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO112RC2AN" , 0x00111212, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO112VB0AN" , 0x00111213, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO112VB1AN" , 0x00111214, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO112VC1AN" , 0x00111215, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO112VC2AN" , 0x00111216, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO102ZB0AN" , 0x00110201, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO102ZB1AN" , 0x00110202, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO102ZC1AN" , 0x00110203, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO102ZC2AN" , 0x00110204, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO102LB0AN" , 0x00110205, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO102LB1AN" , 0x00110206, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO102LC1AN" , 0x00110207, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO102LC2AN" , 0x00110208, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO102SB0AN" , 0x00110209, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO102SB1AN" , 0x00110210, NUMICRO_BANKS_NANO(16*1024)},
+- {"NANO102SC1AN" , 0x00110211, NUMICRO_BANKS_NANO(32*1024)},
+- {"NANO102SC2AN" , 0x00110212, NUMICRO_BANKS_NANO(32*1024)},
+-
+- /* NUC103/NUC105/NUC123 */
+- {"NUC123SC2AN" , 0x00012305, NUMICRO_BANKS_NUC100(36*1024)},
+- {"NUC123SD4AN" , 0x00012315, NUMICRO_BANKS_NUC100(68*1024)},
+- {"NUC123LC2AN" , 0x00012325, NUMICRO_BANKS_NUC100(36*1024)},
+- {"NUC103LC2AN" , 0x00010325, NUMICRO_BANKS_NUC100(36*1024)},
+- {"NUC105LC2AN" , 0x00010525, NUMICRO_BANKS_NUC100(36*1024)},
+- {"NUC123LD4AN" , 0x00012335, NUMICRO_BANKS_NUC100(68*1024)},
+- {"NUC103LD4AN" , 0x00010335, NUMICRO_BANKS_NUC100(68*1024)},
+- {"NUC105LD4AN" , 0x00010535, NUMICRO_BANKS_NUC100(68*1024)},
+- {"NUC123ZC2AN" , 0x00012345, NUMICRO_BANKS_NUC100(36*1024)},
+- {"NUC103ZC2AN" , 0x00010345, NUMICRO_BANKS_NUC100(36*1024)},
+- {"NUC105ZC2AN" , 0x00010545, NUMICRO_BANKS_NUC100(36*1024)},
+- {"NUC123ZD4AN" , 0x00012355, NUMICRO_BANKS_NUC100(68*1024)},
+- {"NUC103ZD4AN" , 0x00010355, NUMICRO_BANKS_NUC100(68*1024)},
+- {"NUC105ZD4AN" , 0x00010555, NUMICRO_BANKS_NUC100(68*1024)},
+-
+- /* NUC200 */
+- {"NUC200LC2AN" , 0x00020007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC200LD2AN" , 0x00020004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC200LE3AN" , 0x00020000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC200SC1AN" , 0x00020035, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC200SD2AN" , 0x00020031, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC200SE3AN" , 0x00020027, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC200VE3AN" , 0x00020018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC220LC2AN" , 0x00022007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC220LD2AN" , 0x00022004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC220LE3AN" , 0x00022000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC220SC1AN" , 0x00022035, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC220SD2AN" , 0x00022031, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC220SE3AN" , 0x00022027, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC220VE3AN" , 0x00022018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC230LC2AN" , 0x00023007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC230LD2AN" , 0x00023004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC230LE3AN" , 0x00023000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC230SC1AN" , 0x00023035, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC230SD2AN" , 0x00023031, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC230SE3AN" , 0x00023027, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC230VE3AN" , 0x00023018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC240LC2AN" , 0x00024007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC240LD2AN" , 0x00024004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC240LE3AN" , 0x00024000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC240SC1AN" , 0x00024035, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC240SD2AN" , 0x00024031, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC240SE3AN" , 0x00024027, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC240VE3AN" , 0x00024018, NUMICRO_BANKS_NUC100(128*1024)},
+-
+- /* NUC200 NUC2XXAE */
+- {"NUC230RC1AE" , 0x40013017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC200LC2AE" , 0x10020007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC200LD2AE" , 0x10020004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC200LE3AE" , 0x10020000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC200SC2AE" , 0x10020034, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC200SD2AE" , 0x10020031, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC200SE3AE" , 0x10020027, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC200VE3AE" , 0x10020018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC230LC2AE" , 0x10023007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC230LD2AE" , 0x10023004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC230LE3AE" , 0x10023000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC230SC2AE" , 0x10023034, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC230SD2AE" , 0x10023031, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC230SE3AE" , 0x10023027, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC230VE3AE" , 0x10023018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC240LC2AE" , 0x10024007, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC240LD2AE" , 0x10024004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC240LE3AE" , 0x10024000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC240SC2AE" , 0x10024034, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC240SD2AE" , 0x10024031, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC240SE3AE" , 0x10024027, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC240VE3AE" , 0x10024018, NUMICRO_BANKS_NUC100(128*1024)},
+-
+- /* NUC100 Version D */
+- {"NUC100LC1DN" , 0x30010008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100LD1DN" , 0x30010005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LD2DN" , 0x30010004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RC1DN" , 0x30010017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC100RD1DN" , 0x30010014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RD2DN" , 0x30010013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LD3DN" , 0x30010003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100LE3DN" , 0x30010000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100RD3DN" , 0x30010012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100RE3DN" , 0x30010009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC100VD2DN" , 0x30010022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100VD3DN" , 0x30010021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC100VE3DN" , 0x30010018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120LC1DN" , 0x30012008, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120LD1DN" , 0x30012005, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LD2DN" , 0x30012004, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RC1DN" , 0x30012017, NUMICRO_BANKS_NUC100(32*1024)},
+- {"NUC120RD1DN" , 0x30012014, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RD2DN" , 0x30012013, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LD3DN" , 0x30012003, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120LE3DN" , 0x30012000, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120RD3DN" , 0x30012012, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120RE3DN" , 0x30012009, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC120VD2DN" , 0x30012022, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120VD3DN" , 0x30012021, NUMICRO_BANKS_NUC100(64*1024)},
+- {"NUC120VE3DN" , 0x30012018, NUMICRO_BANKS_NUC100(128*1024)},
+- {"NUC130RC1DN" , 0x30013017, NUMICRO_BANKS_NUC100(32*1024)},
+-
+- {"UNKNOWN" , 0x00000000, NUMICRO_BANKS_NUC100(128*1024)},
++ /* M051AN */
++ {"M052LAN", 0x00005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M054LAN", 0x00005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M058LAN", 0x00005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M0516LAN", 0x00005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M052ZAN", 0x00005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M054ZAN", 0x00005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M058ZAN", 0x00005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M0516ZAN", 0x00005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
++
++ /* M051BN */
++ {"M052LBN", 0x10005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M054LBN", 0x10005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M058LBN", 0x10005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M0516LBN", 0x10005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M052ZBN", 0x10005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M054ZBN", 0x10005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M058ZBN", 0x10005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M0516ZBN", 0x10005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
++
++ /* M051DN */
++ {"M0516LDN", 0x20005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M0516ZDN", 0x20005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M052LDN", 0x20005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M052ZDN", 0x20005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M054LDN", 0x20005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M054ZDN", 0x20005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M058LDN", 0x20005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M058ZDN", 0x20005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
++
++ /* M051DE */
++ {"M0516LDE", 0x30005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M0516ZDE", 0x30005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M052LDE", 0x30005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M052ZDE", 0x30005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M054LDE", 0x30005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M054ZDE", 0x30005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M058LDE", 0x30005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"M058ZDE", 0x30005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
++
++ /* M0518 */
++ {"M0518LC2AE", 0x10051803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"M0518LD2AE", 0x10051800, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"M0518SC2AE", 0x10051813, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"M0518SD2AE", 0x10051810, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++
++ /* M0519 */
++ {"M0519LD3AE", 0x00051902, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"M0519LE3AE", 0x00051900, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
++ {"M0519SD3AE", 0x00051922, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"M0519SE3AE", 0x00051920, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
++ {"M0519VE3AE", 0x00051930, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
++
++ /* M058S */
++ {"M058SFAN", 0x00005818, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"M058SLAN", 0x00005810, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"M058SSAN", 0x00005816, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"M058SZAN", 0x00005813, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++
++ /* MINI51AN */
++ {"MINI51LAN", 0x00205100, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI51TAN", 0x00205104, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI51ZAN", 0x00205103, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI52LAN", 0x00205200, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI52TAN", 0x00205204, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI52ZAN", 0x00205203, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI54LAN", 0x00205400, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI54TAN", 0x00205404, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI54ZAN", 0x00205403, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
++
++ /* MINI51DE */
++ {"MINI51FDE", 0x20205105, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI51LDE", 0x20205100, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI51TDE", 0x20205104, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI51ZDE", 0x20205103, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI52FDE", 0x20205205, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI52LDE", 0x20205200, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI52TDE", 0x20205204, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI52ZDE", 0x20205203, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI54FDE", 0x20205405, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI54LDE", 0x20205400, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI54TDE", 0x20205404, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
++ {"MINI54ZDE", 0x20205403, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
++
++ /* MINI55 */
++ {"MINI55LDE", 0x00505500, NUMICRO_BANKS_GENERAL(35 * 512, 0 * 1024, 2 * 1024, 8)},
++ {"MINI55ZDE", 0x00505503, NUMICRO_BANKS_GENERAL(35 * 512, 0 * 1024, 2 * 1024, 8)},
++
++ /* MINI58 */
++ {"MINI58FDE", 0x00A05805, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
++ {"MINI58LDE", 0x00A05800, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
++ {"MINI58TDE", 0x00A05804, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
++ {"MINI58ZDE", 0x00A05803, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
++
++ /* NANO100AN */
++ {"NANO100LC2AN", 0x00110025, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100LD2AN", 0x00110019, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100LD3AN", 0x00110018, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100SC2AN", 0x00110023, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100SD2AN", 0x00110016, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100SD3AN", 0x00110015, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100VD2AN", 0x00110013, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100VD3AN", 0x00110012, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100ZC2AN", 0x00110029, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100ZD2AN", 0x00110028, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100ZD3AN", 0x00110027, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120LC2AN", 0x00112025, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120LD2AN", 0x00112019, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120LD3AN", 0x00112018, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120SC2AN", 0x00112023, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120SD2AN", 0x00112016, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120SD3AN", 0x00112015, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120VD2AN", 0x00112013, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120VD3AN", 0x00112012, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120ZC2AN", 0x00112029, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120ZD2AN", 0x00112028, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120ZD3AN", 0x00112027, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++
++ /* NANO100BN */
++ {"NANO100KC2BN", 0x00110040, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100KD2BN", 0x00110039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100KD3BN", 0x00110038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100KE3BN", 0x00110030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100LC2BN", 0x00110043, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100LD2BN", 0x0011003F, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100LD3BN", 0x0011003E, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100LE3BN", 0x00110036, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100ND2BN", 0x00110046, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100ND3BN", 0x00110045, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100NE3BN", 0x00110044, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100SC2BN", 0x00110042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100SD2BN", 0x0011003D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100SD3BN", 0x0011003C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO100SE3BN", 0x00110034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110KC2BN", 0x00111040, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110KD2BN", 0x00111039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110KD3BN", 0x00111038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110KE3BN", 0x00111030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110RC2BN", 0x00111043, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110RD2BN", 0x00111044, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110RD3BN", 0x00111045, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110SC2BN", 0x00111042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110SD2BN", 0x0011103D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110SD3BN", 0x0011103C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO110SE3BN", 0x00111034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120KC2BN", 0x00112040, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120KD2BN", 0x00112039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120KD3BN", 0x00112038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120KE3BN", 0x00112030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120LC2BN", 0x00112043, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120LD2BN", 0x0011203F, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120LD3BN", 0x0011203E, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120LE3BN", 0x00112036, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120SC2BN", 0x00112042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120SD2BN", 0x0011203D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120SD3BN", 0x0011203C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO120SE3BN", 0x00112034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO130KC2BN", 0x00113040, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO130KD2BN", 0x00113039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO130KD3BN", 0x00113038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO130KE3BN", 0x00113030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO130SC2BN", 0x00113042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO130SD2BN", 0x0011303D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO130SD3BN", 0x0011303C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO130SE3BN", 0x00113034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
++
++ /* NANO103 */
++ {"NANO103SD3AE", 0x00110301, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO103LD3AE", 0x00110304, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO103ZD3AE", 0x00110307, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
++
++ /* NANO112AN */
++ {"NANO102LB1AN", 0x00110206, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO102LC2AN", 0x00110208, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO102SC2AN", 0x00110212, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO102ZB1AN", 0x00110202, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO102ZC2AN", 0x00110204, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO112LB1AN", 0x00111202, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO112LC2AN", 0x00111204, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO112RB1AN", 0x00111210, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO112RC2AN", 0x00111212, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO112SB1AN", 0x00111206, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO112SC2AN", 0x00111208, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NANO112VC2AN", 0x00111216, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
++
++ /* NUC029AN */
++ {"NUC029LAN", 0x00295A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
++ {"NUC029TAN", 0x00295804, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
++
++ /* NUC029AE */
++ {"NUC029FAE", 0x00295415, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
++
++ /* NUC100AN */
++ {"NUC100LD3AN", 0x00010003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100LE3AN", 0x00010000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC100RD3AN", 0x00010012, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100RE3AN", 0x00010009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC100VD2AN", 0x00010022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100VD3AN", 0x00010021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100VE3AN", 0x00100018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC120LD3AN", 0x00012003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120LE3AN", 0x00120000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC120RD3AN", 0x00012012, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120RE3AN", 0x00012009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC120VD2AN", 0x00012022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120VD3AN", 0x00012021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120VE3AN", 0x00012018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++
++ /* NUC100BN */
++ {"NUC100LC1BN", 0x10010008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100LD1BN", 0x10010005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100LD2BN", 0x10010004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100RC1BN", 0x10010017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100RD1BN", 0x10010014, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100RD2BN", 0x10010013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120LC1BN", 0x10012008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120LD1BN", 0x10012005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120LD2BN", 0x10012004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120RC1BN", 0x10012017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120RD1BN", 0x10012014, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120RD2BN", 0x10012013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++
++ /* NUC100CN */
++ {"NUC130LC1CN", 0x20013008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC130LD2CN", 0x20013004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC130LE3CN", 0x20013000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC130RC1CN", 0x20013017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC130RD2CN", 0x20013013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC130RE3CN", 0x20013009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC130VE3CN", 0x20013018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC140LC1CN", 0x20014008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC140LD2CN", 0x20014004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC140LE3CN", 0x20014000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC140RC1CN", 0x20014017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC140RD2CN", 0x20014013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC140RE3CN", 0x20014009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC140VE3CN", 0x20014018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++
++ /* NUC100DN */
++ {"NUC100LC1DN", 0x30010008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100LD1DN", 0x30010005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100LD2DN", 0x30010004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100LD3DN", 0x30010003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100LE3DN", 0x30010000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC100RC1DN", 0x30010017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100RD1DN", 0x30010014, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100RD2DN", 0x30010013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100RD3DN", 0x30010012, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100RE3DN", 0x30010009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC100VD2DN", 0x30010022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100VD3DN", 0x30010021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC100VE3DN", 0x30010018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC120LC1DN", 0x30012008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120LD1DN", 0x30012005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120LD2DN", 0x30012004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120LD3DN", 0x30012003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120LE3DN", 0x30012000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC120RC1DN", 0x30012035, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120RD1DN", 0x30012032, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120RD2DN", 0x30012031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120RD3DN", 0x30012030, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120RE3DN", 0x30012027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC120VD2DN", 0x30012022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120VD3DN", 0x30012021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC120VE3DN", 0x30012018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++
++ /* NUC121 */
++ {"NUC121SC2AE", 0x00012105, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
++ {"NUC121LC2AE", 0x00012125, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
++ {"NUC121ZC2AE", 0x00012145, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
++ {"NUC125SC2AE", 0x00012505, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
++ {"NUC125LC2AE", 0x00012525, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
++ {"NUC125ZC2AE", 0x00012545, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
++
++ /* NUC122 */
++ {"NUC122LC1AN", 0x00012208, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC122LD2AN", 0x00012204, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC122SC1AN", 0x00012226, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC122SD2AN", 0x00012222, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC122ZC1AN", 0x00012235, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC122ZD2AN", 0x00012231, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++
++ /* NUC123AN */
++ {"NUC123LC2AN1", 0x00012325, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123LD4AN0", 0x00012335, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123SC2AN1", 0x00012305, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123SD4AN0", 0x00012315, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123ZC2AN1", 0x00012345, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123ZD4AN0", 0x00012355, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++
++ /* NUC123AE */
++ {"NUC123LC2AE1", 0x10012325, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123LD4AE0", 0x10012335, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123SC2AE1", 0x10012305, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123SD4AE0", 0x10012315, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123ZC2AE1", 0x10012345, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC123ZD4AE0", 0x10012355, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++
++ /* NUC131AE */
++ {"NUC131LC2AE", 0x10013103, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC131LD2AE", 0x10013100, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC131SC2AE", 0x10013113, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC131SD2AE", 0x10013110, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++
++ /* NUC200/220AN */
++ {"NUC200LC2AN", 0x00020007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC200LD2AN", 0x00020004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC200LE3AN", 0x00020000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC200SC2AN", 0x00020034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC200SD2AN", 0x00020031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC200SE3AN", 0x00020027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC200VE3AN", 0x00020018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC220LC2AN", 0x00022007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC220LD2AN", 0x00022004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC220LE3AN", 0x00022000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC220SC2AN", 0x00022034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC220SD2AN", 0x00022031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
++ {"NUC220SE3AN", 0x00022027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"NUC220VE3AN", 0x00022018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++
++ /* NUC230/240AE */
++ {"NUC230LC2AE", 0x10023007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"NUC230LD2AE", 0x10023004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"NUC230LE3AE", 0x10023000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
++ {"NUC230SC2AE", 0x10023034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"NUC230SD2AE", 0x10023031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"NUC230SE3AE", 0x10023027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
++ {"NUC230VE3AE", 0x10023018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
++ {"NUC240LC2AE", 0x10024007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"NUC240LD2AE", 0x10024004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"NUC240LE3AE", 0x10024000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
++ {"NUC240SC2AE", 0x10024034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"NUC240SD2AE", 0x10024031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
++ {"NUC240SE3AE", 0x10024027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
++ {"NUC240VE3AE", 0x10024018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
++
++ {"UNKNOWN", 0x00000000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 16 * 1024, 8)},
+ };
+
+ /* Private bank information for NuMicro. */
new file mode 100644
@@ -0,0 +1,649 @@
+From d1b0cb2b774c1033a6ca8e531781df82baac40f7 Mon Sep 17 00:00:00 2001
+From: Zale Yu <cyyu@nuvoton.com>
+Date: Sun, 6 Nov 2022 23:32:22 +0800
+Subject: [PATCH] flash: support Nuvoton M541 & NUC442/472 series
+
+This patch is picked from the flash part of OpenOCD-Nuvoton's commit
+("flash: supported Nuvoton M4 series. jtag: Used HW reset instead of
+auto reset. tcl: added a configuration file for Nuvoton M4 series.") [1]
+to support flashing Nuvoton's Cortex-M4 chips: M541 & NUC442/472 series.
+
+The code comes from the commit basically. Jian-Hong Pan tweaked for the
+compatibility with current OpenOCD. So, leave the author as Zale Yu.
+
+[1]: https://github.com/OpenNuvoton/OpenOCD-Nuvoton/commit/c2d5b8bfc705
+
+Signed-off-by: Zale Yu <cyyu@nuvoton.com>
+Signed-off-by: Jian-Hong Pan <chienhung.pan@gmail.com>
+Change-Id: I9dc69eccb851df14c1b0ce2f619d7b3da0aa92aa
+Reviewed-on: https://review.openocd.org/c/openocd/+/7329
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/numicro.c | 334 ++++++++++++++++++++++++++++++----------
+ 1 file changed, 253 insertions(+), 81 deletions(-)
+
+diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c
+index bafad80ce..2bba7b746 100644
+--- a/src/flash/nor/numicro.c
++++ b/src/flash/nor/numicro.c
+@@ -466,6 +466,65 @@ static const struct numicro_cpu_type numicro_parts[] = {
+ {"NUC240SE3AE", 0x10024027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
+ {"NUC240VE3AE", 0x10024018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
+
++ /* M451 */
++ {"M451LC3AE", 0x00945101, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451LD3AE", 0x00945100, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451LE6AE", 0x00845101, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451LG6AE", 0x00845100, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451MLC3AE", 0x00945001, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451MLD3AE", 0x00945000, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451MLE6AE", 0x00845001, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451MLG6AE", 0x00845000, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451MSC3AE", 0x00945011, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451MSD3AE", 0x00945010, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451RC3AE", 0x00945121, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451RD3AE", 0x00945120, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451RE6AE", 0x00845121, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451RG6AE", 0x00845120, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451VE6AE", 0x00845131, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M451VG6AE", 0x00845130, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M452LC3AE", 0x00945201, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M452LD3AE", 0x00945200, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M452LE6AE", 0x00845201, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M452LG6AE", 0x00845200, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M452RD3AE", 0x00945220, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M452RE6AE", 0x00845221, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M452RG6AE", 0x00845220, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453LC3AE", 0x00945301, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453LD3AE", 0x00945300, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453LE6AE", 0x00845301, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453LG6AE", 0x00845300, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453RD3AE", 0x00945320, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453RE6AE", 0x00845321, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453RG6AE", 0x00845320, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453VD3AE", 0x00945330, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453VE6AE", 0x00845331, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M453VG6AE", 0x00845330, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M4TKVG6AE", 0x00845430, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M4TKVE6AE", 0x00845431, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M4TKRG6AE", 0x00845420, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M4TKRE6AE", 0x00845421, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M4TKLG6AE", 0x00845400, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
++ {"M4TKLE6AE", 0x00845401, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
++
++ /* NUC442_472 */
++ {"NUC442JG8AE", 0x00044203, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC442JI8AE", 0x00044201, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC442KG8AE", 0x00044206, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC442KI8AE", 0x00044204, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC442RG8AE", 0x00044212, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC442RI8AE", 0x00044210, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC442VG8AE", 0x00044209, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC442VI8AE", 0x00044207, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC472HG8AE", 0x00047203, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC472HI8AE", 0x00047201, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC472JG8AE", 0x00047206, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC472JI8AE", 0x00047204, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC472KG8AE", 0x00047209, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC472KI8AE", 0x00047207, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC472VG8AE", 0x00047212, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
++ {"NUC472VI8AE", 0x00047210, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
++
+ {"UNKNOWN", 0x00000000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 16 * 1024, 8)},
+ };
+
+@@ -476,32 +535,53 @@ struct numicro_flash_bank {
+ const struct numicro_cpu_type *cpu;
+ };
+
++/* Private variables */
++uint32_t m_page_size = NUMICRO_PAGESIZE;
++uint32_t m_address_bias_offset;
++
+ /* Private methods */
++static int numicro_get_arm_arch(struct target *target)
++{
++ struct armv7m_common *armv7m = target_to_armv7m(target);
++
++ if (armv7m->arm.arch != ARM_ARCH_V6M) {
++ LOG_DEBUG("NuMicro arm architecture: armv7m\n");
++ m_page_size = NUMICRO_PAGESIZE * 4;
++ m_address_bias_offset = 0x10000000;
++ } else {
++ LOG_DEBUG("NuMicro arm architecture: armv6m\n");
++ m_page_size = NUMICRO_PAGESIZE;
++ m_address_bias_offset = 0x0;
++ }
++
++ return ERROR_OK;
++}
++
+ static int numicro_reg_unlock(struct target *target)
+ {
+ uint32_t is_protected;
+ int retval = ERROR_OK;
+
+ /* Check to see if NUC is register unlocked or not */
+- retval = target_read_u32(target, NUMICRO_SYS_WRPROT, &is_protected);
++ retval = target_read_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, &is_protected);
+ if (retval != ERROR_OK)
+ return retval;
+
+ LOG_DEBUG("protected = 0x%08" PRIx32 "", is_protected);
+ if (is_protected == 0) { /* means protected - so unlock it */
+ /* unlock flash registers */
+- retval = target_write_u32(target, NUMICRO_SYS_WRPROT, REG_KEY1);
++ retval = target_write_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, REG_KEY1);
+ if (retval != ERROR_OK)
+ return retval;
+- retval = target_write_u32(target, NUMICRO_SYS_WRPROT, REG_KEY2);
++ retval = target_write_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, REG_KEY2);
+ if (retval != ERROR_OK)
+ return retval;
+- retval = target_write_u32(target, NUMICRO_SYS_WRPROT, REG_KEY3);
++ retval = target_write_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, REG_KEY3);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ /* Check that unlock worked */
+- retval = target_read_u32(target, NUMICRO_SYS_WRPROT, &is_protected);
++ retval = target_read_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, &is_protected);
+ if (retval != ERROR_OK)
+ return retval;
+
+@@ -529,27 +609,27 @@ static int numicro_init_isp(struct target *target)
+ return retval;
+
+ /* Enable ISP/SRAM/TICK Clock */
+- retval = target_read_u32(target, NUMICRO_SYSCLK_AHBCLK, ®_stat);
++ retval = target_read_u32(target, NUMICRO_SYSCLK_AHBCLK - m_address_bias_offset, ®_stat);
+ if (retval != ERROR_OK)
+ return retval;
+
+ reg_stat |= AHBCLK_ISP_EN | AHBCLK_SRAM_EN | AHBCLK_TICK_EN;
+- retval = target_write_u32(target, NUMICRO_SYSCLK_AHBCLK, reg_stat);
++ retval = target_write_u32(target, NUMICRO_SYSCLK_AHBCLK - m_address_bias_offset, reg_stat);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Enable ISP */
+- retval = target_read_u32(target, NUMICRO_FLASH_ISPCON, ®_stat);
++ retval = target_read_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, ®_stat);
+ if (retval != ERROR_OK)
+ return retval;
+
+ reg_stat |= ISPCON_ISPFF | ISPCON_LDUEN | ISPCON_APUEN | ISPCON_CFGUEN | ISPCON_ISPEN;
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPCON, reg_stat);
++ retval = target_write_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, reg_stat);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Write one to undocumented flash control register */
+- retval = target_write_u32(target, NUMICRO_FLASH_CHEAT, 1);
++ retval = target_write_u32(target, NUMICRO_FLASH_CHEAT - m_address_bias_offset, 1);
+ if (retval != ERROR_OK)
+ return retval;
+
+@@ -561,29 +641,28 @@ static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t ad
+ uint32_t timeout, status;
+ int retval = ERROR_OK;
+
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD, cmd);
++ retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD - m_address_bias_offset, cmd);
+ if (retval != ERROR_OK)
+ return retval;
+
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPDAT, wdata);
++ retval = target_write_u32(target, NUMICRO_FLASH_ISPDAT - m_address_bias_offset, wdata);
+ if (retval != ERROR_OK)
+ return retval;
+
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, addr);
++ retval = target_write_u32(target, NUMICRO_FLASH_ISPADR - m_address_bias_offset, addr);
+ if (retval != ERROR_OK)
+ return retval;
+
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO);
++ retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG - m_address_bias_offset, ISPTRG_ISPGO);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Wait for busy to clear - check the GO flag */
+ timeout = 100;
+ for (;;) {
+- retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
++ retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG - m_address_bias_offset, &status);
+ if (retval != ERROR_OK)
+ return retval;
+- LOG_DEBUG("status: 0x%" PRIx32 "", status);
+ if ((status & (ISPTRG_ISPGO)) == 0)
+ break;
+ if (timeout-- <= 0) {
+@@ -593,79 +672,138 @@ static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t ad
+ busy_sleep(1); /* can use busy sleep for short times. */
+ }
+
+- retval = target_read_u32(target, NUMICRO_FLASH_ISPDAT, rdata);
++ retval = target_read_u32(target, NUMICRO_FLASH_ISPDAT - m_address_bias_offset, rdata);
+ if (retval != ERROR_OK)
+ return retval;
+
+ return ERROR_OK;
+ }
+
+-
+ /* NuMicro Program-LongWord Microcodes */
+ static const uint8_t numicro_flash_write_code[] = {
+- /* Params:
+- * r0 - workarea buffer / result
+- * r1 - target address
+- * r2 - wordcount
+- * Clobbered:
+- * r4 - tmp
+- * r5 - tmp
+- * r6 - tmp
+- * r7 - tmp
+- */
+-
+- /* .L1: */
+- /* for(register uint32_t i=0;i<wcount;i++){ */
++ /* Params:
++ * r0 - workarea buffer / result
++ * r1 - target address
++ * r2 - wordcount
++ * Clobbered:
++ * r4 - tmp
++ * r5 - tmp
++ * r6 - tmp
++ * r7 - tmp
++ */
++
++ /* .L1: */
++ /* for(register uint32_t i=0;i<wcount;i++){ */
+ 0x04, 0x1C, /* mov r4, r0 */
+ 0x00, 0x23, /* mov r3, #0 */
+- /* .L2: */
++ /* .L2: */
+ 0x0D, 0x1A, /* sub r5, r1, r0 */
+ 0x67, 0x19, /* add r7, r4, r7 */
+ 0x93, 0x42, /* cmp r3, r2 */
+ 0x0C, 0xD0, /* beq .L7 */
+- /* .L4: */
+- /* NUMICRO_FLASH_ISPADR = faddr; */
++ /* .L4: */
++ /* NUMICRO_FLASH_ISPADR = faddr; */
+ 0x08, 0x4E, /* ldr r6, .L8 */
+ 0x37, 0x60, /* str r7, [r6] */
+- /* NUMICRO_FLASH_ISPDAT = *pLW; */
++ /* NUMICRO_FLASH_ISPDAT = *pLW; */
+ 0x80, 0xCC, /* ldmia r4!, {r7} */
+ 0x08, 0x4D, /* ldr r5, .L8+4 */
+ 0x2F, 0x60, /* str r7, [r5] */
+- /* faddr += 4; */
+- /* pLW++; */
+- /* Trigger write action */
+- /* NUMICRO_FLASH_ISPTRG = ISPTRG_ISPGO; */
++ /* faddr += 4; */
++ /* pLW++; */
++ /* Trigger write action */
++ /* NUMICRO_FLASH_ISPTRG = ISPTRG_ISPGO; */
+ 0x08, 0x4D, /* ldr r5, .L8+8 */
+ 0x01, 0x26, /* mov r6, #1 */
+ 0x2E, 0x60, /* str r6, [r5] */
+- /* .L3: */
+- /* while((NUMICRO_FLASH_ISPTRG & ISPTRG_ISPGO) == ISPTRG_ISPGO){}; */
++ /* .L3: */
++ /* while((NUMICRO_FLASH_ISPTRG & ISPTRG_ISPGO) == ISPTRG_ISPGO){}; */
+ 0x2F, 0x68, /* ldr r7, [r5] */
+ 0xFF, 0x07, /* lsl r7, r7, #31 */
+ 0xFC, 0xD4, /* bmi .L3 */
+
+ 0x01, 0x33, /* add r3, r3, #1 */
+ 0xEE, 0xE7, /* b .L2 */
+- /* .L7: */
+- /* return (NUMICRO_FLASH_ISPCON & ISPCON_ISPFF); */
++ /* .L7: */
++ /* return (NUMICRO_FLASH_ISPCON & ISPCON_ISPFF); */
+ 0x05, 0x4B, /* ldr r3, .L8+12 */
+ 0x18, 0x68, /* ldr r0, [r3] */
+ 0x40, 0x21, /* mov r1, #64 */
+ 0x08, 0x40, /* and r0, r1 */
+- /* .L9: */
++ /* .L9: */
+ 0x00, 0xBE, /* bkpt #0 */
+- /* .L8: */
++ /* .L8: */
+ 0x04, 0xC0, 0x00, 0x50,/* .word 1342226436 */
+ 0x08, 0xC0, 0x00, 0x50,/* .word 1342226440 */
+ 0x10, 0xC0, 0x00, 0x50,/* .word 1342226448 */
+ 0x00, 0xC0, 0x00, 0x50 /* .word 1342226432 */
+ };
++
++static const uint8_t numicro_m4_flash_write_code[] = {
++ /* Params:
++ * r0 - workarea buffer / result
++ * r1 - target address
++ * r2 - wordcount
++ * Clobbered:
++ * r4 - tmp
++ * r5 - tmp
++ * r6 - tmp
++ * r7 - tmp
++ */
++
++ /* .L1: */
++ /* for(register uint32_t i=0;i<wcount;i++){ */
++ 0x04, 0x1C, /* mov r4, r0 */
++ 0x00, 0x23, /* mov r3, #0 */
++ /* .L2: */
++ 0x0D, 0x1A, /* sub r5, r1, r0 */
++ 0x67, 0x19, /* add r7, r4, r7 */
++ 0x93, 0x42, /* cmp r3, r2 */
++ 0x0C, 0xD0, /* beq .L7 */
++ /* .L4: */
++ /* NUMICRO_FLASH_ISPADR = faddr; */
++ 0x08, 0x4E, /* ldr r6, .L8 */
++ 0x37, 0x60, /* str r7, [r6] */
++ /* NUMICRO_FLASH_ISPDAT = *pLW; */
++ 0x80, 0xCC, /* ldmia r4!, {r7} */
++ 0x08, 0x4D, /* ldr r5, .L8+4 */
++ 0x2F, 0x60, /* str r7, [r5] */
++ /* faddr += 4; */
++ /* pLW++; */
++ /* Trigger write action */
++ /* NUMICRO_FLASH_ISPTRG = ISPTRG_ISPGO; */
++ 0x08, 0x4D, /* ldr r5, .L8+8 */
++ 0x01, 0x26, /* mov r6, #1 */
++ 0x2E, 0x60, /* str r6, [r5] */
++ /* .L3: */
++ /* while((NUMICRO_FLASH_ISPTRG & ISPTRG_ISPGO) == ISPTRG_ISPGO){}; */
++ 0x2F, 0x68, /* ldr r7, [r5] */
++ 0xFF, 0x07, /* lsl r7, r7, #31 */
++ 0xFC, 0xD4, /* bmi .L3 */
++
++ 0x01, 0x33, /* add r3, r3, #1 */
++ 0xEE, 0xE7, /* b .L2 */
++ /* .L7: */
++ /* return (NUMICRO_FLASH_ISPCON & ISPCON_ISPFF); */
++ 0x05, 0x4B, /* ldr r3, .L8+12 */
++ 0x18, 0x68, /* ldr r0, [r3] */
++ 0x40, 0x21, /* mov r1, #64 */
++ 0x08, 0x40, /* and r0, r1 */
++ /* .L9: */
++ 0x00, 0xBE, /* bkpt #0 */
++ /* .L8: */
++ 0x04, 0xC0, 0x00, 0x40,/* .word 0x4000C004 */
++ 0x08, 0xC0, 0x00, 0x40,/* .word 0x4000C008 */
++ 0x10, 0xC0, 0x00, 0x40,/* .word 0x4000C010 */
++ 0x00, 0xC0, 0x00, 0x40 /* .word 0x4000C000 */
++};
++
+ /* Program LongWord Block Write */
+ static int numicro_writeblock(struct flash_bank *bank, const uint8_t *buffer,
+ uint32_t offset, uint32_t count)
+ {
+ struct target *target = bank->target;
+- uint32_t buffer_size = 1024; /* Default minimum value */
++ uint32_t buffer_size = 1024; /* Default minimum value */
+ struct working_area *write_algorithm;
+ struct working_area *source;
+ uint32_t address = bank->base + offset;
+@@ -693,18 +831,34 @@ static int numicro_writeblock(struct flash_bank *bank, const uint8_t *buffer,
+ LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
+ return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+ }
++ /* Difference between M0 and M4 */
++ if (m_page_size == NUMICRO_PAGESIZE) {
++ /* allocate working area with flash programming code */
++ if (target_alloc_working_area(target, sizeof(numicro_flash_write_code),
++ &write_algorithm) != ERROR_OK) {
++ LOG_WARNING("no working area available, can't do block memory writes");
++ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
++ }
+
+- /* allocate working area with flash programming code */
+- if (target_alloc_working_area(target, sizeof(numicro_flash_write_code),
++ retval = target_write_buffer(target, write_algorithm->address,
++ sizeof(numicro_flash_write_code), numicro_flash_write_code);
++ if (retval != ERROR_OK)
++ return retval;
++ } else { /* for M4 */
++ /* allocate working area with flash programming code */
++ if (target_alloc_working_area(target, sizeof(numicro_m4_flash_write_code),
+ &write_algorithm) != ERROR_OK) {
+- LOG_WARNING("no working area available, can't do block memory writes");
+- return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+- }
++ LOG_WARNING("no working area available, can't do block memory writes");
++ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
++ }
+
+- retval = target_write_buffer(target, write_algorithm->address,
+- sizeof(numicro_flash_write_code), numicro_flash_write_code);
+- if (retval != ERROR_OK)
+- return retval;
++ retval = target_write_buffer(target, write_algorithm->address,
++ sizeof(numicro_m4_flash_write_code), numicro_m4_flash_write_code);
++ if (retval != ERROR_OK)
++ return retval;
++
++ buffer_size = m_page_size;
++ }
+
+ /* memory buffer */
+ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
+@@ -775,13 +929,14 @@ static int numicro_protect_check(struct flash_bank *bank)
+
+ LOG_INFO("Nuvoton NuMicro: Flash Lock Check...");
+
++ numicro_get_arm_arch(target);
+ retval = numicro_init_isp(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* Read CONFIG0,CONFIG1 */
+- numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG0, 0 , &config[0]);
+- numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG1, 0 , &config[1]);
++ numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG0 - m_address_bias_offset, 0, &config[0]);
++ numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG1 - m_address_bias_offset, 0, &config[1]);
+
+ LOG_DEBUG("CONFIG0: 0x%" PRIx32 ",CONFIG1: 0x%" PRIx32 "", config[0], config[1]);
+
+@@ -821,31 +976,34 @@ static int numicro_erase(struct flash_bank *bank, unsigned int first,
+
+ LOG_INFO("Nuvoton NuMicro: Sector Erase ... (%u to %u)", first, last);
+
++ numicro_get_arm_arch(target);
+ retval = numicro_init_isp(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD, ISPCMD_ERASE);
++ retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD - m_address_bias_offset, ISPCMD_ERASE);
+ if (retval != ERROR_OK)
+ return retval;
+
+ for (unsigned int i = first; i <= last; i++) {
+- LOG_DEBUG("erasing sector %u at address " TARGET_ADDR_FMT, i,
+- bank->base + bank->sectors[i].offset);
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, bank->base + bank->sectors[i].offset);
++ LOG_DEBUG("erasing sector %u at address " TARGET_ADDR_FMT, i, bank->base + bank->sectors[i].offset);
++ retval = target_write_u32(target,
++ NUMICRO_FLASH_ISPADR - m_address_bias_offset,
++ bank->base + bank->sectors[i].offset);
+ if (retval != ERROR_OK)
+ return retval;
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO); /* This is the only bit available */
++ retval = target_write_u32(target,
++ NUMICRO_FLASH_ISPTRG - m_address_bias_offset,
++ ISPTRG_ISPGO); /* This is the only bit available */
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* wait for busy to clear - check the GO flag */
+ timeout = 100;
+ for (;;) {
+- retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
++ retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG - m_address_bias_offset, &status);
+ if (retval != ERROR_OK)
+ return retval;
+- LOG_DEBUG("status: 0x%" PRIx32 "", status);
+ if (status == 0)
+ break;
+ if (timeout-- <= 0) {
+@@ -856,13 +1014,13 @@ static int numicro_erase(struct flash_bank *bank, unsigned int first,
+ }
+
+ /* check for failure */
+- retval = target_read_u32(target, NUMICRO_FLASH_ISPCON, &status);
++ retval = target_read_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, &status);
+ if (retval != ERROR_OK)
+ return retval;
+ if ((status & ISPCON_ISPFF) != 0) {
+ LOG_DEBUG("failure: 0x%" PRIx32 "", status);
+ /* if bit is set, then must write to it to clear it. */
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPCON, (status | ISPCON_ISPFF));
++ retval = target_write_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, (status | ISPCON_ISPFF));
+ if (retval != ERROR_OK)
+ return retval;
+ }
+@@ -889,11 +1047,12 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
+
+ LOG_INFO("Nuvoton NuMicro: Flash Write ...");
+
++ numicro_get_arm_arch(target);
+ retval = numicro_init_isp(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD, ISPCMD_WRITE);
++ retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD - m_address_bias_offset, ISPCMD_WRITE);
+ if (retval != ERROR_OK)
+ return retval;
+
+@@ -913,26 +1072,34 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
+
+ /* program command */
+ for (uint32_t i = 0; i < count; i += 4) {
++ /* write 4 bytes each time with 0xff padding to avoid unaligned case */
++ uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff};
++ memcpy(padding, buffer + i, MIN(4, count - i));
+
+- LOG_DEBUG("write longword @ %08" PRIX32, offset + i);
+-
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, bank->base + offset + i);
++ retval = target_write_u32(target,
++ NUMICRO_FLASH_ISPADR - m_address_bias_offset,
++ bank->base + offset + i);
+ if (retval != ERROR_OK)
+ return retval;
+- retval = target_write_memory(target, NUMICRO_FLASH_ISPDAT, 4, 1, buffer + i);
++ retval = target_write_memory(target,
++ NUMICRO_FLASH_ISPDAT - m_address_bias_offset,
++ 4, 1, padding);
+ if (retval != ERROR_OK)
+ return retval;
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO);
++ retval = target_write_u32(target,
++ NUMICRO_FLASH_ISPTRG - m_address_bias_offset,
++ ISPTRG_ISPGO);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* wait for busy to clear - check the GO flag */
+ timeout = 100;
+ for (;;) {
+- retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
++ retval = target_read_u32(target,
++ NUMICRO_FLASH_ISPTRG - m_address_bias_offset,
++ &status);
+ if (retval != ERROR_OK)
+ return retval;
+- LOG_DEBUG("status: 0x%" PRIx32 "", status);
+ if (status == 0)
+ break;
+ if (timeout-- <= 0) {
+@@ -946,13 +1113,15 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
+ }
+
+ /* check for failure */
+- retval = target_read_u32(target, NUMICRO_FLASH_ISPCON, &status);
++ retval = target_read_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, &status);
+ if (retval != ERROR_OK)
+ return retval;
+ if ((status & ISPCON_ISPFF) != 0) {
+ LOG_DEBUG("failure: 0x%" PRIx32 "", status);
+ /* if bit is set, then must write to it to clear it. */
+- retval = target_write_u32(target, NUMICRO_FLASH_ISPCON, (status | ISPCON_ISPFF));
++ retval = target_write_u32(target,
++ NUMICRO_FLASH_ISPCON - m_address_bias_offset,
++ (status | ISPCON_ISPFF));
+ if (retval != ERROR_OK)
+ return retval;
+ } else {
+@@ -970,8 +1139,9 @@ static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_
+ uint32_t part_id;
+ int retval = ERROR_OK;
+
++ numicro_get_arm_arch(target);
+ /* Read NuMicro PartID */
+- retval = target_read_u32(target, NUMICRO_SYS_BASE, &part_id);
++ retval = target_read_u32(target, NUMICRO_SYS_BASE - m_address_bias_offset, &part_id);
+ if (retval != ERROR_OK) {
+ LOG_WARNING("NuMicro flash driver: Failed to Get PartID\n");
+ return ERROR_FLASH_OPERATION_FAILED;
+@@ -1023,7 +1193,7 @@ static int numicro_probe(struct flash_bank *bank)
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+- num_pages = flash_size / NUMICRO_PAGESIZE;
++ num_pages = flash_size / m_page_size;
+
+ bank->num_sectors = num_pages;
+ bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
+@@ -1031,10 +1201,10 @@ static int numicro_probe(struct flash_bank *bank)
+
+ for (int i = 0; i < num_pages; i++) {
+ bank->sectors[i].offset = offset;
+- bank->sectors[i].size = NUMICRO_PAGESIZE;
++ bank->sectors[i].size = m_page_size;
+ bank->sectors[i].is_erased = -1;
+ bank->sectors[i].is_protected = 0;
+- offset += NUMICRO_PAGESIZE;
++ offset += m_page_size;
+ }
+
+ struct numicro_flash_bank *numicro_info = bank->driver_priv;
+@@ -1073,7 +1243,6 @@ FLASH_BANK_COMMAND_HANDLER(numicro_flash_bank_command)
+ bank->write_start_alignment = bank->write_end_alignment = 4;
+
+ return ERROR_OK;
+-
+ }
+
+ COMMAND_HANDLER(numicro_handle_read_isp_command)
+@@ -1089,6 +1258,7 @@ COMMAND_HANDLER(numicro_handle_read_isp_command)
+
+ struct target *target = get_current_target(CMD_CTX);
+
++ numicro_get_arm_arch(target);
+ retval = numicro_init_isp(target);
+ if (retval != ERROR_OK)
+ return retval;
+@@ -1116,6 +1286,7 @@ COMMAND_HANDLER(numicro_handle_write_isp_command)
+
+ struct target *target = get_current_target(CMD_CTX);
+
++ numicro_get_arm_arch(target);
+ retval = numicro_init_isp(target);
+ if (retval != ERROR_OK)
+ return retval;
+@@ -1138,6 +1309,7 @@ COMMAND_HANDLER(numicro_handle_chip_erase_command)
+
+ struct target *target = get_current_target(CMD_CTX);
+
++ numicro_get_arm_arch(target);
+ retval = numicro_init_isp(target);
+ if (retval != ERROR_OK)
+ return retval;
new file mode 100644
@@ -0,0 +1,101 @@
+From 21b14028ad7565f4916ae05a6c28b465eceb9150 Mon Sep 17 00:00:00 2001
+From: Zale Yu <cyyu@nuvoton.com>
+Date: Fri, 4 Nov 2022 23:07:29 +0800
+Subject: [PATCH] tcl: add a configuration file for Nuvoton M541 & NUC442/472
+ series
+
+This patch is picked from the tcl part of OpenOCD-Nuvoton's commit
+("flash: supported Nuvoton M4 series. jtag: Used HW reset instead of
+auto reset. tcl: added a configuration file for Nuvoton M4 series.") [1]
+to support the communication with Nuvoton's Cortex-M4 chips: M541 &
+NUC442/472 series.
+
+This patch has been tested with Nuvoton's NuTiny-SDK-NUC472 development
+board [2].
+
+The code comes from the commit basically. Jian-Hong Pan tweaked for the
+compatibility with current OpenOCD. So, leave the author as Zale Yu.
+
+[1]: https://github.com/OpenNuvoton/OpenOCD-Nuvoton/commit/c2d5b8bfc705
+[2]: https://www.nuvoton.com/export/resource-files/UM_NuTiny-SDK-
+ NUC472_EN_Rev1.02.pdf
+
+Signed-off-by: Zale Yu <cyyu@nuvoton.com>
+Signed-off-by: Jian-Hong Pan <chienhung.pan@gmail.com>
+Change-Id: I27ac58dd1c98a76e791a4f1117c31060cf5522e8
+Reviewed-on: https://review.openocd.org/c/openocd/+/7330
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ tcl/target/numicro_m4.cfg | 62 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 62 insertions(+)
+ create mode 100644 tcl/target/numicro_m4.cfg
+
+diff --git a/tcl/target/numicro_m4.cfg b/tcl/target/numicro_m4.cfg
+new file mode 100644
+index 000000000..1302515d3
+--- /dev/null
++++ b/tcl/target/numicro_m4.cfg
+@@ -0,0 +1,62 @@
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++# script for Nuvoton MuMicro Cortex-M4 Series
++
++source [find target/swj-dp.tcl]
++
++# Set Chipname
++if { [info exists CHIPNAME] } {
++ set _CHIPNAME $CHIPNAME
++} else {
++ set _CHIPNAME NuMicro
++}
++
++# SWD DP-ID Nuvoton NuMicro Cortex-M4 has SWD Transport only.
++if { [info exists CPUDAPID] } {
++ set _CPUDAPID $CPUDAPID
++} else {
++ set _CPUDAPID 0x2BA01477
++}
++
++# Work-area is a space in RAM used for flash programming
++# By default use 16kB
++if { [info exists WORKAREASIZE] } {
++ set _WORKAREASIZE $WORKAREASIZE
++} else {
++ set _WORKAREASIZE 0x4000
++}
++
++
++# Debug Adapter Target Settings
++swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUDAPID
++dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
++set _TARGETNAME $_CHIPNAME.cpu
++target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap
++
++$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
++
++# flash bank <name> numicro <base> <size(autodetect,set to 0)> 0 0 <target#>
++#set _FLASHNAME $_CHIPNAME.flash
++#flash bank $_FLASHNAME numicro 0 $_FLASHSIZE 0 0 $_TARGETNAME
++# flash size will be probed
++set _FLASHNAME $_CHIPNAME.flash_aprom
++flash bank $_FLASHNAME numicro 0x00000000 0 0 0 $_TARGETNAME
++set _FLASHNAME $_CHIPNAME.flash_data
++flash bank $_FLASHNAME numicro 0x0001F000 0 0 0 $_TARGETNAME
++set _FLASHNAME $_CHIPNAME.flash_ldrom
++flash bank $_FLASHNAME numicro 0x00100000 0 0 0 $_TARGETNAME
++set _FLASHNAME $_CHIPNAME.flash_config
++flash bank $_FLASHNAME numicro 0x00300000 0 0 0 $_TARGETNAME
++
++# set default SWCLK frequency
++adapter speed 1000
++
++# set default srst setting "none"
++reset_config none
++
++# HLA doesn't have cortex_m commands
++if {![using_hla]} {
++ # if srst is not fitted use SYSRESETREQ to
++ # perform a soft reset
++ cortex_m reset_config sysresetreq
++}
new file mode 100644
@@ -0,0 +1,216 @@
+From 63336f4aaf672899db78de4ce6781c9451851472 Mon Sep 17 00:00:00 2001
+From: Jian-Hong Pan <chienhung.pan@gmail.com>
+Date: Thu, 10 Nov 2022 00:14:10 +0800
+Subject: [PATCH] flash/nor, contrib/loaders: move numicro M4 write assembly to
+ contrib/loaders
+
+Simply move numicro M4 flash write assembly to contrib/loaders. Also,
+add corresponding Makefile and generated numicro_m4.inc.
+
+Signed-off-by: Jian-Hong Pan <chienhung.pan@gmail.com>
+Change-Id: I22b8be0a245857335b11bd0b538db415fc34748d
+Reviewed-on: https://review.openocd.org/c/openocd/+/7343
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ contrib/loaders/flash/numicro_m4/Makefile | 31 ++++++++
+ contrib/loaders/flash/numicro_m4/numicro_m4.S | 70 +++++++++++++++++++
+ .../loaders/flash/numicro_m4/numicro_m4.inc | 5 ++
+ src/flash/nor/numicro.c | 57 +--------------
+ 4 files changed, 107 insertions(+), 56 deletions(-)
+ create mode 100644 contrib/loaders/flash/numicro_m4/Makefile
+ create mode 100644 contrib/loaders/flash/numicro_m4/numicro_m4.S
+ create mode 100644 contrib/loaders/flash/numicro_m4/numicro_m4.inc
+
+diff --git a/contrib/loaders/flash/numicro_m4/Makefile b/contrib/loaders/flash/numicro_m4/Makefile
+new file mode 100644
+index 000000000..0f9c507cd
+--- /dev/null
++++ b/contrib/loaders/flash/numicro_m4/Makefile
+@@ -0,0 +1,31 @@
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++BIN2C = ../../../../src/helper/bin2char.sh
++
++CROSS_COMPILE ?= arm-none-eabi-
++
++CC=$(CROSS_COMPILE)gcc
++OBJCOPY=$(CROSS_COMPILE)objcopy
++OBJDUMP=$(CROSS_COMPILE)objdump
++
++
++AFLAGS = -static -nostartfiles -mlittle-endian -mcpu=cortex-m4 -Wa,-EL
++
++all: numicro_m4.inc
++
++.PHONY: clean
++
++%.elf: %.S
++ $(CC) $(AFLAGS) $< -o $@
++
++%.lst: %.elf
++ $(OBJDUMP) -S $< > $@
++
++%.bin: %.elf
++ $(OBJCOPY) -Obinary $< $@
++
++%.inc: %.bin
++ $(BIN2C) < $< > $@
++
++clean:
++ -rm -f *.elf *.lst *.bin *.inc
+diff --git a/contrib/loaders/flash/numicro_m4/numicro_m4.S b/contrib/loaders/flash/numicro_m4/numicro_m4.S
+new file mode 100644
+index 000000000..6c59cca57
+--- /dev/null
++++ b/contrib/loaders/flash/numicro_m4/numicro_m4.S
+@@ -0,0 +1,70 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++/***************************************************************************
++ * Copyright (C) 2017 Zale Yu *
++ * CYYU@nuvoton.com *
++ * *
++ * Copyright (C) 2022 Jian-Hong Pan *
++ * chienhung.pan@gmail.com *
++ ***************************************************************************/
++
++ .text
++ .cpu cortex-m4
++ .thumb
++
++ /* Params:
++ * r0 - workarea buffer / result
++ * r1 - target address
++ * r2 - wordcount
++ * Clobbered:
++ * r4 - tmp
++ * r5 - tmp
++ * r6 - tmp
++ * r7 - tmp
++ */
++
++.L1:
++ /* for(register uint32_t i=0;i<wcount;i++){ */
++ mov r4, r0
++ mov r3, #0
++.L2:
++ sub r5, r1, r0
++ add r7, r4, r5
++ cmp r3, r2
++ beq .L7
++.L4:
++ /* NUMICRO_FLASH_ISPADR = faddr; */
++ ldr r6, .L8
++ str r7, [r6]
++ /* NUMICRO_FLASH_ISPDAT = *pLW; */
++ ldmia r4!, {r7}
++ ldr r5, .L8+4
++ str r7, [r5]
++ /* faddr += 4; */
++ /* pLW++; */
++ /* Trigger write action */
++ /* NUMICRO_FLASH_ISPTRG = ISPTRG_ISPGO; */
++ ldr r5, .L8+8
++ mov r6, #1
++ str r6, [r5]
++.L3:
++ /* while((NUMICRO_FLASH_ISPTRG & ISPTRG_ISPGO) == ISPTRG_ISPGO){}; */
++ ldr r7, [r5]
++ lsl r7, r7, #31
++ bmi .L3
++
++ add r3, r3, #1
++ b .L2
++.L7:
++ /* return (NUMICRO_FLASH_ISPCON & ISPCON_ISPFF); */
++ ldr r3, .L8+12
++ ldr r0, [r3]
++ mov r1, #64
++ and r0, r1
++.L9:
++ bkpt #0
++.L8:
++ .word 0x4000C004
++ .word 0x4000C008
++ .word 0x4000C010
++ .word 0x4000C000
+diff --git a/contrib/loaders/flash/numicro_m4/numicro_m4.inc b/contrib/loaders/flash/numicro_m4/numicro_m4.inc
+new file mode 100644
+index 000000000..c3e605292
+--- /dev/null
++++ b/contrib/loaders/flash/numicro_m4/numicro_m4.inc
+@@ -0,0 +1,5 @@
++/* Autogenerated with ../../../../src/helper/bin2char.sh */
++0x04,0x1c,0x00,0x23,0x0d,0x1a,0x67,0x19,0x93,0x42,0x0c,0xd0,0x08,0x4e,0x37,0x60,
++0x80,0xcc,0x08,0x4d,0x2f,0x60,0x08,0x4d,0x01,0x26,0x2e,0x60,0x2f,0x68,0xff,0x07,
++0xfc,0xd4,0x01,0x33,0xee,0xe7,0x05,0x4b,0x18,0x68,0x40,0x21,0x08,0x40,0x00,0xbe,
++0x04,0xc0,0x00,0x40,0x08,0xc0,0x00,0x40,0x10,0xc0,0x00,0x40,0x00,0xc0,0x00,0x40,
+diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c
+index 2bba7b746..cbd2450b0 100644
+--- a/src/flash/nor/numicro.c
++++ b/src/flash/nor/numicro.c
+@@ -740,62 +740,7 @@ static const uint8_t numicro_flash_write_code[] = {
+ };
+
+ static const uint8_t numicro_m4_flash_write_code[] = {
+- /* Params:
+- * r0 - workarea buffer / result
+- * r1 - target address
+- * r2 - wordcount
+- * Clobbered:
+- * r4 - tmp
+- * r5 - tmp
+- * r6 - tmp
+- * r7 - tmp
+- */
+-
+- /* .L1: */
+- /* for(register uint32_t i=0;i<wcount;i++){ */
+- 0x04, 0x1C, /* mov r4, r0 */
+- 0x00, 0x23, /* mov r3, #0 */
+- /* .L2: */
+- 0x0D, 0x1A, /* sub r5, r1, r0 */
+- 0x67, 0x19, /* add r7, r4, r7 */
+- 0x93, 0x42, /* cmp r3, r2 */
+- 0x0C, 0xD0, /* beq .L7 */
+- /* .L4: */
+- /* NUMICRO_FLASH_ISPADR = faddr; */
+- 0x08, 0x4E, /* ldr r6, .L8 */
+- 0x37, 0x60, /* str r7, [r6] */
+- /* NUMICRO_FLASH_ISPDAT = *pLW; */
+- 0x80, 0xCC, /* ldmia r4!, {r7} */
+- 0x08, 0x4D, /* ldr r5, .L8+4 */
+- 0x2F, 0x60, /* str r7, [r5] */
+- /* faddr += 4; */
+- /* pLW++; */
+- /* Trigger write action */
+- /* NUMICRO_FLASH_ISPTRG = ISPTRG_ISPGO; */
+- 0x08, 0x4D, /* ldr r5, .L8+8 */
+- 0x01, 0x26, /* mov r6, #1 */
+- 0x2E, 0x60, /* str r6, [r5] */
+- /* .L3: */
+- /* while((NUMICRO_FLASH_ISPTRG & ISPTRG_ISPGO) == ISPTRG_ISPGO){}; */
+- 0x2F, 0x68, /* ldr r7, [r5] */
+- 0xFF, 0x07, /* lsl r7, r7, #31 */
+- 0xFC, 0xD4, /* bmi .L3 */
+-
+- 0x01, 0x33, /* add r3, r3, #1 */
+- 0xEE, 0xE7, /* b .L2 */
+- /* .L7: */
+- /* return (NUMICRO_FLASH_ISPCON & ISPCON_ISPFF); */
+- 0x05, 0x4B, /* ldr r3, .L8+12 */
+- 0x18, 0x68, /* ldr r0, [r3] */
+- 0x40, 0x21, /* mov r1, #64 */
+- 0x08, 0x40, /* and r0, r1 */
+- /* .L9: */
+- 0x00, 0xBE, /* bkpt #0 */
+- /* .L8: */
+- 0x04, 0xC0, 0x00, 0x40,/* .word 0x4000C004 */
+- 0x08, 0xC0, 0x00, 0x40,/* .word 0x4000C008 */
+- 0x10, 0xC0, 0x00, 0x40,/* .word 0x4000C010 */
+- 0x00, 0xC0, 0x00, 0x40 /* .word 0x4000C000 */
++#include "../../../contrib/loaders/flash/numicro_m4/numicro_m4.inc"
+ };
+
+ /* Program LongWord Block Write */
new file mode 100644
@@ -0,0 +1,222 @@
+From 9ffda10298eff870bde12dec580f98de6f497257 Mon Sep 17 00:00:00 2001
+From: Jian-Hong Pan <chienhung.pan@gmail.com>
+Date: Sun, 13 Nov 2022 12:43:14 +0800
+Subject: [PATCH] flash/nor, contrib/loaders: move numicro M0 write assembly to
+ contrib/loaders
+
+Simply move numicro M0 flash write assembly to contrib/loaders. Also,
+modify corresponding Makefile and generated numicro_m0.inc.
+
+To make the path more general, this patch rename the path
+"contrib/loaders/flash/numicro_m4" to "contrib/loaders/flash/numicro" as
+well.
+
+Signed-off-by: Jian-Hong Pan <chienhung.pan@gmail.com>
+Change-Id: I9adea24c2b3c97319a9b015cf50257f3d131dc26
+Reviewed-on: https://review.openocd.org/c/openocd/+/7346
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ .../flash/{numicro_m4 => numicro}/Makefile | 4 +-
+ contrib/loaders/flash/numicro/numicro_m0.S | 73 +++++++++++++++++++
+ contrib/loaders/flash/numicro/numicro_m0.inc | 5 ++
+ .../{numicro_m4 => numicro}/numicro_m4.S | 0
+ .../{numicro_m4 => numicro}/numicro_m4.inc | 0
+ src/flash/nor/numicro.c | 59 +--------------
+ 6 files changed, 82 insertions(+), 59 deletions(-)
+ rename contrib/loaders/flash/{numicro_m4 => numicro}/Makefile (82%)
+ create mode 100644 contrib/loaders/flash/numicro/numicro_m0.S
+ create mode 100644 contrib/loaders/flash/numicro/numicro_m0.inc
+ rename contrib/loaders/flash/{numicro_m4 => numicro}/numicro_m4.S (100%)
+ rename contrib/loaders/flash/{numicro_m4 => numicro}/numicro_m4.inc (100%)
+
+diff --git a/contrib/loaders/flash/numicro_m4/Makefile b/contrib/loaders/flash/numicro/Makefile
+similarity index 82%
+rename from contrib/loaders/flash/numicro_m4/Makefile
+rename to contrib/loaders/flash/numicro/Makefile
+index 0f9c507cd..e4f44417c 100644
+--- a/contrib/loaders/flash/numicro_m4/Makefile
++++ b/contrib/loaders/flash/numicro/Makefile
+@@ -9,9 +9,9 @@ OBJCOPY=$(CROSS_COMPILE)objcopy
+ OBJDUMP=$(CROSS_COMPILE)objdump
+
+
+-AFLAGS = -static -nostartfiles -mlittle-endian -mcpu=cortex-m4 -Wa,-EL
++AFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL
+
+-all: numicro_m4.inc
++all: numicro_m0.inc numicro_m4.inc
+
+ .PHONY: clean
+
+diff --git a/contrib/loaders/flash/numicro/numicro_m0.S b/contrib/loaders/flash/numicro/numicro_m0.S
+new file mode 100644
+index 000000000..37d435532
+--- /dev/null
++++ b/contrib/loaders/flash/numicro/numicro_m0.S
+@@ -0,0 +1,73 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++/***************************************************************************
++ * Copyright (C) 2015 Nemui Trinomius *
++ * nemuisan_kawausogasuki@live.jp *
++ * *
++ * Copyright (C) 2017 Zale Yu *
++ * CYYU@nuvoton.com *
++ * *
++ * Copyright (C) 2022 Jian-Hong Pan *
++ * chienhung.pan@gmail.com *
++ ***************************************************************************/
++
++ .text
++ .cpu cortex-m0
++ .thumb
++
++ /* Params:
++ * r0 - workarea buffer / result
++ * r1 - target address
++ * r2 - wordcount
++ * Clobbered:
++ * r4 - tmp
++ * r5 - tmp
++ * r6 - tmp
++ * r7 - tmp
++ */
++
++.L1:
++ /* for(register uint32_t i=0;i<wcount;i++){ */
++ mov r4, r0
++ mov r3, #0
++.L2:
++ sub r5, r1, r0
++ add r7, r4, r5
++ cmp r3, r2
++ beq .L7
++.L4:
++ /* NUMICRO_FLASH_ISPADR = faddr; */
++ ldr r6, .L8
++ str r7, [r6]
++ /* NUMICRO_FLASH_ISPDAT = *pLW; */
++ ldmia r4!, {r7}
++ ldr r5, .L8+4
++ str r7, [r5]
++ /* faddr += 4; */
++ /* pLW++; */
++ /* Trigger write action */
++ /* NUMICRO_FLASH_ISPTRG = ISPTRG_ISPGO; */
++ ldr r5, .L8+8
++ mov r6, #1
++ str r6, [r5]
++.L3:
++ /* while((NUMICRO_FLASH_ISPTRG & ISPTRG_ISPGO) == ISPTRG_ISPGO){}; */
++ ldr r7, [r5]
++ lsl r7, r7, #31
++ bmi .L3
++
++ add r3, r3, #1
++ b .L2
++.L7:
++ /* return (NUMICRO_FLASH_ISPCON & ISPCON_ISPFF); */
++ ldr r3, .L8+12
++ ldr r0, [r3]
++ mov r1, #64
++ and r0, r1
++.L9:
++ bkpt #0
++.L8:
++ .word 0x5000C004
++ .word 0x5000C008
++ .word 0x5000C010
++ .word 0x5000C000
+diff --git a/contrib/loaders/flash/numicro/numicro_m0.inc b/contrib/loaders/flash/numicro/numicro_m0.inc
+new file mode 100644
+index 000000000..db9c7742f
+--- /dev/null
++++ b/contrib/loaders/flash/numicro/numicro_m0.inc
+@@ -0,0 +1,5 @@
++/* Autogenerated with ../../../../src/helper/bin2char.sh */
++0x04,0x1c,0x00,0x23,0x0d,0x1a,0x67,0x19,0x93,0x42,0x0c,0xd0,0x08,0x4e,0x37,0x60,
++0x80,0xcc,0x08,0x4d,0x2f,0x60,0x08,0x4d,0x01,0x26,0x2e,0x60,0x2f,0x68,0xff,0x07,
++0xfc,0xd4,0x01,0x33,0xee,0xe7,0x05,0x4b,0x18,0x68,0x40,0x21,0x08,0x40,0x00,0xbe,
++0x04,0xc0,0x00,0x50,0x08,0xc0,0x00,0x50,0x10,0xc0,0x00,0x50,0x00,0xc0,0x00,0x50,
+diff --git a/contrib/loaders/flash/numicro_m4/numicro_m4.S b/contrib/loaders/flash/numicro/numicro_m4.S
+similarity index 100%
+rename from contrib/loaders/flash/numicro_m4/numicro_m4.S
+rename to contrib/loaders/flash/numicro/numicro_m4.S
+diff --git a/contrib/loaders/flash/numicro_m4/numicro_m4.inc b/contrib/loaders/flash/numicro/numicro_m4.inc
+similarity index 100%
+rename from contrib/loaders/flash/numicro_m4/numicro_m4.inc
+rename to contrib/loaders/flash/numicro/numicro_m4.inc
+diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c
+index cbd2450b0..0b04ce4b7 100644
+--- a/src/flash/nor/numicro.c
++++ b/src/flash/nor/numicro.c
+@@ -681,66 +681,11 @@ static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t ad
+
+ /* NuMicro Program-LongWord Microcodes */
+ static const uint8_t numicro_flash_write_code[] = {
+- /* Params:
+- * r0 - workarea buffer / result
+- * r1 - target address
+- * r2 - wordcount
+- * Clobbered:
+- * r4 - tmp
+- * r5 - tmp
+- * r6 - tmp
+- * r7 - tmp
+- */
+-
+- /* .L1: */
+- /* for(register uint32_t i=0;i<wcount;i++){ */
+- 0x04, 0x1C, /* mov r4, r0 */
+- 0x00, 0x23, /* mov r3, #0 */
+- /* .L2: */
+- 0x0D, 0x1A, /* sub r5, r1, r0 */
+- 0x67, 0x19, /* add r7, r4, r7 */
+- 0x93, 0x42, /* cmp r3, r2 */
+- 0x0C, 0xD0, /* beq .L7 */
+- /* .L4: */
+- /* NUMICRO_FLASH_ISPADR = faddr; */
+- 0x08, 0x4E, /* ldr r6, .L8 */
+- 0x37, 0x60, /* str r7, [r6] */
+- /* NUMICRO_FLASH_ISPDAT = *pLW; */
+- 0x80, 0xCC, /* ldmia r4!, {r7} */
+- 0x08, 0x4D, /* ldr r5, .L8+4 */
+- 0x2F, 0x60, /* str r7, [r5] */
+- /* faddr += 4; */
+- /* pLW++; */
+- /* Trigger write action */
+- /* NUMICRO_FLASH_ISPTRG = ISPTRG_ISPGO; */
+- 0x08, 0x4D, /* ldr r5, .L8+8 */
+- 0x01, 0x26, /* mov r6, #1 */
+- 0x2E, 0x60, /* str r6, [r5] */
+- /* .L3: */
+- /* while((NUMICRO_FLASH_ISPTRG & ISPTRG_ISPGO) == ISPTRG_ISPGO){}; */
+- 0x2F, 0x68, /* ldr r7, [r5] */
+- 0xFF, 0x07, /* lsl r7, r7, #31 */
+- 0xFC, 0xD4, /* bmi .L3 */
+-
+- 0x01, 0x33, /* add r3, r3, #1 */
+- 0xEE, 0xE7, /* b .L2 */
+- /* .L7: */
+- /* return (NUMICRO_FLASH_ISPCON & ISPCON_ISPFF); */
+- 0x05, 0x4B, /* ldr r3, .L8+12 */
+- 0x18, 0x68, /* ldr r0, [r3] */
+- 0x40, 0x21, /* mov r1, #64 */
+- 0x08, 0x40, /* and r0, r1 */
+- /* .L9: */
+- 0x00, 0xBE, /* bkpt #0 */
+- /* .L8: */
+- 0x04, 0xC0, 0x00, 0x50,/* .word 1342226436 */
+- 0x08, 0xC0, 0x00, 0x50,/* .word 1342226440 */
+- 0x10, 0xC0, 0x00, 0x50,/* .word 1342226448 */
+- 0x00, 0xC0, 0x00, 0x50 /* .word 1342226432 */
++#include "../../../contrib/loaders/flash/numicro/numicro_m0.inc"
+ };
+
+ static const uint8_t numicro_m4_flash_write_code[] = {
+-#include "../../../contrib/loaders/flash/numicro_m4/numicro_m4.inc"
++#include "../../../contrib/loaders/flash/numicro/numicro_m4.inc"
+ };
+
+ /* Program LongWord Block Write */
new file mode 100644
@@ -0,0 +1,103 @@
+From 2c191ef1da1f7f4dd38606c9936948a958aece20 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sat, 22 Oct 2022 18:12:16 +0200
+Subject: [PATCH] doc: usb_adapters: add container for lsusb dump of adapters
+
+When extending an existing adapter driver, developer has to
+carefully avoid to break backward compatibility.
+But not all developers have access to many adapters for testing.
+
+Prepare a folder aimed at containing 'lsusb -v' dumps of adapters
+to be used as reference.
+Add documentation and a simple dump script.
+
+Change-Id: Ia3a9132d65ec8869734721f9605cebcebcf33608
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7296
+Tested-by: jenkins
+---
+ doc/usb_adapters/dump.sh | 24 +++++++++++++++++++++
+ doc/usb_adapters/readme.txt | 43 +++++++++++++++++++++++++++++++++++++
+ 2 files changed, 67 insertions(+)
+ create mode 100755 doc/usb_adapters/dump.sh
+ create mode 100644 doc/usb_adapters/readme.txt
+
+diff --git a/doc/usb_adapters/dump.sh b/doc/usb_adapters/dump.sh
+new file mode 100755
+index 000000000..1ecfb40f0
+--- /dev/null
++++ b/doc/usb_adapters/dump.sh
+@@ -0,0 +1,24 @@
++#!/bin/sh
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++devs=$(lsusb -d $1:$2 | wc -l)
++case "$devs" in
++ 0 )
++ echo "Error: USB device $1:$2 not found" > /dev/stderr
++ exit 1
++ ;;
++ 1 )
++ echo "Dumping $(lsusb -d $1:$2)" > /dev/stderr
++ ;;
++ * )
++ echo "Error: Multiple matches for 'lsusb -d $1:$2'" > /dev/stderr
++ exit 1
++ ;;
++esac
++
++# break SPDX tag to hide it to checkpatch
++echo '# SPDX-''License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later'
++echo ''
++echo '# Optional comment'
++
++lsusb -v -d $1:$2 | sed 's/ *$//'
+diff --git a/doc/usb_adapters/readme.txt b/doc/usb_adapters/readme.txt
+new file mode 100644
+index 000000000..1d995e99f
+--- /dev/null
++++ b/doc/usb_adapters/readme.txt
+@@ -0,0 +1,43 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++This folder contains a collection of dumps of USB descriptors, obtained through
++Linux lsusb command, of several USB adapters supported by OpenOCD.
++This collection should help maintaining adapter drivers even if the developer
++doesn't have access to all the devices supported by the driver.
++
++To add a new file, run:
++
++ ./doc/usb_adapters/dump.sh ${vid} ${pid} \
++ > doc/usb_adapters/${driver}/${vid}_${pid}_${short_description}.txt
++
++eventually edit the file to add some extra comment, then submit the file to
++OpenOCD gerrit, as explained in HACKING.
++
++The dumps are organized in subfolders corresponding to OpenOCD drivers:
++- cmsis_dap;
++- ft232r;
++- ftdi;
++- icdi;
++- jlink;
++- kitprog;
++- nulink;
++- stlink;
++- xds110.
++
++The script above assumes the user has granted access permissions to the USB
++device file in
++ /dev/bus/usb/<n>/<m>
++This is usually the case when the device is listed in
++ contrib/60-openocd.rules
++and this udev rules file is properly installed in the host machine.
++If the user has no proper access permissions, the script has to be run as
++root or through 'sudo'.
++
++Old versions of 'lsusb -v' dump cryptic errors like:
++ can't get device qualifier: Resource temporarily unavailable
++ can't get debug descriptor: Resource temporarily unavailable
++when some optional descriptor is not present.
++This is fixed in usbutils v014.
++If you get such messages simply ignore them. They are printed on stderr, so
++will not be included in the generated file as the redirection '>' does only
++redirects stdout.
new file mode 100644
@@ -0,0 +1,2773 @@
+From e0059dfffae4f8a55c39e25d0e8b2285559db65c Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sat, 22 Oct 2022 18:16:59 +0200
+Subject: [PATCH] doc: usb_adapters: add lsusb dump of few adapters
+
+Real dumps from adapters I have access to.
+Serial numbers have been manually edited but are still consistent.
+
+Change-Id: Iee2d16e09615746e29588f91fdfb77eb9fad4daa
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7297
+Tested-by: jenkins
+---
+ .../cmsis_dap/0d28_0204_nxp_daplink.txt | 175 +++++++++++
+ .../cmsis_dap/c251_2722_keil_ulink2.txt | 72 +++++
+ doc/usb_adapters/ft232r/0403_6001_ft232r.txt | 64 ++++
+ doc/usb_adapters/ftdi/0403_6010_ft2232h.txt | 103 +++++++
+ .../ftdi/0403_cff8_amontec_jtagkey2.txt | 104 +++++++
+ .../ftdi/09fb_6001_altera_blaster.txt | 64 ++++
+ doc/usb_adapters/icdi/1cbe_00fd_ti_icdi.txt | 156 ++++++++++
+ .../1366_0101_segger_jlink_plus_10_1.txt | 71 +++++
+ .../nulink/0416_511d_nuvoton_nulink.txt | 142 +++++++++
+ .../nulink/0416_5200_nuvoton_nulink.txt | 211 +++++++++++++
+ .../stlink/0483_3744_stlinkv1.txt | 62 ++++
+ .../stlink/0483_3748_stlinkv2.txt | 72 +++++
+ .../stlink/0483_374b_stlinkv2.txt | 173 +++++++++++
+ .../stlink/0483_374d_stlinkv3.txt | 71 +++++
+ .../stlink/0483_374e_stlinkv3.txt | 182 ++++++++++++
+ .../stlink/0483_374f_stlinkv3.txt | 212 ++++++++++++++
+ .../stlink/0483_3752_stlinkv2.txt | 143 +++++++++
+ .../stlink/0483_3753_stlinkv3.txt | 253 ++++++++++++++++
+ .../xds110/0451_0451_ti_xds110.txt | 276 ++++++++++++++++++
+ 19 files changed, 2606 insertions(+)
+ create mode 100644 doc/usb_adapters/cmsis_dap/0d28_0204_nxp_daplink.txt
+ create mode 100644 doc/usb_adapters/cmsis_dap/c251_2722_keil_ulink2.txt
+ create mode 100644 doc/usb_adapters/ft232r/0403_6001_ft232r.txt
+ create mode 100644 doc/usb_adapters/ftdi/0403_6010_ft2232h.txt
+ create mode 100644 doc/usb_adapters/ftdi/0403_cff8_amontec_jtagkey2.txt
+ create mode 100644 doc/usb_adapters/ftdi/09fb_6001_altera_blaster.txt
+ create mode 100644 doc/usb_adapters/icdi/1cbe_00fd_ti_icdi.txt
+ create mode 100644 doc/usb_adapters/jlink/1366_0101_segger_jlink_plus_10_1.txt
+ create mode 100644 doc/usb_adapters/nulink/0416_511d_nuvoton_nulink.txt
+ create mode 100644 doc/usb_adapters/nulink/0416_5200_nuvoton_nulink.txt
+ create mode 100644 doc/usb_adapters/stlink/0483_3744_stlinkv1.txt
+ create mode 100644 doc/usb_adapters/stlink/0483_3748_stlinkv2.txt
+ create mode 100644 doc/usb_adapters/stlink/0483_374b_stlinkv2.txt
+ create mode 100644 doc/usb_adapters/stlink/0483_374d_stlinkv3.txt
+ create mode 100644 doc/usb_adapters/stlink/0483_374e_stlinkv3.txt
+ create mode 100644 doc/usb_adapters/stlink/0483_374f_stlinkv3.txt
+ create mode 100644 doc/usb_adapters/stlink/0483_3752_stlinkv2.txt
+ create mode 100644 doc/usb_adapters/stlink/0483_3753_stlinkv3.txt
+ create mode 100644 doc/usb_adapters/xds110/0451_0451_ti_xds110.txt
+
+diff --git a/doc/usb_adapters/cmsis_dap/0d28_0204_nxp_daplink.txt b/doc/usb_adapters/cmsis_dap/0d28_0204_nxp_daplink.txt
+new file mode 100644
+index 000000000..2ec0d58e2
+--- /dev/null
++++ b/doc/usb_adapters/cmsis_dap/0d28_0204_nxp_daplink.txt
+@@ -0,0 +1,175 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: NXP FRDM-K64F
++
++Bus 001 Device 006: ID 0d28:0204 NXP ARM mbed
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x0d28 NXP
++ idProduct 0x0204 ARM mbed
++ bcdDevice 10.00
++ iManufacturer 1 ARM
++ iProduct 2 DAPLink CMSIS-DAP
++ iSerial 3 0240000031754e45002f00199485002b6461000097969900
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0082
++ bNumInterfaces 4
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 500mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 8 Mass Storage
++ bInterfaceSubClass 6 SCSI
++ bInterfaceProtocol 80 Bulk-Only
++ iInterface 7 USB_MSC
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 6 CMSIS-DAP
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.00
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 33
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 1
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 4 mbed Serial Port
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 4 mbed Serial Port
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x03
++ call management
++ use DataInterface
++ bDataInterface 2
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 1
++ bSlaveInterface 2
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0010 1x 16 bytes
++ bInterval 32
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 5 mbed Serial Port
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x04 EP 4 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/cmsis_dap/c251_2722_keil_ulink2.txt b/doc/usb_adapters/cmsis_dap/c251_2722_keil_ulink2.txt
+new file mode 100644
+index 000000000..520f7c553
+--- /dev/null
++++ b/doc/usb_adapters/cmsis_dap/c251_2722_keil_ulink2.txt
+@@ -0,0 +1,72 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Standalone adapter
++
++Bus 001 Device 010: ID c251:2722 Keil Software, Inc. Keil ULINK2 CMSIS-DAP
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0xc251 Keil Software, Inc.
++ idProduct 0x2722
++ bcdDevice 1.00
++ iManufacturer 1 Keil Software
++ iProduct 2 Keil ULINK2 CMSIS-DAP
++ iSerial 3 V0022U9E
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0029
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 4 CMSIS-DAP
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.00
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 33
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/ft232r/0403_6001_ft232r.txt b/doc/usb_adapters/ft232r/0403_6001_ft232r.txt
+new file mode 100644
+index 000000000..8bfb058fd
+--- /dev/null
++++ b/doc/usb_adapters/ft232r/0403_6001_ft232r.txt
+@@ -0,0 +1,64 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: FT232RL
++# Chip: FT232RL
++
++Bus 001 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 8
++ idVendor 0x0403 Future Technology Devices International, Ltd
++ idProduct 0x6001 FT232 Serial (UART) IC
++ bcdDevice 6.00
++ iManufacturer 1 FTDI
++ iProduct 2 FT232R USB UART
++ iSerial 3 A50285BI
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0020
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0xa0
++ (Bus Powered)
++ Remote Wakeup
++ MaxPower 90mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 2 FT232R USB UART
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/ftdi/0403_6010_ft2232h.txt b/doc/usb_adapters/ftdi/0403_6010_ft2232h.txt
+new file mode 100644
+index 000000000..8bb33e6e5
+--- /dev/null
++++ b/doc/usb_adapters/ftdi/0403_6010_ft2232h.txt
+@@ -0,0 +1,103 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: Steppenprobe
++# Link: https://github.com/diegoherranz/steppenprobe
++# Chip: FT2232HL
++
++Bus 001 Device 012: ID 0403:6010 Future Technology Devices International, Ltd FT2232C/D/H Dual UART/FIFO IC
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0x0403 Future Technology Devices International, Ltd
++ idProduct 0x6010 FT2232C/D/H Dual UART/FIFO IC
++ bcdDevice 7.00
++ iManufacturer 1 FTDI
++ iProduct 2 Dual RS232-HS
++ iSerial 0
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0037
++ bNumInterfaces 2
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 500mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 2 Dual RS232-HS
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 2 Dual RS232-HS
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x04 EP 4 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/ftdi/0403_cff8_amontec_jtagkey2.txt b/doc/usb_adapters/ftdi/0403_cff8_amontec_jtagkey2.txt
+new file mode 100644
+index 000000000..f056502ad
+--- /dev/null
++++ b/doc/usb_adapters/ftdi/0403_cff8_amontec_jtagkey2.txt
+@@ -0,0 +1,104 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Link: http://www.amontec.com
++# Casing: Hi-Speed JTAGkey-2 (c) 2009, Amontec
++# PCB: Amontec JTAGkey2 v5.3
++# Chip: FT2232HQ
++
++Bus 001 Device 017: ID 0403:cff8 Future Technology Devices International, Ltd Amontec JTAGkey
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0x0403 Future Technology Devices International, Ltd
++ idProduct 0xcff8 Amontec JTAGkey
++ bcdDevice 7.00
++ iManufacturer 1 Amontec
++ iProduct 2 Amontec JTAGkey-2
++ iSerial 3 53U2ML49
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0037
++ bNumInterfaces 2
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 2 Amontec JTAGkey-2
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 2 Amontec JTAGkey-2
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x04 EP 4 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/ftdi/09fb_6001_altera_blaster.txt b/doc/usb_adapters/ftdi/09fb_6001_altera_blaster.txt
+new file mode 100644
+index 000000000..25f43a416
+--- /dev/null
++++ b/doc/usb_adapters/ftdi/09fb_6001_altera_blaster.txt
+@@ -0,0 +1,64 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Clone www.terasic.com "USB Blaster"
++# PCB reports: "USB Blaster-B", "FOR ALTERA ONLY"
++# Chip: FT245BL
++
++Bus 001 Device 005: ID 09fb:6001 Altera Blaster
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 1.10
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 8
++ idVendor 0x09fb Altera
++ idProduct 0x6001 Blaster
++ bcdDevice 4.00
++ iManufacturer 1 Altera
++ iProduct 2 USB-Blaster
++ iSerial 3 91f28492
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0020
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 150mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 2 USB-Blaster
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/icdi/1cbe_00fd_ti_icdi.txt b/doc/usb_adapters/icdi/1cbe_00fd_ti_icdi.txt
+new file mode 100644
+index 000000000..14fc86fd6
+--- /dev/null
++++ b/doc/usb_adapters/icdi/1cbe_00fd_ti_icdi.txt
+@@ -0,0 +1,156 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: TI Tiva C Series TM4C1294 Connected LaunchPad
++# ICDI firmware update to add OpenOCD support
++
++Bus 001 Device 016: ID 1cbe:00fd Luminary Micro Inc. In-Circuit Debug Interface
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 1.10
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x1cbe Luminary Micro Inc.
++ idProduct 0x00fd In-Circuit Debug Interface
++ bcdDevice 1.00
++ iManufacturer 1 Texas Instruments
++ iProduct 2 In-Circuit Debug Interface
++ iSerial 3 0F00CAC2
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0074
++ bNumInterfaces 4
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 250mA
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 0
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 0
++ CDC Header:
++ bcdCDC 1.10
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 0
++ bSlaveInterface 1
++ CDC Call Management:
++ bmCapabilities 0x01
++ call management
++ bDataInterface 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0010 1x 16 bytes
++ bInterval 1
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 0
++ bInterfaceClass 254 Application Specific Interface
++ bInterfaceSubClass 1 Device Firmware Update
++ bInterfaceProtocol 1
++ iInterface 0
++ Device Firmware Upgrade Interface Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bmAttributes 15
++ Will Detach
++ Manifestation Tolerant
++ Upload Supported
++ Download Supported
++ wDetachTimeout 65535 milliseconds
++ wTransferSize 1024 bytes
++ bcdDFUVersion 1.10
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/jlink/1366_0101_segger_jlink_plus_10_1.txt b/doc/usb_adapters/jlink/1366_0101_segger_jlink_plus_10_1.txt
+new file mode 100644
+index 000000000..fd31e9c78
+--- /dev/null
++++ b/doc/usb_adapters/jlink/1366_0101_segger_jlink_plus_10_1.txt
+@@ -0,0 +1,71 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Standalone adapter, original Segger, HW version 10.1
++
++Bus 001 Device 005: ID 1366:0101 SEGGER J-Link PLUS
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0x1366 SEGGER
++ idProduct 0x0101 J-Link PLUS
++ bcdDevice 1.00
++ iManufacturer 1 SEGGER
++ iProduct 2 J-Link
++ iSerial 3 123456
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0020
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 4 Configuration
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 5 BULK interface
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 1
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/nulink/0416_511d_nuvoton_nulink.txt b/doc/usb_adapters/nulink/0416_511d_nuvoton_nulink.txt
+new file mode 100644
+index 000000000..fb4392351
+--- /dev/null
++++ b/doc/usb_adapters/nulink/0416_511d_nuvoton_nulink.txt
+@@ -0,0 +1,142 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: nuvoTon NuMaker-PFM-M2351
++# Adapter: ICE V3.0
++
++Bus 001 Device 013: ID 0416:511d Winbond Electronics Corp. Nuvoton Nu-Link1 ICE/VCOM
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 1.10
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x0416 Winbond Electronics Corp.
++ idProduct 0x511d Nuvoton Nu-Link1 ICE/VCOM
++ bcdDevice 1.00
++ iManufacturer 1 Nuvoton
++ iProduct 2 Nu-Link
++ iSerial 0
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x006b
++ bNumInterfaces 3
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.10
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 28
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 1
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 2 Nu-Link
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 0
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 1
++ CDC ACM:
++ bmCapabilities 0x00
++ CDC Union:
++ bMasterInterface 1
++ bSlaveInterface 2
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0008 1x 8 bytes
++ bInterval 255
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x04 EP 4 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/nulink/0416_5200_nuvoton_nulink.txt b/doc/usb_adapters/nulink/0416_5200_nuvoton_nulink.txt
+new file mode 100644
+index 000000000..1d8661f18
+--- /dev/null
++++ b/doc/usb_adapters/nulink/0416_5200_nuvoton_nulink.txt
+@@ -0,0 +1,211 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: nuvoTon NuMaker-M483KG V1.1
++# Adapter: Nu-Link2-Me V1.0
++
++Bus 001 Device 014: ID 0416:5200 Winbond Electronics Corp. Nuvoton Nu-Link2-ME ICE/MSC/VCOM
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x0416 Winbond Electronics Corp.
++ idProduct 0x5200 Nuvoton Nu-Link2-ME ICE/MSC/VCOM
++ bcdDevice 0.00
++ iManufacturer 1 Nuvoton
++ iProduct 2 Nu-Link2 Bulk
++ iSerial 6 13010000AAAAAAAAAAAAAAAAAAAAAAAA
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0099
++ bNumInterfaces 5
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 1
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 3 Nu-Link2 VCOM
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 1
++ CDC ACM:
++ bmCapabilities 0x00
++ CDC Union:
++ bMasterInterface 1
++ bSlaveInterface 2
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0100 1x 256 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x04 EP 4 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0100 1x 256 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 4 Nu-Link2 HID
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.10
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 35
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x86 EP 6 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0400 1x 1024 bytes
++ bInterval 4
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x07 EP 7 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0400 1x 1024 bytes
++ bInterval 4
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 4
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 8 Mass Storage
++ bInterfaceSubClass 6 SCSI
++ bInterfaceProtocol 80 Bulk-Only
++ iInterface 5 Nu-Link2 MSC
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x88 EP 8 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x09 EP 9 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/stlink/0483_3744_stlinkv1.txt b/doc/usb_adapters/stlink/0483_3744_stlinkv1.txt
+new file mode 100644
+index 000000000..b887f7971
+--- /dev/null
++++ b/doc/usb_adapters/stlink/0483_3744_stlinkv1.txt
+@@ -0,0 +1,62 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Standalone adapter
++
++Bus 001 Device 009: ID 0483:3744 STMicroelectronics ST-LINK/V1
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0x0483 STMicroelectronics
++ idProduct 0x3744 ST-LINK/V1
++ bcdDevice 1.00
++ iManufacturer 1 STMicroelectronics
++ iProduct 2 STM32 STLink
++ iSerial 3 0000001
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0020
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 8 Mass Storage
++ bInterfaceSubClass 6 SCSI
++ bInterfaceProtocol 80 Bulk-Only
++ iInterface 4 ST Link
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/stlink/0483_3748_stlinkv2.txt b/doc/usb_adapters/stlink/0483_3748_stlinkv2.txt
+new file mode 100644
+index 000000000..ac6dfc7f6
+--- /dev/null
++++ b/doc/usb_adapters/stlink/0483_3748_stlinkv2.txt
+@@ -0,0 +1,72 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# ST-Link/V2 standalone or ST-Link/V2 in firmware update mode
++
++Bus 001 Device 006: ID 0483:3748 STMicroelectronics ST-LINK/V2
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0x0483 STMicroelectronics
++ idProduct 0x3748 ST-LINK/V2
++ bcdDevice 1.00
++ iManufacturer 1 STMicroelectronics
++ iProduct 2 STM32 STLink
++ iSerial 3 0668FF323637414257071827
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0027
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 3
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 4 ST Link
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/stlink/0483_374b_stlinkv2.txt b/doc/usb_adapters/stlink/0483_374b_stlinkv2.txt
+new file mode 100644
+index 000000000..cc0156d74
+--- /dev/null
++++ b/doc/usb_adapters/stlink/0483_374b_stlinkv2.txt
+@@ -0,0 +1,173 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: ST Nucleo F411
++
++Bus 001 Device 007: ID 0483:374b STMicroelectronics ST-LINK/V2.1
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x0483 STMicroelectronics
++ idProduct 0x374b ST-LINK/V2.1
++ bcdDevice 1.00
++ iManufacturer 1 STMicroelectronics
++ iProduct 2 STM32 STLink
++ iSerial 3 066EFF373535503457062922
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0080
++ bNumInterfaces 4
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 3
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 4 ST-Link Debug
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0020 1x 32 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 8 Mass Storage
++ bInterfaceSubClass 6 SCSI
++ bInterfaceProtocol 80 Bulk-Only
++ iInterface 5 ST-Link mass storage
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x03 EP 3 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 2
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 6 ST-Link VCP Ctrl
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 6 ST-Link VCP Ctrl
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 3
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 2
++ bSlaveInterface 3
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0002 1x 2 bytes
++ bInterval 255
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 7 ST-Link VCP Data
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x05 EP 5 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0008 1x 8 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0010 1x 16 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/stlink/0483_374d_stlinkv3.txt b/doc/usb_adapters/stlink/0483_374d_stlinkv3.txt
+new file mode 100644
+index 000000000..e964872c3
+--- /dev/null
++++ b/doc/usb_adapters/stlink/0483_374d_stlinkv3.txt
+@@ -0,0 +1,71 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# ST-Link/V3 in firmware update mode
++
++Bus 001 Device 009: ID 0483:374d STMicroelectronics STLINK-V3 Loader
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0x0483 STMicroelectronics
++ idProduct 0x374d STLINK-V3 Loader
++ bcdDevice 2.00
++ iManufacturer 1 STMicroelectronics
++ iProduct 2 STM32 ST-LINK/V3
++ iSerial 3 003500463137510239383538
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0020
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 4 DFU Config
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 5 ST-LINK/V3
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 1
++Device Status: 0x0001
++ Self Powered
+diff --git a/doc/usb_adapters/stlink/0483_374e_stlinkv3.txt b/doc/usb_adapters/stlink/0483_374e_stlinkv3.txt
+new file mode 100644
+index 000000000..55c968cce
+--- /dev/null
++++ b/doc/usb_adapters/stlink/0483_374e_stlinkv3.txt
+@@ -0,0 +1,182 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: ST Nucleo-H745AI-Q
++
++Bus 001 Device 008: ID 0483:374e STMicroelectronics STLINK-V3
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x0483 STMicroelectronics
++ idProduct 0x374e STLINK-V3
++ bcdDevice 1.00
++ iManufacturer 1 STMicroelectronics
++ iProduct 2 STLINK-V3
++ iSerial 3 005100313137511039383538
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0080
++ bNumInterfaces 4
++ bConfigurationValue 1
++ iConfiguration 4 Default Config
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 500mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 3
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 5 ST-Link Debug
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 8 Mass Storage
++ bInterfaceSubClass 6 SCSI
++ bInterfaceProtocol 80 Bulk-Only
++ iInterface 6 ST-Link mass storage
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x03 EP 3 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 2
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 7 ST-Link VCP Ctrl
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 7 ST-Link VCP Ctrl
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 3
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 2
++ bSlaveInterface 3
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x000a 1x 10 bytes
++ bInterval 16
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 8 ST-Link VCP Data
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x05 EP 5 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/stlink/0483_374f_stlinkv3.txt b/doc/usb_adapters/stlink/0483_374f_stlinkv3.txt
+new file mode 100644
+index 000000000..1974001c7
+--- /dev/null
++++ b/doc/usb_adapters/stlink/0483_374f_stlinkv3.txt
+@@ -0,0 +1,212 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Standalone adapter
++
++Bus 001 Device 008: ID 0483:374f STMicroelectronics STLINK-V3
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x0483 STMicroelectronics
++ idProduct 0x374f STLINK-V3
++ bcdDevice 1.00
++ iManufacturer 1 STMicroelectronics
++ iProduct 2 STLINK-V3
++ iSerial 3 003500463137510239383538
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0097
++ bNumInterfaces 5
++ bConfigurationValue 1
++ iConfiguration 4 Default Config
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 500mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 3
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 5 ST-Link Debug
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 8 Mass Storage
++ bInterfaceSubClass 6 SCSI
++ bInterfaceProtocol 80 Bulk-Only
++ iInterface 6 ST-Link mass storage
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x03 EP 3 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 2
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 7 ST-Link VCP Ctrl
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 7 ST-Link VCP Ctrl
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 3
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 2
++ bSlaveInterface 3
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x000a 1x 10 bytes
++ bInterval 16
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 8 ST-Link VCP Data
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x05 EP 5 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 4
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 9 ST-Link Bridge
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x86 EP 6 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x06 EP 6 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/stlink/0483_3752_stlinkv2.txt b/doc/usb_adapters/stlink/0483_3752_stlinkv2.txt
+new file mode 100644
+index 000000000..798b5276e
+--- /dev/null
++++ b/doc/usb_adapters/stlink/0483_3752_stlinkv2.txt
+@@ -0,0 +1,143 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: ST STM32MP157f-DK2
++
++Bus 001 Device 005: ID 0483:3752 STMicroelectronics ST-LINK/V2.1
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x0483 STMicroelectronics
++ idProduct 0x3752 ST-LINK/V2.1
++ bcdDevice 1.00
++ iManufacturer 1 STMicroelectronics
++ iProduct 2 STM32 STLink
++ iSerial 3 0668FF323637414257071827
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0069
++ bNumInterfaces 3
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 300mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 3
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 4 ST-Link Debug
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0020 1x 32 bytes
++ bInterval 0
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 1
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 6 ST-Link VCP Ctrl
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 6 ST-Link VCP Ctrl
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 2
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 1
++ bSlaveInterface 2
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0008 1x 8 bytes
++ bInterval 16
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 7 ST-Link VCP Data
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x05 EP 5 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/stlink/0483_3753_stlinkv3.txt b/doc/usb_adapters/stlink/0483_3753_stlinkv3.txt
+new file mode 100644
+index 000000000..e3a951f99
+--- /dev/null
++++ b/doc/usb_adapters/stlink/0483_3753_stlinkv3.txt
+@@ -0,0 +1,253 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board STM32MP135F-DK
++
++Bus 001 Device 011: ID 0483:3753 STMicroelectronics STLINK-V3
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x0483 STMicroelectronics
++ idProduct 0x3753 STLINK-V3
++ bcdDevice 1.00
++ iManufacturer 1 STMicroelectronics
++ iProduct 2 STLINK-V3
++ iSerial 3 001000294741500120383733
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x00c2
++ bNumInterfaces 6
++ bConfigurationValue 1
++ iConfiguration 4 Default Config
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 300mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 3
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 5 ST-Link Debug
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 1
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 7 ST-Link VCP Ctrl
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 7 ST-Link VCP Ctrl
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 2
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 1
++ bSlaveInterface 2
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x000a 1x 10 bytes
++ bInterval 16
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 8 ST-Link VCP Data
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x05 EP 5 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 9 ST-Link Bridge
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x86 EP 6 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x06 EP 6 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 4
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 10 ST-Link VCP2 Ctrl
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 4
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 10 ST-Link VCP2 Ctrl
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 5
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 4
++ bSlaveInterface 5
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x000a 1x 10 bytes
++ bInterval 16
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 5
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 11 ST-Link VCP2 Data
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x07 EP 7 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x87 EP 7 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/xds110/0451_0451_ti_xds110.txt b/doc/usb_adapters/xds110/0451_0451_ti_xds110.txt
+new file mode 100644
+index 000000000..9ad9b7dbf
+--- /dev/null
++++ b/doc/usb_adapters/xds110/0451_0451_ti_xds110.txt
+@@ -0,0 +1,276 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Board: TI CC2650 LaunchPad
++
++Bus 001 Device 005: ID 0451:bef3 Texas Instruments, Inc. CC1352R1 Launchpad
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 1.10
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x0451 Texas Instruments, Inc.
++ idProduct 0xbef3 CC1352R1 Launchpad
++ bcdDevice 1.00
++ iManufacturer 1 Texas Instruments
++ iProduct 2 XDS110 (03.00.00.13) Embed with CMSIS-DAP
++ iSerial 3 L1002566
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x00db
++ bNumInterfaces 7
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 500mA
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 0
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 0
++ CDC Header:
++ bcdCDC 1.10
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 0
++ bSlaveInterface 1
++ CDC Call Management:
++ bmCapabilities 0x01
++ call management
++ bDataInterface 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0010 1x 16 bytes
++ bInterval 1
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 3
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 0
++ CDC Header:
++ bcdCDC 1.10
++ CDC ACM:
++ bmCapabilities 0x06
++ sends break
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 3
++ bSlaveInterface 4
++ CDC Call Management:
++ bmCapabilities 0x01
++ call management
++ bDataInterface 4
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0010 1x 16 bytes
++ bInterval 1
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 4
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x03 EP 3 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 5
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 6 XDS110 CMSIS-DAP
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.11
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 24
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x86 EP 6 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x04 EP 4 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 6
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x05 EP 5 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x87 EP 7 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
new file mode 100644
@@ -0,0 +1,1326 @@
+From 6d76a915214f06a4960710ae171434265409a705 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sat, 22 Oct 2022 17:58:28 +0200
+Subject: [PATCH] doc: usb_adapters: add other adapters
+
+Mainly get from web or from OpenOCD users
+
+Change-Id: Id4d6354bc9b6972622adfacf3549c7c3e0549bc2
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7298
+Tested-by: jenkins
+---
+ .../cmsis_dap/04b4_f155_cypress_kitprog3.txt | 173 ++++++++++++++++++
+ .../cmsis_dap/1a6a_2000_spansion_sk_fm4.txt | 143 +++++++++++++++
+ .../cmsis_dap/2a86_8011_wch_link.txt | 143 +++++++++++++++
+ .../cmsis_dap/c251_2723_keil_ulink_me.txt | 72 ++++++++
+ .../cmsis_dap/c251_2750_keil_ulinkplus.txt | 161 ++++++++++++++++
+ .../cmsis_dap/c251_f001_jixin.pro.txt | 143 +++++++++++++++
+ .../ftdi/0403_6014_digilent_hs2.txt | 71 +++++++
+ .../ftdi/9e88_9e8f_sheevaplug_jtagkey.txt | 92 ++++++++++
+ .../jlink/1366_0101_segger_jlink.txt | 62 +++++++
+ .../kitprog/04b4_f139_cypress_kitprog.txt | 172 +++++++++++++++++
+ 10 files changed, 1232 insertions(+)
+ create mode 100644 doc/usb_adapters/cmsis_dap/04b4_f155_cypress_kitprog3.txt
+ create mode 100644 doc/usb_adapters/cmsis_dap/1a6a_2000_spansion_sk_fm4.txt
+ create mode 100644 doc/usb_adapters/cmsis_dap/2a86_8011_wch_link.txt
+ create mode 100644 doc/usb_adapters/cmsis_dap/c251_2723_keil_ulink_me.txt
+ create mode 100644 doc/usb_adapters/cmsis_dap/c251_2750_keil_ulinkplus.txt
+ create mode 100644 doc/usb_adapters/cmsis_dap/c251_f001_jixin.pro.txt
+ create mode 100644 doc/usb_adapters/ftdi/0403_6014_digilent_hs2.txt
+ create mode 100644 doc/usb_adapters/ftdi/9e88_9e8f_sheevaplug_jtagkey.txt
+ create mode 100644 doc/usb_adapters/jlink/1366_0101_segger_jlink.txt
+ create mode 100644 doc/usb_adapters/kitprog/04b4_f139_cypress_kitprog.txt
+
+diff --git a/doc/usb_adapters/cmsis_dap/04b4_f155_cypress_kitprog3.txt b/doc/usb_adapters/cmsis_dap/04b4_f155_cypress_kitprog3.txt
+new file mode 100644
+index 000000000..3109c6912
+--- /dev/null
++++ b/doc/usb_adapters/cmsis_dap/04b4_f155_cypress_kitprog3.txt
+@@ -0,0 +1,173 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# KitProg3 Firmware 1.01
++# Has inconsistent class code 0 for CMSIS-DAP interface
++
++Bus 002 Device 017: ID 04b4:f155 Cypress Semiconductor Corp.
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2 ?
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 8
++ idVendor 0x04b4 Cypress Semiconductor Corp.
++ idProduct 0xf155
++ bcdDevice 1.01
++ iManufacturer 1 Cypress Semiconductor
++ iProduct 6 KitProg3 CMSIS-DAP
++ iSerial 128 102015B003137400
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 130
++ bNumInterfaces 4
++ bConfigurationValue 1
++ iConfiguration 11 KitProg3 CMSIS-DAP
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 400mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 0 (Defined at Interface level)
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 6 KitProg3 CMSIS-DAP
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0 No Subclass
++ bInterfaceProtocol 0 None
++ iInterface 12 KitProg3 bridge
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.11
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 43
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x86 EP 6 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x07 EP 7 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 2
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 0 None
++ iFunction 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 15 KitProg3 USBUART
++ CDC Header:
++ bcdCDC 1.10
++ CDC ACM:
++ bmCapabilities 0x02
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 2
++ bSlaveInterface 3
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 3
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0008 1x 8 bytes
++ bInterval 2
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0 Unused
++ bInterfaceProtocol 0
++ iInterface 4 KitProg3 USBUART
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x05 EP 5 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/cmsis_dap/1a6a_2000_spansion_sk_fm4.txt b/doc/usb_adapters/cmsis_dap/1a6a_2000_spansion_sk_fm4.txt
+new file mode 100644
+index 000000000..368ec2a2b
+--- /dev/null
++++ b/doc/usb_adapters/cmsis_dap/1a6a_2000_spansion_sk_fm4.txt
+@@ -0,0 +1,143 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Reported in https://en.opensuse.org/User:A_faerber/SK-FM4-176L-S6E2CC
++
++Bus 002 Device 009: ID 1a6a:2000 Spansion Inc.
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 1.01
++ bDeviceClass 0 (Defined at Interface level)
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0x1a6a Spansion Inc.
++ idProduct 0x2000
++ bcdDevice 1.60
++ iManufacturer 1 Spansion
++ iProduct 2 Spansion CMSIS-DAP + COM Port
++ iSerial 0
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 107
++ bNumInterfaces 3
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x00
++ (Missing must-be-set bit!)
++ (Bus Powered)
++ MaxPower 62mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0 No Subclass
++ bInterfaceProtocol 0 None
++ iInterface 4 Spansion CMSIS-DAP
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.11
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 29
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 1
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 5 Spansion USB Serial Port
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 1 AT-commands (v.25ter)
++ iInterface 0
++ CDC Header:
++ bcdCDC 10.01
++ CDC ACM:
++ bmCapabilities 0x00
++ CDC Union:
++ bMasterInterface 1
++ bSlaveInterface 2
++ CDC Call Management:
++ bmCapabilities 0x01
++ call management
++ bDataInterface 2
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 255
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0 Unused
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x04 EP 4 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/cmsis_dap/2a86_8011_wch_link.txt b/doc/usb_adapters/cmsis_dap/2a86_8011_wch_link.txt
+new file mode 100644
+index 000000000..f27d9932f
+--- /dev/null
++++ b/doc/usb_adapters/cmsis_dap/2a86_8011_wch_link.txt
+@@ -0,0 +1,143 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Reported in https://github.com/pyocd/pyOCD/issues/1395
++
++Bus 003 Device 118: ID 2a86:8011 wch.cn WCH-Link
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 8
++ idVendor 0x2a86
++ idProduct 0x8011
++ bcdDevice 1.00
++ iManufacturer 1 wch.cn
++ iProduct 2 WCH-Link
++ iSerial 3 0001A0000001
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x006b
++ bNumInterfaces 3
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 500mA
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 0
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 4 QYF CMSIS-DAP
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 0
++ iInterface 4 QYF CMSIS-DAP
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x01
++ call management
++ bDataInterface 1
++ CDC ACM:
++ bmCapabilities 0x02
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 0
++ bSlaveInterface 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 2
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 5 (error)
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x03 EP 3 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 6 QYF CMSIS-DAP
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.00
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 33
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/cmsis_dap/c251_2723_keil_ulink_me.txt b/doc/usb_adapters/cmsis_dap/c251_2723_keil_ulink_me.txt
+new file mode 100644
+index 000000000..df2b9243e
+--- /dev/null
++++ b/doc/usb_adapters/cmsis_dap/c251_2723_keil_ulink_me.txt
+@@ -0,0 +1,72 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Reported in https://stackoverflow.com/questions/27087281/jtag-adapter-ulink-me-and-openocd-on-archlinux
++
++Bus 005 Device 026: ID c251:2723 Keil Software, Inc.
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0 (Defined at Interface level)
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0xc251 Keil Software, Inc.
++ idProduct 0x2723
++ bcdDevice 1.00
++ iManufacturer 1 Keil Software
++ iProduct 2 Keil ULINK-ME CMSIS-DAP
++ iSerial 3 M0489MAE
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 41
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0 No Subclass
++ bInterfaceProtocol 0 None
++ iInterface 4 CMSIS-DAP
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.00
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 33
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/cmsis_dap/c251_2750_keil_ulinkplus.txt b/doc/usb_adapters/cmsis_dap/c251_2750_keil_ulinkplus.txt
+new file mode 100644
+index 000000000..4504ef0eb
+--- /dev/null
++++ b/doc/usb_adapters/cmsis_dap/c251_2750_keil_ulinkplus.txt
+@@ -0,0 +1,161 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# firmware 2.0.11
++
++Bus 001 Device 005: ID c251:2750 Keil Software, Inc.
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0 (Defined at Interface level)
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0xc251 Keil Software, Inc.
++ idProduct 0x2750
++ bcdDevice 1.00
++ iManufacturer 1 KEIL - Tools By ARM
++ iProduct 2 Keil ULINKplus
++ iSerial 3 L78440715A
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 101
++ bNumInterfaces 4
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 500mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 3
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 4 ULINKplus CMSIS-DAP
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 5 ULINKplus Digital I/O
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 6 ULINKplus Analog I/O
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x03 EP 3 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 7 ULINKplus Power Probe
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x84 EP 4 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0 (Defined at Interface level)
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/cmsis_dap/c251_f001_jixin.pro.txt b/doc/usb_adapters/cmsis_dap/c251_f001_jixin.pro.txt
+new file mode 100644
+index 000000000..c08f679a6
+--- /dev/null
++++ b/doc/usb_adapters/cmsis_dap/c251_f001_jixin.pro.txt
+@@ -0,0 +1,143 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Reported in https://sourceforge.net/p/openocd/tickets/368/
++
++Bus 001 Device 008: ID c251:f001 Keil Software, Inc.
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2 ?
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0xc251 Keil Software, Inc.
++ idProduct 0xf001
++ bcdDevice 1.00
++ iManufacturer 1 jixin.pro
++ iProduct 2 CMSIS-DAP_LU
++ iSerial 3 LU_2022_8888
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 107
++ bNumInterfaces 3
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 100mA
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 0
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 1 AT-commands (v.25ter)
++ iFunction 4 CMSIS-DAP CDC
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 0 None
++ iInterface 4 CMSIS-DAP CDC
++ CDC Header:
++ bcdCDC 1.10
++ CDC Call Management:
++ bmCapabilities 0x01
++ call management
++ bDataInterface 1
++ CDC ACM:
++ bmCapabilities 0x02
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 0
++ bSlaveInterface 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 2
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0 Unused
++ bInterfaceProtocol 0
++ iInterface 5 CMSIS-DAP DCI
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0 No Subclass
++ bInterfaceProtocol 0 None
++ iInterface 6 CMSIS-DAP_LU
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.00
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 33
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x03 EP 3 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/ftdi/0403_6014_digilent_hs2.txt b/doc/usb_adapters/ftdi/0403_6014_digilent_hs2.txt
+new file mode 100644
+index 000000000..68fc119e1
+--- /dev/null
++++ b/doc/usb_adapters/ftdi/0403_6014_digilent_hs2.txt
+@@ -0,0 +1,71 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Reported in https://sourceforge.net/p/openocd/tickets/357/
++
++Bus 001 Device 084: ID 0403:6014 Future Technology Devices International, Ltd FT232H Single HS USB-UART/FIFO IC
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ idVendor 0x0403 Future Technology Devices International, Ltd
++ idProduct 0x6014 FT232H Single HS USB-UART/FIFO IC
++ bcdDevice 9.00
++ iManufacturer 1 Digilent
++ iProduct 2 Digilent USB Device
++ iSerial 3 210249AFCD0B
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0020
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 500mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 2 Digilent USB Device
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0200 1x 512 bytes
++ bInterval 0
++Device Qualifier (for other device speed):
++ bLength 10
++ bDescriptorType 6
++ bcdUSB 2.00
++ bDeviceClass 0
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 64
++ bNumConfigurations 1
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/ftdi/9e88_9e8f_sheevaplug_jtagkey.txt b/doc/usb_adapters/ftdi/9e88_9e8f_sheevaplug_jtagkey.txt
+new file mode 100644
+index 000000000..c61044335
+--- /dev/null
++++ b/doc/usb_adapters/ftdi/9e88_9e8f_sheevaplug_jtagkey.txt
+@@ -0,0 +1,92 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Reported in https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=837989
++
++Bus 003 Device 002: ID 9e88:9e8f
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 0 (Defined at Interface level)
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 8
++ idVendor 0x9e88
++ idProduct 0x9e8f
++ bcdDevice 5.00
++ iManufacturer 1 FTDI
++ iProduct 2 SheevaPlug JTAGKey FT2232D B
++ iSerial 3 FTU85Z4Y
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 55
++ bNumInterfaces 2
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0xc0
++ Self Powered
++ MaxPower 0mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 2 SheevaPlug JTAGKey FT2232D B
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 2 SheevaPlug JTAGKey FT2232D B
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x04 EP 4 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
+diff --git a/doc/usb_adapters/jlink/1366_0101_segger_jlink.txt b/doc/usb_adapters/jlink/1366_0101_segger_jlink.txt
+new file mode 100644
+index 000000000..8fa4e7d29
+--- /dev/null
++++ b/doc/usb_adapters/jlink/1366_0101_segger_jlink.txt
+@@ -0,0 +1,62 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Reported in https://forums.gentoo.org/viewtopic-t-781442-start-0.html
++
++Bus 002 Device 002: ID 1366:0101
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 1.10
++ bDeviceClass 0 (Defined at Interface level)
++ bDeviceSubClass 0
++ bDeviceProtocol 0
++ bMaxPacketSize0 8
++ idVendor 0x1366
++ idProduct 0x0101
++ bcdDevice 0.01
++ iManufacturer 1 SEGGER
++ iProduct 2 J-Link
++ iSerial 3 123456
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 32
++ bNumInterfaces 1
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0xc0
++ Self Powered
++ MaxPower 100mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 255 Vendor Specific Protocol
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0001
++ Self Powered
+diff --git a/doc/usb_adapters/kitprog/04b4_f139_cypress_kitprog.txt b/doc/usb_adapters/kitprog/04b4_f139_cypress_kitprog.txt
+new file mode 100644
+index 000000000..e3430d87e
+--- /dev/null
++++ b/doc/usb_adapters/kitprog/04b4_f139_cypress_kitprog.txt
+@@ -0,0 +1,172 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Reported in http://false.ekta.is/tag/unboxing/
++
++Bus 003 Device 011: ID 04b4:f139 Cypress Semiconductor Corp.
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2 ?
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 8
++ idVendor 0x04b4 Cypress Semiconductor Corp.
++ idProduct 0xf139
++ bcdDevice 2.0b
++ iManufacturer 1 Cypress Semiconductor
++ iProduct 2 Cypress KitProg
++ iSerial 128 1C210338012E4400
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 130
++ bNumInterfaces 4
++ bConfigurationValue 1
++ iConfiguration 2 Cypress KitProg
++ bmAttributes 0x80
++ (Bus Powered)
++ MaxPower 400mA
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 3 Human Interface Device
++ bInterfaceSubClass 0 No Subclass
++ bInterfaceProtocol 0 None
++ iInterface 3 KitBridge
++ HID Device Descriptor:
++ bLength 9
++ bDescriptorType 33
++ bcdHID 1.11
++ bCountryCode 0 Not supported
++ bNumDescriptors 1
++ bDescriptorType 34 Report
++ wDescriptorLength 43
++ Report Descriptors:
++ ** UNAVAILABLE **
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x04 EP 4 OUT
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 0
++ bInterfaceProtocol 0
++ iInterface 5 KitProg Programmer
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 2
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 0
++ bFunctionProtocol 0
++ iFunction 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 0 None
++ iInterface 4 KitProg USBUART
++ CDC Header:
++ bcdCDC 1.10
++ CDC ACM:
++ bmCapabilities 0x02
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 2
++ bSlaveInterface 1
++ CDC Call Management:
++ bmCapabilities 0x00
++ bDataInterface 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x85 EP 5 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0008 1x 8 bytes
++ bInterval 2
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 3
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 0 Unused
++ bInterfaceProtocol 0
++ iInterface 4 KitProg USBUART
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x86 EP 6 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x07 EP 7 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 0
++Device Status: 0x0000
++ (Bus Powered)
new file mode 100644
@@ -0,0 +1,80 @@
+From 9dac3b247b43d8b91821560b7c99fbd33d736419 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 13 Nov 2022 15:46:19 +0100
+Subject: [PATCH] tools: add disassembler helper for files .inc
+
+We are moving the binary helpers in files .inc in contrib/loaders/
+but we have no support to disassemble them for checking their
+content, nor documentation to give any hint.
+
+Add a simple script that uses objdump to directly disassemble a
+file .inc
+Use Cortex-M settings as default, but provide the flexibility to
+reuse the script for any other target CPU.
+
+Change-Id: I12e79580f2936b1622fb7231d9a2484a763ba72a
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7347
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ tools/disassemble_inc.sh | 50 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+ create mode 100755 tools/disassemble_inc.sh
+
+diff --git a/tools/disassemble_inc.sh b/tools/disassemble_inc.sh
+new file mode 100755
+index 000000000..d4b5f80dc
+--- /dev/null
++++ b/tools/disassemble_inc.sh
+@@ -0,0 +1,50 @@
++#!/bin/sh
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++# Simple script to disassemble a file .inc generated by
++# src/helper/bin2char.sh
++# Can be useful to check the correctness of the file .inc
++#
++# By default it decodes ARM thumb little-endian, e.g. cortex-m.
++# Set CROSS_COMPILE for other toolchains.
++# Set OBJDUMP_FLAGS for different objdump flags.
++#
++# Usage:
++# contrib/loaders/disassemble_inc.sh file.inc
++
++default_CROSS_COMPILE="arm-none-eabi-"
++default_OBJDUMP_FLAGS="-m arm -EL -M force-thumb"
++
++if [ $# != 1 -o ! -f "$1" ]; then
++ echo "Usage:"
++ echo " $0 path/to/file.inc"
++ echo ""
++ echo "Set CROSS_COMPILE and/or OBJDUMP_FLAGS to override current default:"
++ echo " export CROSS_COMPILE=\"${default_CROSS_COMPILE}\""
++ echo " export OBJDUMP_FLAGS=\"${default_OBJDUMP_FLAGS}\""
++ exit 1
++fi
++
++if [ -z "${CROSS_COMPILE}" ]; then
++ CROSS_COMPILE="${default_CROSS_COMPILE}"
++fi
++
++if [ -z "${OBJDUMP_FLAGS}" ]; then
++ OBJDUMP_FLAGS="${default_OBJDUMP_FLAGS}"
++fi
++
++perl -v > /dev/null 2>&1
++if [ $? != 0 ]; then
++ echo "Error: 'perl' interpreter not available."
++ exit 1
++fi
++
++tmpfile=$(mktemp --suffix=.bin)
++
++echo "Disassemble $1:"
++echo "${CROSS_COMPILE}objdump ${OBJDUMP_FLAGS} -b binary -D ${tmpfile}"
++
++perl -e 'while (<>){while ($_=~/(0x..)/g){print chr(hex($1));}}' $1 > ${tmpfile}
++${CROSS_COMPILE}objdump ${OBJDUMP_FLAGS} -b binary -D ${tmpfile}
++
++rm ${tmpfile}
new file mode 100644
@@ -0,0 +1,269 @@
+From 128736d23f0e92a245d51c10e889ed3e6da4c2b1 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sat, 19 Nov 2022 06:57:56 +0100
+Subject: [PATCH] jtag/drivers/cmsis_dap: move pending request FIFO
+
+Move all pending request FIFO related variables to
+the struct cmsis_dap
+
+Pure refactoring, no functional changes.
+
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Change-Id: I2cea9c1e265ac102ec0f314767b8b9afdcda9ee9
+Reviewed-on: https://review.openocd.org/c/openocd/+/7360
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/cmsis_dap.c | 91 +++++++++++++++---------------------
+ src/jtag/drivers/cmsis_dap.h | 24 +++++++++-
+ 2 files changed, 59 insertions(+), 56 deletions(-)
+
+diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
+index 44a7dd8cb..c2f01f33d 100644
+--- a/src/jtag/drivers/cmsis_dap.c
++++ b/src/jtag/drivers/cmsis_dap.c
+@@ -209,17 +209,6 @@ static const char * const info_caps_str[INFO_CAPS__NUM_CAPS] = {
+ "UART via USB COM port supported",
+ };
+
+-struct pending_transfer_result {
+- uint8_t cmd;
+- uint32_t data;
+- void *buffer;
+-};
+-
+-struct pending_request_block {
+- struct pending_transfer_result *transfers;
+- int transfer_count;
+-};
+-
+ struct pending_scan_result {
+ /** Offset in bytes in the CMD_DAP_JTAG_SEQ response buffer. */
+ unsigned first;
+@@ -231,16 +220,8 @@ struct pending_scan_result {
+ unsigned buffer_offset;
+ };
+
+-/* Up to MIN(packet_count, MAX_PENDING_REQUESTS) requests may be issued
+- * until the first response arrives */
+-#define MAX_PENDING_REQUESTS 3
+-
+-/* Pending requests are organized as a FIFO - circular buffer */
+ /* Each block in FIFO can contain up to pending_queue_len transfers */
+ static int pending_queue_len;
+-static struct pending_request_block pending_fifo[MAX_PENDING_REQUESTS];
+-static int pending_fifo_put_idx, pending_fifo_get_idx;
+-static int pending_fifo_block_count;
+
+ /* pointers to buffers that will receive jtag scan results on the next flush */
+ #define MAX_PENDING_SCAN_RESULTS 256
+@@ -314,8 +295,8 @@ static void cmsis_dap_close(struct cmsis_dap *dap)
+ cmsis_dap_handle = NULL;
+
+ for (int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+- free(pending_fifo[i].transfers);
+- pending_fifo[i].transfers = NULL;
++ free(dap->pending_fifo[i].transfers);
++ dap->pending_fifo[i].transfers = NULL;
+ }
+ }
+
+@@ -337,14 +318,14 @@ static void cmsis_dap_flush_read(struct cmsis_dap *dap)
+ /* Send a message and receive the reply */
+ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
+ {
+- if (pending_fifo_block_count) {
+- LOG_ERROR("pending %d blocks, flushing", pending_fifo_block_count);
+- while (pending_fifo_block_count) {
++ if (dap->pending_fifo_block_count) {
++ LOG_ERROR("pending %u blocks, flushing", dap->pending_fifo_block_count);
++ while (dap->pending_fifo_block_count) {
+ dap->backend->read(dap, 10);
+- pending_fifo_block_count--;
++ dap->pending_fifo_block_count--;
+ }
+- pending_fifo_put_idx = 0;
+- pending_fifo_get_idx = 0;
++ dap->pending_fifo_put_idx = 0;
++ dap->pending_fifo_get_idx = 0;
+ }
+
+ uint8_t current_cmd = cmsis_dap_handle->command[0];
+@@ -763,9 +744,10 @@ static int cmsis_dap_cmd_dap_swo_data(
+ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
+ {
+ uint8_t *command = cmsis_dap_handle->command;
+- struct pending_request_block *block = &pending_fifo[pending_fifo_put_idx];
++ struct pending_request_block *block = &dap->pending_fifo[dap->pending_fifo_put_idx];
+
+- LOG_DEBUG_IO("Executing %d queued transactions from FIFO index %d", block->transfer_count, pending_fifo_put_idx);
++ LOG_DEBUG_IO("Executing %d queued transactions from FIFO index %u",
++ block->transfer_count, dap->pending_fifo_put_idx);
+
+ if (queued_retval != ERROR_OK) {
+ LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
+@@ -824,10 +806,10 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
+ queued_retval = ERROR_OK;
+ }
+
+- pending_fifo_put_idx = (pending_fifo_put_idx + 1) % dap->packet_count;
+- pending_fifo_block_count++;
+- if (pending_fifo_block_count > dap->packet_count)
+- LOG_ERROR("too much pending writes %d", pending_fifo_block_count);
++ dap->pending_fifo_put_idx = (dap->pending_fifo_put_idx + 1) % dap->packet_count;
++ dap->pending_fifo_block_count++;
++ if (dap->pending_fifo_block_count > dap->packet_count)
++ LOG_ERROR("too much pending writes %u", dap->pending_fifo_block_count);
+
+ return;
+
+@@ -837,9 +819,9 @@ skip:
+
+ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
+ {
+- struct pending_request_block *block = &pending_fifo[pending_fifo_get_idx];
++ struct pending_request_block *block = &dap->pending_fifo[dap->pending_fifo_get_idx];
+
+- if (pending_fifo_block_count == 0)
++ if (dap->pending_fifo_block_count == 0)
+ LOG_ERROR("no pending write");
+
+ /* get reply */
+@@ -880,8 +862,8 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
+ LOG_ERROR("CMSIS-DAP transfer count mismatch: expected %d, got %d",
+ block->transfer_count, transfer_count);
+
+- LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %d",
+- transfer_count, pending_fifo_get_idx);
++ LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u timeout %i",
++ transfer_count, dap->pending_fifo_get_idx, timeout_ms);
+ size_t idx = 3;
+ for (int i = 0; i < transfer_count; i++) {
+ struct pending_transfer_result *transfer = &(block->transfers[i]);
+@@ -907,22 +889,22 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
+
+ skip:
+ block->transfer_count = 0;
+- pending_fifo_get_idx = (pending_fifo_get_idx + 1) % dap->packet_count;
+- pending_fifo_block_count--;
++ dap->pending_fifo_get_idx = (dap->pending_fifo_get_idx + 1) % dap->packet_count;
++ dap->pending_fifo_block_count--;
+ }
+
+ static int cmsis_dap_swd_run_queue(void)
+ {
+- if (pending_fifo_block_count)
++ if (cmsis_dap_handle->pending_fifo_block_count)
+ cmsis_dap_swd_read_process(cmsis_dap_handle, 0);
+
+ cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
+
+- while (pending_fifo_block_count)
++ while (cmsis_dap_handle->pending_fifo_block_count)
+ cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS);
+
+- pending_fifo_put_idx = 0;
+- pending_fifo_get_idx = 0;
++ cmsis_dap_handle->pending_fifo_put_idx = 0;
++ cmsis_dap_handle->pending_fifo_get_idx = 0;
+
+ int retval = queued_retval;
+ queued_retval = ERROR_OK;
+@@ -934,15 +916,15 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
+ {
+ bool targetsel_cmd = swd_cmd(false, false, DP_TARGETSEL) == cmd;
+
+- if (pending_fifo[pending_fifo_put_idx].transfer_count == pending_queue_len
+- || targetsel_cmd) {
+- if (pending_fifo_block_count)
++ if (cmsis_dap_handle->pending_fifo[cmsis_dap_handle->pending_fifo_put_idx].transfer_count == pending_queue_len
++ || targetsel_cmd) {
++ if (cmsis_dap_handle->pending_fifo_block_count)
+ cmsis_dap_swd_read_process(cmsis_dap_handle, 0);
+
+ /* Not enough room in the queue. Run the queue. */
+ cmsis_dap_swd_write_from_queue(cmsis_dap_handle);
+
+- if (pending_fifo_block_count >= cmsis_dap_handle->packet_count)
++ if (cmsis_dap_handle->pending_fifo_block_count >= cmsis_dap_handle->packet_count)
+ cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS);
+ }
+
+@@ -954,7 +936,7 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
+ return;
+ }
+
+- struct pending_request_block *block = &pending_fifo[pending_fifo_put_idx];
++ struct pending_request_block *block = &cmsis_dap_handle->pending_fifo[cmsis_dap_handle->pending_fifo_put_idx];
+ struct pending_transfer_result *transfer = &(block->transfers[block->transfer_count]);
+ transfer->data = data;
+ transfer->cmd = cmd;
+@@ -1231,17 +1213,18 @@ static int cmsis_dap_init(void)
+ goto init_err;
+
+ if (data[0] == 1) { /* byte */
+- int pkt_cnt = data[1];
++ unsigned int pkt_cnt = data[1];
+ if (pkt_cnt > 1)
+ cmsis_dap_handle->packet_count = MIN(MAX_PENDING_REQUESTS, pkt_cnt);
+
+- LOG_DEBUG("CMSIS-DAP: Packet Count = %d", pkt_cnt);
++ LOG_DEBUG("CMSIS-DAP: Packet Count = %u", pkt_cnt);
+ }
+
+- LOG_DEBUG("Allocating FIFO for %d pending packets", cmsis_dap_handle->packet_count);
+- for (int i = 0; i < cmsis_dap_handle->packet_count; i++) {
+- pending_fifo[i].transfers = malloc(pending_queue_len * sizeof(struct pending_transfer_result));
+- if (!pending_fifo[i].transfers) {
++ LOG_DEBUG("Allocating FIFO for %u pending packets", cmsis_dap_handle->packet_count);
++ for (unsigned int i = 0; i < cmsis_dap_handle->packet_count; i++) {
++ cmsis_dap_handle->pending_fifo[i].transfers = malloc(pending_queue_len
++ * sizeof(struct pending_transfer_result));
++ if (!cmsis_dap_handle->pending_fifo[i].transfers) {
+ LOG_ERROR("Unable to allocate memory for CMSIS-DAP queue");
+ retval = ERROR_FAIL;
+ goto init_err;
+diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
+index cf929b069..7eaa1f216 100644
+--- a/src/jtag/drivers/cmsis_dap.h
++++ b/src/jtag/drivers/cmsis_dap.h
+@@ -7,17 +7,37 @@
+
+ struct cmsis_dap_backend;
+ struct cmsis_dap_backend_data;
+-struct command_registration;
++
++struct pending_transfer_result {
++ uint8_t cmd;
++ uint32_t data;
++ void *buffer;
++};
++
++/* Up to MIN(packet_count, MAX_PENDING_REQUESTS) requests may be issued
++ * until the first response arrives */
++#define MAX_PENDING_REQUESTS 4
++
++struct pending_request_block {
++ struct pending_transfer_result *transfers;
++ int transfer_count;
++};
+
+ struct cmsis_dap {
+ struct cmsis_dap_backend_data *bdata;
+ const struct cmsis_dap_backend *backend;
+ uint16_t packet_size;
+- int packet_count;
+ uint8_t *packet_buffer;
+ uint16_t packet_buffer_size;
+ uint8_t *command;
+ uint8_t *response;
++
++ /* Pending requests are organized as a FIFO - circular buffer */
++ struct pending_request_block pending_fifo[MAX_PENDING_REQUESTS];
++ unsigned int packet_count;
++ unsigned int pending_fifo_put_idx, pending_fifo_get_idx;
++ unsigned int pending_fifo_block_count;
++
+ uint16_t caps;
+ uint8_t mode;
+ uint32_t swo_buf_sz;
new file mode 100644
@@ -0,0 +1,68 @@
+From a9b48a6f481344c592e7e05ca06564cdadfe0721 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sat, 19 Nov 2022 07:08:32 +0100
+Subject: [PATCH] jtag/drivers/cmsis_dap: use dap parameter instead of
+ cmsis_dap_handle
+
+Replace the direct dereference of cmsis_dap_handle by dereference
+of the dap function parameter wherever possible.
+
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Change-Id: I32601dbe0270267642720a8524706aa76d187c3b
+Reviewed-on: https://review.openocd.org/c/openocd/+/7361
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/cmsis_dap.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
+index c2f01f33d..49181ad90 100644
+--- a/src/jtag/drivers/cmsis_dap.c
++++ b/src/jtag/drivers/cmsis_dap.c
+@@ -290,14 +290,15 @@ static void cmsis_dap_close(struct cmsis_dap *dap)
+ dap->backend = NULL;
+ }
+
+- free(cmsis_dap_handle->packet_buffer);
+- free(cmsis_dap_handle);
+- cmsis_dap_handle = NULL;
++ free(dap->packet_buffer);
+
+ for (int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+ free(dap->pending_fifo[i].transfers);
+ dap->pending_fifo[i].transfers = NULL;
+ }
++
++ free(cmsis_dap_handle);
++ cmsis_dap_handle = NULL;
+ }
+
+ static void cmsis_dap_flush_read(struct cmsis_dap *dap)
+@@ -328,7 +329,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
+ dap->pending_fifo_get_idx = 0;
+ }
+
+- uint8_t current_cmd = cmsis_dap_handle->command[0];
++ uint8_t current_cmd = dap->command[0];
+ int retval = dap->backend->write(dap, txlen, LIBUSB_TIMEOUT_MS);
+ if (retval < 0)
+ return retval;
+@@ -338,7 +339,7 @@ static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen)
+ if (retval < 0)
+ return retval;
+
+- uint8_t *resp = cmsis_dap_handle->response;
++ uint8_t *resp = dap->response;
+ if (resp[0] == DAP_ERROR) {
+ LOG_ERROR("CMSIS-DAP command 0x%" PRIx8 " not implemented", current_cmd);
+ return ERROR_NOT_IMPLEMENTED;
+@@ -743,7 +744,7 @@ static int cmsis_dap_cmd_dap_swo_data(
+
+ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
+ {
+- uint8_t *command = cmsis_dap_handle->command;
++ uint8_t *command = dap->command;
+ struct pending_request_block *block = &dap->pending_fifo[dap->pending_fifo_put_idx];
+
+ LOG_DEBUG_IO("Executing %d queued transactions from FIFO index %u",
new file mode 100644
@@ -0,0 +1,179 @@
+From 600d0165cc041a36d3707168aeb113d7a2e6747f Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sat, 19 Nov 2022 07:08:32 +0100
+Subject: [PATCH] jtag/drivers/cmsis_dap: use unsigned types
+
+Not all variables converted, JTAG part is left as is.
+
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Change-Id: Ie9cc890769a2f53cb3a07fd457030e1b98910d44
+Reviewed-on: https://review.openocd.org/c/openocd/+/7362
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/cmsis_dap.c | 41 ++++++++++++++++++------------------
+ src/jtag/drivers/cmsis_dap.h | 6 +++---
+ 2 files changed, 24 insertions(+), 23 deletions(-)
+
+diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
+index 49181ad90..5e01d0647 100644
+--- a/src/jtag/drivers/cmsis_dap.c
++++ b/src/jtag/drivers/cmsis_dap.c
+@@ -211,17 +211,17 @@ static const char * const info_caps_str[INFO_CAPS__NUM_CAPS] = {
+
+ struct pending_scan_result {
+ /** Offset in bytes in the CMD_DAP_JTAG_SEQ response buffer. */
+- unsigned first;
++ unsigned int first;
+ /** Number of bits to read. */
+- unsigned length;
++ unsigned int length;
+ /** Location to store the result */
+ uint8_t *buffer;
+ /** Offset in the destination buffer */
+- unsigned buffer_offset;
++ unsigned int buffer_offset;
+ };
+
+ /* Each block in FIFO can contain up to pending_queue_len transfers */
+-static int pending_queue_len;
++static unsigned int pending_queue_len;
+
+ /* pointers to buffers that will receive jtag scan results on the next flush */
+ #define MAX_PENDING_SCAN_RESULTS 256
+@@ -292,7 +292,7 @@ static void cmsis_dap_close(struct cmsis_dap *dap)
+
+ free(dap->packet_buffer);
+
+- for (int i = 0; i < MAX_PENDING_REQUESTS; i++) {
++ for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) {
+ free(dap->pending_fifo[i].transfers);
+ dap->pending_fifo[i].transfers = NULL;
+ }
+@@ -403,7 +403,7 @@ static int cmsis_dap_cmd_dap_swj_sequence(uint8_t s_len, const uint8_t *sequence
+
+ #ifdef CMSIS_DAP_JTAG_DEBUG
+ LOG_DEBUG("cmsis-dap TMS sequence: len=%d", s_len);
+- for (int i = 0; i < DIV_ROUND_UP(s_len, 8); ++i)
++ for (unsigned int i = 0; i < DIV_ROUND_UP(s_len, 8); ++i)
+ printf("%02X ", sequence[i]);
+
+ printf("\n");
+@@ -763,7 +763,7 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
+ command[2] = block->transfer_count;
+ size_t idx = 3;
+
+- for (int i = 0; i < block->transfer_count; i++) {
++ for (unsigned int i = 0; i < block->transfer_count; i++) {
+ struct pending_transfer_result *transfer = &(block->transfers[i]);
+ uint8_t cmd = transfer->cmd;
+ uint32_t data = transfer->data;
+@@ -844,7 +844,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
+ goto skip;
+ }
+
+- uint8_t transfer_count = resp[1];
++ unsigned int transfer_count = resp[1];
+ uint8_t ack = resp[2] & 0x07;
+ if (resp[2] & 0x08) {
+ LOG_DEBUG("CMSIS-DAP Protocol Error @ %d (wrong parity)", transfer_count);
+@@ -865,8 +865,8 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
+
+ LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u timeout %i",
+ transfer_count, dap->pending_fifo_get_idx, timeout_ms);
+- size_t idx = 3;
+- for (int i = 0; i < transfer_count; i++) {
++ unsigned int idx = 3;
++ for (unsigned int i = 0; i < transfer_count; i++) {
+ struct pending_transfer_result *transfer = &(block->transfers[i]);
+ if (transfer->cmd & SWD_CMD_RNW) {
+ static uint32_t last_read;
+@@ -1005,7 +1005,7 @@ static int cmsis_dap_get_caps_info(void)
+
+ cmsis_dap_handle->caps = caps;
+
+- for (int i = 0; i < INFO_CAPS__NUM_CAPS; ++i) {
++ for (unsigned int i = 0; i < INFO_CAPS__NUM_CAPS; ++i) {
+ if (caps & BIT(i))
+ LOG_INFO("CMSIS-DAP: %s", info_caps_str[i]);
+ }
+@@ -1351,7 +1351,7 @@ static void cmsis_dap_end_state(tap_state_t state)
+ }
+
+ #ifdef SPRINT_BINARY
+-static void sprint_binary(char *s, const uint8_t *buf, int offset, int len)
++static void sprint_binary(char *s, const uint8_t *buf, unsigned int offset, unsigned int len)
+ {
+ if (!len)
+ return;
+@@ -1362,7 +1362,7 @@ static void sprint_binary(char *s, const uint8_t *buf, int offset, int len)
+ buf = { 0xc0 0x18 } offset=3 len=10 should result in: 11000 11000
+ i=3 there means i/8 = 0 so c = 0xFF, and
+ */
+- for (int i = offset; i < offset + len; ++i) {
++ for (unsigned int i = offset; i < offset + len; ++i) {
+ uint8_t c = buf[i / 8], mask = 1 << (i % 8);
+ if ((i != offset) && !(i % 8))
+ putchar(' ');
+@@ -1476,10 +1476,11 @@ static void cmsis_dap_flush(void)
+ * sequence=NULL means clock out zeros on TDI
+ * tdo_buffer=NULL means don't capture TDO
+ */
+-static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int s_offset,
+- bool tms, uint8_t *tdo_buffer, int tdo_buffer_offset)
++static void cmsis_dap_add_jtag_sequence(unsigned int s_len, const uint8_t *sequence,
++ unsigned int s_offset, bool tms,
++ uint8_t *tdo_buffer, unsigned int tdo_buffer_offset)
+ {
+- LOG_DEBUG_IO("[at %d] %d bits, tms %s, seq offset %d, tdo buf %p, tdo offset %d",
++ LOG_DEBUG_IO("[at %d] %u bits, tms %s, seq offset %u, tdo buf %p, tdo offset %u",
+ queued_seq_buf_end,
+ s_len, tms ? "HIGH" : "LOW", s_offset, tdo_buffer, tdo_buffer_offset);
+
+@@ -1488,11 +1489,11 @@ static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int
+
+ if (s_len > 64) {
+ LOG_DEBUG_IO("START JTAG SEQ SPLIT");
+- for (int offset = 0; offset < s_len; offset += 64) {
+- int len = s_len - offset;
++ for (unsigned int offset = 0; offset < s_len; offset += 64) {
++ unsigned int len = s_len - offset;
+ if (len > 64)
+ len = 64;
+- LOG_DEBUG_IO("Splitting long jtag sequence: %d-bit chunk starting at offset %d", len, offset);
++ LOG_DEBUG_IO("Splitting long jtag sequence: %u-bit chunk starting at offset %u", len, offset);
+ cmsis_dap_add_jtag_sequence(
+ len,
+ sequence,
+@@ -1506,7 +1507,7 @@ static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int
+ return;
+ }
+
+- int cmd_len = 1 + DIV_ROUND_UP(s_len, 8);
++ unsigned int cmd_len = 1 + DIV_ROUND_UP(s_len, 8);
+ if (queued_seq_count >= 255 || queued_seq_buf_end + cmd_len > QUEUED_SEQ_BUF_LEN)
+ /* empty out the buffer */
+ cmsis_dap_flush();
+diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
+index 7eaa1f216..80044199b 100644
+--- a/src/jtag/drivers/cmsis_dap.h
++++ b/src/jtag/drivers/cmsis_dap.h
+@@ -20,15 +20,15 @@ struct pending_transfer_result {
+
+ struct pending_request_block {
+ struct pending_transfer_result *transfers;
+- int transfer_count;
++ unsigned int transfer_count;
+ };
+
+ struct cmsis_dap {
+ struct cmsis_dap_backend_data *bdata;
+ const struct cmsis_dap_backend *backend;
+- uint16_t packet_size;
++ unsigned int packet_size;
++ unsigned int packet_buffer_size;
+ uint8_t *packet_buffer;
+- uint16_t packet_buffer_size;
+ uint8_t *command;
+ uint8_t *response;
+
new file mode 100644
@@ -0,0 +1,104 @@
+From 3d3d35c9b87243a14b37478f1120c4c8d0a6d0bb Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sat, 19 Nov 2022 07:16:30 +0100
+Subject: [PATCH] jtag/drivers/cmsis_dap: introduce packet_usable_size
+
+USB bulk backend needs to avoid zero sized USB packets
+sent after each full sized packed for performance reasons.
+
+HID backend uses fixed size HID reports so the full size
+of the report can be utilized.
+
+Introduce packet_usable_size to reflect it.
+
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Change-Id: I34094c9edac5730624480711cbd6aa65883c47c7
+Reviewed-on: https://review.openocd.org/c/openocd/+/7363
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/cmsis_dap.c | 2 +-
+ src/jtag/drivers/cmsis_dap.h | 1 +
+ src/jtag/drivers/cmsis_dap_usb_bulk.c | 16 +++++-----------
+ src/jtag/drivers/cmsis_dap_usb_hid.c | 1 +
+ 4 files changed, 8 insertions(+), 12 deletions(-)
+
+diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
+index 5e01d0647..364a17746 100644
+--- a/src/jtag/drivers/cmsis_dap.c
++++ b/src/jtag/drivers/cmsis_dap.c
+@@ -229,7 +229,7 @@ static int pending_scan_result_count;
+ static struct pending_scan_result pending_scan_results[MAX_PENDING_SCAN_RESULTS];
+
+ /* queued JTAG sequences that will be executed on the next flush */
+-#define QUEUED_SEQ_BUF_LEN (cmsis_dap_handle->packet_size - 3)
++#define QUEUED_SEQ_BUF_LEN (cmsis_dap_handle->packet_usable_size - 3)
+ static int queued_seq_count;
+ static int queued_seq_buf_end;
+ static int queued_seq_tdo_ptr;
+diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
+index 80044199b..72e07fb04 100644
+--- a/src/jtag/drivers/cmsis_dap.h
++++ b/src/jtag/drivers/cmsis_dap.h
+@@ -27,6 +27,7 @@ struct cmsis_dap {
+ struct cmsis_dap_backend_data *bdata;
+ const struct cmsis_dap_backend *backend;
+ unsigned int packet_size;
++ unsigned int packet_usable_size;
+ unsigned int packet_buffer_size;
+ uint8_t *packet_buffer;
+ uint8_t *command;
+diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c
+index 55b9a558a..6599c414c 100644
+--- a/src/jtag/drivers/cmsis_dap_usb_bulk.c
++++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c
+@@ -352,25 +352,17 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p
+ return ERROR_FAIL;
+ }
+
+- dap->packet_size = packet_size;
+- dap->packet_buffer_size = packet_size;
+ dap->bdata->usb_ctx = ctx;
+ dap->bdata->dev_handle = dev_handle;
+ dap->bdata->ep_out = ep_out;
+ dap->bdata->ep_in = ep_in;
+ dap->bdata->interface = interface_num;
+
+- dap->packet_buffer = malloc(dap->packet_buffer_size);
+- if (!dap->packet_buffer) {
+- LOG_ERROR("unable to allocate memory");
++ err = cmsis_dap_usb_alloc(dap, packet_size);
++ if (err != ERROR_OK)
+ cmsis_dap_usb_close(dap);
+- return ERROR_FAIL;
+- }
+-
+- dap->command = dap->packet_buffer;
+- dap->response = dap->packet_buffer;
+
+- return ERROR_OK;
++ return err;
+ }
+
+ libusb_close(dev_handle);
+@@ -445,6 +437,8 @@ static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
+ dap->packet_buffer = buf;
+ dap->packet_size = pkt_sz;
+ dap->packet_buffer_size = pkt_sz;
++ /* Prevent sending zero size USB packets */
++ dap->packet_usable_size = pkt_sz - 1;
+
+ dap->command = dap->packet_buffer;
+ dap->response = dap->packet_buffer;
+diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c
+index 592eb0925..52dfd7616 100644
+--- a/src/jtag/drivers/cmsis_dap_usb_hid.c
++++ b/src/jtag/drivers/cmsis_dap_usb_hid.c
+@@ -213,6 +213,7 @@ static int cmsis_dap_hid_alloc(struct cmsis_dap *dap, unsigned int pkt_sz)
+
+ dap->packet_buffer = buf;
+ dap->packet_size = pkt_sz;
++ dap->packet_usable_size = pkt_sz;
+ dap->packet_buffer_size = packet_buffer_size;
+
+ dap->command = dap->packet_buffer + REPORT_ID_SIZE;
new file mode 100644
@@ -0,0 +1,180 @@
+From 40bac8e8c4e556faaf9c8adc1a030dbc52080fdb Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sat, 19 Nov 2022 07:21:10 +0100
+Subject: [PATCH] jtag/drivers/cmsis_dap: improve USB packets filling
+
+DAP write transaction occupies 5 bytes of a command packet.
+DAP read transaction needs just one byte in a command packet
+and expect 4 bytes in a response.
+
+The fixed maximal number of transactions in a packet caused
+packet filling less than optimal.
+
+Compute both command and expected response sizes based on
+read or write direction of each transaction.
+Run the queue if one of sizes does not fit into a packet.
+
+The change increases the speed of the mostly read transfer
+from 36 KiB/s to almost 40 KiB/s @ USB FS, adapter speed 1000
+due to reduction of adapter inserted RDBUFF reads.
+
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Change-Id: Ib70812600eaae0403b8ee8673b6f897348496569
+Reviewed-on: https://review.openocd.org/c/openocd/+/7364
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/cmsis_dap.c | 65 +++++++++++++++++++++++++++++++-----
+ src/jtag/drivers/cmsis_dap.h | 5 +++
+ 2 files changed, 62 insertions(+), 8 deletions(-)
+
+diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
+index 364a17746..10e663862 100644
+--- a/src/jtag/drivers/cmsis_dap.c
++++ b/src/jtag/drivers/cmsis_dap.c
+@@ -222,6 +222,8 @@ struct pending_scan_result {
+
+ /* Each block in FIFO can contain up to pending_queue_len transfers */
+ static unsigned int pending_queue_len;
++static unsigned int tfer_max_command_size;
++static unsigned int tfer_max_response_size;
+
+ /* pointers to buffers that will receive jtag scan results on the next flush */
+ #define MAX_PENDING_SCAN_RESULTS 256
+@@ -742,11 +744,18 @@ static int cmsis_dap_cmd_dap_swo_data(
+ return ERROR_OK;
+ }
+
++
+ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
+ {
+ uint8_t *command = dap->command;
+ struct pending_request_block *block = &dap->pending_fifo[dap->pending_fifo_put_idx];
+
++ assert(dap->write_count + dap->read_count == block->transfer_count);
++
++ /* Reset packet size check counters for the next packet */
++ dap->write_count = 0;
++ dap->read_count = 0;
++
+ LOG_DEBUG_IO("Executing %d queued transactions from FIFO index %u",
+ block->transfer_count, dap->pending_fifo_put_idx);
+
+@@ -913,11 +922,43 @@ static int cmsis_dap_swd_run_queue(void)
+ return retval;
+ }
+
++static unsigned int cmsis_dap_tfer_cmd_size(unsigned int write_count,
++ unsigned int read_count)
++{
++ unsigned int size = 3; /* header */
++ size += write_count * (1 + 4); /* DAP register + data */
++ size += read_count; /* DAP register */
++ return size;
++}
++
++static unsigned int cmsis_dap_tfer_resp_size(unsigned int write_count,
++ unsigned int read_count)
++{
++ unsigned int size = 3; /* header */
++ size += read_count * 4; /* data */
++ return size;
++}
++
+ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
+ {
++ /* Compute sizes of the DAP Transfer command and the expected response
++ * for all queued and this operation */
+ bool targetsel_cmd = swd_cmd(false, false, DP_TARGETSEL) == cmd;
+
+- if (cmsis_dap_handle->pending_fifo[cmsis_dap_handle->pending_fifo_put_idx].transfer_count == pending_queue_len
++ unsigned int write_count = cmsis_dap_handle->write_count;
++ unsigned int read_count = cmsis_dap_handle->read_count;
++ if (cmd & SWD_CMD_RNW)
++ read_count++;
++ else
++ write_count++;
++
++ unsigned int cmd_size = cmsis_dap_tfer_cmd_size(write_count, read_count);
++ unsigned int resp_size = cmsis_dap_tfer_resp_size(write_count, read_count);
++
++ /* Does the DAP Transfer command and the expected response fit into one packet?
++ * Run the queue also before a targetsel - it cannot be queued */
++ if (cmd_size > tfer_max_command_size
++ || resp_size > tfer_max_response_size
+ || targetsel_cmd) {
+ if (cmsis_dap_handle->pending_fifo_block_count)
+ cmsis_dap_swd_read_process(cmsis_dap_handle, 0);
+@@ -929,6 +970,8 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
+ cmsis_dap_swd_read_process(cmsis_dap_handle, LIBUSB_TIMEOUT_MS);
+ }
+
++ assert(cmsis_dap_handle->pending_fifo[cmsis_dap_handle->pending_fifo_put_idx].transfer_count < pending_queue_len);
++
+ if (queued_retval != ERROR_OK)
+ return;
+
+@@ -944,6 +987,9 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
+ if (cmd & SWD_CMD_RNW) {
+ /* Queue a read transaction */
+ transfer->buffer = dst;
++ cmsis_dap_handle->read_count++;
++ } else {
++ cmsis_dap_handle->write_count++;
+ }
+ block->transfer_count++;
+ }
+@@ -1183,7 +1229,6 @@ static int cmsis_dap_init(void)
+ /* Be conservative and suppress submitting multiple HID requests
+ * until we get packet count info from the adaptor */
+ cmsis_dap_handle->packet_count = 1;
+- pending_queue_len = 12;
+
+ /* INFO_ID_PKT_SZ - short */
+ retval = cmsis_dap_cmd_dap_info(INFO_ID_PKT_SZ, &data);
+@@ -1193,12 +1238,6 @@ static int cmsis_dap_init(void)
+ if (data[0] == 2) { /* short */
+ uint16_t pkt_sz = data[1] + (data[2] << 8);
+ if (pkt_sz != cmsis_dap_handle->packet_size) {
+-
+- /* 4 bytes of command header + 5 bytes per register
+- * write. For bulk read sequences just 4 bytes are
+- * needed per transfer, so this is suboptimal. */
+- pending_queue_len = (pkt_sz - 4) / 5;
+-
+ free(cmsis_dap_handle->packet_buffer);
+ retval = cmsis_dap_handle->backend->packet_buffer_alloc(cmsis_dap_handle, pkt_sz);
+ if (retval != ERROR_OK)
+@@ -1208,6 +1247,16 @@ static int cmsis_dap_init(void)
+ }
+ }
+
++ /* Maximal number of transfers which fit to one packet:
++ * Limited by response size: 3 bytes of response header + 4 per read
++ * Plus writes to full command size: 3 bytes cmd header + 1 per read + 5 per write */
++ tfer_max_command_size = cmsis_dap_handle->packet_usable_size;
++ tfer_max_response_size = cmsis_dap_handle->packet_usable_size;
++ unsigned int max_reads = tfer_max_response_size / 4;
++ pending_queue_len = max_reads + (tfer_max_command_size - max_reads) / 5;
++ cmsis_dap_handle->write_count = 0;
++ cmsis_dap_handle->read_count = 0;
++
+ /* INFO_ID_PKT_CNT - byte */
+ retval = cmsis_dap_cmd_dap_info(INFO_ID_PKT_CNT, &data);
+ if (retval != ERROR_OK)
+diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
+index 72e07fb04..1c30975da 100644
+--- a/src/jtag/drivers/cmsis_dap.h
++++ b/src/jtag/drivers/cmsis_dap.h
+@@ -33,6 +33,11 @@ struct cmsis_dap {
+ uint8_t *command;
+ uint8_t *response;
+
++ /* DAP register r/w operation counters used for checking the packet size
++ * that would result from the queue run */
++ unsigned int write_count;
++ unsigned int read_count;
++
+ /* Pending requests are organized as a FIFO - circular buffer */
+ struct pending_request_block pending_fifo[MAX_PENDING_REQUESTS];
+ unsigned int packet_count;
new file mode 100644
@@ -0,0 +1,239 @@
+From 630cb5ea4d65edba42d1c77fa17d9fe78f7b38c2 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Tue, 22 Nov 2022 12:29:52 +0100
+Subject: [PATCH] jtag/drivers/cmsis_dap: speed up long transfers using
+ DAP_TransferBlock
+
+DAP_TransferBlock command saves n - 3 bytes in comparison to DAP_Transfer,
+where n is number of transfers.
+
+Use DAP_TransferBlock optionaly to save some USB bandwidth.
+
+The change increases the speed of the write transfer
+from 40 KiB/s to 42 KiB/s @ USB FS, adapter speed 1000.
+
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Change-Id: Ifde0159cfd44481d2b81b90daa088e731c03e26d
+Reviewed-on: https://review.openocd.org/c/openocd/+/7372
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/cmsis_dap.c | 96 ++++++++++++++++++++++++++++--------
+ src/jtag/drivers/cmsis_dap.h | 9 +++-
+ 2 files changed, 83 insertions(+), 22 deletions(-)
+
+diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
+index 10e663862..d2c30cc79 100644
+--- a/src/jtag/drivers/cmsis_dap.c
++++ b/src/jtag/drivers/cmsis_dap.c
+@@ -160,6 +160,11 @@ static bool swd_mode;
+ #define CMD_DAP_TFER_BLOCK 0x06
+ #define CMD_DAP_TFER_ABORT 0x07
+
++/* DAP_TransferBlock increases the sum of command/response sizes
++ * (due to 16-bit Transfer Count) if used in a small packet.
++ * Prevent using it until we have at least r/w operations. */
++#define CMD_DAP_TFER_BLOCK_MIN_OPS 4
++
+ /* DAP Status Code */
+ #define DAP_OK 0
+ #define DAP_ERROR 0xFF
+@@ -756,8 +761,9 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
+ dap->write_count = 0;
+ dap->read_count = 0;
+
+- LOG_DEBUG_IO("Executing %d queued transactions from FIFO index %u",
+- block->transfer_count, dap->pending_fifo_put_idx);
++ LOG_DEBUG_IO("Executing %d queued transactions from FIFO index %u%s",
++ block->transfer_count, dap->pending_fifo_put_idx,
++ cmsis_dap_handle->swd_cmds_differ ? "" : ", same swd ops");
+
+ if (queued_retval != ERROR_OK) {
+ LOG_DEBUG("Skipping due to previous errors: %d", queued_retval);
+@@ -767,10 +773,21 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
+ if (block->transfer_count == 0)
+ goto skip;
+
+- command[0] = CMD_DAP_TFER;
++ bool block_cmd = !cmsis_dap_handle->swd_cmds_differ
++ && block->transfer_count >= CMD_DAP_TFER_BLOCK_MIN_OPS;
++ block->command = block_cmd ? CMD_DAP_TFER_BLOCK : CMD_DAP_TFER;
++
++ command[0] = block->command;
+ command[1] = 0x00; /* DAP Index */
+- command[2] = block->transfer_count;
+- size_t idx = 3;
++
++ unsigned int idx;
++ if (block_cmd) {
++ h_u16_to_le(&command[2], block->transfer_count);
++ idx = 4; /* The first transfer will store the common DAP register */
++ } else {
++ command[2] = block->transfer_count;
++ idx = 3;
++ }
+
+ for (unsigned int i = 0; i < block->transfer_count; i++) {
+ struct pending_transfer_result *transfer = &(block->transfers[i]);
+@@ -801,7 +818,9 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap)
+ data &= ~CORUNDETECT;
+ }
+
+- command[idx++] = (cmd >> 1) & 0x0f;
++ if (!block_cmd || i == 0)
++ command[idx++] = (cmd >> 1) & 0x0f;
++
+ if (!(cmd & SWD_CMD_RNW)) {
+ h_u32_to_le(&command[idx], data);
+ idx += 4;
+@@ -846,20 +865,28 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
+ }
+
+ uint8_t *resp = dap->response;
+- if (resp[0] != CMD_DAP_TFER) {
++ if (resp[0] != block->command) {
+ LOG_ERROR("CMSIS-DAP command mismatch. Expected 0x%x received 0x%" PRIx8,
+- CMD_DAP_TFER, resp[0]);
++ block->command, resp[0]);
+ queued_retval = ERROR_FAIL;
+ goto skip;
+ }
+
+- unsigned int transfer_count = resp[1];
+- uint8_t ack = resp[2] & 0x07;
+- if (resp[2] & 0x08) {
++ unsigned int transfer_count;
++ unsigned int idx;
++ if (block->command == CMD_DAP_TFER_BLOCK) {
++ transfer_count = le_to_h_u16(&resp[1]);
++ idx = 3;
++ } else {
++ transfer_count = resp[1];
++ idx = 2;
++ }
++ if (resp[idx] & 0x08) {
+ LOG_DEBUG("CMSIS-DAP Protocol Error @ %d (wrong parity)", transfer_count);
+ queued_retval = ERROR_FAIL;
+ goto skip;
+ }
++ uint8_t ack = resp[idx++] & 0x07;
+ if (ack != SWD_ACK_OK) {
+ LOG_DEBUG("SWD ack not OK @ %d %s", transfer_count,
+ ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
+@@ -874,7 +901,7 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms)
+
+ LOG_DEBUG_IO("Received results of %d queued transactions FIFO index %u timeout %i",
+ transfer_count, dap->pending_fifo_get_idx, timeout_ms);
+- unsigned int idx = 3;
++
+ for (unsigned int i = 0; i < transfer_count; i++) {
+ struct pending_transfer_result *transfer = &(block->transfers[i]);
+ if (transfer->cmd & SWD_CMD_RNW) {
+@@ -923,19 +950,30 @@ static int cmsis_dap_swd_run_queue(void)
+ }
+
+ static unsigned int cmsis_dap_tfer_cmd_size(unsigned int write_count,
+- unsigned int read_count)
++ unsigned int read_count, bool block_tfer)
+ {
+- unsigned int size = 3; /* header */
+- size += write_count * (1 + 4); /* DAP register + data */
+- size += read_count; /* DAP register */
++ unsigned int size;
++ if (block_tfer) {
++ size = 5; /* DAP_TransferBlock header */
++ size += write_count * 4; /* data */
++ } else {
++ size = 3; /* DAP_Transfer header */
++ size += write_count * (1 + 4); /* DAP register + data */
++ size += read_count; /* DAP register */
++ }
+ return size;
+ }
+
+ static unsigned int cmsis_dap_tfer_resp_size(unsigned int write_count,
+- unsigned int read_count)
++ unsigned int read_count, bool block_tfer)
+ {
+- unsigned int size = 3; /* header */
+- size += read_count * 4; /* data */
++ unsigned int size;
++ if (block_tfer)
++ size = 4; /* DAP_TransferBlock response header */
++ else
++ size = 3; /* DAP_Transfer response header */
++
++ size += read_count * 4; /* data */
+ return size;
+ }
+
+@@ -947,13 +985,22 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
+
+ unsigned int write_count = cmsis_dap_handle->write_count;
+ unsigned int read_count = cmsis_dap_handle->read_count;
++ bool block_cmd;
++ if (write_count + read_count < CMD_DAP_TFER_BLOCK_MIN_OPS)
++ block_cmd = false;
++ else
++ block_cmd = !cmsis_dap_handle->swd_cmds_differ
++ && cmd == cmsis_dap_handle->common_swd_cmd;
++
+ if (cmd & SWD_CMD_RNW)
+ read_count++;
+ else
+ write_count++;
+
+- unsigned int cmd_size = cmsis_dap_tfer_cmd_size(write_count, read_count);
+- unsigned int resp_size = cmsis_dap_tfer_resp_size(write_count, read_count);
++ unsigned int cmd_size = cmsis_dap_tfer_cmd_size(write_count, read_count,
++ block_cmd);
++ unsigned int resp_size = cmsis_dap_tfer_resp_size(write_count, read_count,
++ block_cmd);
+
+ /* Does the DAP Transfer command and the expected response fit into one packet?
+ * Run the queue also before a targetsel - it cannot be queued */
+@@ -984,6 +1031,13 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
+ struct pending_transfer_result *transfer = &(block->transfers[block->transfer_count]);
+ transfer->data = data;
+ transfer->cmd = cmd;
++ if (block->transfer_count == 0) {
++ cmsis_dap_handle->swd_cmds_differ = false;
++ cmsis_dap_handle->common_swd_cmd = cmd;
++ } else if (cmd != cmsis_dap_handle->common_swd_cmd) {
++ cmsis_dap_handle->swd_cmds_differ = true;
++ }
++
+ if (cmd & SWD_CMD_RNW) {
+ /* Queue a read transaction */
+ transfer->buffer = dst;
+diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h
+index 1c30975da..16885a51d 100644
+--- a/src/jtag/drivers/cmsis_dap.h
++++ b/src/jtag/drivers/cmsis_dap.h
+@@ -21,6 +21,7 @@ struct pending_transfer_result {
+ struct pending_request_block {
+ struct pending_transfer_result *transfers;
+ unsigned int transfer_count;
++ uint8_t command;
+ };
+
+ struct cmsis_dap {
+@@ -33,11 +34,17 @@ struct cmsis_dap {
+ uint8_t *command;
+ uint8_t *response;
+
+- /* DAP register r/w operation counters used for checking the packet size
++ /* DP/AP register r/w operation counters used for checking the packet size
+ * that would result from the queue run */
+ unsigned int write_count;
+ unsigned int read_count;
+
++ /* We can use DAP_TransferBlock only if all SWD operations in the packet
++ * are either all writes or all reads and use the same DP/AP register.
++ * The following variables keep track of it */
++ uint8_t common_swd_cmd;
++ bool swd_cmds_differ;
++
+ /* Pending requests are organized as a FIFO - circular buffer */
+ struct pending_request_block pending_fifo[MAX_PENDING_REQUESTS];
+ unsigned int packet_count;
new file mode 100644
@@ -0,0 +1,34 @@
+From 5292c7eae925d59d6b6c0017b6a4995d39a6e9ee Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Thu, 24 Nov 2022 14:21:59 +0100
+Subject: [PATCH] jtag/drivers/cmsis_dap: prevent conn/discon workaround before
+ line reset
+
+The line reset SWD sequence is used quite often in SWD multidrop mode.
+Prevent the ugly connect/disconnect adapter firmware bug workaround
+to be called before each line reset.
+
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Change-Id: Id85bff075dba9077e4e501e2cdcfd64d5d9d0531
+Reviewed-on: https://review.openocd.org/c/openocd/+/7381
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/cmsis_dap.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
+index d2c30cc79..0c42a7f1e 100644
+--- a/src/jtag/drivers/cmsis_dap.c
++++ b/src/jtag/drivers/cmsis_dap.c
+@@ -1158,7 +1158,9 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq)
+ unsigned int s_len;
+ int retval;
+
+- if ((output_pins & (SWJ_PIN_SRST | SWJ_PIN_TRST)) == (SWJ_PIN_SRST | SWJ_PIN_TRST)) {
++ if (seq != LINE_RESET &&
++ (output_pins & (SWJ_PIN_SRST | SWJ_PIN_TRST))
++ == (SWJ_PIN_SRST | SWJ_PIN_TRST)) {
+ /* Following workaround deasserts reset on most adapters.
+ * Do not reconnect if a reset line is active!
+ * Reconnecting would break connecting under reset. */
new file mode 100644
@@ -0,0 +1,84 @@
+From a3ed12401b1f7d9578fb7da881d3504e07acfc27 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Tue, 29 Nov 2022 00:34:44 +0100
+Subject: [PATCH] tcl/target: enable -rtos hwthread
+
+The rtos hwthread has been merged in 2019 with commit 85ba2dc4c6ab
+("rtos/hwthread: add hardware-thread pseudo rtos").
+During review in patchset 19 the name of the rtos has been changed
+from 'hawt' to 'hwthread'.
+
+Some target config file was already merged ready for hwthread, but
+keeping the relevant lines commented and still reporting the old
+name.
+
+Enable rtos hwtread to the target that were supposed to use it.
+Fix the name of the rtos.
+
+Change-Id: I877862dcdba39f26462bb542bac06d1a5f5f222d
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7384
+Tested-by: jenkins
+---
+ tcl/target/hi3798.cfg | 3 +--
+ tcl/target/hi6220.cfg | 3 +--
+ tcl/target/marvell/88f37x0.cfg | 3 +--
+ tcl/target/xilinx_zynqmp.cfg | 3 +--
+ 4 files changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/tcl/target/hi3798.cfg b/tcl/target/hi3798.cfg
+index 4373962e4..722305dcf 100644
+--- a/tcl/target/hi3798.cfg
++++ b/tcl/target/hi3798.cfg
+@@ -42,8 +42,7 @@ for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
+ #set _command "$_command -defer-examine"
+ set _smp_command "$_smp_command ${_TARGETNAME}$_core"
+ } else {
+- # uncomment when "hawt" rtos is merged
+- # set _command "$_command -rtos hawt"
++ set _command "$_command -rtos hwthread"
+ set _smp_command "target smp ${_TARGETNAME}$_core"
+ }
+
+diff --git a/tcl/target/hi6220.cfg b/tcl/target/hi6220.cfg
+index f5f7fc9a4..5b0389925 100644
+--- a/tcl/target/hi6220.cfg
++++ b/tcl/target/hi6220.cfg
+@@ -49,8 +49,7 @@ for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
+ set _command "$_command -defer-examine"
+ set _smp_command "$_smp_command ${_TARGETNAME}$_core"
+ } else {
+- # uncomment when "hawt" rtos is merged
+- # set _command "$_command -rtos hawt"
++ set _command "$_command -rtos hwthread"
+ set _smp_command "target smp ${_TARGETNAME}$_core"
+ }
+
+diff --git a/tcl/target/marvell/88f37x0.cfg b/tcl/target/marvell/88f37x0.cfg
+index d80f4ef6f..738d22110 100644
+--- a/tcl/target/marvell/88f37x0.cfg
++++ b/tcl/target/marvell/88f37x0.cfg
+@@ -57,8 +57,7 @@ for { set _core 0 } { $_core < $_cores } { incr _core 1 } {
+ set _command "$_command -defer-examine"
+ set _smp_command "$_smp_command ${_TARGETNAME}$_core"
+ } else {
+- # uncomment when "hawt" rtos is merged
+- # set _command "$_command -rtos hawt"
++ set _command "$_command -rtos hwthread"
+ set _smp_command "target smp ${_TARGETNAME}$_core"
+ }
+
+diff --git a/tcl/target/xilinx_zynqmp.cfg b/tcl/target/xilinx_zynqmp.cfg
+index 893372978..9734a1837 100644
+--- a/tcl/target/xilinx_zynqmp.cfg
++++ b/tcl/target/xilinx_zynqmp.cfg
+@@ -86,8 +86,7 @@ for { set _core 0 } { $_core < $_cores } { incr _core } {
+ set _command "$_command -defer-examine"
+ set _smp_command "$_smp_command $_TARGETNAME.$_core"
+ } else {
+- # uncomment when "hawt" rtos is merged
+- #set _command "$_command -rtos hawt"
++ set _command "$_command -rtos hwthread"
+ set _smp_command "target smp $_TARGETNAME.$_core"
+ }
+
new file mode 100644
@@ -0,0 +1,27 @@
+From dbb42ca18d471b6bffddbd441b1da2ffe18d7400 Mon Sep 17 00:00:00 2001
+From: Marc Schink <dev@zapb.de>
+Date: Wed, 7 Dec 2022 13:13:04 +0100
+Subject: [PATCH] flash/nor/stm32l4x: Add revision 'X' and 'C' for
+ STM32U575/585 devices
+
+Change-Id: I4d950dc0a1421036418f2e5c1f0ed8eca86efc1a
+Signed-off-by: Marc Schink <dev@zapb.de>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7390
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/stm32l4x.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
+index 92d511c17..c67dbf75d 100644
+--- a/src/flash/nor/stm32l4x.c
++++ b/src/flash/nor/stm32l4x.c
+@@ -327,6 +327,7 @@ static const struct stm32l4_rev stm32g49_g4axx_revs[] = {
+
+ static const struct stm32l4_rev stm32u57_u58xx_revs[] = {
+ { 0x1000, "A" }, { 0x1001, "Z" }, { 0x1003, "Y" }, { 0x2000, "B" },
++ { 0x2001, "X" }, { 0x3000, "C" },
+ };
+
+ static const struct stm32l4_rev stm32wb1xx_revs[] = {
new file mode 100644
@@ -0,0 +1,43 @@
+From 69571354f4741f791a4a70c68ca082f765f98c88 Mon Sep 17 00:00:00 2001
+From: Marian Buschsieweke <marian.buschsieweke@ovgu.de>
+Date: Wed, 21 Dec 2022 11:00:53 +0100
+Subject: [PATCH] .gitignore: Add .cache and compile_commands.json
+
+Enhancing the editor / IDE experience with the use of the language
+server protocol (lsp) is getting more and more common. The most widely
+used lsp implementation for C/C++ outside of Redmond is clangd.
+
+Clangd uses compile_commands.json, that contains the compiler invocation
+for each compilation unit, to get the required $CFLAGS to successfully
+located header files etc. This is best automatically generated from with
+bear on Makefile based build systems. Hence, there is little value in
+adding it to the git repo.
+
+In addition, clangd generates cache files in the .cache folder. Again,
+there is no reason in tracking it with git.
+
+Change-Id: Ic5165d10aca3a1cc9e9398af9dd2fbf0977608b3
+Signed-off-by: Marian Buschsieweke <marian.buschsieweke@ovgu.de>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7414
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ .gitignore | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/.gitignore b/.gitignore
+index 818bb0cd3..103dad2c7 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -103,3 +103,11 @@ GTAGS
+
+ # checkpatch script files
+ .checkpatch-camelcase.*
++
++# clangd (e.g. for advanced code completion and linting) generates cache files
++# into .cache
++.cache
++
++# A compile_commands.json can be generated using bear and will help tools such
++# as clangd to locate header files and use correct $CFLAGS
++compile_commands.json
new file mode 100644
@@ -0,0 +1,49 @@
+From 7a890a8f256f28b1c8b0dde3b62ab81c7c139d55 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 1 Jan 2023 18:26:53 +0100
+Subject: [PATCH] jtag: parse command options in 'swd newdap'
+
+The same code is currently used for commands 'jtag newtap' and
+'swd newdap' (plus dapdirect versions), but for SWD case the code
+skips the parsing of the command line as not every flag is used.
+This has the drawback that syntax errors get unchecked.
+
+Move the check about the transport so the command line get always
+parsed even when the corresponding flags are not useful.
+
+Change-Id: I596c3beb04e9e8a9ebe6ee68a61395b679d43b3e
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7427
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/jtag/tcl.c | 9 +--------
+ 1 file changed, 1 insertion(+), 8 deletions(-)
+
+diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
+index b1815b79d..fc0d562e2 100644
+--- a/src/jtag/tcl.c
++++ b/src/jtag/tcl.c
+@@ -557,13 +557,6 @@ static int jim_newtap_cmd(struct jim_getopt_info *goi)
+ LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
+ tap->chip, tap->tapname, tap->dotted_name, goi->argc);
+
+- if (!transport_is_jtag()) {
+- /* SWD doesn't require any JTAG tap parameters */
+- tap->enabled = true;
+- jtag_tap_init(tap);
+- return JIM_OK;
+- }
+-
+ /* IEEE specifies that the two LSBs of an IR scan are 01, so make
+ * that the default. The "-ircapture" and "-irmask" options are only
+ * needed to cope with nonstandard TAPs, or to specify more bits.
+@@ -618,7 +611,7 @@ static int jim_newtap_cmd(struct jim_getopt_info *goi)
+ tap->enabled = !tap->disabled_after_reset;
+
+ /* Did all the required option bits get cleared? */
+- if (tap->ir_length != 0) {
++ if (!transport_is_jtag() || tap->ir_length != 0) {
+ jtag_tap_init(tap);
+ return JIM_OK;
+ }
new file mode 100644
@@ -0,0 +1,270 @@
+From cda39f929e65316478f2f41f461b0cbb3338806c Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 1 Jan 2023 19:17:18 +0100
+Subject: [PATCH] jtag: hla: use generic helper for commands 'jtag newtap' 'swd
+ newdap'
+
+The commands 'jtag newtap' and 'swd newdap' have to work either on
+HLA transport and on standard JTAG/SWD. Having a dedicated
+implementation for HLA is a non-sense.
+
+Reuse the generic code jim_jtag_newtap() and drop the files
+hla_tcl.[ch] as they are now empty.
+
+Change-Id: I9dabbdc2a6f338f23b2fd3ed1a4dc3da0200c080
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7428
+Tested-by: jenkins
+---
+ src/jtag/hla/Makefile.am | 4 +-
+ src/jtag/hla/hla_interface.c | 1 -
+ src/jtag/hla/hla_layout.c | 1 -
+ src/jtag/hla/hla_tcl.c | 143 -----------------------------------
+ src/jtag/hla/hla_tcl.h | 17 -----
+ src/jtag/hla/hla_transport.c | 5 +-
+ 6 files changed, 3 insertions(+), 168 deletions(-)
+ delete mode 100644 src/jtag/hla/hla_tcl.c
+ delete mode 100644 src/jtag/hla/hla_tcl.h
+
+diff --git a/src/jtag/hla/Makefile.am b/src/jtag/hla/Makefile.am
+index 41117868a..ea6e11dd6 100644
+--- a/src/jtag/hla/Makefile.am
++++ b/src/jtag/hla/Makefile.am
+@@ -4,10 +4,8 @@ noinst_LTLIBRARIES += %D%/libocdhla.la
+
+ %C%_libocdhla_la_SOURCES = \
+ %D%/hla_transport.c \
+- %D%/hla_tcl.c \
+ %D%/hla_interface.c \
+ %D%/hla_layout.c \
+ %D%/hla_transport.h \
+ %D%/hla_interface.h \
+- %D%/hla_layout.h \
+- %D%/hla_tcl.h
++ %D%/hla_layout.h
+diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c
+index 6198b3db4..f4bfeb1a1 100644
+--- a/src/jtag/hla/hla_interface.c
++++ b/src/jtag/hla/hla_interface.c
+@@ -17,7 +17,6 @@
+ #include <transport/transport.h>
+ #include <helper/time_support.h>
+
+-#include <jtag/hla/hla_tcl.h>
+ #include <jtag/hla/hla_layout.h>
+ #include <jtag/hla/hla_transport.h>
+ #include <jtag/hla/hla_interface.h>
+diff --git a/src/jtag/hla/hla_layout.c b/src/jtag/hla/hla_layout.c
+index a760f0b3c..51671d60a 100644
+--- a/src/jtag/hla/hla_layout.c
++++ b/src/jtag/hla/hla_layout.c
+@@ -18,7 +18,6 @@
+ #include <helper/time_support.h>
+
+ #include <jtag/hla/hla_layout.h>
+-#include <jtag/hla/hla_tcl.h>
+ #include <jtag/hla/hla_transport.h>
+ #include <jtag/hla/hla_interface.h>
+
+diff --git a/src/jtag/hla/hla_tcl.c b/src/jtag/hla/hla_tcl.c
+deleted file mode 100644
+index 328339955..000000000
+--- a/src/jtag/hla/hla_tcl.c
++++ /dev/null
+@@ -1,143 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-
+-/***************************************************************************
+- * Copyright (C) 2011 by Mathias Kuester *
+- * Mathias Kuester <kesmtp@freenet.de> *
+- * *
+- * Copyright (C) 2012 by Spencer Oliver *
+- * spen@spen-soft.co.uk *
+- ***************************************************************************/
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-/* project specific includes */
+-#include <jtag/interface.h>
+-#include <transport/transport.h>
+-#include <helper/time_support.h>
+-
+-static int jim_newtap_expected_id(struct jim_nvp *n, struct jim_getopt_info *goi,
+- struct jtag_tap *tap)
+-{
+- jim_wide w;
+- int e = jim_getopt_wide(goi, &w);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi->interp, "option: %s bad parameter",
+- n->name);
+- return e;
+- }
+-
+- uint32_t *p = realloc(tap->expected_ids,
+- (tap->expected_ids_cnt + 1) * sizeof(uint32_t));
+- if (!p) {
+- Jim_SetResultFormatted(goi->interp, "no memory");
+- return JIM_ERR;
+- }
+-
+- tap->expected_ids = p;
+- tap->expected_ids[tap->expected_ids_cnt++] = w;
+-
+- return JIM_OK;
+-}
+-
+-#define NTAP_OPT_IRLEN 0
+-#define NTAP_OPT_IRMASK 1
+-#define NTAP_OPT_IRCAPTURE 2
+-#define NTAP_OPT_ENABLED 3
+-#define NTAP_OPT_DISABLED 4
+-#define NTAP_OPT_EXPECTED_ID 5
+-#define NTAP_OPT_VERSION 6
+-#define NTAP_OPT_BYPASS 7
+-
+-static int jim_hl_newtap_cmd(struct jim_getopt_info *goi)
+-{
+- struct jtag_tap *tap;
+- int x;
+- int e;
+- struct jim_nvp *n;
+- char *cp;
+- const struct jim_nvp opts[] = {
+- { .name = "-irlen", .value = NTAP_OPT_IRLEN },
+- { .name = "-irmask", .value = NTAP_OPT_IRMASK },
+- { .name = "-ircapture", .value = NTAP_OPT_IRCAPTURE },
+- { .name = "-enable", .value = NTAP_OPT_ENABLED },
+- { .name = "-disable", .value = NTAP_OPT_DISABLED },
+- { .name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID },
+- { .name = "-ignore-version", .value = NTAP_OPT_VERSION },
+- { .name = "-ignore-bypass", .value = NTAP_OPT_BYPASS },
+- { .name = NULL, .value = -1},
+- };
+-
+- tap = calloc(1, sizeof(struct jtag_tap));
+- if (!tap) {
+- Jim_SetResultFormatted(goi->interp, "no memory");
+- return JIM_ERR;
+- }
+-
+- /*
+- * we expect CHIP + TAP + OPTIONS
+- * */
+- if (goi->argc < 3) {
+- Jim_SetResultFormatted(goi->interp,
+- "Missing CHIP TAP OPTIONS ....");
+- free(tap);
+- return JIM_ERR;
+- }
+-
+- const char *tmp;
+- jim_getopt_string(goi, &tmp, NULL);
+- tap->chip = strdup(tmp);
+-
+- jim_getopt_string(goi, &tmp, NULL);
+- tap->tapname = strdup(tmp);
+-
+- /* name + dot + name + null */
+- x = strlen(tap->chip) + 1 + strlen(tap->tapname) + 1;
+- cp = malloc(x);
+- sprintf(cp, "%s.%s", tap->chip, tap->tapname);
+- tap->dotted_name = cp;
+-
+- LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
+- tap->chip, tap->tapname, tap->dotted_name, goi->argc);
+-
+- while (goi->argc) {
+- e = jim_getopt_nvp(goi, opts, &n);
+- if (e != JIM_OK) {
+- jim_getopt_nvp_unknown(goi, opts, 0);
+- free(cp);
+- free(tap);
+- return e;
+- }
+- LOG_DEBUG("Processing option: %s", n->name);
+- switch (n->value) {
+- case NTAP_OPT_EXPECTED_ID:
+- e = jim_newtap_expected_id(n, goi, tap);
+- if (e != JIM_OK) {
+- free(cp);
+- free(tap);
+- return e;
+- }
+- break;
+- case NTAP_OPT_IRLEN:
+- case NTAP_OPT_IRMASK:
+- case NTAP_OPT_IRCAPTURE:
+- /* dummy read to ignore the next argument */
+- jim_getopt_wide(goi, NULL);
+- break;
+- } /* switch (n->value) */
+- } /* while (goi->argc) */
+-
+- /* default is enabled-after-reset */
+- tap->enabled = !tap->disabled_after_reset;
+-
+- jtag_tap_init(tap);
+- return JIM_OK;
+-}
+-
+-int jim_hl_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+-{
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+- return jim_hl_newtap_cmd(&goi);
+-}
+diff --git a/src/jtag/hla/hla_tcl.h b/src/jtag/hla/hla_tcl.h
+deleted file mode 100644
+index b028e4b50..000000000
+--- a/src/jtag/hla/hla_tcl.h
++++ /dev/null
+@@ -1,17 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright (C) 2011 by Mathias Kuester *
+- * Mathias Kuester <kesmtp@freenet.de> *
+- * *
+- * Copyright (C) 2012 by Spencer Oliver *
+- * spen@spen-soft.co.uk *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_JTAG_HLA_HLA_TCL_H
+-#define OPENOCD_JTAG_HLA_HLA_TCL_H
+-
+-/** */
+-int jim_hl_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv);
+-
+-#endif /* OPENOCD_JTAG_HLA_HLA_TCL_H */
+diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c
+index 91228bed2..004e9f0c5 100644
+--- a/src/jtag/hla/hla_transport.c
++++ b/src/jtag/hla/hla_transport.c
+@@ -18,7 +18,6 @@
+ #include <transport/transport.h>
+ #include <helper/time_support.h>
+ #include <target/target.h>
+-#include <jtag/hla/hla_tcl.h>
+ #include <jtag/hla/hla_transport.h>
+ #include <jtag/hla/hla_interface.h>
+
+@@ -38,7 +37,7 @@ static const struct command_registration hl_swd_transport_subcommand_handlers[]
+ {
+ .name = "newdap",
+ .mode = COMMAND_CONFIG,
+- .jim_handler = jim_hl_newtap,
++ .jim_handler = jim_jtag_newtap,
+ .help = "declare a new SWD DAP",
+ },
+ COMMAND_REGISTRATION_DONE
+@@ -59,7 +58,7 @@ static const struct command_registration hl_transport_jtag_subcommand_handlers[]
+ {
+ .name = "newtap",
+ .mode = COMMAND_CONFIG,
+- .jim_handler = jim_hl_newtap,
++ .jim_handler = jim_jtag_newtap,
+ .help = "Create a new TAP instance named basename.tap_type, "
+ "and appends it to the scan chain.",
+ .usage = "basename tap_type '-irlen' count "
new file mode 100644
@@ -0,0 +1,40 @@
+From 92dd917f5a2af4470b151adc3492f9b3c68caaa9 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sun, 4 Sep 2022 14:18:26 +0200
+Subject: [PATCH] flash/nor/psoc4: drop jtag_poll_mask() from flash write
+
+Polling the target makes no harm during PSoC 4 flash write in the current
+OpenOCD code. Don't mask it.
+
+Change-Id: I6625ded0162ee3a96b92188844d0d2d6c30101c2
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7162
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/psoc4.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/src/flash/nor/psoc4.c b/src/flash/nor/psoc4.c
+index c935bd5f2..fb462c1e5 100644
+--- a/src/flash/nor/psoc4.c
++++ b/src/flash/nor/psoc4.c
+@@ -651,9 +651,6 @@ static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
+ if (row_offset)
+ memset(row_buffer, bank->default_padded_value, row_offset);
+
+- /* Mask automatic polling triggered by execution of halted events */
+- bool save_poll_mask = jtag_poll_mask();
+-
+ while (count) {
+ uint32_t chunk_size = psoc4_info->row_size - row_offset;
+ if (chunk_size > count) {
+@@ -693,8 +690,6 @@ static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
+ }
+
+ cleanup:
+- jtag_poll_unmask(save_poll_mask);
+-
+ free(sysrq_buffer);
+ return retval;
+ }
new file mode 100644
@@ -0,0 +1,216 @@
+From 6e67f1473af15adc7c4052cee27ad84883b286d4 Mon Sep 17 00:00:00 2001
+From: Marian Buschsieweke <marian.buschsieweke@ovgu.de>
+Date: Thu, 22 Dec 2022 13:20:07 +0100
+Subject: [PATCH] helper: Add generic little endian CRC32 function
+
+This generalizes the little endian CRC32 function used in the OR1K
+target and moves it to a common helper, so that other places do not need
+to reinvent the wheel. It is directly used in the OR1K target.
+
+Change-Id: I0e55340281a5bfd80669bb1994f3a96fecc1248a
+Signed-off-by: Marian Buschsieweke <marian.buschsieweke@ovgu.de>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7415
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/helper/Makefile.am | 2 ++
+ src/helper/crc32.c | 50 +++++++++++++++++++++++++++++++
+ src/helper/crc32.h | 37 +++++++++++++++++++++++
+ src/target/openrisc/or1k_du_adv.c | 34 ++++-----------------
+ 4 files changed, 95 insertions(+), 28 deletions(-)
+ create mode 100644 src/helper/crc32.c
+ create mode 100644 src/helper/crc32.h
+
+diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am
+index 7354f5422..c4c60d96b 100644
+--- a/src/helper/Makefile.am
++++ b/src/helper/Makefile.am
+@@ -9,6 +9,7 @@ noinst_LTLIBRARIES += %D%/libhelper.la
+ %D%/configuration.c \
+ %D%/log.c \
+ %D%/command.c \
++ %D%/crc32.c \
+ %D%/time_support.c \
+ %D%/replacements.c \
+ %D%/fileio.c \
+@@ -24,6 +25,7 @@ noinst_LTLIBRARIES += %D%/libhelper.la
+ %D%/types.h \
+ %D%/log.h \
+ %D%/command.h \
++ %D%/crc32.h \
+ %D%/time_support.h \
+ %D%/replacements.h \
+ %D%/fileio.h \
+diff --git a/src/helper/crc32.c b/src/helper/crc32.c
+new file mode 100644
+index 000000000..441a46c57
+--- /dev/null
++++ b/src/helper/crc32.c
+@@ -0,0 +1,50 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++/***************************************************************************
++ * Copyright (C) 2013-2014 by Franck Jullien *
++ * elec4fun@gmail.com *
++ * *
++ * Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg *
++ * marian.buschsieweke@ovgu.de *
++ ***************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include "crc32.h"
++#include <stdint.h>
++#include <stddef.h>
++
++static uint32_t crc_le_step(uint32_t poly, uint32_t crc, uint32_t data_in,
++ unsigned int data_bits)
++{
++ for (unsigned int i = 0; i < data_bits; i++) {
++ uint32_t d, c;
++ d = ((data_in >> i) & 0x1) ? 0xffffffff : 0;
++ c = (crc & 0x1) ? 0xffffffff : 0;
++ crc = crc >> 1;
++ crc = crc ^ ((d ^ c) & poly);
++ }
++
++ return crc;
++}
++
++uint32_t crc32_le(uint32_t poly, uint32_t seed, const void *_data,
++ size_t data_len)
++{
++ if (((uintptr_t)_data & 0x3) || (data_len & 0x3)) {
++ /* data is unaligned, processing data one byte at a time */
++ const uint8_t *data = _data;
++ for (size_t i = 0; i < data_len; i++)
++ seed = crc_le_step(poly, seed, data[i], 8);
++ } else {
++ /* data is aligned, processing 32 bit at a time */
++ data_len >>= 2;
++ const uint32_t *data = _data;
++ for (size_t i = 0; i < data_len; i++)
++ seed = crc_le_step(poly, seed, data[i], 32);
++ }
++
++ return seed;
++}
+diff --git a/src/helper/crc32.h b/src/helper/crc32.h
+new file mode 100644
+index 000000000..8f077863a
+--- /dev/null
++++ b/src/helper/crc32.h
+@@ -0,0 +1,37 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++/***************************************************************************
++ * Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg *
++ * marian.buschsieweke@ovgu.de *
++ ***************************************************************************/
++
++#ifndef OPENOCD_HELPER_CRC32_H
++#define OPENOCD_HELPER_CRC32_H
++
++#include <stdint.h>
++#include <stddef.h>
++
++/** @file
++ * A generic CRC32 implementation
++ */
++
++/**
++ * CRC32 polynomial commonly used for little endian CRC32
++ */
++#define CRC32_POLY_LE 0xedb88320
++
++/**
++ * Calculate the CRC32 value of the given data
++ * @param poly The polynomial of the CRC
++ * @param seed The seed to use (mostly either `0` or `0xffffffff`)
++ * @param data The data to calculate the CRC32 of
++ * @param data_len The length of the data in @p data in bytes
++ * @return The CRC value of the first @p data_len bytes at @p data
++ * @note This function can be used to incrementally compute the CRC one
++ * chunk of data at a time by using the CRC32 of the previous chunk
++ * as @p seed for the next chunk.
++ */
++uint32_t crc32_le(uint32_t poly, uint32_t seed, const void *data,
++ size_t data_len);
++
++#endif /* OPENOCD_HELPER_CRC32_H */
+diff --git a/src/target/openrisc/or1k_du_adv.c b/src/target/openrisc/or1k_du_adv.c
+index e4c89e5b5..e4003a213 100644
+--- a/src/target/openrisc/or1k_du_adv.c
++++ b/src/target/openrisc/or1k_du_adv.c
+@@ -22,8 +22,9 @@
+ #include "or1k_du.h"
+ #include "jsp_server.h"
+
+-#include <target/target.h>
++#include <helper/crc32.h>
+ #include <jtag/jtag.h>
++#include <target/target.h>
+
+ #define JSP_BANNER "\n\r" \
+ "******************************\n\r" \
+@@ -67,13 +68,6 @@
+ #define DBG_CPU_CR_STALL 0x01
+ #define DBG_CPU_CR_RESET 0x02
+
+-/* Polynomial for the CRC calculation
+- * Yes, it's backwards. Yes, this is on purpose.
+- * The hardware is designed this way to save on logic and routing,
+- * and it's really all the same to us here.
+- */
+-#define ADBG_CRC_POLY 0xedb88320
+-
+ /* These are for the internal registers in the Wishbone module
+ * The first is the length of the index register,
+ * the indexes of the various registers are defined after that.
+@@ -133,20 +127,6 @@ static struct or1k_du or1k_du_adv;
+
+ static const char * const chain_name[] = {"WISHBONE", "CPU0", "CPU1", "JSP"};
+
+-static uint32_t adbg_compute_crc(uint32_t crc, uint32_t data_in,
+- int length_bits)
+-{
+- for (int i = 0; i < length_bits; i++) {
+- uint32_t d, c;
+- d = ((data_in >> i) & 0x1) ? 0xffffffff : 0;
+- c = (crc & 0x1) ? 0xffffffff : 0;
+- crc = crc >> 1;
+- crc = crc ^ ((d ^ c) & ADBG_CRC_POLY);
+- }
+-
+- return crc;
+-}
+-
+ static int find_status_bit(void *_buf, int len)
+ {
+ int i = 0;
+@@ -522,9 +502,8 @@ retry_read_full:
+ memcpy(data, in_buffer, total_size_bytes);
+ memcpy(&crc_read, &in_buffer[total_size_bytes], 4);
+
+- uint32_t crc_calc = 0xffffffff;
+- for (int i = 0; i < total_size_bytes; i++)
+- crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
++ uint32_t crc_calc = crc32_le(CRC32_POLY_LE, 0xffffffff, data,
++ total_size_bytes);
+
+ if (crc_calc != crc_read) {
+ LOG_WARNING("CRC ERROR! Computed 0x%08" PRIx32 ", read CRC 0x%08" PRIx32, crc_calc, crc_read);
+@@ -650,9 +629,8 @@ retry_full_write:
+ field[0].out_value = &value;
+ field[0].in_value = NULL;
+
+- uint32_t crc_calc = 0xffffffff;
+- for (int i = 0; i < (count * size); i++)
+- crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
++ uint32_t crc_calc = crc32_le(CRC32_POLY_LE, 0xffffffff, data,
++ count * size);
+
+ field[1].num_bits = count * size * 8;
+ field[1].out_value = data;
new file mode 100644
@@ -0,0 +1,44 @@
+From bc3c07b1768df878d04aa7cc8e9187e90cd93821 Mon Sep 17 00:00:00 2001
+From: Andreas Fritiofson <andreas.fritiofson@gmail.com>
+Date: Wed, 18 Jan 2023 09:23:32 +0100
+Subject: [PATCH] stm32f3x: Allow overriding the flash bank size
+
+Same mechanism as in stm32f1x.cfg reused here.
+
+Change-Id: I81f02feb2b655e8259341b22180f3a8b82e28d05
+Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7438
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ tcl/target/stm32f3x.cfg | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/tcl/target/stm32f3x.cfg b/tcl/target/stm32f3x.cfg
+index 4ecc7eda3..aa978d9c8 100644
+--- a/tcl/target/stm32f3x.cfg
++++ b/tcl/target/stm32f3x.cfg
+@@ -24,6 +24,14 @@ if { [info exists WORKAREASIZE] } {
+ set _WORKAREASIZE 0x4000
+ }
+
++# Allow overriding the Flash bank size
++if { [info exists FLASH_SIZE] } {
++ set _FLASH_SIZE $FLASH_SIZE
++} else {
++ # autodetect size
++ set _FLASH_SIZE 0
++}
++
+ # JTAG speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz
+ #
+ # Since we may be running of an RC oscilator, we crank down the speed a
+@@ -63,7 +71,7 @@ target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
+ $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
+
+ set _FLASHNAME $_CHIPNAME.flash
+-flash bank $_FLASHNAME stm32f1x 0 0 0 0 $_TARGETNAME
++flash bank $_FLASHNAME stm32f1x 0 $_FLASH_SIZE 0 0 $_TARGETNAME
+
+ reset_config srst_nogate
+
new file mode 100644
@@ -0,0 +1,30 @@
+From 98d816ff772ffb45b1f4fbba06cb48b30ca7d98f Mon Sep 17 00:00:00 2001
+From: N S <nlshipp@yahoo.com>
+Date: Wed, 18 Jan 2023 21:58:43 -0800
+Subject: [PATCH] doc: fix broken link to IgnoreHardwareSerialNumber in
+ README.Windows
+
+ URL for Microsoft documentation on IgnoreHardwareSerialNumber
+ redirects to generic USB driver landing page instead of specific
+ article. Update link to go to correct page.
+
+Signed-off-by: N S <nlshipp@yahoo.com>
+Change-Id: Ifac6c730a1438242cdfe0a0a2867e043e03ceec7
+Reviewed-on: https://review.openocd.org/c/openocd/+/7439
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ README.Windows | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/README.Windows b/README.Windows
+index 7326a356c..64bf5c0c6 100644
+--- a/README.Windows
++++ b/README.Windows
+@@ -52,5 +52,5 @@ port depending on which application to use.
+
+ For more information, see:
+
+- http://msdn.microsoft.com/en-us/library/windows/hardware/jj649944(v=vs.85).aspx
++ https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/usb-device-specific-registry-settings
+ http://www.ftdichip.com/Support/Knowledgebase/index.html?ignorehardwareserialnumber.htm
new file mode 100644
@@ -0,0 +1,185 @@
+From 41231db3f08150145fe7ddde53cd027e72128d4c Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Fri, 20 Jan 2023 18:33:43 +0100
+Subject: [PATCH] doc:usb_adapters: add lsusb dump of esp_usb_jtag
+
+Also, esp_usb_jtag added to the supported driver list of
+"adapter serial" command.
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: Ie65cbf9b44f5de6d7995102d1a281161468f6103
+Reviewed-on: https://review.openocd.org/c/openocd/+/7440
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ doc/openocd.texi | 2 +-
+ .../esp_usb_jtag/303a_1001_esp_usb_jtag.txt | 134 ++++++++++++++++++
+ doc/usb_adapters/readme.txt | 1 +
+ 3 files changed, 136 insertions(+), 1 deletion(-)
+ create mode 100644 doc/usb_adapters/esp_usb_jtag/303a_1001_esp_usb_jtag.txt
+
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index aa1707b7d..b9ad3ff77 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -2480,7 +2480,7 @@ This command is only available if your libusb1 is at least version 1.0.16.
+ Specifies the @var{serial_string} of the adapter to use.
+ If this command is not specified, serial strings are not checked.
+ Only the following adapter drivers use the serial string from this command:
+-arm-jtag-ew, cmsis_dap, ft232r, ftdi, hla (stlink, ti-icdi), jlink, kitprog, opendus,
++arm-jtag-ew, cmsis_dap, esp_usb_jtag, ft232r, ftdi, hla (stlink, ti-icdi), jlink, kitprog, opendus,
+ openjtag, osbdm, presto, rlink, st-link, usb_blaster (ublast2), usbprog, vsllink, xds110.
+ @end deffn
+
+diff --git a/doc/usb_adapters/esp_usb_jtag/303a_1001_esp_usb_jtag.txt b/doc/usb_adapters/esp_usb_jtag/303a_1001_esp_usb_jtag.txt
+new file mode 100644
+index 000000000..8da58e581
+--- /dev/null
++++ b/doc/usb_adapters/esp_usb_jtag/303a_1001_esp_usb_jtag.txt
+@@ -0,0 +1,134 @@
++# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
++
++# Optional comment
++
++Bus 002 Device 035: ID 303a:1001
++Device Descriptor:
++ bLength 18
++ bDescriptorType 1
++ bcdUSB 2.00
++ bDeviceClass 239 Miscellaneous Device
++ bDeviceSubClass 2
++ bDeviceProtocol 1 Interface Association
++ bMaxPacketSize0 64
++ idVendor 0x303a
++ idProduct 0x1001
++ bcdDevice 1.01
++ iManufacturer 1 Espressif
++ iProduct 2 USB JTAG/serial debug unit
++ iSerial 3 7C:DF:A1:A2:8F:38
++ bNumConfigurations 1
++ Configuration Descriptor:
++ bLength 9
++ bDescriptorType 2
++ wTotalLength 0x0062
++ bNumInterfaces 3
++ bConfigurationValue 1
++ iConfiguration 0
++ bmAttributes 0xc0
++ Self Powered
++ MaxPower 500mA
++ Interface Association:
++ bLength 8
++ bDescriptorType 11
++ bFirstInterface 0
++ bInterfaceCount 2
++ bFunctionClass 2 Communications
++ bFunctionSubClass 2 Abstract (modem)
++ bFunctionProtocol 0
++ iFunction 0
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 0
++ bAlternateSetting 0
++ bNumEndpoints 1
++ bInterfaceClass 2 Communications
++ bInterfaceSubClass 2 Abstract (modem)
++ bInterfaceProtocol 0
++ iInterface 0
++ CDC Header:
++ bcdCDC 1.10
++ CDC ACM:
++ bmCapabilities 0x02
++ line coding and serial state
++ CDC Union:
++ bMasterInterface 0
++ bSlaveInterface 1
++ CDC Call Management:
++ bmCapabilities 0x03
++ call management
++ use DataInterface
++ bDataInterface 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x82 EP 2 IN
++ bmAttributes 3
++ Transfer Type Interrupt
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 1
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 10 CDC Data
++ bInterfaceSubClass 2
++ bInterfaceProtocol 0
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x01 EP 1 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x81 EP 1 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Interface Descriptor:
++ bLength 9
++ bDescriptorType 4
++ bInterfaceNumber 2
++ bAlternateSetting 0
++ bNumEndpoints 2
++ bInterfaceClass 255 Vendor Specific Class
++ bInterfaceSubClass 255 Vendor Specific Subclass
++ bInterfaceProtocol 1
++ iInterface 0
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x02 EP 2 OUT
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++ Endpoint Descriptor:
++ bLength 7
++ bDescriptorType 5
++ bEndpointAddress 0x83 EP 3 IN
++ bmAttributes 2
++ Transfer Type Bulk
++ Synch Type None
++ Usage Type Data
++ wMaxPacketSize 0x0040 1x 64 bytes
++ bInterval 1
++Device Status: 0x0001
++ Self Powered
+diff --git a/doc/usb_adapters/readme.txt b/doc/usb_adapters/readme.txt
+index 1d995e99f..19df4cf70 100644
+--- a/doc/usb_adapters/readme.txt
++++ b/doc/usb_adapters/readme.txt
+@@ -15,6 +15,7 @@ OpenOCD gerrit, as explained in HACKING.
+
+ The dumps are organized in subfolders corresponding to OpenOCD drivers:
+ - cmsis_dap;
++- esp_usb_jtag;
+ - ft232r;
+ - ftdi;
+ - icdi;
new file mode 100644
@@ -0,0 +1,204 @@
+From 463df952157227866335e398102abe960ffa4131 Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Wed, 5 Oct 2022 17:59:54 +0200
+Subject: [PATCH] rtos/nuttx: move stacking info to the new nuttx stackings
+ file
+
+Other OSes have separate files to keep stack register offsets.
+Adding them for NuttX as well will provide a clearer way to expand.
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: I1428fefefa199a95431f2073c0279dd7028ad8da
+Reviewed-on: https://review.openocd.org/c/openocd/+/7250
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/rtos/Makefile.am | 2 ++
+ src/rtos/nuttx.c | 58 +-----------------------------
+ src/rtos/rtos_nuttx_stackings.c | 64 +++++++++++++++++++++++++++++++++
+ src/rtos/rtos_nuttx_stackings.h | 11 ++++++
+ 4 files changed, 78 insertions(+), 57 deletions(-)
+ create mode 100644 src/rtos/rtos_nuttx_stackings.c
+ create mode 100644 src/rtos/rtos_nuttx_stackings.h
+
+diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am
+index f00d7194e..fc3ab8b42 100644
+--- a/src/rtos/Makefile.am
++++ b/src/rtos/Makefile.am
+@@ -10,6 +10,7 @@ noinst_LTLIBRARIES += %D%/librtos.la
+ %D%/rtos_mqx_stackings.c \
+ %D%/rtos_ucos_iii_stackings.c \
+ %D%/rtos_riot_stackings.c \
++ %D%/rtos_nuttx_stackings.c \
+ %D%/FreeRTOS.c \
+ %D%/ThreadX.c \
+ %D%/eCos.c \
+@@ -32,4 +33,5 @@ noinst_LTLIBRARIES += %D%/librtos.la
+ %D%/rtos_mqx_stackings.h \
+ %D%/rtos_riot_stackings.h \
+ %D%/rtos_ucos_iii_stackings.h \
++ %D%/rtos_nuttx_stackings.h \
+ %D%/nuttx_header.h
+diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c
+index 87b28c632..993ff84bd 100644
+--- a/src/rtos/nuttx.c
++++ b/src/rtos/nuttx.c
+@@ -21,7 +21,7 @@
+ #include "server/gdb_server.h"
+
+ #include "nuttx_header.h"
+-
++#include "rtos_nuttx_stackings.h"
+
+ int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
+
+@@ -85,62 +85,6 @@ static char *task_state_str[] = {
+ #endif /* CONFIG_PAGING */
+ };
+
+-/* see arch/arm/include/armv7-m/irq_cmnvector.h */
+-static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = {
+- { ARMV7M_R0, 0x28, 32 }, /* r0 */
+- { ARMV7M_R1, 0x2c, 32 }, /* r1 */
+- { ARMV7M_R2, 0x30, 32 }, /* r2 */
+- { ARMV7M_R3, 0x34, 32 }, /* r3 */
+- { ARMV7M_R4, 0x08, 32 }, /* r4 */
+- { ARMV7M_R5, 0x0c, 32 }, /* r5 */
+- { ARMV7M_R6, 0x10, 32 }, /* r6 */
+- { ARMV7M_R7, 0x14, 32 }, /* r7 */
+- { ARMV7M_R8, 0x18, 32 }, /* r8 */
+- { ARMV7M_R9, 0x1c, 32 }, /* r9 */
+- { ARMV7M_R10, 0x20, 32 }, /* r10 */
+- { ARMV7M_R11, 0x24, 32 }, /* r11 */
+- { ARMV7M_R12, 0x38, 32 }, /* r12 */
+- { ARMV7M_R13, 0, 32 }, /* sp */
+- { ARMV7M_R14, 0x3c, 32 }, /* lr */
+- { ARMV7M_PC, 0x40, 32 }, /* pc */
+- { ARMV7M_XPSR, 0x44, 32 }, /* xPSR */
+-};
+-
+-
+-static const struct rtos_register_stacking nuttx_stacking_cortex_m = {
+- .stack_registers_size = 0x48,
+- .stack_growth_direction = -1,
+- .num_output_registers = 17,
+- .register_offsets = nuttx_stack_offsets_cortex_m
+-};
+-
+-static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = {
+- { ARMV7M_R0, 0x6c, 32 }, /* r0 */
+- { ARMV7M_R1, 0x70, 32 }, /* r1 */
+- { ARMV7M_R2, 0x74, 32 }, /* r2 */
+- { ARMV7M_R3, 0x78, 32 }, /* r3 */
+- { ARMV7M_R4, 0x08, 32 }, /* r4 */
+- { ARMV7M_R5, 0x0c, 32 }, /* r5 */
+- { ARMV7M_R6, 0x10, 32 }, /* r6 */
+- { ARMV7M_R7, 0x14, 32 }, /* r7 */
+- { ARMV7M_R8, 0x18, 32 }, /* r8 */
+- { ARMV7M_R9, 0x1c, 32 }, /* r9 */
+- { ARMV7M_R10, 0x20, 32 }, /* r10 */
+- { ARMV7M_R11, 0x24, 32 }, /* r11 */
+- { ARMV7M_R12, 0x7c, 32 }, /* r12 */
+- { ARMV7M_R13, 0, 32 }, /* sp */
+- { ARMV7M_R14, 0x80, 32 }, /* lr */
+- { ARMV7M_PC, 0x84, 32 }, /* pc */
+- { ARMV7M_XPSR, 0x88, 32 }, /* xPSR */
+-};
+-
+-static const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = {
+- .stack_registers_size = 0x8c,
+- .stack_growth_direction = -1,
+- .num_output_registers = 17,
+- .register_offsets = nuttx_stack_offsets_cortex_m_fpu
+-};
+-
+ static int pid_offset = PID;
+ static int state_offset = STATE;
+ static int name_offset = NAME;
+diff --git a/src/rtos/rtos_nuttx_stackings.c b/src/rtos/rtos_nuttx_stackings.c
+new file mode 100644
+index 000000000..cb3a2b9b2
+--- /dev/null
++++ b/src/rtos/rtos_nuttx_stackings.c
+@@ -0,0 +1,64 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include "rtos.h"
++#include "target/armv7m.h"
++#include "rtos_nuttx_stackings.h"
++
++/* see arch/arm/include/armv7-m/irq_cmnvector.h */
++static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = {
++ { ARMV7M_R0, 0x28, 32 }, /* r0 */
++ { ARMV7M_R1, 0x2c, 32 }, /* r1 */
++ { ARMV7M_R2, 0x30, 32 }, /* r2 */
++ { ARMV7M_R3, 0x34, 32 }, /* r3 */
++ { ARMV7M_R4, 0x08, 32 }, /* r4 */
++ { ARMV7M_R5, 0x0c, 32 }, /* r5 */
++ { ARMV7M_R6, 0x10, 32 }, /* r6 */
++ { ARMV7M_R7, 0x14, 32 }, /* r7 */
++ { ARMV7M_R8, 0x18, 32 }, /* r8 */
++ { ARMV7M_R9, 0x1c, 32 }, /* r9 */
++ { ARMV7M_R10, 0x20, 32 }, /* r10 */
++ { ARMV7M_R11, 0x24, 32 }, /* r11 */
++ { ARMV7M_R12, 0x38, 32 }, /* r12 */
++ { ARMV7M_R13, 0, 32 }, /* sp */
++ { ARMV7M_R14, 0x3c, 32 }, /* lr */
++ { ARMV7M_PC, 0x40, 32 }, /* pc */
++ { ARMV7M_XPSR, 0x44, 32 }, /* xPSR */
++};
++
++const struct rtos_register_stacking nuttx_stacking_cortex_m = {
++ .stack_registers_size = 0x48,
++ .stack_growth_direction = -1,
++ .num_output_registers = 17,
++ .register_offsets = nuttx_stack_offsets_cortex_m,
++};
++
++static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = {
++ { ARMV7M_R0, 0x6c, 32 }, /* r0 */
++ { ARMV7M_R1, 0x70, 32 }, /* r1 */
++ { ARMV7M_R2, 0x74, 32 }, /* r2 */
++ { ARMV7M_R3, 0x78, 32 }, /* r3 */
++ { ARMV7M_R4, 0x08, 32 }, /* r4 */
++ { ARMV7M_R5, 0x0c, 32 }, /* r5 */
++ { ARMV7M_R6, 0x10, 32 }, /* r6 */
++ { ARMV7M_R7, 0x14, 32 }, /* r7 */
++ { ARMV7M_R8, 0x18, 32 }, /* r8 */
++ { ARMV7M_R9, 0x1c, 32 }, /* r9 */
++ { ARMV7M_R10, 0x20, 32 }, /* r10 */
++ { ARMV7M_R11, 0x24, 32 }, /* r11 */
++ { ARMV7M_R12, 0x7c, 32 }, /* r12 */
++ { ARMV7M_R13, 0, 32 }, /* sp */
++ { ARMV7M_R14, 0x80, 32 }, /* lr */
++ { ARMV7M_PC, 0x84, 32 }, /* pc */
++ { ARMV7M_XPSR, 0x88, 32 }, /* xPSR */
++};
++
++const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = {
++ .stack_registers_size = 0x8c,
++ .stack_growth_direction = -1,
++ .num_output_registers = 17,
++ .register_offsets = nuttx_stack_offsets_cortex_m_fpu,
++};
+diff --git a/src/rtos/rtos_nuttx_stackings.h b/src/rtos/rtos_nuttx_stackings.h
+new file mode 100644
+index 000000000..bfbc049f8
+--- /dev/null
++++ b/src/rtos/rtos_nuttx_stackings.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++#ifndef INCLUDED_RTOS_NUTTX_STACKINGS_H
++#define INCLUDED_RTOS_NUTTX_STACKINGS_H
++
++#include "rtos.h"
++
++extern const struct rtos_register_stacking nuttx_stacking_cortex_m;
++extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu;
++
++#endif /* INCLUDED_RTOS_NUTTX_STACKINGS_H */
new file mode 100644
@@ -0,0 +1,89 @@
+From dfbbfac4d72e247e8094a49c8573b2f49689b6d5 Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Wed, 5 Oct 2022 18:38:23 +0200
+Subject: [PATCH] rtos/nuttx: add riscv stacking info
+
+Tested with Espressif ESP32-C3 MCU
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: Ia71ace4909f2dc93ddc07a2ec5524cf374f1937c
+Reviewed-on: https://review.openocd.org/c/openocd/+/7251
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/rtos/rtos_nuttx_stackings.c | 46 +++++++++++++++++++++++++++++++++
+ src/rtos/rtos_nuttx_stackings.h | 1 +
+ 2 files changed, 47 insertions(+)
+
+diff --git a/src/rtos/rtos_nuttx_stackings.c b/src/rtos/rtos_nuttx_stackings.c
+index cb3a2b9b2..b59b1356b 100644
+--- a/src/rtos/rtos_nuttx_stackings.c
++++ b/src/rtos/rtos_nuttx_stackings.c
+@@ -7,6 +7,8 @@
+ #include "rtos.h"
+ #include "target/armv7m.h"
+ #include "rtos_nuttx_stackings.h"
++#include "rtos_standard_stackings.h"
++#include <target/riscv/riscv.h>
+
+ /* see arch/arm/include/armv7-m/irq_cmnvector.h */
+ static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = {
+@@ -62,3 +64,47 @@ const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = {
+ .num_output_registers = 17,
+ .register_offsets = nuttx_stack_offsets_cortex_m_fpu,
+ };
++
++static const struct stack_register_offset nuttx_stack_offsets_riscv[] = {
++ { GDB_REGNO_ZERO, -1, 32 },
++ { GDB_REGNO_RA, 0x04, 32 },
++ { GDB_REGNO_SP, 0x08, 32 },
++ { GDB_REGNO_GP, 0x0c, 32 },
++ { GDB_REGNO_TP, 0x10, 32 },
++ { GDB_REGNO_T0, 0x14, 32 },
++ { GDB_REGNO_T1, 0x18, 32 },
++ { GDB_REGNO_T2, 0x1c, 32 },
++ { GDB_REGNO_FP, 0x20, 32 },
++ { GDB_REGNO_S1, 0x24, 32 },
++ { GDB_REGNO_A0, 0x28, 32 },
++ { GDB_REGNO_A1, 0x2c, 32 },
++ { GDB_REGNO_A2, 0x30, 32 },
++ { GDB_REGNO_A3, 0x34, 32 },
++ { GDB_REGNO_A4, 0x38, 32 },
++ { GDB_REGNO_A5, 0x3c, 32 },
++ { GDB_REGNO_A6, 0x40, 32 },
++ { GDB_REGNO_A7, 0x44, 32 },
++ { GDB_REGNO_S2, 0x48, 32 },
++ { GDB_REGNO_S3, 0x4c, 32 },
++ { GDB_REGNO_S4, 0x50, 32 },
++ { GDB_REGNO_S5, 0x54, 32 },
++ { GDB_REGNO_S6, 0x58, 32 },
++ { GDB_REGNO_S7, 0x5c, 32 },
++ { GDB_REGNO_S8, 0x60, 32 },
++ { GDB_REGNO_S9, 0x64, 32 },
++ { GDB_REGNO_S10, 0x68, 32 },
++ { GDB_REGNO_S11, 0x6c, 32 },
++ { GDB_REGNO_T3, 0x70, 32 },
++ { GDB_REGNO_T4, 0x74, 32 },
++ { GDB_REGNO_T5, 0x78, 32 },
++ { GDB_REGNO_T6, 0x7c, 32 },
++ { GDB_REGNO_PC, 0x00, 32 },
++};
++
++const struct rtos_register_stacking nuttx_riscv_stacking = {
++ .stack_registers_size = 33 * 4,
++ .stack_growth_direction = -1,
++ .num_output_registers = 33,
++ .calculate_process_stack = rtos_generic_stack_align8,
++ .register_offsets = nuttx_stack_offsets_riscv,
++};
+diff --git a/src/rtos/rtos_nuttx_stackings.h b/src/rtos/rtos_nuttx_stackings.h
+index bfbc049f8..2e5f09212 100644
+--- a/src/rtos/rtos_nuttx_stackings.h
++++ b/src/rtos/rtos_nuttx_stackings.h
+@@ -7,5 +7,6 @@
+
+ extern const struct rtos_register_stacking nuttx_stacking_cortex_m;
+ extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu;
++extern const struct rtos_register_stacking nuttx_riscv_stacking;
+
+ #endif /* INCLUDED_RTOS_NUTTX_STACKINGS_H */
new file mode 100644
@@ -0,0 +1,52 @@
+From 59bc761d56f9ce9a76c917e267a2c37f1a680611 Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Sat, 21 Jan 2023 20:10:21 +0100
+Subject: [PATCH] rtos: add custom stack read function
+
+This is optional field for the targets which has to implement
+their custom stack read function.
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: Icbc9ed66a052fc2cc0ef67e3ec4d85ab0c2c1b94
+Reviewed-on: https://review.openocd.org/c/openocd/+/7442
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/rtos/rtos.c | 5 ++++-
+ src/rtos/rtos.h | 7 +++++++
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
+index 2e76b501a..dfa158d01 100644
+--- a/src/rtos/rtos.c
++++ b/src/rtos/rtos.c
+@@ -632,7 +632,10 @@ int rtos_generic_stack_read(struct target *target,
+
+ if (stacking->stack_growth_direction == 1)
+ address -= stacking->stack_registers_size;
+- retval = target_read_buffer(target, address, stacking->stack_registers_size, stack_data);
++ if (stacking->read_stack)
++ retval = stacking->read_stack(target, address, stacking, stack_data);
++ else
++ retval = target_read_buffer(target, address, stacking->stack_registers_size, stack_data);
+ if (retval != ERROR_OK) {
+ free(stack_data);
+ LOG_ERROR("Error reading stack frame from thread");
+diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h
+index ace57514a..9128c163c 100644
+--- a/src/rtos/rtos.h
++++ b/src/rtos/rtos.h
+@@ -102,6 +102,13 @@ struct rtos_register_stacking {
+ const struct rtos_register_stacking *stacking,
+ target_addr_t stack_ptr);
+ const struct stack_register_offset *register_offsets;
++ /* Optional field for targets which may have to implement their own stack read function.
++ * Because stack format can be weird or stack data needed to be edited before passing to the gdb.
++ */
++ int (*read_stack)(struct target *target,
++ int64_t stack_ptr,
++ const struct rtos_register_stacking *stacking,
++ uint8_t *stack_data);
+ };
+
+ #define GDB_THREAD_PACKET_NOT_CONSUMED (-40)
new file mode 100644
@@ -0,0 +1,382 @@
+From cf50bcb841238726697dc1250d6b6cb49fc6d19d Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Sat, 21 Jan 2023 20:23:07 +0100
+Subject: [PATCH] rtos/nuttx: add stacking info for Espressif Xtensa chips
+
+ESP32, ESP32-S2 and ESP32-S3 stack register offsets added
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: Ic6215c1d0152853fd08f82cbd3c138c7d62dbc46
+Reviewed-on: https://review.openocd.org/c/openocd/+/7443
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/rtos/rtos_nuttx_stackings.c | 358 ++++++++++++++++++++++++++++++++
+ 1 file changed, 358 insertions(+)
+
+diff --git a/src/rtos/rtos_nuttx_stackings.c b/src/rtos/rtos_nuttx_stackings.c
+index b59b1356b..b70cccb33 100644
+--- a/src/rtos/rtos_nuttx_stackings.c
++++ b/src/rtos/rtos_nuttx_stackings.c
+@@ -108,3 +108,361 @@ const struct rtos_register_stacking nuttx_riscv_stacking = {
+ .calculate_process_stack = rtos_generic_stack_align8,
+ .register_offsets = nuttx_stack_offsets_riscv,
+ };
++
++static int nuttx_esp_xtensa_stack_read(struct target *target,
++ int64_t stack_ptr, const struct rtos_register_stacking *stacking,
++ uint8_t *stack_data)
++{
++ int retval = target_read_buffer(target, stack_ptr, stacking->stack_registers_size, stack_data);
++ if (retval != ERROR_OK)
++ return retval;
++
++ stack_data[4] &= ~0x10; /* Clear exception bit in PS */
++
++ return ERROR_OK;
++}
++
++static const struct stack_register_offset nuttx_stack_offsets_esp32[] = {
++ { 0, 0x00, 32 }, /* PC */
++ { 1, 0x08, 32 }, /* A0 */
++ { 2, 0x0c, 32 }, /* A1 */
++ { 3, 0x10, 32 }, /* A2 */
++ { 4, 0x14, 32 }, /* A3 */
++ { 5, 0x18, 32 }, /* A4 */
++ { 6, 0x1c, 32 }, /* A5 */
++ { 7, 0x20, 32 }, /* A6 */
++ { 8, 0x24, 32 }, /* A7 */
++ { 9, 0x28, 32 }, /* A8 */
++ { 10, 0x2c, 32 }, /* A9 */
++ { 11, 0x30, 32 }, /* A10 */
++ { 12, 0x34, 32 }, /* A11 */
++ { 13, 0x38, 32 }, /* A12 */
++ { 14, 0x3c, 32 }, /* A13 */
++ { 15, 0x40, 32 }, /* A14 */
++ { 16, 0x44, 32 }, /* A15 */
++ /* A16-A63 aren't in the stack frame because they've been flushed to the stack earlier */
++ { 17, -1, 32 }, /* A16 */
++ { 18, -1, 32 }, /* A17 */
++ { 19, -1, 32 }, /* A18 */
++ { 20, -1, 32 }, /* A19 */
++ { 21, -1, 32 }, /* A20 */
++ { 22, -1, 32 }, /* A21 */
++ { 23, -1, 32 }, /* A22 */
++ { 24, -1, 32 }, /* A23 */
++ { 25, -1, 32 }, /* A24 */
++ { 26, -1, 32 }, /* A25 */
++ { 27, -1, 32 }, /* A26 */
++ { 28, -1, 32 }, /* A27 */
++ { 29, -1, 32 }, /* A28 */
++ { 30, -1, 32 }, /* A29 */
++ { 31, -1, 32 }, /* A30 */
++ { 32, -1, 32 }, /* A31 */
++ { 33, -1, 32 }, /* A32 */
++ { 34, -1, 32 }, /* A33 */
++ { 35, -1, 32 }, /* A34 */
++ { 36, -1, 32 }, /* A35 */
++ { 37, -1, 32 }, /* A36 */
++ { 38, -1, 32 }, /* A37 */
++ { 39, -1, 32 }, /* A38 */
++ { 40, -1, 32 }, /* A39 */
++ { 41, -1, 32 }, /* A40 */
++ { 42, -1, 32 }, /* A41 */
++ { 43, -1, 32 }, /* A42 */
++ { 44, -1, 32 }, /* A43 */
++ { 45, -1, 32 }, /* A44 */
++ { 46, -1, 32 }, /* A45 */
++ { 47, -1, 32 }, /* A46 */
++ { 48, -1, 32 }, /* A47 */
++ { 49, -1, 32 }, /* A48 */
++ { 50, -1, 32 }, /* A49 */
++ { 51, -1, 32 }, /* A50 */
++ { 52, -1, 32 }, /* A51 */
++ { 53, -1, 32 }, /* A52 */
++ { 54, -1, 32 }, /* A53 */
++ { 55, -1, 32 }, /* A54 */
++ { 56, -1, 32 }, /* A55 */
++ { 57, -1, 32 }, /* A56 */
++ { 58, -1, 32 }, /* A57 */
++ { 59, -1, 32 }, /* A58 */
++ { 60, -1, 32 }, /* A59 */
++ { 61, -1, 32 }, /* A60 */
++ { 62, -1, 32 }, /* A61 */
++ { 63, -1, 32 }, /* A62 */
++ { 64, -1, 32 }, /* A63 */
++ { 65, 0x58, 32 }, /* lbeg */
++ { 66, 0x5c, 32 }, /* lend */
++ { 67, 0x60, 32 }, /* lcount */
++ { 68, 0x48, 32 }, /* SAR */
++ { 69, -1, 32 }, /* windowbase */
++ { 70, -1, 32 }, /* windowstart */
++ { 71, -1, 32 }, /* configid0 */
++ { 72, -1, 32 }, /* configid1 */
++ { 73, 0x04, 32 }, /* PS */
++ { 74, -1, 32 }, /* threadptr */
++ { 75, -1, 32 }, /* br */
++ { 76, 0x54, 32 }, /* scompare1 */
++ { 77, -1, 32 }, /* acclo */
++ { 78, -1, 32 }, /* acchi */
++ { 79, -1, 32 }, /* m0 */
++ { 80, -1, 32 }, /* m1 */
++ { 81, -1, 32 }, /* m2 */
++ { 82, -1, 32 }, /* m3 */
++ { 83, -1, 32 }, /* expstate */
++ { 84, -1, 32 }, /* f64r_lo */
++ { 85, -1, 32 }, /* f64r_hi */
++ { 86, -1, 32 }, /* f64s */
++ { 87, -1, 32 }, /* f0 */
++ { 88, -1, 32 }, /* f1 */
++ { 89, -1, 32 }, /* f2 */
++ { 90, -1, 32 }, /* f3 */
++ { 91, -1, 32 }, /* f4 */
++ { 92, -1, 32 }, /* f5 */
++ { 93, -1, 32 }, /* f6 */
++ { 94, -1, 32 }, /* f7 */
++ { 95, -1, 32 }, /* f8 */
++ { 96, -1, 32 }, /* f9 */
++ { 97, -1, 32 }, /* f10 */
++ { 98, -1, 32 }, /* f11 */
++ { 99, -1, 32 }, /* f12 */
++ { 100, -1, 32 }, /* f13 */
++ { 101, -1, 32 }, /* f14 */
++ { 102, -1, 32 }, /* f15 */
++ { 103, -1, 32 }, /* fcr */
++ { 104, -1, 32 }, /* fsr */
++};
++
++const struct rtos_register_stacking nuttx_esp32_stacking = {
++ .stack_registers_size = 26 * 4,
++ .stack_growth_direction = -1,
++ .num_output_registers = ARRAY_SIZE(nuttx_stack_offsets_esp32),
++ .calculate_process_stack = rtos_generic_stack_align8,
++ .register_offsets = nuttx_stack_offsets_esp32,
++ .read_stack = nuttx_esp_xtensa_stack_read,
++};
++
++static const struct stack_register_offset nuttx_stack_offsets_esp32s2[] = {
++ { 0, 0x00, 32 }, /* PC */
++ { 1, 0x08, 32 }, /* A0 */
++ { 2, 0x0c, 32 }, /* A1 */
++ { 3, 0x10, 32 }, /* A2 */
++ { 4, 0x14, 32 }, /* A3 */
++ { 5, 0x18, 32 }, /* A4 */
++ { 6, 0x1c, 32 }, /* A5 */
++ { 7, 0x20, 32 }, /* A6 */
++ { 8, 0x24, 32 }, /* A7 */
++ { 9, 0x28, 32 }, /* A8 */
++ { 10, 0x2c, 32 }, /* A9 */
++ { 11, 0x30, 32 }, /* A10 */
++ { 12, 0x34, 32 }, /* A11 */
++ { 13, 0x38, 32 }, /* A12 */
++ { 14, 0x3c, 32 }, /* A13 */
++ { 15, 0x40, 32 }, /* A14 */
++ { 16, 0x44, 32 }, /* A15 */
++ /* A16-A63 aren't in the stack frame because they've been flushed to the stack earlier */
++ { 17, -1, 32 }, /* A16 */
++ { 18, -1, 32 }, /* A17 */
++ { 19, -1, 32 }, /* A18 */
++ { 20, -1, 32 }, /* A19 */
++ { 21, -1, 32 }, /* A20 */
++ { 22, -1, 32 }, /* A21 */
++ { 23, -1, 32 }, /* A22 */
++ { 24, -1, 32 }, /* A23 */
++ { 25, -1, 32 }, /* A24 */
++ { 26, -1, 32 }, /* A25 */
++ { 27, -1, 32 }, /* A26 */
++ { 28, -1, 32 }, /* A27 */
++ { 29, -1, 32 }, /* A28 */
++ { 30, -1, 32 }, /* A29 */
++ { 31, -1, 32 }, /* A30 */
++ { 32, -1, 32 }, /* A31 */
++ { 33, -1, 32 }, /* A32 */
++ { 34, -1, 32 }, /* A33 */
++ { 35, -1, 32 }, /* A34 */
++ { 36, -1, 32 }, /* A35 */
++ { 37, -1, 32 }, /* A36 */
++ { 38, -1, 32 }, /* A37 */
++ { 39, -1, 32 }, /* A38 */
++ { 40, -1, 32 }, /* A39 */
++ { 41, -1, 32 }, /* A40 */
++ { 42, -1, 32 }, /* A41 */
++ { 43, -1, 32 }, /* A42 */
++ { 44, -1, 32 }, /* A43 */
++ { 45, -1, 32 }, /* A44 */
++ { 46, -1, 32 }, /* A45 */
++ { 47, -1, 32 }, /* A46 */
++ { 48, -1, 32 }, /* A47 */
++ { 49, -1, 32 }, /* A48 */
++ { 50, -1, 32 }, /* A49 */
++ { 51, -1, 32 }, /* A50 */
++ { 52, -1, 32 }, /* A51 */
++ { 53, -1, 32 }, /* A52 */
++ { 54, -1, 32 }, /* A53 */
++ { 55, -1, 32 }, /* A54 */
++ { 56, -1, 32 }, /* A55 */
++ { 57, -1, 32 }, /* A56 */
++ { 58, -1, 32 }, /* A57 */
++ { 59, -1, 32 }, /* A58 */
++ { 60, -1, 32 }, /* A59 */
++ { 61, -1, 32 }, /* A60 */
++ { 62, -1, 32 }, /* A61 */
++ { 63, -1, 32 }, /* A62 */
++ { 64, -1, 32 }, /* A63 */
++ { 65, 0x48, 32 }, /* SAR */
++ { 66, -1, 32 }, /* windowbase */
++ { 67, -1, 32 }, /* windowstart */
++ { 68, -1, 32 }, /* configid0 */
++ { 69, -1, 32 }, /* configid1 */
++ { 70, 0x04, 32 }, /* PS */
++ { 71, -1, 32 }, /* threadptr */
++ { 72, -1, 32 }, /* gpio_out */
++};
++
++const struct rtos_register_stacking nuttx_esp32s2_stacking = {
++ .stack_registers_size = 25 * 4,
++ .stack_growth_direction = -1,
++ .num_output_registers = ARRAY_SIZE(nuttx_stack_offsets_esp32s2),
++ .calculate_process_stack = rtos_generic_stack_align8,
++ .register_offsets = nuttx_stack_offsets_esp32s2,
++ .read_stack = nuttx_esp_xtensa_stack_read,
++};
++
++static const struct stack_register_offset nuttx_stack_offsets_esp32s3[] = {
++ { 0, 0x00, 32 }, /* PC */
++ { 1, 0x08, 32 }, /* A0 */
++ { 2, 0x0c, 32 }, /* A1 */
++ { 3, 0x10, 32 }, /* A2 */
++ { 4, 0x14, 32 }, /* A3 */
++ { 5, 0x18, 32 }, /* A4 */
++ { 6, 0x1c, 32 }, /* A5 */
++ { 7, 0x20, 32 }, /* A6 */
++ { 8, 0x24, 32 }, /* A7 */
++ { 9, 0x28, 32 }, /* A8 */
++ { 10, 0x2c, 32 }, /* A9 */
++ { 11, 0x30, 32 }, /* A10 */
++ { 12, 0x34, 32 }, /* A11 */
++ { 13, 0x38, 32 }, /* A12 */
++ { 14, 0x3c, 32 }, /* A13 */
++ { 15, 0x40, 32 }, /* A14 */
++ { 16, 0x44, 32 }, /* A15 */
++ /* A16-A63 aren't in the stack frame because they've been flushed to the stack earlier */
++ { 17, -1, 32 }, /* A16 */
++ { 18, -1, 32 }, /* A17 */
++ { 19, -1, 32 }, /* A18 */
++ { 20, -1, 32 }, /* A19 */
++ { 21, -1, 32 }, /* A20 */
++ { 22, -1, 32 }, /* A21 */
++ { 23, -1, 32 }, /* A22 */
++ { 24, -1, 32 }, /* A23 */
++ { 25, -1, 32 }, /* A24 */
++ { 26, -1, 32 }, /* A25 */
++ { 27, -1, 32 }, /* A26 */
++ { 28, -1, 32 }, /* A27 */
++ { 29, -1, 32 }, /* A28 */
++ { 30, -1, 32 }, /* A29 */
++ { 31, -1, 32 }, /* A30 */
++ { 32, -1, 32 }, /* A31 */
++ { 33, -1, 32 }, /* A32 */
++ { 34, -1, 32 }, /* A33 */
++ { 35, -1, 32 }, /* A34 */
++ { 36, -1, 32 }, /* A35 */
++ { 37, -1, 32 }, /* A36 */
++ { 38, -1, 32 }, /* A37 */
++ { 39, -1, 32 }, /* A38 */
++ { 40, -1, 32 }, /* A39 */
++ { 41, -1, 32 }, /* A40 */
++ { 42, -1, 32 }, /* A41 */
++ { 43, -1, 32 }, /* A42 */
++ { 44, -1, 32 }, /* A43 */
++ { 45, -1, 32 }, /* A44 */
++ { 46, -1, 32 }, /* A45 */
++ { 47, -1, 32 }, /* A46 */
++ { 48, -1, 32 }, /* A47 */
++ { 49, -1, 32 }, /* A48 */
++ { 50, -1, 32 }, /* A49 */
++ { 51, -1, 32 }, /* A50 */
++ { 52, -1, 32 }, /* A51 */
++ { 53, -1, 32 }, /* A52 */
++ { 54, -1, 32 }, /* A53 */
++ { 55, -1, 32 }, /* A54 */
++ { 56, -1, 32 }, /* A55 */
++ { 57, -1, 32 }, /* A56 */
++ { 58, -1, 32 }, /* A57 */
++ { 59, -1, 32 }, /* A58 */
++ { 60, -1, 32 }, /* A59 */
++ { 61, -1, 32 }, /* A60 */
++ { 62, -1, 32 }, /* A61 */
++ { 63, -1, 32 }, /* A62 */
++ { 64, -1, 32 }, /* A63 */
++ { 65, 0x58, 32 }, /* lbeg */
++ { 66, 0x5c, 32 }, /* lend */
++ { 67, 0x60, 32 }, /* lcount */
++ { 68, 0x48, 32 }, /* SAR */
++ { 69, -1, 32 }, /* windowbase */
++ { 70, -1, 32 }, /* windowstart */
++ { 71, -1, 32 }, /* configid0 */
++ { 72, -1, 32 }, /* configid1 */
++ { 73, 0x04, 32 }, /* PS */
++ { 74, -1, 32 }, /* threadptr */
++ { 75, -1, 32 }, /* br */
++ { 76, 0x54, 32 }, /* scompare1 */
++ { 77, -1, 32 }, /* acclo */
++ { 78, -1, 32 }, /* acchi */
++ { 79, -1, 32 }, /* m0 */
++ { 80, -1, 32 }, /* m1 */
++ { 81, -1, 32 }, /* m2 */
++ { 82, -1, 32 }, /* m3 */
++ { 83, -1, 32 }, /* gpio_out */
++ { 84, -1, 32 }, /* f0 */
++ { 85, -1, 32 }, /* f1 */
++ { 86, -1, 32 }, /* f2 */
++ { 87, -1, 32 }, /* f3 */
++ { 88, -1, 32 }, /* f4 */
++ { 89, -1, 32 }, /* f5 */
++ { 90, -1, 32 }, /* f6 */
++ { 91, -1, 32 }, /* f7 */
++ { 92, -1, 32 }, /* f8 */
++ { 93, -1, 32 }, /* f9 */
++ { 94, -1, 32 }, /* f10 */
++ { 95, -1, 32 }, /* f11 */
++ { 96, -1, 32 }, /* f12 */
++ { 97, -1, 32 }, /* f13 */
++ { 98, -1, 32 }, /* f14 */
++ { 99, -1, 32 }, /* f15 */
++ { 100, -1, 32 }, /* fcr */
++ { 101, -1, 32 }, /* fsr */
++ { 102, -1, 32 }, /* accx_0 */
++ { 103, -1, 32 }, /* accx_1 */
++ { 104, -1, 32 }, /* qacc_h_0 */
++ { 105, -1, 32 }, /* qacc_h_1 */
++ { 106, -1, 32 }, /* qacc_h_2 */
++ { 107, -1, 32 }, /* qacc_h_3 */
++ { 108, -1, 32 }, /* qacc_h_4 */
++ { 109, -1, 32 }, /* qacc_l_0 */
++ { 110, -1, 32 }, /* qacc_l_1 */
++ { 111, -1, 32 }, /* qacc_l_2 */
++ { 112, -1, 32 }, /* qacc_l_3 */
++ { 113, -1, 32 }, /* qacc_l_4 */
++ { 114, -1, 32 }, /* sar_byte */
++ { 115, -1, 32 }, /* fft_bit_width */
++ { 116, -1, 32 }, /* ua_state_0 */
++ { 117, -1, 32 }, /* ua_state_1 */
++ { 118, -1, 32 }, /* ua_state_2 */
++ { 119, -1, 32 }, /* ua_state_3 */
++ { 120, -1, 128 }, /* q0 */
++ { 121, -1, 128 }, /* q1 */
++ { 122, -1, 128 }, /* q2 */
++ { 123, -1, 128 }, /* q3 */
++ { 124, -1, 128 }, /* q4 */
++ { 125, -1, 128 }, /* q5 */
++ { 126, -1, 128 }, /* q6 */
++ { 127, -1, 128 }, /* q7 */
++};
++
++const struct rtos_register_stacking nuttx_esp32s3_stacking = {
++ .stack_registers_size = 26 * 4,
++ .stack_growth_direction = -1,
++ .num_output_registers = ARRAY_SIZE(nuttx_stack_offsets_esp32s3),
++ .calculate_process_stack = rtos_generic_stack_align8,
++ .register_offsets = nuttx_stack_offsets_esp32s3,
++ .read_stack = nuttx_esp_xtensa_stack_read,
++};
new file mode 100644
@@ -0,0 +1,473 @@
+From 43c8aa28cb1570c11e1099c43e685af228190679 Mon Sep 17 00:00:00 2001
+From: Andreas Fritiofson <andreas.fritiofson@gmail.com>
+Date: Fri, 15 Apr 2016 12:38:43 +0200
+Subject: [PATCH] rtos: Support rt-kernel
+
+Works for the proprietary rt-kernel from rt-labs.
+
+See: https://rt-labs.com/product/rt-kernel/
+Change-Id: Id2c2e292c15fb17eab25e3d07db05014daa2a2b0
+Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/6668
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ doc/openocd.texi | 5 +-
+ src/rtos/Makefile.am | 1 +
+ src/rtos/rtkernel.c | 384 +++++++++++++++++++++++++++++++++++++++++++
+ src/rtos/rtos.c | 2 +
+ 4 files changed, 391 insertions(+), 1 deletion(-)
+ create mode 100644 src/rtos/rtkernel.c
+
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index b9ad3ff77..6c853f2ce 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -5000,7 +5000,7 @@ The value should normally correspond to a static mapping for the
+ @var{rtos_type} can be one of @option{auto}, @option{none}, @option{eCos},
+ @option{ThreadX}, @option{FreeRTOS}, @option{linux}, @option{ChibiOS},
+ @option{embKernel}, @option{mqx}, @option{uCOS-III}, @option{nuttx},
+-@option{RIOT}, @option{Zephyr}
++@option{RIOT}, @option{Zephyr}, @option{rtkernel}
+ @xref{gdbrtossupport,,RTOS Support}.
+
+ @item @code{-defer-examine} -- skip target examination at initial JTAG chain
+@@ -11867,6 +11867,7 @@ Currently supported rtos's include:
+ @item @option{RIOT}
+ @item @option{hwthread} (This is not an actual RTOS. @xref{usingopenocdsmpwithgdb,,Using OpenOCD SMP with GDB}.)
+ @item @option{Zephyr}
++@item @option{rtkernel}
+ @end itemize
+
+ At any time, it's possible to drop the selected RTOS using:
+@@ -11908,6 +11909,8 @@ _tcb_name_offset.
+ @end raggedright
+ @item Zephyr symbols
+ _kernel, _kernel_openocd_offsets, _kernel_openocd_size_t_size
++@item rtkernel symbols
++Multiple struct offsets.
+ @end table
+
+ For most RTOS supported the above symbols will be exported by default. However for
+diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am
+index fc3ab8b42..b0f7daf5f 100644
+--- a/src/rtos/Makefile.am
++++ b/src/rtos/Makefile.am
+@@ -21,6 +21,7 @@ noinst_LTLIBRARIES += %D%/librtos.la
+ %D%/mqx.c \
+ %D%/uCOS-III.c \
+ %D%/nuttx.c \
++ %D%/rtkernel.c \
+ %D%/hwthread.c \
+ %D%/zephyr.c \
+ %D%/riot.c \
+diff --git a/src/rtos/rtkernel.c b/src/rtos/rtkernel.c
+new file mode 100644
+index 000000000..ba1de2517
+--- /dev/null
++++ b/src/rtos/rtkernel.c
+@@ -0,0 +1,384 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++/***************************************************************************
++ * Copyright (C) 2016-2023 by Andreas Fritiofson *
++ * andreas.fritiofson@gmail.com *
++ ***************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <helper/time_support.h>
++#include <jtag/jtag.h>
++#include "target/target.h"
++#include "target/target_type.h"
++#include "rtos.h"
++#include "helper/log.h"
++#include "helper/types.h"
++#include "rtos_standard_stackings.h"
++#include "target/armv7m.h"
++#include "target/cortex_m.h"
++
++#define ST_DEAD BIT(0) /* Task is waiting to be deleted */
++#define ST_WAIT BIT(1) /* Task is blocked: */
++#define ST_SEM BIT(2) /* on semaphore */
++#define ST_MTX BIT(3) /* on mutex */
++#define ST_SIG BIT(4) /* on signal */
++#define ST_DLY BIT(5) /* on timer */
++#define ST_FLAG BIT(6) /* on flag */
++#define ST_FLAG_ALL BIT(7) /* on flag and flag mode is "ALL" */
++#define ST_MBOX BIT(8) /* on mailbox */
++#define ST_STP BIT(9) /* self stopped */
++#define ST_SUSPEND BIT(10) /* Task is suspended */
++#define ST_TT BIT(11) /* Time triggered task */
++#define ST_TT_YIELD BIT(12) /* Time triggered task that yields */
++#define ST_CREATE BIT(13) /* Task was created by task_create() */
++
++struct rtkernel_params {
++ const char *target_name;
++ const struct rtos_register_stacking *stacking_info_cm3;
++ const struct rtos_register_stacking *stacking_info_cm4f;
++ const struct rtos_register_stacking *stacking_info_cm4f_fpu;
++};
++
++static const struct rtkernel_params rtkernel_params_list[] = {
++ {
++ "cortex_m", /* target_name */
++ &rtos_standard_cortex_m3_stacking, /* stacking_info */
++ &rtos_standard_cortex_m4f_stacking,
++ &rtos_standard_cortex_m4f_fpu_stacking,
++ },
++ {
++ "hla_target", /* target_name */
++ &rtos_standard_cortex_m3_stacking, /* stacking_info */
++ &rtos_standard_cortex_m4f_stacking,
++ &rtos_standard_cortex_m4f_fpu_stacking,
++ },
++};
++
++enum rtkernel_symbol_values {
++ sym_os_state = 0,
++ sym___off_os_state2chain = 1,
++ sym___off_os_state2current = 2,
++ sym___off_task2chain = 3,
++ sym___off_task2magic = 4,
++ sym___off_task2stack = 5,
++ sym___off_task2state = 6,
++ sym___off_task2name = 7,
++ sym___val_task_magic = 8,
++};
++
++struct symbols {
++ const char *name;
++ bool optional;
++};
++
++static const struct symbols rtkernel_symbol_list[] = {
++ { "os_state", false },
++ { "__off_os_state2chain", false },
++ { "__off_os_state2current", false },
++ { "__off_task2chain", false },
++ { "__off_task2magic", false },
++ { "__off_task2stack", false },
++ { "__off_task2state", false },
++ { "__off_task2name", false },
++ { "__val_task_magic", false },
++ { NULL, false }
++};
++
++static void *realloc_preserve(void *ptr, size_t old_size, size_t new_size)
++{
++ void *new_ptr = malloc(new_size);
++
++ if (new_ptr) {
++ memcpy(new_ptr, ptr, MIN(old_size, new_size));
++ free(ptr);
++ }
++
++ return new_ptr;
++}
++
++static int rtkernel_add_task(struct rtos *rtos, uint32_t task, uint32_t current_task)
++{
++ int retval;
++ int new_thread_count = rtos->thread_count + 1;
++ struct thread_detail *new_thread_details = realloc_preserve(rtos->thread_details,
++ rtos->thread_count * sizeof(struct thread_detail),
++ new_thread_count * sizeof(struct thread_detail));
++ if (!new_thread_details) {
++ LOG_ERROR("Error growing memory to %d threads", new_thread_count);
++ return ERROR_FAIL;
++ }
++ rtos->thread_details = new_thread_details;
++ struct thread_detail *thread = &new_thread_details[rtos->thread_count];
++
++ *thread = (struct thread_detail){ .threadid = task, .exists = true };
++
++ /* Read the task name */
++ uint32_t name;
++ retval = target_read_u32(rtos->target, task + rtos->symbols[sym___off_task2name].address, &name);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Could not read task name pointer from target");
++ return retval;
++ }
++ uint8_t tmp_str[33];
++ retval = target_read_buffer(rtos->target, name, sizeof(tmp_str) - 1, tmp_str);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Error reading task name from target");
++ return retval;
++ }
++ tmp_str[sizeof(tmp_str) - 1] = '\0';
++ LOG_DEBUG("task name at 0x%" PRIx32 ", value \"%s\"", name, tmp_str);
++
++ if (tmp_str[0] != '\0')
++ thread->thread_name_str = strdup((char *)tmp_str);
++ else
++ thread->thread_name_str = strdup("No Name");
++
++ /* Read the task state */
++ uint16_t state;
++ retval = target_read_u16(rtos->target, task + rtos->symbols[sym___off_task2state].address, &state);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Could not read task state from target");
++ return retval;
++ }
++
++ LOG_DEBUG("task state 0x%" PRIx16, state);
++
++ char state_str[64] = "";
++ if (state & ST_TT)
++ strcat(state_str, "TT|");
++ if (task == current_task) {
++ strcat(state_str, "RUN");
++ } else {
++ if (state & (ST_TT | ST_TT_YIELD))
++ strcat(state_str, "YIELD");
++ else if (state & ST_DEAD)
++ strcat(state_str, "DEAD");
++ else if (state & ST_WAIT)
++ strcat(state_str, "WAIT");
++ else if (state & ST_SUSPEND)
++ strcat(state_str, "SUSP");
++ else
++ strcat(state_str, "READY");
++ }
++ if (state & ST_SEM)
++ strcat(state_str, "|SEM");
++ if (state & ST_MTX)
++ strcat(state_str, "|MTX");
++ if (state & ST_SIG)
++ strcat(state_str, "|SIG");
++ if (state & ST_DLY)
++ strcat(state_str, "|DLY");
++ if ((state & ST_FLAG) || (state & ST_FLAG_ALL))
++ strcat(state_str, "|FLAG");
++ if (state & ST_FLAG_ALL)
++ strcat(state_str, "_ALL");
++ if (state & ST_MBOX)
++ strcat(state_str, "|MBOX");
++ if (state & ST_STP)
++ strcat(state_str, "|STP");
++
++ thread->extra_info_str = strdup(state_str);
++
++ rtos->thread_count = new_thread_count;
++ if (task == current_task)
++ rtos->current_thread = task;
++ return ERROR_OK;
++}
++
++static int rtkernel_verify_task(struct rtos *rtos, uint32_t task)
++{
++ int retval;
++ uint32_t magic;
++ retval = target_read_u32(rtos->target, task + rtos->symbols[sym___off_task2magic].address, &magic);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Could not read task magic from target");
++ return retval;
++ }
++ if (magic != rtos->symbols[sym___val_task_magic].address) {
++ LOG_ERROR("Invalid task found (magic=0x%" PRIx32 ")", magic);
++ return ERROR_FAIL;
++ }
++ return retval;
++}
++
++static int rtkernel_update_threads(struct rtos *rtos)
++{
++ /* wipe out previous thread details if any */
++ /* do this first because rtos layer does not check our retval */
++ rtos_free_threadlist(rtos);
++ rtos->current_thread = 0;
++
++ if (!rtos->symbols) {
++ LOG_ERROR("No symbols for rt-kernel");
++ return -3;
++ }
++
++ /* read the current task */
++ uint32_t current_task;
++ int retval = target_read_u32(rtos->target,
++ rtos->symbols[sym_os_state].address + rtos->symbols[sym___off_os_state2current].address,
++ ¤t_task);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Error reading current task");
++ return retval;
++ }
++ LOG_DEBUG("current task is 0x%" PRIx32, current_task);
++
++ retval = rtkernel_verify_task(rtos, current_task);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Current task is invalid");
++ return retval;
++ }
++
++ /* loop through kernel task list */
++ uint32_t chain = rtos->symbols[sym_os_state].address + rtos->symbols[sym___off_os_state2chain].address;
++ LOG_DEBUG("chain start at 0x%" PRIx32, chain);
++
++ uint32_t next = chain;
++ for (;;) {
++ retval = target_read_u32(rtos->target, next, &next);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Could not read rt-kernel data structure from target");
++ return retval;
++ }
++ LOG_DEBUG("next entry at 0x%" PRIx32, next);
++ if (next == chain) {
++ LOG_DEBUG("end of chain detected");
++ break;
++ }
++ uint32_t task = next - rtos->symbols[sym___off_task2chain].address;
++ LOG_DEBUG("found task at 0x%" PRIx32, task);
++
++ retval = rtkernel_verify_task(rtos, task);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Invalid task found");
++ return retval;
++ }
++
++ retval = rtkernel_add_task(rtos, task, current_task);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Could not add task to rtos system");
++ return retval;
++ }
++ }
++ return ERROR_OK;
++}
++
++static int rtkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
++ struct rtos_reg **reg_list, int *num_regs)
++{
++ uint32_t stack_ptr = 0;
++
++ if (!rtos)
++ return -1;
++
++ if (thread_id == 0)
++ return -2;
++
++ if (!rtos->rtos_specific_params)
++ return -1;
++
++ const struct rtkernel_params *param = rtos->rtos_specific_params;
++
++ /* Read the stack pointer */
++ int retval = target_read_u32(rtos->target, thread_id + rtos->symbols[sym___off_task2stack].address, &stack_ptr);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Error reading stack pointer from rtkernel thread");
++ return retval;
++ }
++ LOG_DEBUG("stack pointer at 0x%" PRIx64 ", value 0x%" PRIx32,
++ thread_id + rtos->symbols[sym___off_task2stack].address,
++ stack_ptr);
++
++ /* Adjust stack pointer to ignore non-standard BASEPRI register stacking */
++ stack_ptr += 4;
++
++ /* Check for armv7m with *enabled* FPU, i.e. a Cortex M4F */
++ bool cm4_fpu_enabled = false;
++ struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
++ if (is_armv7m(armv7m_target)) {
++ if (armv7m_target->fp_feature != FP_NONE) {
++ /* Found ARM v7m target which includes a FPU */
++ uint32_t cpacr;
++
++ retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Could not read CPACR register to check FPU state");
++ return -1;
++ }
++
++ /* Check if CP10 and CP11 are set to full access. */
++ if (cpacr & 0x00F00000) {
++ /* Found target with enabled FPU */
++ cm4_fpu_enabled = true;
++ }
++ }
++ }
++
++ if (!cm4_fpu_enabled) {
++ LOG_DEBUG("cm3 stacking");
++ return rtos_generic_stack_read(rtos->target, param->stacking_info_cm3, stack_ptr, reg_list, num_regs);
++ }
++
++ /* Read the LR to decide between stacking with or without FPU */
++ uint32_t lr_svc;
++ retval = target_read_u32(rtos->target, stack_ptr + 0x20, &lr_svc);
++ if (retval != ERROR_OK) {
++ LOG_OUTPUT("Error reading stack frame from rtkernel thread\r\n");
++ return retval;
++ }
++
++ if ((lr_svc & 0x10) == 0) {
++ LOG_DEBUG("cm4f_fpu stacking");
++ return rtos_generic_stack_read(rtos->target, param->stacking_info_cm4f_fpu, stack_ptr, reg_list, num_regs);
++ }
++
++ LOG_DEBUG("cm4f stacking");
++ return rtos_generic_stack_read(rtos->target, param->stacking_info_cm4f, stack_ptr, reg_list, num_regs);
++}
++
++static int rtkernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
++{
++ *symbol_list = calloc(ARRAY_SIZE(rtkernel_symbol_list), sizeof(struct symbol_table_elem));
++ if (!*symbol_list)
++ return ERROR_FAIL;
++
++ for (size_t i = 0; i < ARRAY_SIZE(rtkernel_symbol_list); i++) {
++ (*symbol_list)[i].symbol_name = rtkernel_symbol_list[i].name;
++ (*symbol_list)[i].optional = rtkernel_symbol_list[i].optional;
++ }
++
++ return ERROR_OK;
++}
++
++static bool rtkernel_detect_rtos(struct target *target)
++{
++ return (target->rtos->symbols) &&
++ (target->rtos->symbols[sym___off_os_state2chain].address != 0);
++}
++
++static int rtkernel_create(struct target *target)
++{
++ for (size_t i = 0; i < ARRAY_SIZE(rtkernel_params_list); i++) {
++ if (strcmp(rtkernel_params_list[i].target_name, target->type->name) == 0) {
++ target->rtos->rtos_specific_params = (void *)&rtkernel_params_list[i];
++ return 0;
++ }
++ }
++
++ LOG_ERROR("Could not find target in rt-kernel compatibility list");
++ return -1;
++}
++
++const struct rtos_type rtkernel_rtos = {
++ .name = "rtkernel",
++
++ .detect_rtos = rtkernel_detect_rtos,
++ .create = rtkernel_create,
++ .update_threads = rtkernel_update_threads,
++ .get_thread_reg_list = rtkernel_get_thread_reg_list,
++ .get_symbol_list_to_lookup = rtkernel_get_symbol_list_to_lookup,
++};
+diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
+index dfa158d01..bcd556a7b 100644
+--- a/src/rtos/rtos.c
++++ b/src/rtos/rtos.c
+@@ -29,6 +29,7 @@ extern struct rtos_type nuttx_rtos;
+ extern struct rtos_type hwthread_rtos;
+ extern struct rtos_type riot_rtos;
+ extern struct rtos_type zephyr_rtos;
++extern struct rtos_type rtkernel_rtos;
+
+ static struct rtos_type *rtos_types[] = {
+ &threadx_rtos,
+@@ -43,6 +44,7 @@ static struct rtos_type *rtos_types[] = {
+ &nuttx_rtos,
+ &riot_rtos,
+ &zephyr_rtos,
++ &rtkernel_rtos,
+ /* keep this as last, as it always matches with rtos auto */
+ &hwthread_rtos,
+ NULL
new file mode 100644
@@ -0,0 +1,168 @@
+From d032e7ec8c2978feda5df2ca7c4ddbcaec2fcbf5 Mon Sep 17 00:00:00 2001
+From: Andreas Fritiofson <andreas.fritiofson@gmail.com>
+Date: Mon, 8 Nov 2021 19:35:27 +0100
+Subject: [PATCH] rtos: Fix constness of struct rtos_type
+
+Change-Id: Iaa89f2ff4036c23f944ffb4f37fe0c7afaf5069b
+Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/6680
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/rtos/FreeRTOS.c | 2 +-
+ src/rtos/chibios.c | 2 +-
+ src/rtos/embKernel.c | 2 +-
+ src/rtos/mqx.c | 2 +-
+ src/rtos/nuttx.c | 2 +-
+ src/rtos/rtos.c | 38 +++++++++++++++++++-------------------
+ src/rtos/zephyr.c | 2 +-
+ 7 files changed, 25 insertions(+), 25 deletions(-)
+
+diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c
+index 945c4b875..070275f2c 100644
+--- a/src/rtos/FreeRTOS.c
++++ b/src/rtos/FreeRTOS.c
+@@ -80,7 +80,7 @@ static int freertos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ struct rtos_reg **reg_list, int *num_regs);
+ static int freertos_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
+
+-struct rtos_type freertos_rtos = {
++const struct rtos_type freertos_rtos = {
+ .name = "FreeRTOS",
+
+ .detect_rtos = freertos_detect_rtos,
+diff --git a/src/rtos/chibios.c b/src/rtos/chibios.c
+index 8319cc883..68fe8a14c 100644
+--- a/src/rtos/chibios.c
++++ b/src/rtos/chibios.c
+@@ -97,7 +97,7 @@ static int chibios_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ struct rtos_reg **reg_list, int *num_regs);
+ static int chibios_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
+
+-struct rtos_type chibios_rtos = {
++const struct rtos_type chibios_rtos = {
+ .name = "chibios",
+
+ .detect_rtos = chibios_detect_rtos,
+diff --git a/src/rtos/embKernel.c b/src/rtos/embKernel.c
+index c1b5723fc..a03b039e0 100644
+--- a/src/rtos/embKernel.c
++++ b/src/rtos/embKernel.c
+@@ -27,7 +27,7 @@ static int embkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
+ struct rtos_reg **reg_list, int *num_regs);
+ static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
+
+-struct rtos_type embkernel_rtos = {
++const struct rtos_type embkernel_rtos = {
+ .name = "embKernel",
+ .detect_rtos = embkernel_detect_rtos,
+ .create = embkernel_create,
+diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c
+index 8d483ed3b..d9b694282 100644
+--- a/src/rtos/mqx.c
++++ b/src/rtos/mqx.c
+@@ -498,7 +498,7 @@ static int mqx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]
+ return ERROR_OK;
+ }
+
+-struct rtos_type mqx_rtos = {
++const struct rtos_type mqx_rtos = {
+ .name = "mqx",
+ .detect_rtos = mqx_detect_rtos,
+ .create = mqx_create,
+diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c
+index 993ff84bd..78271181e 100644
+--- a/src/rtos/nuttx.c
++++ b/src/rtos/nuttx.c
+@@ -324,7 +324,7 @@ static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list
+ return 0;
+ }
+
+-struct rtos_type nuttx_rtos = {
++const struct rtos_type nuttx_rtos = {
+ .name = "nuttx",
+ .detect_rtos = nuttx_detect_rtos,
+ .create = nuttx_create,
+diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
+index bcd556a7b..f1e8956a3 100644
+--- a/src/rtos/rtos.c
++++ b/src/rtos/rtos.c
+@@ -16,22 +16,22 @@
+ #include "server/gdb_server.h"
+
+ /* RTOSs */
+-extern struct rtos_type freertos_rtos;
+-extern struct rtos_type threadx_rtos;
+-extern struct rtos_type ecos_rtos;
+-extern struct rtos_type linux_rtos;
+-extern struct rtos_type chibios_rtos;
+-extern struct rtos_type chromium_ec_rtos;
+-extern struct rtos_type embkernel_rtos;
+-extern struct rtos_type mqx_rtos;
+-extern struct rtos_type ucos_iii_rtos;
+-extern struct rtos_type nuttx_rtos;
+-extern struct rtos_type hwthread_rtos;
+-extern struct rtos_type riot_rtos;
+-extern struct rtos_type zephyr_rtos;
+-extern struct rtos_type rtkernel_rtos;
+-
+-static struct rtos_type *rtos_types[] = {
++extern const struct rtos_type freertos_rtos;
++extern const struct rtos_type threadx_rtos;
++extern const struct rtos_type ecos_rtos;
++extern const struct rtos_type linux_rtos;
++extern const struct rtos_type chibios_rtos;
++extern const struct rtos_type chromium_ec_rtos;
++extern const struct rtos_type embkernel_rtos;
++extern const struct rtos_type mqx_rtos;
++extern const struct rtos_type ucos_iii_rtos;
++extern const struct rtos_type nuttx_rtos;
++extern const struct rtos_type hwthread_rtos;
++extern const struct rtos_type riot_rtos;
++extern const struct rtos_type zephyr_rtos;
++extern const struct rtos_type rtkernel_rtos;
++
++static const struct rtos_type *rtos_types[] = {
+ &threadx_rtos,
+ &freertos_rtos,
+ &ecos_rtos,
+@@ -70,7 +70,7 @@ static int rtos_target_for_threadid(struct connection *connection, int64_t threa
+ return ERROR_OK;
+ }
+
+-static int os_alloc(struct target *target, struct rtos_type *ostype)
++static int os_alloc(struct target *target, const struct rtos_type *ostype)
+ {
+ struct rtos *os = target->rtos = calloc(1, sizeof(struct rtos));
+
+@@ -100,7 +100,7 @@ static void os_free(struct target *target)
+ target->rtos = NULL;
+ }
+
+-static int os_alloc_create(struct target *target, struct rtos_type *ostype)
++static int os_alloc_create(struct target *target, const struct rtos_type *ostype)
+ {
+ int ret = os_alloc(target, ostype);
+
+@@ -683,7 +683,7 @@ int rtos_generic_stack_read(struct target *target,
+ static int rtos_try_next(struct target *target)
+ {
+ struct rtos *os = target->rtos;
+- struct rtos_type **type = rtos_types;
++ const struct rtos_type **type = rtos_types;
+
+ if (!os)
+ return 0;
+diff --git a/src/rtos/zephyr.c b/src/rtos/zephyr.c
+index b00b4b341..934a8dd1c 100644
+--- a/src/rtos/zephyr.c
++++ b/src/rtos/zephyr.c
+@@ -785,7 +785,7 @@ static int zephyr_get_symbol_list_to_lookup(struct symbol_table_elem **symbol_li
+ return ERROR_OK;
+ }
+
+-struct rtos_type zephyr_rtos = {
++const struct rtos_type zephyr_rtos = {
+ .name = "Zephyr",
+
+ .detect_rtos = zephyr_detect_rtos,
new file mode 100644
@@ -0,0 +1,51 @@
+From 20285b91008106c9fa966cea3269c6f6a81e539a Mon Sep 17 00:00:00 2001
+From: N S <nlshipp@yahoo.com>
+Date: Fri, 23 Dec 2022 16:59:18 -0800
+Subject: [PATCH] jtag/drivers/openjtag: fix annoying num_cycles > 16 warning
+
+The OpenJTAG driver logs "num_cycles > 16 on run test" warning
+whenever the JTAG_RUNTEST operation cycle count is larger than 16.
+
+Instead of logging the warning and only running the first 16 TCLK
+cycles, remove the warning and queue up multiple operations of up
+to 16 cycles each.
+
+Signed-off-by: N S <nlshipp@yahoo.com>
+Change-Id: Id405fa802ff1cf3db7a21e76bd6df0c2d3a0fe61
+Reviewed-on: https://review.openocd.org/c/openocd/+/7420
+Tested-by: jenkins
+Reviewed-by: Jonathan McDowell <noodles-openocd@earth.li>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/openjtag.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c
+index 6be950718..12ea46330 100644
+--- a/src/jtag/drivers/openjtag.c
++++ b/src/jtag/drivers/openjtag.c
+@@ -742,16 +742,18 @@ static void openjtag_execute_runtest(struct jtag_command *cmd)
+ tap_set_state(TAP_IDLE);
+ }
+
+- if (cmd->cmd.runtest->num_cycles > 16)
+- LOG_WARNING("num_cycles > 16 on run test");
+-
+ if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 ||
+ cmd->cmd.runtest->num_cycles) {
+ uint8_t command;
+- command = 7;
+- command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4;
++ int cycles = cmd->cmd.runtest->num_cycles;
+
+- openjtag_add_byte(command);
++ do {
++ command = 7;
++ command |= (((cycles > 16 ? 16 : cycles) - 1) & 0x0F) << 4;
++
++ openjtag_add_byte(command);
++ cycles -= 16;
++ } while (cycles > 0);
+ }
+
+ tap_set_end_state(end_state);
new file mode 100644
@@ -0,0 +1,68 @@
+From 148bc7e2151740527b4ca67d0a7c7c9f01725981 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Fri, 14 Oct 2022 09:19:29 +0200
+Subject: [PATCH] jtag/drivers/bitbang: avoid mostly harmless glitch on SWDIO
+
+bitbang_swd_exchange(rnw=true,...) calls bitbang_interface->swd_write()
+with swdio clamped to 0.
+bitbang_swd_write_reg() reads 1 turnaround bit, 3 ack bits
+and 1 turnaround by one call to bitbang_swd_exchange()
+and then switches SWDIO to output.
+AFAIK all bitbang interfaces switch SWDIO GPIO direction immediately
+in bitbang_interface->swdio_drive().
+The GPIO now drives SWDIO line to the value stored in the output register
+which is always zero from previous bitbang_swd_exchange(rnw=true,...).
+In case the following data bit (bit 0) is 1 we can observe a glitch
+on SWDIO:
+ _____ out 1 ____
+HiZ/pull-up ----\ /
+ \ /
+ \______ out 0 ______/
+ swdio_drive(true) swd_write(0,1)
+
+The glitch fortunately takes place far enough from SWCLK rising edge
+where SWDIO is sampled by the target, so I believe it is harmless
+except some corner cases where the reflected wave is delayed on long
+line.
+
+Anyway keeping electrical signals glitch free is a good practice.
+To keep performance penalty minimal, pre-write the first data
+bit to SWDIO GPIO output buffer while clocking the turnaround bit.
+Following swdio_drive(true) outputs the pre-written value
+and the same value is rewritten by the next swd_write()
+instead of glitching SWDIO.
+
+Change-Id: I72ea9c0b2fae57e8ff5aa616859182c67abc924f
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7260
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/bitbang.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c
+index 2ab0a2a76..665dbf329 100644
+--- a/src/jtag/drivers/bitbang.c
++++ b/src/jtag/drivers/bitbang.c
+@@ -525,7 +525,19 @@ static void bitbang_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay
+ bitbang_swd_exchange(false, &cmd, 0, 8);
+
+ bitbang_interface->swdio_drive(false);
+- bitbang_swd_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3 + 1);
++ bitbang_swd_exchange(true, trn_ack_data_parity_trn, 0, 1 + 3);
++
++ /* Avoid a glitch on SWDIO when changing the direction to output.
++ * To keep performance penalty minimal, pre-write the first data
++ * bit to SWDIO GPIO output buffer while clocking the turnaround bit.
++ * Following swdio_drive(true) outputs the pre-written value
++ * and the same value is rewritten by the next swd_write()
++ * instead of glitching SWDIO
++ * HiZ/pull-up --------------> 0 -------------> 1
++ * swdio_drive(true) swd_write(0,1)
++ * in case of data bit 0 = 1
++ */
++ bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 1);
+ bitbang_interface->swdio_drive(true);
+ bitbang_swd_exchange(false, trn_ack_data_parity_trn, 1 + 3 + 1, 32 + 1);
+
new file mode 100644
@@ -0,0 +1,50 @@
+From b4dd8dbc37daf073bf6481fdc7f0f9d7f2e96809 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Thu, 13 Oct 2022 16:46:31 +0200
+Subject: [PATCH] jtag/drivers/bcm2835gpio: use rounding in delay math
+
+After setting adapter speed to some values, the driver
+shows the real speed little bit higher.
+Although it does not impose a problem from technical point
+of view because the difference is smaller than usual speed error,
+it looks at least strange to the user. The documentation reads
+that real frequency should be same or lower than requested.
+
+Use proper rounding in speed -> delay and delay -> speed
+conversions.
+
+Change-Id: I1831112cc58681875548d2aeb688391fb79fa37f
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7261
+Tested-by: jenkins
+Reviewed-by: Jonathan Bell <jonathan@raspberrypi.com>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/bcm2835gpio.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c
+index 5aa1a99e4..320baba09 100644
+--- a/src/jtag/drivers/bcm2835gpio.c
++++ b/src/jtag/drivers/bcm2835gpio.c
+@@ -264,7 +264,8 @@ static int bcm2835gpio_khz(int khz, int *jtag_speed)
+ LOG_DEBUG("BCM2835 GPIO: RCLK not supported");
+ return ERROR_FAIL;
+ }
+- *jtag_speed = speed_coeff/khz - speed_offset;
++ *jtag_speed = DIV_ROUND_UP(speed_coeff, khz) - speed_offset;
++ LOG_DEBUG("jtag_delay %d", *jtag_speed);
+ if (*jtag_speed < 0)
+ *jtag_speed = 0;
+ return ERROR_OK;
+@@ -272,7 +273,9 @@ static int bcm2835gpio_khz(int khz, int *jtag_speed)
+
+ static int bcm2835gpio_speed_div(int speed, int *khz)
+ {
+- *khz = speed_coeff/(speed + speed_offset);
++ int divisor = speed + speed_offset;
++ /* divide with roundig to the closest */
++ *khz = (speed_coeff + divisor / 2) / divisor;
+ return ERROR_OK;
+ }
+
new file mode 100644
@@ -0,0 +1,63 @@
+From 2dde7e914b429ffa5bc56faa20fb474ca451412e Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Thu, 13 Oct 2022 22:33:12 +0200
+Subject: [PATCH] jtag/drivers/bcm2835gpio: refactor delays to inline function
+
+No functional change, the delay is unchanged.
+
+Change-Id: I5b5e837d741ac01fc573657357c5fe61ad901319
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7262
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/bcm2835gpio.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c
+index 320baba09..635d9a5ff 100644
+--- a/src/jtag/drivers/bcm2835gpio.c
++++ b/src/jtag/drivers/bcm2835gpio.c
+@@ -66,6 +66,12 @@ static inline void bcm2835_gpio_synchronize(void)
+ __sync_synchronize();
+ }
+
++static inline void bcm2835_delay(void)
++{
++ for (unsigned int i = 0; i < jtag_delay; i++)
++ asm volatile ("");
++}
++
+ static bool is_gpio_config_valid(enum adapter_gpio_config_index idx)
+ {
+ /* Only chip 0 is supported, accept unset value (-1) too */
+@@ -178,8 +184,7 @@ static int bcm2835gpio_write(int tck, int tms, int tdi)
+ GPIO_CLR = clear;
+ bcm2835_gpio_synchronize();
+
+- for (unsigned int i = 0; i < jtag_delay; i++)
+- asm volatile ("");
++ bcm2835_delay();
+
+ return ERROR_OK;
+ }
+@@ -199,8 +204,7 @@ static int bcm2835gpio_swd_write_fast(int swclk, int swdio)
+ GPIO_CLR = clear;
+ bcm2835_gpio_synchronize();
+
+- for (unsigned int i = 0; i < jtag_delay; i++)
+- asm volatile ("");
++ bcm2835_delay();
+
+ return ERROR_OK;
+ }
+@@ -211,8 +215,7 @@ static int bcm2835gpio_swd_write_generic(int swclk, int swdio)
+ set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO], swdio);
+ set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK], swclk); /* Write clock last */
+
+- for (unsigned int i = 0; i < jtag_delay; ++i)
+- asm volatile ("");
++ bcm2835_delay();
+
+ return ERROR_OK;
+ }
new file mode 100644
@@ -0,0 +1,242 @@
+From bec6c0eb094fb7ca1752688118f41193dc83e026 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Fri, 14 Oct 2022 11:16:58 +0200
+Subject: [PATCH] tcl/interface: universal config for all Raspberry Pi models
+
+Speed calibration coeffs are computed from cpufreq/scaling_max_freq
+and from the device-tree compatibility information.
+
+Raspberry Pi linux offers /dev/gpiomem for non-root access
+to the GPIO registers since ~2016.
+Do not configure 'bcm2835gpio peripheral_base' as it is necessary
+only if /dev/mem is used - it requires running OpenOCD as root
+- it's a security risk so it should be avoided.
+
+The configuration of the GPIO connector (40-pin header)
+is factored out and ready to use in interface configuration
+for other driver (e.g. linux gpiod).
+
+Mark raspberrypi2-native.cfg as deprecated and redirect
+it to raspberrypi-native.cfg
+
+Change-Id: Icce856fb660b45374e94174da279feb51f529908
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7264
+Tested-by: jenkins
+Reviewed-by: Jonathan Bell <jonathan@raspberrypi.com>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ tcl/interface/raspberrypi-gpio-connector.cfg | 42 +++++++++
+ tcl/interface/raspberrypi-native.cfg | 91 +++++++++++++-------
+ tcl/interface/raspberrypi2-native.cfg | 44 +---------
+ 3 files changed, 104 insertions(+), 73 deletions(-)
+ create mode 100644 tcl/interface/raspberrypi-gpio-connector.cfg
+
+diff --git a/tcl/interface/raspberrypi-gpio-connector.cfg b/tcl/interface/raspberrypi-gpio-connector.cfg
+new file mode 100644
+index 000000000..eff73fc92
+--- /dev/null
++++ b/tcl/interface/raspberrypi-gpio-connector.cfg
+@@ -0,0 +1,42 @@
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++#
++# Config for Raspberry Pi GPIO header
++#
++# This is best used with a fast enough buffer but also
++# is suitable for direct connection if the target voltage
++# matches RPi's 3.3V and the cable is short enough.
++#
++# Do not forget the GND connection, e.g. pin 20 of the GPIO header.
++#
++
++# GPIO 25 (pin 22) previously used for TMS/SWDIO is pulled-down by default.
++# The JTAG/SWD specification requires pull-up at the target board
++# for either signal. Connecting the signal pulled-up on the target
++# to the pull-down on the adapter is not a good idea.
++# GPIO 8 is pulled-up by default.
++echo "Warn : TMS/SWDIO moved to GPIO 8 (pin 24). Check the wiring please!"
++
++# Each of the JTAG lines need a gpio number set: tck tms tdi tdo
++# Header pin numbers: 23 24 19 21
++adapter gpio tck -chip 0 11
++adapter gpio tms -chip 0 8
++adapter gpio tdi -chip 0 10
++adapter gpio tdo -chip 0 9
++
++# Each of the SWD lines need a gpio number set: swclk swdio
++# Header pin numbers: 23 24
++adapter gpio swclk -chip 0 11
++adapter gpio swdio -chip 0 8
++
++# If you define trst or srst, use appropriate reset_config
++# Header pin numbers: TRST - 26, SRST - 18
++
++# adapter gpio trst -chip 0 7
++# reset_config trst_only
++
++# adapter gpio srst -chip 0 24
++# reset_config srst_only srst_push_pull
++
++# or if you have both connected,
++# reset_config trst_and_srst srst_push_pull
+diff --git a/tcl/interface/raspberrypi-native.cfg b/tcl/interface/raspberrypi-native.cfg
+index 02a356350..95426c226 100644
+--- a/tcl/interface/raspberrypi-native.cfg
++++ b/tcl/interface/raspberrypi-native.cfg
+@@ -1,44 +1,71 @@
+ # SPDX-License-Identifier: GPL-2.0-or-later
+
+-#
+-# Config for using Raspberry Pi's expansion header
+-#
+-# This is best used with a fast enough buffer but also
+-# is suitable for direct connection if the target voltage
+-# matches RPi's 3.3V and the cable is short enough.
+-#
+-# Do not forget the GND connection, pin 6 of the expansion header.
+-#
++# Config for Raspberry Pi used as a bitbang adapter.
++# https://www.raspberrypi.com/documentation/computers/raspberry-pi.html
++
++# Supports all models with 40-pin or 26-pin GPIO connector up to Raspberry Pi 4 B
++# also supports Raspberry Pi Zero, Zero W and Zero 2 W.
++
++# Adapter speed calibration is computed from cpufreq/scaling_max_freq.
++# Adjusts automatically if CPU is overclocked.
+
+ adapter driver bcm2835gpio
+
+-bcm2835gpio peripheral_base 0x20000000
++proc read_file { name } {
++ if {[catch {open $name r} fd]} {
++ return ""
++ }
++ set result [read $fd]
++ close $fd
++ return $result
++}
+
+-# Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET
+-# These depend on system clock, calibrated for stock 700MHz
+-# bcm2835gpio speed SPEED_COEFF SPEED_OFFSET
+-bcm2835gpio speed_coeffs 113714 28
++proc measure_clock {} {
++ set result [exec vcgencmd measure_clock arm]
++ set clock_hz [lindex [split $result "="] 1]
++ expr { $clock_hz / 1000 }
++}
++
++proc get_max_cpu_clock { default } {
++ set clock [read_file /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq]
++ if { $clock > 100000 } {
++ return $clock
++ }
+
+-# Each of the JTAG lines need a gpio number set: tck tms tdi tdo
+-# Header pin numbers: 23 22 19 21
+-adapter gpio tck -chip 0 11
+-adapter gpio tms -chip 0 25
+-adapter gpio tdi -chip 0 10
+-adapter gpio tdo -chip 0 9
++ # cpufreq not available. As the last resort try Broadcom's proprietary utility
++ if {![catch measure_clock clock] && $clock > 100000} {
++ return $clock
++ }
+
+-# Each of the SWD lines need a gpio number set: swclk swdio
+-# Header pin numbers: 23 22
+-adapter gpio swclk -chip 0 11
+-adapter gpio swdio -chip 0 25
++ echo "WARNING: Host CPU clock unknown."
++ echo "WARNING: Using the highest possible value $default kHz as a safe default."
++ echo "WARNING: Expect JTAG/SWD clock significantly slower than requested."
+
+-# If you define trst or srst, use appropriate reset_config
+-# Header pin numbers: TRST - 26, SRST - 18
++ return $default
++}
+
+-# adapter gpio trst -chip 0 7
+-# reset_config trst_only
++set compat [read_file /proc/device-tree/compatible]
++set clocks_per_timing_loop 4
+
+-# adapter gpio srst -chip 0 24
+-# reset_config srst_only srst_push_pull
++if {[string match *bcm2711* $compat]} {
++ set speed_offset 52
++} elseif {[string match *bcm2837* $compat] || [string match *bcm2710* $compat]} {
++ set speed_offset 34
++} elseif {[string match *bcm2836* $compat] || [string match *bcm2709* $compat]} {
++ set speed_offset 36
++} elseif {[string match *bcm2835* $compat] || [string match *bcm2708* $compat]} {
++ set clocks_per_timing_loop 6
++ set speed_offset 32
++} else {
++ set speed_offset 32
++ echo "WARNING: Unknown type of the host SoC. Expect JTAG/SWD clock slower than requested."
++}
++
++set clock [get_max_cpu_clock 2000000]
++set speed_coeff [expr { $clock / $clocks_per_timing_loop }]
++
++# Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET
++# The coefficients depend on system clock and CPU frequency scaling.
++bcm2835gpio speed_coeffs $speed_coeff $speed_offset
+
+-# or if you have both connected,
+-# reset_config trst_and_srst srst_push_pull
++source raspberrypi-gpio-connector.cfg
+diff --git a/tcl/interface/raspberrypi2-native.cfg b/tcl/interface/raspberrypi2-native.cfg
+index d5edded0f..fe9186f23 100644
+--- a/tcl/interface/raspberrypi2-native.cfg
++++ b/tcl/interface/raspberrypi2-native.cfg
+@@ -1,44 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0-or-later
+
+-#
+-# Config for using Raspberry Pi's expansion header
+-#
+-# This is best used with a fast enough buffer but also
+-# is suitable for direct connection if the target voltage
+-# matches RPi's 3.3V and the cable is short enough.
+-#
+-# Do not forget the GND connection, pin 6 of the expansion header.
+-#
++echo "WARNING: interface/raspberrypi2-native.cfg is deprecated."
++echo "WARNING: Please use interface/raspberrypi-native.cfg for all Raspberry Pi models."
+
+-adapter driver bcm2835gpio
+-
+-bcm2835gpio peripheral_base 0x3F000000
+-
+-# Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET
+-# These depend on system clock, calibrated for scaling_max_freq 900MHz
+-# bcm2835gpio speed SPEED_COEFF SPEED_OFFSET
+-bcm2835gpio speed_coeffs 225000 36
+-
+-# Each of the JTAG lines need a gpio number set: tck tms tdi tdo
+-# Header pin numbers: 23 22 19 21
+-adapter gpio tck -chip 0 11
+-adapter gpio tms -chip 0 25
+-adapter gpio tdi -chip 0 10
+-adapter gpio tdo -chip 0 9
+-
+-# Each of the SWD lines need a gpio number set: swclk swdio
+-# Header pin numbers: 23 22
+-adapter gpio swclk -chip 0 11
+-adapter gpio swdio -chip 0 25
+-
+-# If you define trst or srst, use appropriate reset_config
+-# Header pin numbers: TRST - 26, SRST - 18
+-
+-# adapter gpio trst -chip 0 7
+-# reset_config trst_only
+-
+-# adapter gpio srst -chip 0 24
+-# reset_config srst_only srst_push_pull
+-
+-# or if you have both connected,
+-# reset_config trst_and_srst srst_push_pull
++source [find interface/raspberrypi-native.cfg]
new file mode 100644
@@ -0,0 +1,237 @@
+From 227577ba7616ca129790090e1101b503f7b9cdb7 Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Sat, 21 Jan 2023 12:46:33 +0100
+Subject: [PATCH] rtos: remove config.h includes from stackings headers
+
+And add its own header to the rtos_xxx_stackings.c
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: I084130fde7ee8645129a7cf60bb7bf59448e2f39
+Reviewed-on: https://review.openocd.org/c/openocd/+/7441
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/rtos/rtos_chibios_stackings.c | 1 +
+ src/rtos/rtos_chibios_stackings.h | 4 ----
+ src/rtos/rtos_ecos_stackings.c | 3 ++-
+ src/rtos/rtos_ecos_stackings.h | 4 ----
+ src/rtos/rtos_embkernel_stackings.c | 1 +
+ src/rtos/rtos_embkernel_stackings.h | 4 ----
+ src/rtos/rtos_mqx_stackings.c | 2 +-
+ src/rtos/rtos_mqx_stackings.h | 4 ----
+ src/rtos/rtos_riot_stackings.c | 1 +
+ src/rtos/rtos_riot_stackings.h | 5 -----
+ src/rtos/rtos_standard_stackings.c | 1 +
+ src/rtos/rtos_standard_stackings.h | 4 ----
+ src/rtos/rtos_ucos_iii_stackings.c | 10 +++++-----
+ src/rtos/rtos_ucos_iii_stackings.h | 6 +-----
+ 14 files changed, 13 insertions(+), 37 deletions(-)
+
+diff --git a/src/rtos/rtos_chibios_stackings.c b/src/rtos/rtos_chibios_stackings.c
+index e2fe0a27f..c0816ac3c 100644
+--- a/src/rtos/rtos_chibios_stackings.c
++++ b/src/rtos/rtos_chibios_stackings.c
+@@ -14,6 +14,7 @@
+
+ #include "rtos.h"
+ #include "target/armv7m.h"
++#include "rtos_chibios_stackings.h"
+
+ static const struct stack_register_offset rtos_chibios_arm_v7m_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
+ { ARMV7M_R0, -1, 32 }, /* r0 */
+diff --git a/src/rtos/rtos_chibios_stackings.h b/src/rtos/rtos_chibios_stackings.h
+index 23ad44ae3..e909451e2 100644
+--- a/src/rtos/rtos_chibios_stackings.h
++++ b/src/rtos/rtos_chibios_stackings.h
+@@ -8,10 +8,6 @@
+ #ifndef OPENOCD_RTOS_RTOS_CHIBIOS_STACKINGS_H
+ #define OPENOCD_RTOS_RTOS_CHIBIOS_STACKINGS_H
+
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+ #include "rtos.h"
+
+ extern const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking;
+diff --git a/src/rtos/rtos_ecos_stackings.c b/src/rtos/rtos_ecos_stackings.c
+index 86e176507..cae271270 100644
+--- a/src/rtos/rtos_ecos_stackings.c
++++ b/src/rtos/rtos_ecos_stackings.c
+@@ -5,8 +5,9 @@
+ #endif
+
+ #include "rtos.h"
+-#include "rtos_standard_stackings.h"
+ #include "target/armv7m.h"
++#include "rtos_standard_stackings.h"
++#include "rtos_ecos_stackings.h"
+
+ /* For Cortex-M eCos applications the actual thread context register layout can
+ * be different between active threads of an application depending on whether
+diff --git a/src/rtos/rtos_ecos_stackings.h b/src/rtos/rtos_ecos_stackings.h
+index 0375e2d1c..a6bcf1acb 100644
+--- a/src/rtos/rtos_ecos_stackings.h
++++ b/src/rtos/rtos_ecos_stackings.h
+@@ -3,10 +3,6 @@
+ #ifndef OPENOCD_RTOS_RTOS_ECOS_STACKINGS_H
+ #define OPENOCD_RTOS_RTOS_ECOS_STACKINGS_H
+
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+ #include "rtos.h"
+
+ extern const struct rtos_register_stacking rtos_ecos_cortex_m3_stacking;
+diff --git a/src/rtos/rtos_embkernel_stackings.c b/src/rtos/rtos_embkernel_stackings.c
+index 809b622e0..b98628a13 100644
+--- a/src/rtos/rtos_embkernel_stackings.c
++++ b/src/rtos/rtos_embkernel_stackings.c
+@@ -12,6 +12,7 @@
+ #include "rtos.h"
+ #include "target/armv7m.h"
+ #include "rtos_standard_stackings.h"
++#include "rtos_embkernel_stackings.h"
+
+ static const struct stack_register_offset rtos_embkernel_cortex_m_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
+ { ARMV7M_R0, 0x24, 32 }, /* r0 */
+diff --git a/src/rtos/rtos_embkernel_stackings.h b/src/rtos/rtos_embkernel_stackings.h
+index 972bce66d..87bd0e73b 100644
+--- a/src/rtos/rtos_embkernel_stackings.h
++++ b/src/rtos/rtos_embkernel_stackings.h
+@@ -8,10 +8,6 @@
+ #ifndef OPENOCD_RTOS_RTOS_EMBKERNEL_STACKINGS_H
+ #define OPENOCD_RTOS_RTOS_EMBKERNEL_STACKINGS_H
+
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+ #include "rtos.h"
+
+ extern const struct rtos_register_stacking rtos_embkernel_cortex_m_stacking;
+diff --git a/src/rtos/rtos_mqx_stackings.c b/src/rtos/rtos_mqx_stackings.c
+index 8c8fd2053..5ab743bf3 100644
+--- a/src/rtos/rtos_mqx_stackings.c
++++ b/src/rtos/rtos_mqx_stackings.c
+@@ -11,7 +11,7 @@
+
+ #include "rtos.h"
+ #include "target/armv7m.h"
+-
++#include "rtos_mqx_stackings.h"
+
+ /*
+ * standard exception stack
+diff --git a/src/rtos/rtos_mqx_stackings.h b/src/rtos/rtos_mqx_stackings.h
+index f86c05a40..faa741de6 100644
+--- a/src/rtos/rtos_mqx_stackings.h
++++ b/src/rtos/rtos_mqx_stackings.h
+@@ -8,10 +8,6 @@
+ #ifndef OPENOCD_RTOS_RTOS_MQX_STACKINGS_H
+ #define OPENOCD_RTOS_RTOS_MQX_STACKINGS_H
+
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+ #include "rtos.h"
+
+ extern const struct rtos_register_stacking rtos_mqx_arm_v7m_stacking;
+diff --git a/src/rtos/rtos_riot_stackings.c b/src/rtos/rtos_riot_stackings.c
+index e717e8cfe..e46762168 100644
+--- a/src/rtos/rtos_riot_stackings.c
++++ b/src/rtos/rtos_riot_stackings.c
+@@ -12,6 +12,7 @@
+ #include "rtos.h"
+ #include "target/armv7m.h"
+ #include "rtos_standard_stackings.h"
++#include "rtos_riot_stackings.h"
+
+ /* This works for the M0 and M34 stackings as xPSR is in a fixed
+ * location
+diff --git a/src/rtos/rtos_riot_stackings.h b/src/rtos/rtos_riot_stackings.h
+index 3b6c5f41c..ebd533756 100644
+--- a/src/rtos/rtos_riot_stackings.h
++++ b/src/rtos/rtos_riot_stackings.h
+@@ -8,14 +8,9 @@
+ #ifndef OPENOCD_RTOS_RTOS_RIOT_STACKINGS_H
+ #define OPENOCD_RTOS_RTOS_RIOT_STACKINGS_H
+
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+ #include "rtos.h"
+
+ extern const struct rtos_register_stacking rtos_riot_cortex_m0_stacking;
+ extern const struct rtos_register_stacking rtos_riot_cortex_m34_stacking;
+
+ #endif /* OPENOCD_RTOS_RTOS_RIOT_STACKINGS_H */
+-
+diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c
+index f83f0a1fb..5478080cf 100644
+--- a/src/rtos/rtos_standard_stackings.c
++++ b/src/rtos/rtos_standard_stackings.c
+@@ -11,6 +11,7 @@
+
+ #include "rtos.h"
+ #include "target/armv7m.h"
++#include "rtos_standard_stackings.h"
+
+ static const struct stack_register_offset rtos_standard_cortex_m3_stack_offsets[ARMV7M_NUM_CORE_REGS] = {
+ { ARMV7M_R0, 0x20, 32 }, /* r0 */
+diff --git a/src/rtos/rtos_standard_stackings.h b/src/rtos/rtos_standard_stackings.h
+index 2477fffd1..99fbe07e4 100644
+--- a/src/rtos/rtos_standard_stackings.h
++++ b/src/rtos/rtos_standard_stackings.h
+@@ -8,10 +8,6 @@
+ #ifndef OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H
+ #define OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H
+
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+ #include "rtos.h"
+
+ extern const struct rtos_register_stacking rtos_standard_cortex_m3_stacking;
+diff --git a/src/rtos/rtos_ucos_iii_stackings.c b/src/rtos/rtos_ucos_iii_stackings.c
+index 9ba5288bf..f1e248231 100644
+--- a/src/rtos/rtos_ucos_iii_stackings.c
++++ b/src/rtos/rtos_ucos_iii_stackings.c
+@@ -9,11 +9,11 @@
+ #include "config.h"
+ #endif
+
+-#include <helper/types.h>
+-#include <rtos/rtos.h>
+-#include <rtos/rtos_standard_stackings.h>
+-#include <target/armv7m.h>
+-#include <target/esirisc.h>
++#include "rtos.h"
++#include "target/armv7m.h"
++#include "target/esirisc.h"
++#include "rtos_standard_stackings.h"
++#include "rtos_ucos_iii_stackings.h"
+
+ static const struct stack_register_offset rtos_ucos_iii_cortex_m_stack_offsets[] = {
+ { ARMV7M_R0, 0x20, 32 }, /* r0 */
+diff --git a/src/rtos/rtos_ucos_iii_stackings.h b/src/rtos/rtos_ucos_iii_stackings.h
+index 831c68e1c..dfe60b27b 100644
+--- a/src/rtos/rtos_ucos_iii_stackings.h
++++ b/src/rtos/rtos_ucos_iii_stackings.h
+@@ -8,11 +8,7 @@
+ #ifndef OPENOCD_RTOS_RTOS_UCOS_III_STACKINGS_H
+ #define OPENOCD_RTOS_RTOS_UCOS_III_STACKINGS_H
+
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif
+-
+-#include <rtos/rtos.h>
++#include "rtos.h"
+
+ extern const struct rtos_register_stacking rtos_ucos_iii_cortex_m_stacking;
+ extern const struct rtos_register_stacking rtos_ucos_iii_esi_risc_stacking;
new file mode 100644
@@ -0,0 +1,60 @@
+From 4423e05d9df8803e2311e70d5a2ffc55a92e5676 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Mon, 28 Nov 2022 10:54:48 +0100
+Subject: [PATCH] jtag/drivers/jlink: allow SWD multidrop
+
+SW-DPv2 and SWJ-DPv2 devices do not reply to DP_TARGETSEL write cmd.
+
+Ignore the received ACK after TARGETSEL write.
+
+While on it, use swd_ack_to_error_code() for unified error code
+translation of the received ACK value for all other commands.
+
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Change-Id: If978c88c8496e31581175385e59c32faebfd20aa
+Reviewed-on: https://review.openocd.org/c/openocd/+/7383
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-by: zapb <dev@zapb.de>
+---
+ src/jtag/drivers/jlink.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
+index 0a96ac255..243d1a46b 100644
+--- a/src/jtag/drivers/jlink.c
++++ b/src/jtag/drivers/jlink.c
+@@ -1976,6 +1976,8 @@ struct pending_scan_result {
+ void *buffer;
+ /** Offset in the destination buffer */
+ unsigned buffer_offset;
++ /** SWD command */
++ uint8_t swd_cmd;
+ };
+
+ #define MAX_PENDING_SCAN_RESULTS 256
+@@ -2179,12 +2181,13 @@ static int jlink_swd_run_queue(void)
+ }
+
+ for (i = 0; i < pending_scan_results_length; i++) {
++ /* Devices do not reply to DP_TARGETSEL write cmd, ignore received ack */
++ bool check_ack = swd_cmd_returns_ack(pending_scan_results_buffer[i].swd_cmd);
+ int ack = buf_get_u32(tdo_buffer, pending_scan_results_buffer[i].first, 3);
+-
+- if (ack != SWD_ACK_OK) {
++ if (check_ack && ack != SWD_ACK_OK) {
+ LOG_DEBUG("SWD ack not OK: %d %s", ack,
+ ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
+- queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
++ queued_retval = swd_ack_to_error_code(ack);
+ goto skip;
+ } else if (pending_scan_results_buffer[i].length) {
+ uint32_t data = buf_get_u32(tdo_buffer, 3 + pending_scan_results_buffer[i].first, 32);
+@@ -2221,6 +2224,7 @@ static void jlink_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint3
+ if (queued_retval != ERROR_OK)
+ return;
+
++ pending_scan_results_buffer[pending_scan_results_length].swd_cmd = cmd;
+ cmd |= SWD_CMD_START | SWD_CMD_PARK;
+
+ jlink_queue_data_out(&cmd, 8);
new file mode 100644
@@ -0,0 +1,71 @@
+From 0b6f53e94cd81ee9c85ddc122004fa403b9cc454 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Sun, 2 Oct 2022 14:46:11 +0200
+Subject: [PATCH] tcl/target: add rescue mode to RP2040 config
+
+Integrate a rescue mode inspired by [1].
+
+The current OpenOCD must be restarted before normal work with the RP2040
+because the rescue debug port must not be activated (or the target
+is reset every 'dap init'). To continue without restarting OpenOCD
+we would need to switch off the configured rescue dap.
+
+Change-Id: Ia05b960f06747063550c166e461939d92e232830
+Link: [1] https://github.com/raspberrypi/openocd/blob/rp2040/tcl/target/rp2040-rescue.cfg
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7327
+Reviewed-by: Jonathan Bell <jonathan@raspberrypi.com>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+Tested-by: jenkins
+---
+ tcl/target/rp2040.cfg | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/tcl/target/rp2040.cfg b/tcl/target/rp2040.cfg
+index 0593e03ba..de76b4e29 100644
+--- a/tcl/target/rp2040.cfg
++++ b/tcl/target/rp2040.cfg
+@@ -26,6 +26,13 @@ if { [info exists CPUTAPID] } {
+ set _CPUTAPID 0x01002927
+ }
+
++# Set to '1' to start rescue mode
++if { [info exists RESCUE] } {
++ set _RESCUE $RESCUE
++} else {
++ set _RESCUE 0
++}
++
+ # Set to '0' or '1' for single core configuration, 'SMP' for -rtos hwthread
+ # handling of both cores, anything else for isolated debugging of both cores
+ if { [info exists USE_CORE] } {
+@@ -37,6 +44,29 @@ set _BOTH_CORES [expr { $_USE_CORE != 0 && $_USE_CORE != 1 }]
+
+ swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID
+
++# The rescue debug port uses the DP CTRL/STAT bit DBGPWRUPREQ to reset the
++# PSM (power on state machine) of the RP2040 with a flag set in the
++# VREG_AND_POR_CHIP_RESET register. Once the reset is released
++# (by clearing the DBGPWRUPREQ flag), the bootrom will run, see this flag,
++# and halt. Allowing the user to load some fresh code, rather than loading
++# the potentially broken code stored in flash
++if { $_RESCUE } {
++ dap create $_CHIPNAME.rescue_dap -chain-position $_CHIPNAME.cpu -dp-id $_CPUTAPID -instance-id 0xf -ignore-syspwrupack
++ init
++
++ # Clear DBGPWRUPREQ
++ $_CHIPNAME.rescue_dap dpreg 0x4 0x00000000
++
++ # Verifying CTRL/STAT is 0
++ set _CTRLSTAT [$_CHIPNAME.rescue_dap dpreg 0x4]
++ if {[expr {$_CTRLSTAT & 0xf0000000}]} {
++ echo "Rescue failed, DP CTRL/STAT readback $_CTRLSTAT"
++ } else {
++ echo "Now restart OpenOCD without RESCUE flag and load code to RP2040"
++ }
++ shutdown
++}
++
+ # core 0
+ if { $_USE_CORE != 1 } {
+ dap create $_CHIPNAME.dap0 -chain-position $_CHIPNAME.cpu -dp-id $_CPUTAPID -instance-id 0
new file mode 100644
@@ -0,0 +1,50 @@
+From 9d97cace0e95437137e3c57e40347dfcce39ebc9 Mon Sep 17 00:00:00 2001
+From: Daniel Serpell <daniel.serpell@gmail.com>
+Date: Tue, 24 Jan 2023 23:54:43 -0300
+Subject: [PATCH] flash/nor/spi: Add some zbit flash chips.
+
+I have a RP2020 board from aliexpress that uses the ZB25VQ32 flash, this
+allows openocd to correctly identify it with the full flash size.
+
+I also added other models, the datasheets can be found at:
+
+Link: https://datasheet.lcsc.com/lcsc/2203210916_Zbit-Semi-ZB25VQ16ASIG_C2982491.pdf
+Link: https://datasheet.lcsc.com/lcsc/2003141132_Zbit-Semi-ZB25VQ32BSIG_C495744.pdf
+Link: https://datasheet.lcsc.com/lcsc/2003141132_Zbit-Semi-ZB25VQ64ASIG_C495745.pdf
+Link: https://datasheet.lcsc.com/lcsc/2006151421_Zbit-Semi-ZB25VQ128ASIG_C609616.pdf
+
+As noted by Andreas Bolsch, the devices supporting QSPI have different
+ID in QPI mode than SPI, so two entries are needed in the table for each
+one.
+
+Use 0x0B as qread command, as this does not need the dummy M7-0
+parameters.
+
+Signed-off-by: Daniel Serpell <daniel.serpell@gmail.com>
+Change-Id: Id99187b1963b02ac1a786b66bb352f5f48ed0ac2
+Reviewed-on: https://review.openocd.org/c/openocd/+/7445
+Reviewed-by: Andreas Bolsch <hyphen0break@gmail.com>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+Tested-by: jenkins
+---
+ src/flash/nor/spi.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c
+index 373a9a144..9a606d545 100644
+--- a/src/flash/nor/spi.c
++++ b/src/flash/nor/spi.c
+@@ -112,6 +112,13 @@ const struct flash_device flash_devices[] = {
+ FLASH_ID("gd gd25q128c", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
+ FLASH_ID("gd gd25q256c", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x001940c8, 0x100, 0x10000, 0x2000000),
+ FLASH_ID("gd gd25q512mc", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x002040c8, 0x100, 0x10000, 0x4000000),
++ FLASH_ID("zbit zb25vq16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0015605e, 0x100, 0x10000, 0x200000),
++ FLASH_ID("zbit zb25vq32", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0016405e, 0x100, 0x10000, 0x400000),
++ FLASH_ID("zbit zb25vq32", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0016605e, 0x100, 0x10000, 0x400000), /* QPI mode */
++ FLASH_ID("zbit zb25vq64", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0017405e, 0x100, 0x10000, 0x800000),
++ FLASH_ID("zbit zb25vq64", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0017605e, 0x100, 0x10000, 0x800000), /* QPI mode */
++ FLASH_ID("zbit zb25vq128", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0018405e, 0x100, 0x10000, 0x1000000),
++ FLASH_ID("zbit zb25vq128", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0018605e, 0x100, 0x10000, 0x1000000), /* QPI mode */
+ FLASH_ID("issi is25lq040b", 0x03, 0xeb, 0x02, 0x20, 0xc7, 0x0013409d, 0x100, 0x1000, 0x80000),
+ FLASH_ID("issi is25lp032", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0016609d, 0x100, 0x10000, 0x400000),
+ FLASH_ID("issi is25lp064", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0017609d, 0x100, 0x10000, 0x800000),
new file mode 100644
@@ -0,0 +1,81 @@
+From 700cdbfac41014d9f3a9c12cbb13f01e59fb53d8 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 13:27:10 +0100
+Subject: [PATCH] target: arc: rewrite command 'arc jtag get-aux-reg' as
+ COMMAND_HANDLER
+
+This also fixes an incorrect return ERROR_OK from a jim command.
+
+Change-Id: I3c51355e7e05965327ce819a3114e370f2de5249
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7407
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc_cmd.c | 35 ++++++++++++-----------------------
+ 1 file changed, 12 insertions(+), 23 deletions(-)
+
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index 7a8004678..56eb0ec2d 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -318,39 +318,28 @@ static int jim_arc_set_aux_reg(Jim_Interp *interp, int argc, Jim_Obj * const *ar
+ return ERROR_OK;
+ }
+
+-static int jim_arc_get_aux_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(arc_handle_get_aux_reg)
+ {
+- struct command_context *context;
+- struct target *target;
+- uint32_t regnum;
+- uint32_t value;
+-
+- struct jim_getopt_info goi;
+- JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1));
+-
+- if (goi.argc != 1) {
+- Jim_SetResultFormatted(goi.interp,
+- "usage: %s <aux_reg_num>", Jim_GetString(argv[0], NULL));
+- return JIM_ERR;
+- }
+-
+- context = current_command_context(interp);
+- assert(context);
++ if (CMD_ARGC != 1)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- target = get_current_target(context);
++ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+- Jim_SetResultFormatted(goi.interp, "No current target");
+- return JIM_ERR;
++ command_print(CMD, "No current target");
++ return ERROR_FAIL;
+ }
+
+ /* Register number */
+- JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num));
++ uint32_t regnum;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], regnum);
+
+ struct arc_common *arc = target_to_arc(target);
+ assert(arc);
+
++ uint32_t value;
+ CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, regnum, &value));
+- Jim_SetResultInt(interp, value);
++
++ command_print(CMD, "0x%" PRIx32, value);
+
+ return ERROR_OK;
+ }
+@@ -445,7 +434,7 @@ static int jim_arc_set_core_reg(Jim_Interp *interp, int argc, Jim_Obj * const *a
+ static const struct command_registration arc_jtag_command_group[] = {
+ {
+ .name = "get-aux-reg",
+- .jim_handler = jim_arc_get_aux_reg,
++ .handler = arc_handle_get_aux_reg,
+ .mode = COMMAND_EXEC,
+ .help = "Get AUX register by number. This command does a "
+ "raw JTAG request that bypasses OpenOCD register cache "
new file mode 100644
@@ -0,0 +1,78 @@
+From 551d85b123b38d34e15b4e978250ebdfe7b952f7 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 13:32:56 +0100
+Subject: [PATCH] target: arc: rewrite command 'arc jtag set-aux-reg' as
+ COMMAND_HANDLER
+
+This also fixes an incorrect return ERROR_OK from a jim command.
+
+Change-Id: Iab9bc7c25181341a632f608a8ef2d8b0bea72520
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7408
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc_cmd.c | 35 +++++++++++------------------------
+ 1 file changed, 11 insertions(+), 24 deletions(-)
+
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index 56eb0ec2d..a6eb14f03 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -278,37 +278,24 @@ static struct jim_nvp nvp_add_reg_type_struct_opts[] = {
+ { .name = NULL, .value = -1 }
+ };
+
+-static int jim_arc_set_aux_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(arc_handle_set_aux_reg)
+ {
++ if (CMD_ARGC != 2)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- struct command_context *context;
+- struct target *target;
+- uint32_t regnum;
+- uint32_t value;
+-
+- struct jim_getopt_info goi;
+- JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1));
+-
+- if (goi.argc != 2) {
+- Jim_SetResultFormatted(goi.interp,
+- "usage: %s <aux_reg_num> <aux_reg_value>", Jim_GetString(argv[0], NULL));
+- return JIM_ERR;
+- }
+-
+- context = current_command_context(interp);
+- assert(context);
+-
+- target = get_current_target(context);
++ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+- Jim_SetResultFormatted(goi.interp, "No current target");
+- return JIM_ERR;
++ command_print(CMD, "No current target");
++ return ERROR_FAIL;
+ }
+
+ /* Register number */
+- JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num));
++ uint32_t regnum;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], regnum);
+
+ /* Register value */
+- JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &value));
++ uint32_t value;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
+
+ struct arc_common *arc = target_to_arc(target);
+ assert(arc);
+@@ -444,7 +431,7 @@ static const struct command_registration arc_jtag_command_group[] = {
+ },
+ {
+ .name = "set-aux-reg",
+- .jim_handler = jim_arc_set_aux_reg,
++ .handler = arc_handle_set_aux_reg,
+ .mode = COMMAND_EXEC,
+ .help = "Set AUX register by number. This command does a "
+ "raw JTAG request that bypasses OpenOCD register cache "
new file mode 100644
@@ -0,0 +1,89 @@
+From 16af56f6001782752d23567ca78823e2db9c5828 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 13:38:58 +0100
+Subject: [PATCH] target: arc: rewrite command 'arc jtag get-core-reg' as
+ COMMAND_HANDLER
+
+This also fixes an incorrect return ERROR_OK from a jim command.
+
+Change-Id: I1f9cf5d1dfa38b8a06042b5f54209e6ee2fc4e0e
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7409
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc_cmd.c | 39 ++++++++++++++-------------------------
+ 1 file changed, 14 insertions(+), 25 deletions(-)
+
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index a6eb14f03..cede9487b 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -331,45 +331,34 @@ COMMAND_HANDLER(arc_handle_get_aux_reg)
+ return ERROR_OK;
+ }
+
+-static int jim_arc_get_core_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(arc_handle_get_core_reg)
+ {
+- struct command_context *context;
+- struct target *target;
+- uint32_t regnum;
+- uint32_t value;
+-
+- struct jim_getopt_info goi;
+- JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1));
+-
+- if (goi.argc != 1) {
+- Jim_SetResultFormatted(goi.interp,
+- "usage: %s <core_reg_num>", Jim_GetString(argv[0], NULL));
+- return JIM_ERR;
+- }
+-
+- context = current_command_context(interp);
+- assert(context);
++ if (CMD_ARGC != 1)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- target = get_current_target(context);
++ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+- Jim_SetResultFormatted(goi.interp, "No current target");
+- return JIM_ERR;
++ command_print(CMD, "No current target");
++ return ERROR_FAIL;
+ }
+
+ /* Register number */
+- JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num));
++ uint32_t regnum;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], regnum);
+ if (regnum > CORE_REG_MAX_NUMBER || regnum == ARC_R61 || regnum == ARC_R62) {
+- Jim_SetResultFormatted(goi.interp, "Core register number %i "
++ command_print(CMD, "Core register number %i "
+ "is invalid. Must less then 64 and not 61 and 62.", regnum);
+- return JIM_ERR;
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ struct arc_common *arc = target_to_arc(target);
+ assert(arc);
+
+ /* Read value */
++ uint32_t value;
+ CHECK_RETVAL(arc_jtag_read_core_reg_one(&arc->jtag_info, regnum, &value));
+- Jim_SetResultInt(interp, value);
++
++ command_print(CMD, "0x%" PRIx32, value);
+
+ return ERROR_OK;
+ }
+@@ -441,7 +430,7 @@ static const struct command_registration arc_jtag_command_group[] = {
+ },
+ {
+ .name = "get-core-reg",
+- .jim_handler = jim_arc_get_core_reg,
++ .handler = arc_handle_get_core_reg,
+ .mode = COMMAND_EXEC,
+ .help = "Get/Set core register by number. This command does a "
+ "raw JTAG request that bypasses OpenOCD register cache "
new file mode 100644
@@ -0,0 +1,84 @@
+From f0cb5b027238f6beb0bee80a9d385716923ae6eb Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 13:44:00 +0100
+Subject: [PATCH] target: arc: rewrite command 'arc jtag set-core-reg' as
+ COMMAND_HANDLER
+
+This also fixes an incorrect return ERROR_OK from a jim command.
+
+Change-Id: I72a522645f62b99b313573c8bad6d4f674c5ae53
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7410
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc_cmd.c | 38 +++++++++++++-------------------------
+ 1 file changed, 13 insertions(+), 25 deletions(-)
+
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index cede9487b..34ddc6903 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -363,41 +363,29 @@ COMMAND_HANDLER(arc_handle_get_core_reg)
+ return ERROR_OK;
+ }
+
+-static int jim_arc_set_core_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(arc_handle_set_core_reg)
+ {
+- struct command_context *context;
+- struct target *target;
+- uint32_t regnum;
+- uint32_t value;
+-
+- struct jim_getopt_info goi;
+- JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1));
+-
+- if (goi.argc != 2) {
+- Jim_SetResultFormatted(goi.interp,
+- "usage: %s <core_reg_num> <core_reg_value>", Jim_GetString(argv[0], NULL));
+- return JIM_ERR;
+- }
+-
+- context = current_command_context(interp);
+- assert(context);
++ if (CMD_ARGC != 2)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- target = get_current_target(context);
++ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+- Jim_SetResultFormatted(goi.interp, "No current target");
+- return JIM_ERR;
++ command_print(CMD, "No current target");
++ return ERROR_FAIL;
+ }
+
+ /* Register number */
+- JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num));
++ uint32_t regnum;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], regnum);
+ if (regnum > CORE_REG_MAX_NUMBER || regnum == ARC_R61 || regnum == ARC_R62) {
+- Jim_SetResultFormatted(goi.interp, "Core register number %i "
++ command_print(CMD, "Core register number %i "
+ "is invalid. Must less then 64 and not 61 and 62.", regnum);
+- return JIM_ERR;
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ /* Register value */
+- JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &value));
++ uint32_t value;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
+
+ struct arc_common *arc = target_to_arc(target);
+ assert(arc);
+@@ -440,7 +428,7 @@ static const struct command_registration arc_jtag_command_group[] = {
+ },
+ {
+ .name = "set-core-reg",
+- .jim_handler = jim_arc_set_core_reg,
++ .handler = arc_handle_set_core_reg,
+ .mode = COMMAND_EXEC,
+ .help = "Get/Set core register by number. This command does a "
+ "raw JTAG request that bypasses OpenOCD register cache "
new file mode 100644
@@ -0,0 +1,116 @@
+From 996d6f383dfcffbc4550daedb622d3d006e8cd37 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 17:03:03 +0100
+Subject: [PATCH] target: arc: rewrite command 'arc get-reg-field' as
+ COMMAND_HANDLER
+
+This also fixes several incorrect return ERROR_xxx from a jim
+command.
+
+Change-Id: I34fe3552d3dc344eac67bf504c5d5709b707fdfd
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7411
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc_cmd.c | 51 ++++++++++++++------------------------------
+ 1 file changed, 16 insertions(+), 35 deletions(-)
+
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index 34ddc6903..264adc0b5 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -796,59 +796,40 @@ COMMAND_HANDLER(arc_set_reg_exists)
+
+ /* arc reg-field ($reg_name) ($reg_field)
+ * Reads struct type register field */
+-static int jim_arc_get_reg_field(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(arc_handle_get_reg_field)
+ {
+- struct jim_getopt_info goi;
+- const char *reg_name, *field_name;
+- uint32_t value;
+- int retval;
+-
+- JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1));
+-
+- LOG_DEBUG("Reading register field");
+- if (goi.argc != 2) {
+- if (!goi.argc)
+- Jim_WrongNumArgs(interp, goi.argc, goi.argv, "<regname> <fieldname>");
+- else if (goi.argc == 1)
+- Jim_WrongNumArgs(interp, goi.argc, goi.argv, "<fieldname>");
+- else
+- Jim_WrongNumArgs(interp, goi.argc, goi.argv, "<regname> <fieldname>");
++ if (CMD_ARGC != 2)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+- }
+-
+- JIM_CHECK_RETVAL(jim_getopt_string(&goi, ®_name, NULL));
+- JIM_CHECK_RETVAL(jim_getopt_string(&goi, &field_name, NULL));
+- assert(reg_name);
+- assert(field_name);
+
+- struct command_context * const ctx = current_command_context(interp);
+- assert(ctx);
+- struct target * const target = get_current_target(ctx);
++ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+- Jim_SetResultFormatted(goi.interp, "No current target");
+- return JIM_ERR;
++ command_print(CMD, "No current target");
++ return ERROR_FAIL;
+ }
+
+- retval = arc_reg_get_field(target, reg_name, field_name, &value);
++ const char *reg_name = CMD_ARGV[0];
++ const char *field_name = CMD_ARGV[1];
++ uint32_t value;
++ int retval = arc_reg_get_field(target, reg_name, field_name, &value);
+
+ switch (retval) {
+ case ERROR_OK:
+ break;
+ case ERROR_ARC_REGISTER_NOT_FOUND:
+- Jim_SetResultFormatted(goi.interp,
++ command_print(CMD,
+ "Register `%s' has not been found.", reg_name);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ case ERROR_ARC_REGISTER_IS_NOT_STRUCT:
+- Jim_SetResultFormatted(goi.interp,
++ command_print(CMD,
+ "Register `%s' must have 'struct' type.", reg_name);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ case ERROR_ARC_REGISTER_FIELD_NOT_FOUND:
+- Jim_SetResultFormatted(goi.interp,
++ command_print(CMD,
+ "Field `%s' has not been found in register `%s'.",
+ field_name, reg_name);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ case ERROR_ARC_FIELD_IS_NOT_BITFIELD:
+- Jim_SetResultFormatted(goi.interp,
++ command_print(CMD,
+ "Field `%s' is not a 'bitfield' field in a structure.",
+ field_name);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+@@ -857,9 +838,9 @@ static int jim_arc_get_reg_field(Jim_Interp *interp, int argc, Jim_Obj * const *
+ return retval;
+ }
+
+- Jim_SetResultInt(interp, value);
++ command_print(CMD, "0x%" PRIx32, value);
+
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ COMMAND_HANDLER(arc_l1_cache_disable_auto_cmd)
+@@ -1002,7 +983,7 @@ static const struct command_registration arc_core_command_handlers[] = {
+ },
+ {
+ .name = "get-reg-field",
+- .jim_handler = jim_arc_get_reg_field,
++ .handler = arc_handle_get_reg_field,
+ .mode = COMMAND_ANY,
+ .usage = "<regname> <field_name>",
+ .help = "Returns value of field in a register with 'struct' type.",
new file mode 100644
@@ -0,0 +1,105 @@
+From da76ba610b8e6b05de3a837926d06f8e7d964b97 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 17:14:15 +0100
+Subject: [PATCH] target: arc: rewrite command 'arc num-actionpoints' as
+ COMMAND_HANDLER
+
+Also drop arc_cmd_jim_get_uint32() that is now unused.
+
+Change-Id: Ic26c3f008376db3f01215bf736fca736dd1c1a4f
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7412
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc_cmd.c | 44 +++++++++++++-------------------------------
+ 1 file changed, 13 insertions(+), 31 deletions(-)
+
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index 264adc0b5..e7c54446e 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -22,14 +22,6 @@
+ * ------------------------------------------------------------------------- */
+
+
+-static int arc_cmd_jim_get_uint32(struct jim_getopt_info *goi, uint32_t *value)
+-{
+- jim_wide value_wide;
+- JIM_CHECK_RETVAL(jim_getopt_wide(goi, &value_wide));
+- *value = (uint32_t)value_wide;
+- return JIM_OK;
+-}
+-
+ enum add_reg_types {
+ CFG_ADD_REG_TYPE_FLAG,
+ CFG_ADD_REG_TYPE_STRUCT,
+@@ -863,27 +855,17 @@ COMMAND_HANDLER(arc_l2_cache_disable_auto_cmd)
+ &arc->has_l2cache, "target has l2 cache enabled");
+ }
+
+-static int jim_handle_actionpoints_num(Jim_Interp *interp, int argc,
+- Jim_Obj * const *argv)
++COMMAND_HANDLER(arc_handle_actionpoints_num)
+ {
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc - 1, argv + 1);
+-
+ LOG_DEBUG("-");
+
+- if (goi.argc >= 2) {
+- Jim_WrongNumArgs(interp, goi.argc, goi.argv, "[<unsigned integer>]");
+- return JIM_ERR;
+- }
+-
+- struct command_context *context = current_command_context(interp);
+- assert(context);
+-
+- struct target *target = get_current_target(context);
++ if (CMD_ARGC >= 2)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
++ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+- Jim_SetResultFormatted(goi.interp, "No current target");
+- return JIM_ERR;
++ command_print(CMD, "No current target");
++ return ERROR_FAIL;
+ }
+
+ struct arc_common *arc = target_to_arc(target);
+@@ -892,19 +874,19 @@ static int jim_handle_actionpoints_num(Jim_Interp *interp, int argc,
+ * "actionpoint reset, initiated by arc_set_actionpoints_num. */
+ uint32_t ap_num = arc->actionpoints_num;
+
+- if (goi.argc == 1) {
+- JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &ap_num));
++ if (CMD_ARGC == 1) {
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], ap_num);
+ int e = arc_set_actionpoints_num(target, ap_num);
+ if (e != ERROR_OK) {
+- Jim_SetResultFormatted(goi.interp,
++ command_print(CMD,
+ "Failed to set number of actionpoints");
+- return JIM_ERR;
++ return e;
+ }
+ }
+
+- Jim_SetResultInt(interp, ap_num);
++ command_print(CMD, "%" PRIu32, ap_num);
+
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ /* ----- Exported target commands ------------------------------------------ */
+@@ -1004,7 +986,7 @@ static const struct command_registration arc_core_command_handlers[] = {
+ },
+ {
+ .name = "num-actionpoints",
+- .jim_handler = jim_handle_actionpoints_num,
++ .handler = arc_handle_actionpoints_num,
+ .mode = COMMAND_ANY,
+ .usage = "[<unsigned integer>]",
+ .help = "Prints or sets amount of actionpoints in the processor.",
new file mode 100644
@@ -0,0 +1,40 @@
+From 18bafdce615132311fd34f2e1bdf57c193d14097 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 17:20:06 +0100
+Subject: [PATCH] target: arc: fix error handling in command 'arc
+ set-reg-exists'
+
+The command is specified through COMMAND_HANDLER. It should not
+return JIM_OK / JIM_ERR.
+
+Change-Id: I56666414d49b0298ecc23ec7ef30c77e1e27afa8
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7413
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc_cmd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index e7c54446e..fb1817de6 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -763,7 +763,7 @@ COMMAND_HANDLER(arc_set_reg_exists)
+ struct target * const target = get_current_target(CMD_CTX);
+ if (!target) {
+ command_print(CMD, "Unable to get current target.");
+- return JIM_ERR;
++ return ERROR_FAIL;
+ }
+
+ if (!CMD_ARGC) {
+@@ -783,7 +783,7 @@ COMMAND_HANDLER(arc_set_reg_exists)
+ r->exist = true;
+ }
+
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ /* arc reg-field ($reg_name) ($reg_field)
new file mode 100644
@@ -0,0 +1,205 @@
+From ea6a99208e1bc41a878234f7220501e26ec4a7f1 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 26 Dec 2022 21:59:56 +0100
+Subject: [PATCH] helper: nvp: add openocd nvp files
+
+Long ago jim_nvp was part of jimtcl. When jimtcl dropped it,
+OpenOCD kept copy of it in its code base. Current code of jim_nvp
+is still related with jimtcl data types and functions.
+
+With the target of better isolating OpenOCD code from jimtcl,
+create a new file nvp.c that re-proposes only the core of the old
+jim_nvp, dropping any link with jimtcl and removing the string
+'jim' either from the filename and from the code.
+Keep the same license from the old code, as the new files are
+clearly derived from it.
+
+Change-Id: I273448cf1f1484b10f6b6113ed7bb0fcf946482b
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7423
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/helper/Makefile.am | 4 ++-
+ src/helper/nvp.c | 67 +++++++++++++++++++++++++++++++++++++
+ src/helper/nvp.h | 75 ++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 145 insertions(+), 1 deletion(-)
+ create mode 100644 src/helper/nvp.c
+ create mode 100644 src/helper/nvp.h
+
+diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am
+index c4c60d96b..e9c05cfc5 100644
+--- a/src/helper/Makefile.am
++++ b/src/helper/Makefile.am
+@@ -16,6 +16,7 @@ noinst_LTLIBRARIES += %D%/libhelper.la
+ %D%/util.c \
+ %D%/jep106.c \
+ %D%/jim-nvp.c \
++ %D%/nvp.c \
+ %D%/align.h \
+ %D%/binarybuffer.h \
+ %D%/bits.h \
+@@ -32,7 +33,8 @@ noinst_LTLIBRARIES += %D%/libhelper.la
+ %D%/system.h \
+ %D%/jep106.h \
+ %D%/jep106.inc \
+- %D%/jim-nvp.h
++ %D%/jim-nvp.h \
++ %D%/nvp.h
+
+ STARTUP_TCL_SRCS += %D%/startup.tcl
+ EXTRA_DIST += \
+diff --git a/src/helper/nvp.c b/src/helper/nvp.c
+new file mode 100644
+index 000000000..7a8abc2e2
+--- /dev/null
++++ b/src/helper/nvp.c
+@@ -0,0 +1,67 @@
++// SPDX-License-Identifier: BSD-2-Clause-Views
++
++/*
++ * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
++ * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
++ * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
++ * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
++ * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
++ * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
++ * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
++ * Copyright 2008 Steve Bennett <steveb@workware.net.au>
++ * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl>
++ * Copyright 2009 Zachary T Welch zw@superlucidity.net
++ * Copyright 2009 David Brownell
++ * Copyright (c) 2005-2011 Jim Tcl Project. All rights reserved.
++ *
++ * This file is extracted from jim_nvp.c, originally part of jim TCL code.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <string.h>
++
++#include <helper/command.h>
++#include <helper/nvp.h>
++
++const struct nvp *nvp_name2value(const struct nvp *p, const char *name)
++{
++ while (p->name) {
++ if (strcmp(name, p->name) == 0)
++ break;
++ p++;
++ }
++ return p;
++}
++
++const struct nvp *nvp_value2name(const struct nvp *p, int value)
++{
++ while (p->name) {
++ if (value == p->value)
++ break;
++ p++;
++ }
++ return p;
++}
++
++void nvp_unknown_command_print(struct command_invocation *cmd, const struct nvp *nvp,
++ const char *param_name, const char *param_value)
++{
++ if (param_name)
++ command_print_sameline(cmd, "%s: Unknown: %s, try one of: ", param_name, param_value);
++ else
++ command_print_sameline(cmd, "Unknown param: %s, try one of: ", param_value);
++
++ while (nvp->name) {
++ if ((nvp + 1)->name)
++ command_print_sameline(cmd, "%s, ", nvp->name);
++ else
++ command_print(cmd, "or %s", nvp->name);
++
++ nvp++;
++ }
++
++ /* We assume nvp to be not empty and loop has been taken; no need to add a '\n' */
++}
+diff --git a/src/helper/nvp.h b/src/helper/nvp.h
+new file mode 100644
+index 000000000..125164e4e
+--- /dev/null
++++ b/src/helper/nvp.h
+@@ -0,0 +1,75 @@
++/* SPDX-License-Identifier: BSD-2-Clause-Views */
++
++/*
++ * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
++ * Copyright 2005 Clemens Hintze <c.hintze@gmx.net>
++ * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net>
++ * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com
++ * Copyright 2008 Andrew Lunn <andrew@lunn.ch>
++ * Copyright 2008 Duane Ellis <openocd@duaneellis.com>
++ * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de>
++ * Copyright 2008 Steve Bennett <steveb@workware.net.au>
++ * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl>
++ * Copyright 2009 Zachary T Welch zw@superlucidity.net
++ * Copyright 2009 David Brownell
++ * Copyright (c) 2005-2011 Jim Tcl Project. All rights reserved.
++ *
++ * This file is extracted from jim_nvp.h, originally part of jim TCL code.
++ */
++
++#ifndef OPENOCD_HELPER_NVP_H
++#define OPENOCD_HELPER_NVP_H
++
++/** Name Value Pairs, aka: NVP
++ * - Given a string - return the associated int.
++ * - Given a number - return the associated string.
++ * .
++ *
++ * Very useful when the number is not a simple index into an array of
++ * known string, or there may be multiple strings (aliases) that mean then same
++ * thing.
++ *
++ * An NVP Table is terminated with ".name = NULL".
++ *
++ * During the 'name2value' operation, if no matching string is found
++ * the pointer to the terminal element (with p->name == NULL) is returned.
++ *
++ * Example:
++ * \code
++ * const struct nvp yn[] = {
++ * { "yes", 1 },
++ * { "no" , 0 },
++ * { "yep", 1 },
++ * { "nope", 0 },
++ * { NULL, -1 },
++ * };
++ *
++ * struct nvp *result;
++ * result = nvp_name2value(yn, "yes");
++ * returns &yn[0];
++ * result = nvp_name2value(yn, "no");
++ * returns &yn[1];
++ * result = jim_nvp_name2value(yn, "Blah");
++ * returns &yn[4];
++ * \endcode
++ *
++ * During the number2name operation, the first matching value is returned.
++ */
++
++struct nvp {
++ const char *name;
++ int value;
++};
++
++struct command_invocation;
++
++/* Name Value Pairs Operations */
++const struct nvp *nvp_name2value(const struct nvp *nvp_table, const char *name)
++ __attribute__((returns_nonnull, nonnull(1)));
++const struct nvp *nvp_value2name(const struct nvp *nvp_table, int v)
++ __attribute__((returns_nonnull, nonnull(1)));
++
++void nvp_unknown_command_print(struct command_invocation *cmd, const struct nvp *nvp,
++ const char *param_name, const char *param_value);
++
++#endif /* OPENOCD_HELPER_NVP_H */
new file mode 100644
@@ -0,0 +1,293 @@
+From 92ef27494c510a2df7cbbee8b19d5c0d4d943d40 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Tue, 27 Dec 2022 00:28:16 +0100
+Subject: [PATCH] target: arc: rewrite command 'arc add-reg-type-flags' as
+ COMMAND_HANDLER
+
+Use a COMMAND_HELPER() to avoid memory leaks when the helper
+COMMAND_PARSE_NUMBER() returns due to an error.
+
+While there:
+- fix potential SIGSEGV due to dereference 'type' before checking
+ it's not NULL;
+- fix an incorrect NUL byte termination while copying to
+ type->data_type.id and to bitfields[cur_field].name;
+- fix some coding style error.
+
+Change-Id: Ide4cbc829871a6a523026ccc0d3100dadc2afd06
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7424
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc_cmd.c | 197 +++++++++++++++++++++----------------------
+ 1 file changed, 94 insertions(+), 103 deletions(-)
+
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index fb1817de6..32c62d0ca 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -13,6 +13,7 @@
+ #endif
+
+ #include "arc.h"
++#include <helper/nvp.h>
+
+ /* --------------------------------------------------------------------------
+ *
+@@ -32,7 +33,7 @@ enum add_reg_type_flags {
+ CFG_ADD_REG_TYPE_FLAGS_FLAG,
+ };
+
+-static struct jim_nvp nvp_add_reg_type_flags_opts[] = {
++static const struct nvp nvp_add_reg_type_flags_opts[] = {
+ { .name = "-name", .value = CFG_ADD_REG_TYPE_FLAGS_NAME },
+ { .name = "-flag", .value = CFG_ADD_REG_TYPE_FLAGS_FLAG },
+ { .name = NULL, .value = -1 }
+@@ -114,53 +115,113 @@ static int jim_arc_read_reg_type_field(struct jim_getopt_info *goi, const char *
+ return e;
+ }
+
+-static int jim_arc_add_reg_type_flags(Jim_Interp *interp, int argc,
+- Jim_Obj * const *argv)
++static COMMAND_HELPER(arc_handle_add_reg_type_flags_ops, struct arc_reg_data_type *type)
+ {
+- struct jim_getopt_info goi;
+- JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1));
++ struct reg_data_type_flags_field *fields = type->reg_type_flags_field;
++ struct arc_reg_bitfield *bitfields = type->bitfields;
++ struct reg_data_type_flags *flags = &type->data_type_flags;
++ unsigned int cur_field = 0;
+
+- LOG_DEBUG("-");
++ while (CMD_ARGC) {
++ const struct nvp *n = nvp_name2value(nvp_add_reg_type_flags_opts, CMD_ARGV[0]);
++ CMD_ARGC--;
++ CMD_ARGV++;
++ switch (n->value) {
++ case CFG_ADD_REG_TYPE_FLAGS_NAME:
++ if (!CMD_ARGC)
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+
+- struct command_context *ctx;
+- struct target *target;
++ const char *name = CMD_ARGV[0];
++ CMD_ARGC--;
++ CMD_ARGV++;
+
+- ctx = current_command_context(interp);
+- assert(ctx);
+- target = get_current_target(ctx);
+- if (!target) {
+- Jim_SetResultFormatted(goi.interp, "No current target");
+- return JIM_ERR;
++ if (strlen(name) >= REG_TYPE_MAX_NAME_LENGTH) {
++ command_print(CMD, "Reg type name is too big.");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
++
++ strcpy((void *)type->data_type.id, name);
++ break;
++
++ case CFG_ADD_REG_TYPE_FLAGS_FLAG:
++ if (CMD_ARGC < 2)
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++
++ uint32_t val;
++ const char *field_name = CMD_ARGV[0];
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], val);
++ CMD_ARGC -= 2;
++ CMD_ARGV += 2;
++ bitfields[cur_field].bitfield.start = val;
++ bitfields[cur_field].bitfield.end = val;
++
++ if (strlen(field_name) >= REG_TYPE_MAX_NAME_LENGTH) {
++ command_print(CMD, "Reg type field_name is too big.");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
++
++ fields[cur_field].name = bitfields[cur_field].name;
++ strcpy(bitfields[cur_field].name, field_name);
++
++ fields[cur_field].bitfield = &bitfields[cur_field].bitfield;
++ if (cur_field > 0)
++ fields[cur_field - 1].next = &fields[cur_field];
++ else
++ flags->fields = fields;
++
++ cur_field += 1;
++ break;
++
++ default:
++ nvp_unknown_command_print(CMD, nvp_add_reg_type_flags_opts, NULL, CMD_ARGV[-1]);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
+ }
+
+- int e = JIM_OK;
++ if (!type->data_type.id) {
++ command_print(CMD, "-name is a required option");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
+
+- /* Check if the amount of arguments is not zero */
+- if (goi.argc <= 0) {
+- Jim_SetResultFormatted(goi.interp, "The command has no arguments");
+- return JIM_ERR;
++ return ERROR_OK;
++}
++
++COMMAND_HANDLER(arc_handle_add_reg_type_flags)
++{
++ int retval;
++
++ LOG_DEBUG("-");
++
++ struct target *target = get_current_target(CMD_CTX);
++ if (!target) {
++ command_print(CMD, "No current target");
++ return ERROR_FAIL;
+ }
+
++ /* Check if the amount of arguments is not zero */
++ if (CMD_ARGC == 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
+ /* Estimate number of registers as (argc - 2)/3 as each -flag option has 2
+ * arguments while -name is required. */
+- unsigned int fields_sz = (goi.argc - 2) / 3;
+- unsigned int cur_field = 0;
++ unsigned int fields_sz = (CMD_ARGC - 2) / 3;
+
+ /* The maximum amount of bitfields is 32 */
+ if (fields_sz > 32) {
+- Jim_SetResultFormatted(goi.interp, "The amount of bitfields exceed 32");
+- return JIM_ERR;
++ command_print(CMD, "The amount of bitfields exceed 32");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ struct arc_reg_data_type *type = calloc(1, sizeof(*type));
+- struct reg_data_type_flags *flags = &type->data_type_flags;
+ struct reg_data_type_flags_field *fields = calloc(fields_sz, sizeof(*fields));
+- type->reg_type_flags_field = fields;
+ struct arc_reg_bitfield *bitfields = calloc(fields_sz, sizeof(*bitfields));
+- if (!(type && fields && bitfields)) {
+- Jim_SetResultFormatted(goi.interp, "Failed to allocate memory.");
++ if (!type || !fields || !bitfields) {
++ LOG_ERROR("Out of memory");
++ retval = ERROR_FAIL;
+ goto fail;
+ }
++ struct reg_data_type_flags *flags = &type->data_type_flags;
++ type->reg_type_flags_field = fields;
+
+ /* Initialize type */
+ type->bitfields = bitfields;
+@@ -170,92 +231,22 @@ static int jim_arc_add_reg_type_flags(Jim_Interp *interp, int argc,
+ type->data_type.reg_type_flags = flags;
+ flags->size = 4; /* For now ARC has only 32-bit registers */
+
+- while (goi.argc > 0 && e == JIM_OK) {
+- struct jim_nvp *n;
+- e = jim_getopt_nvp(&goi, nvp_add_reg_type_flags_opts, &n);
+- if (e != JIM_OK) {
+- jim_getopt_nvp_unknown(&goi, nvp_add_reg_type_flags_opts, 0);
+- continue;
+- }
+-
+- switch (n->value) {
+- case CFG_ADD_REG_TYPE_FLAGS_NAME:
+- {
+- const char *name = NULL;
+- int name_len = 0;
+-
+- e = jim_arc_read_reg_name_field(&goi, &name, &name_len);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi.interp, "Unable to read reg name.");
+- goto fail;
+- }
+-
+- if (name_len > REG_TYPE_MAX_NAME_LENGTH) {
+- Jim_SetResultFormatted(goi.interp, "Reg type name is too big.");
+- goto fail;
+- }
+-
+- strncpy((void *)type->data_type.id, name, name_len);
+- if (!type->data_type.id) {
+- Jim_SetResultFormatted(goi.interp, "Unable to setup reg type name.");
+- goto fail;
+- }
+-
+- break;
+- }
+-
+- case CFG_ADD_REG_TYPE_FLAGS_FLAG:
+- {
+- const char *field_name = NULL;
+- int field_name_len = 0;
+-
+- e = jim_arc_read_reg_type_field(&goi, &field_name, &field_name_len, bitfields,
+- cur_field, CFG_ADD_REG_TYPE_FLAG);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi.interp, "Unable to add reg_type_flag field.");
+- goto fail;
+- }
+-
+- if (field_name_len > REG_TYPE_MAX_NAME_LENGTH) {
+- Jim_SetResultFormatted(goi.interp, "Reg type field_name_len is too big.");
+- goto fail;
+- }
+-
+- fields[cur_field].name = bitfields[cur_field].name;
+- strncpy(bitfields[cur_field].name, field_name, field_name_len);
+- if (!fields[cur_field].name) {
+- Jim_SetResultFormatted(goi.interp, "Unable to setup field name. ");
+- goto fail;
+- }
+-
+- fields[cur_field].bitfield = &(bitfields[cur_field].bitfield);
+- if (cur_field > 0)
+- fields[cur_field - 1].next = &(fields[cur_field]);
+- else
+- flags->fields = fields;
+-
+- cur_field += 1;
+- break;
+- }
+- }
+- }
+-
+- if (!type->data_type.id) {
+- Jim_SetResultFormatted(goi.interp, "-name is a required option");
++ retval = CALL_COMMAND_HANDLER(arc_handle_add_reg_type_flags_ops, type);
++ if (retval != ERROR_OK)
+ goto fail;
+- }
+
+ arc_reg_data_type_add(target, type);
+
+ LOG_DEBUG("added flags type {name=%s}", type->data_type.id);
+
+- return JIM_OK;
++ return ERROR_OK;
++
+ fail:
+ free(type);
+ free(fields);
+ free(bitfields);
+
+- return JIM_ERR;
++ return retval;
+ }
+
+ /* Add struct register data type */
+@@ -924,7 +915,7 @@ static const struct command_registration arc_cache_group_handlers[] = {
+ static const struct command_registration arc_core_command_handlers[] = {
+ {
+ .name = "add-reg-type-flags",
+- .jim_handler = jim_arc_add_reg_type_flags,
++ .handler = arc_handle_add_reg_type_flags,
+ .mode = COMMAND_CONFIG,
+ .usage = "-name <string> -flag <name> <position> "
+ "[-flag <name> <position>]...",
new file mode 100644
@@ -0,0 +1,345 @@
+From 85f3b10a6914fd44c8f32d345654bed371d0667d Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Tue, 27 Dec 2022 00:56:55 +0100
+Subject: [PATCH] target: arc: rewrite command 'arc add-reg-type-struct' as
+ COMMAND_HANDLER
+
+Use a COMMAND_HELPER() to avoid memory leaks when the helper
+COMMAND_PARSE_NUMBER() returns due to an error.
+
+While there:
+- fix potential SIGSEGV due to dereference 'type' before checking
+ it's not NULL;
+- fix an incorrect NUL byte termination while copying to
+ type->data_type.id and to bitfields[cur_field].name;
+- fix some coding style error;
+- remove the now unused function jim_arc_read_reg_type_field().
+
+Change-Id: I7158fd93b5d4742f11654b8ae4a7abd409ad06e2
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7425
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc_cmd.c | 252 +++++++++++++++++--------------------------
+ 1 file changed, 101 insertions(+), 151 deletions(-)
+
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index 32c62d0ca..3b0bf76f8 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -70,51 +70,6 @@ static int jim_arc_read_reg_name_field(struct jim_getopt_info *goi,
+ return e;
+ }
+
+-/* Helper function to read bitfields/flags of register type. */
+-static int jim_arc_read_reg_type_field(struct jim_getopt_info *goi, const char **field_name, int *field_name_len,
+- struct arc_reg_bitfield *bitfields, int cur_field, int type)
+-{
+- jim_wide start_pos, end_pos;
+-
+- int e = JIM_OK;
+- if ((type == CFG_ADD_REG_TYPE_STRUCT && goi->argc < 3) ||
+- (type == CFG_ADD_REG_TYPE_FLAG && goi->argc < 2)) {
+- Jim_SetResultFormatted(goi->interp, "Not enough arguments after -flag/-bitfield");
+- return JIM_ERR;
+- }
+-
+- e = jim_getopt_string(goi, field_name, field_name_len);
+- if (e != JIM_OK)
+- return e;
+-
+- /* read start position of bitfield/flag */
+- e = jim_getopt_wide(goi, &start_pos);
+- if (e != JIM_OK)
+- return e;
+-
+- end_pos = start_pos;
+-
+- /* Check if any arguments remain,
+- * set bitfields[cur_field].end if flag is multibit */
+- if (goi->argc > 0)
+- /* Check current argv[0], if it is equal to "-flag",
+- * than bitfields[cur_field].end remains start */
+- if ((strcmp(Jim_String(goi->argv[0]), "-flag") && type == CFG_ADD_REG_TYPE_FLAG)
+- || (type == CFG_ADD_REG_TYPE_STRUCT)) {
+- e = jim_getopt_wide(goi, &end_pos);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi->interp, "Error reading end position");
+- return e;
+- }
+- }
+-
+- bitfields[cur_field].bitfield.start = start_pos;
+- bitfields[cur_field].bitfield.end = end_pos;
+- if ((end_pos != start_pos) || (type == CFG_ADD_REG_TYPE_STRUCT))
+- bitfields[cur_field].bitfield.type = REG_TYPE_INT;
+- return e;
+-}
+-
+ static COMMAND_HELPER(arc_handle_add_reg_type_flags_ops, struct arc_reg_data_type *type)
+ {
+ struct reg_data_type_flags_field *fields = type->reg_type_flags_field;
+@@ -255,7 +210,7 @@ enum add_reg_type_struct {
+ CFG_ADD_REG_TYPE_STRUCT_BITFIELD,
+ };
+
+-static struct jim_nvp nvp_add_reg_type_struct_opts[] = {
++static const struct nvp nvp_add_reg_type_struct_opts[] = {
+ { .name = "-name", .value = CFG_ADD_REG_TYPE_STRUCT_NAME },
+ { .name = "-bitfield", .value = CFG_ADD_REG_TYPE_STRUCT_BITFIELD },
+ { .name = NULL, .value = -1 }
+@@ -424,53 +379,117 @@ static const struct command_registration arc_jtag_command_group[] = {
+
+
+ /* This function supports only bitfields. */
+-static int jim_arc_add_reg_type_struct(Jim_Interp *interp, int argc,
+- Jim_Obj * const *argv)
++static COMMAND_HELPER(arc_handle_add_reg_type_struct_opts, struct arc_reg_data_type *type)
+ {
+- struct jim_getopt_info goi;
+- JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1));
++ struct reg_data_type_struct_field *fields = type->reg_type_struct_field;
++ struct arc_reg_bitfield *bitfields = type->bitfields;
++ struct reg_data_type_struct *struct_type = &type->data_type_struct;
++ unsigned int cur_field = 0;
+
+- LOG_DEBUG("-");
++ while (CMD_ARGC) {
++ const struct nvp *n = nvp_name2value(nvp_add_reg_type_struct_opts, CMD_ARGV[0]);
++ CMD_ARGC--;
++ CMD_ARGV++;
++ switch (n->value) {
++ case CFG_ADD_REG_TYPE_STRUCT_NAME:
++ if (!CMD_ARGC)
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+
+- struct command_context *ctx;
+- struct target *target;
++ const char *name = CMD_ARGV[0];
++ CMD_ARGC--;
++ CMD_ARGV++;
+
+- ctx = current_command_context(interp);
+- assert(ctx);
+- target = get_current_target(ctx);
+- if (!target) {
+- Jim_SetResultFormatted(goi.interp, "No current target");
+- return JIM_ERR;
++ if (strlen(name) >= REG_TYPE_MAX_NAME_LENGTH) {
++ command_print(CMD, "Reg type name is too big.");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
++
++ strcpy((void *)type->data_type.id, name);
++ break;
++
++ case CFG_ADD_REG_TYPE_STRUCT_BITFIELD:
++ if (CMD_ARGC < 3)
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++
++ uint32_t start_pos, end_pos;
++ const char *field_name = CMD_ARGV[0];
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], start_pos);
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], end_pos);
++ CMD_ARGC -= 3;
++ CMD_ARGV += 3;
++ bitfields[cur_field].bitfield.start = start_pos;
++ bitfields[cur_field].bitfield.end = end_pos;
++ bitfields[cur_field].bitfield.type = REG_TYPE_INT;
++
++ if (strlen(field_name) >= REG_TYPE_MAX_NAME_LENGTH) {
++ command_print(CMD, "Reg type field_name is too big.");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
++
++ fields[cur_field].name = bitfields[cur_field].name;
++ strcpy(bitfields[cur_field].name, field_name);
++
++ fields[cur_field].bitfield = &bitfields[cur_field].bitfield;
++ fields[cur_field].use_bitfields = true;
++ if (cur_field > 0)
++ fields[cur_field - 1].next = &fields[cur_field];
++ else
++ struct_type->fields = fields;
++
++ cur_field += 1;
++
++ break;
++
++ default:
++ nvp_unknown_command_print(CMD, nvp_add_reg_type_struct_opts, NULL, CMD_ARGV[-1]);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
+ }
+
+- int e = JIM_OK;
++ if (!type->data_type.id) {
++ command_print(CMD, "-name is a required option");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
+
+- /* Check if the amount of arguments is not zero */
+- if (goi.argc <= 0) {
+- Jim_SetResultFormatted(goi.interp, "The command has no arguments");
+- return JIM_ERR;
++ return ERROR_OK;
++}
++
++COMMAND_HANDLER(arc_handle_add_reg_type_struct)
++{
++ int retval;
++
++ LOG_DEBUG("-");
++
++ struct target *target = get_current_target(CMD_CTX);
++ if (!target) {
++ command_print(CMD, "No current target");
++ return ERROR_FAIL;
+ }
+
++ /* Check if the amount of arguments is not zero */
++ if (CMD_ARGC == 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
+ /* Estimate number of registers as (argc - 2)/4 as each -bitfield option has 3
+ * arguments while -name is required. */
+- unsigned int fields_sz = (goi.argc - 2) / 4;
+- unsigned int cur_field = 0;
++ unsigned int fields_sz = (CMD_ARGC - 2) / 4;
+
+ /* The maximum amount of bitfields is 32 */
+ if (fields_sz > 32) {
+- Jim_SetResultFormatted(goi.interp, "The amount of bitfields exceed 32");
+- return JIM_ERR;
++ command_print(CMD, "The amount of bitfields exceed 32");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ struct arc_reg_data_type *type = calloc(1, sizeof(*type));
+- struct reg_data_type_struct *struct_type = &type->data_type_struct;
+ struct reg_data_type_struct_field *fields = calloc(fields_sz, sizeof(*fields));
+- type->reg_type_struct_field = fields;
+ struct arc_reg_bitfield *bitfields = calloc(fields_sz, sizeof(*bitfields));
+- if (!(type && fields && bitfields)) {
+- Jim_SetResultFormatted(goi.interp, "Failed to allocate memory.");
++ if (!type || !fields || !bitfields) {
++ LOG_ERROR("Out of memory");
++ retval = ERROR_FAIL;
+ goto fail;
+ }
++ struct reg_data_type_struct *struct_type = &type->data_type_struct;
++ type->reg_type_struct_field = fields;
+
+ /* Initialize type */
+ type->data_type.id = type->data_type_id;
+@@ -480,91 +499,22 @@ static int jim_arc_add_reg_type_struct(Jim_Interp *interp, int argc,
+ type->data_type.reg_type_struct = struct_type;
+ struct_type->size = 4; /* For now ARC has only 32-bit registers */
+
+- while (goi.argc > 0 && e == JIM_OK) {
+- struct jim_nvp *n;
+- e = jim_getopt_nvp(&goi, nvp_add_reg_type_struct_opts, &n);
+- if (e != JIM_OK) {
+- jim_getopt_nvp_unknown(&goi, nvp_add_reg_type_struct_opts, 0);
+- continue;
+- }
+-
+- switch (n->value) {
+- case CFG_ADD_REG_TYPE_STRUCT_NAME:
+- {
+- const char *name = NULL;
+- int name_len = 0;
+-
+- e = jim_arc_read_reg_name_field(&goi, &name, &name_len);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi.interp, "Unable to read reg name.");
+- goto fail;
+- }
+-
+- if (name_len > REG_TYPE_MAX_NAME_LENGTH) {
+- Jim_SetResultFormatted(goi.interp, "Reg type name is too big.");
+- goto fail;
+- }
+-
+- strncpy((void *)type->data_type.id, name, name_len);
+- if (!type->data_type.id) {
+- Jim_SetResultFormatted(goi.interp, "Unable to setup reg type name.");
+- goto fail;
+- }
+-
+- break;
+- }
+- case CFG_ADD_REG_TYPE_STRUCT_BITFIELD:
+- {
+- const char *field_name = NULL;
+- int field_name_len = 0;
+- e = jim_arc_read_reg_type_field(&goi, &field_name, &field_name_len, bitfields,
+- cur_field, CFG_ADD_REG_TYPE_STRUCT);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi.interp, "Unable to add reg_type_struct field.");
+- goto fail;
+- }
+-
+- if (field_name_len > REG_TYPE_MAX_NAME_LENGTH) {
+- Jim_SetResultFormatted(goi.interp, "Reg type field_name_len is too big.");
+- goto fail;
+- }
+-
+- fields[cur_field].name = bitfields[cur_field].name;
+- strncpy(bitfields[cur_field].name, field_name, field_name_len);
+- if (!fields[cur_field].name) {
+- Jim_SetResultFormatted(goi.interp, "Unable to setup field name. ");
+- goto fail;
+- }
+-
+- fields[cur_field].bitfield = &(bitfields[cur_field].bitfield);
+- fields[cur_field].use_bitfields = true;
+- if (cur_field > 0)
+- fields[cur_field - 1].next = &(fields[cur_field]);
+- else
+- struct_type->fields = fields;
+-
+- cur_field += 1;
+-
+- break;
+- }
+- }
+- }
+-
+- if (!type->data_type.id) {
+- Jim_SetResultFormatted(goi.interp, "-name is a required option");
++ retval = CALL_COMMAND_HANDLER(arc_handle_add_reg_type_struct_opts, type);
++ if (retval != ERROR_OK)
+ goto fail;
+- }
+
+ arc_reg_data_type_add(target, type);
++
+ LOG_DEBUG("added struct type {name=%s}", type->data_type.id);
+- return JIM_OK;
++
++ return ERROR_OK;
+
+ fail:
+- free(type);
+- free(fields);
+- free(bitfields);
++ free(type);
++ free(fields);
++ free(bitfields);
+
+- return JIM_ERR;
++ return retval;
+ }
+
+ /* Add register */
+@@ -925,7 +875,7 @@ static const struct command_registration arc_core_command_handlers[] = {
+ },
+ {
+ .name = "add-reg-type-struct",
+- .jim_handler = jim_arc_add_reg_type_struct,
++ .handler = arc_handle_add_reg_type_struct,
+ .mode = COMMAND_CONFIG,
+ .usage = "-name <string> -bitfield <name> <start> <end> "
+ "[-bitfield <name> <start> <end>]...",
new file mode 100644
@@ -0,0 +1,334 @@
+From 4a79372b6e6e511c9b7ad5cc97b85338ffb860e3 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Tue, 27 Dec 2022 02:38:25 +0100
+Subject: [PATCH] target: arc: rewrite command 'arc add-reg' as COMMAND_HANDLER
+
+While there, fix some coding style error and remove the now unused
+function jim_arc_read_reg_name_field() and the macro
+JIM_CHECK_RETVAL().
+
+Change-Id: I140b4b929978b2936f2310e0b7d1735ba726c517
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7426
+Tested-by: jenkins
+Reviewed-by: Evgeniy Didin <didin@synopsys.com>
+---
+ src/target/arc.h | 10 --
+ src/target/arc_cmd.c | 229 ++++++++++++++++++-------------------------
+ 2 files changed, 96 insertions(+), 143 deletions(-)
+
+diff --git a/src/target/arc.h b/src/target/arc.h
+index bb70a598e..a351802ac 100644
+--- a/src/target/arc.h
++++ b/src/target/arc.h
+@@ -253,16 +253,6 @@ struct arc_common {
+ } \
+ } while (0)
+
+-#define JIM_CHECK_RETVAL(action) \
+- do { \
+- int __retval = (action); \
+- if (__retval != JIM_OK) { \
+- LOG_DEBUG("error while calling \"%s\"", \
+- # action); \
+- return __retval; \
+- } \
+- } while (0)
+-
+ static inline struct arc_common *target_to_arc(struct target *target)
+ {
+ return target->arch_info;
+diff --git a/src/target/arc_cmd.c b/src/target/arc_cmd.c
+index 3b0bf76f8..e7760b037 100644
+--- a/src/target/arc_cmd.c
++++ b/src/target/arc_cmd.c
+@@ -55,21 +55,6 @@ static const char *validate_register(const struct arc_reg_desc * const reg, bool
+ return NULL;
+ }
+
+-/* Helper function to read the name of register type or register from
+- * configure files */
+-static int jim_arc_read_reg_name_field(struct jim_getopt_info *goi,
+- const char **name, int *name_len)
+-{
+- int e = JIM_OK;
+-
+- if (!goi->argc) {
+- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-name <name> ...");
+- return JIM_ERR;
+- }
+- e = jim_getopt_string(goi, name, name_len);
+- return e;
+-}
+-
+ static COMMAND_HELPER(arc_handle_add_reg_type_flags_ops, struct arc_reg_data_type *type)
+ {
+ struct reg_data_type_flags_field *fields = type->reg_type_flags_field;
+@@ -528,7 +513,7 @@ enum opts_add_reg {
+ CFG_ADD_REG_GENERAL,
+ };
+
+-static struct jim_nvp opts_nvp_add_reg[] = {
++static const struct nvp opts_nvp_add_reg[] = {
+ { .name = "-name", .value = CFG_ADD_REG_NAME },
+ { .name = "-num", .value = CFG_ADD_REG_ARCH_NUM },
+ { .name = "-core", .value = CFG_ADD_REG_IS_CORE },
+@@ -546,155 +531,133 @@ void free_reg_desc(struct arc_reg_desc *r)
+ free(r);
+ }
+
+-static int jim_arc_add_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++static COMMAND_HELPER(arc_handle_add_reg_do, struct arc_reg_desc *reg)
+ {
+- struct jim_getopt_info goi;
+- JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1));
+-
+- struct arc_reg_desc *reg = calloc(1, sizeof(*reg));
+- if (!reg) {
+- Jim_SetResultFormatted(goi.interp, "Failed to allocate memory.");
+- return JIM_ERR;
+- }
+-
+ /* There is no architecture number that we could treat as invalid, so
+ * separate variable required to ensure that arch num has been set. */
+ bool arch_num_set = false;
+ const char *type_name = "int"; /* Default type */
+- int type_name_len = strlen(type_name);
+- int e = ERROR_OK;
+
+ /* At least we need to specify 4 parameters: name, number and gdb_feature,
+ * which means there should be 6 arguments. Also there can be additional parameters
+ * "-type <type>", "-g" and "-core" or "-bcr" which makes maximum 10 parameters. */
+- if (goi.argc < 6 || goi.argc > 10) {
+- free_reg_desc(reg);
+- Jim_SetResultFormatted(goi.interp,
+- "Should be at least 6 arguments and not greater than 10: "
+- " -name <name> -num <num> -feature <gdb_feature> "
+- " [-type <type_name>] [-core|-bcr] [-g].");
+- return JIM_ERR;
+- }
++ if (CMD_ARGC < 6 || CMD_ARGC > 10)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ /* Parse options. */
+- while (goi.argc > 0) {
+- struct jim_nvp *n;
+- e = jim_getopt_nvp(&goi, opts_nvp_add_reg, &n);
+- if (e != JIM_OK) {
+- jim_getopt_nvp_unknown(&goi, opts_nvp_add_reg, 0);
+- free_reg_desc(reg);
+- return e;
+- }
+-
++ while (CMD_ARGC) {
++ const struct nvp *n = nvp_name2value(opts_nvp_add_reg, CMD_ARGV[0]);
++ CMD_ARGC--;
++ CMD_ARGV++;
+ switch (n->value) {
+- case CFG_ADD_REG_NAME:
+- {
+- const char *reg_name = NULL;
+- int reg_name_len = 0;
+-
+- e = jim_arc_read_reg_name_field(&goi, ®_name, ®_name_len);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi.interp, "Unable to read register name.");
+- free_reg_desc(reg);
+- return e;
+- }
+-
+- reg->name = strndup(reg_name, reg_name_len);
+- break;
+- }
+- case CFG_ADD_REG_IS_CORE:
+- reg->is_core = true;
+- break;
+- case CFG_ADD_REG_IS_BCR:
+- reg->is_bcr = true;
+- break;
+- case CFG_ADD_REG_ARCH_NUM:
+- {
+- jim_wide archnum;
+-
+- if (!goi.argc) {
+- free_reg_desc(reg);
+- Jim_WrongNumArgs(interp, goi.argc, goi.argv, "-num <int> ...");
+- return JIM_ERR;
+- }
+-
+- e = jim_getopt_wide(&goi, &archnum);
+- if (e != JIM_OK) {
+- free_reg_desc(reg);
+- return e;
+- }
+-
+- reg->arch_num = archnum;
+- arch_num_set = true;
+- break;
++ case CFG_ADD_REG_NAME:
++ if (!CMD_ARGC)
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++
++ reg->name = strdup(CMD_ARGV[0]);
++ if (!reg->name) {
++ LOG_ERROR("Out of memory");
++ return ERROR_FAIL;
+ }
+- case CFG_ADD_REG_GDB_FEATURE:
+- {
+- const char *feature = NULL;
+- int feature_len = 0;
+-
+- e = jim_arc_read_reg_name_field(&goi, &feature, &feature_len);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi.interp, "Unable to read gdb_feature.");
+- free_reg_desc(reg);
+- return e;
+- }
+-
+- reg->gdb_xml_feature = strndup(feature, feature_len);
+- break;
++
++ CMD_ARGC--;
++ CMD_ARGV++;
++ break;
++
++ case CFG_ADD_REG_IS_CORE:
++ reg->is_core = true;
++ break;
++
++ case CFG_ADD_REG_IS_BCR:
++ reg->is_bcr = true;
++ break;
++
++ case CFG_ADD_REG_ARCH_NUM:
++ if (!CMD_ARGC)
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], reg->arch_num);
++ CMD_ARGC--;
++ CMD_ARGV++;
++
++ arch_num_set = true;
++ break;
++
++ case CFG_ADD_REG_GDB_FEATURE:
++ if (!CMD_ARGC)
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++
++ reg->gdb_xml_feature = strdup(CMD_ARGV[0]);
++ if (!reg->gdb_xml_feature) {
++ LOG_ERROR("Out of memory");
++ return ERROR_FAIL;
+ }
+- case CFG_ADD_REG_TYPE:
+- e = jim_arc_read_reg_name_field(&goi, &type_name, &type_name_len);
+- if (e != JIM_OK) {
+- Jim_SetResultFormatted(goi.interp, "Unable to read register type.");
+- free_reg_desc(reg);
+- return e;
+- }
+-
+- break;
+- case CFG_ADD_REG_GENERAL:
+- reg->is_general = true;
+- break;
+- default:
+- LOG_DEBUG("Error: Unknown parameter");
+- free_reg_desc(reg);
+- return JIM_ERR;
++
++ CMD_ARGC--;
++ CMD_ARGV++;
++ break;
++
++ case CFG_ADD_REG_TYPE:
++ if (!CMD_ARGC)
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++
++ type_name = CMD_ARGV[0];
++ CMD_ARGC--;
++ CMD_ARGV++;
++ break;
++
++ case CFG_ADD_REG_GENERAL:
++ reg->is_general = true;
++ break;
++
++ default:
++ nvp_unknown_command_print(CMD, opts_nvp_add_reg, NULL, CMD_ARGV[-1]);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ }
+
+ /* Check that required fields are set */
+ const char * const errmsg = validate_register(reg, arch_num_set);
+ if (errmsg) {
+- Jim_SetResultFormatted(goi.interp, errmsg);
+- free_reg_desc(reg);
+- return JIM_ERR;
++ command_print(CMD, "%s", errmsg);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ /* Add new register */
+- struct command_context *ctx;
+- struct target *target;
+-
+- ctx = current_command_context(interp);
+- assert(ctx);
+- target = get_current_target(ctx);
++ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+- Jim_SetResultFormatted(goi.interp, "No current target");
+- free_reg_desc(reg);
+- return JIM_ERR;
++ command_print(CMD, "No current target");
++ return ERROR_FAIL;
+ }
+
+ reg->target = target;
+
+- e = arc_reg_add(target, reg, type_name, type_name_len);
+- if (e == ERROR_ARC_REGTYPE_NOT_FOUND) {
+- Jim_SetResultFormatted(goi.interp,
++ int retval = arc_reg_add(target, reg, type_name, strlen(type_name));
++ if (retval == ERROR_ARC_REGTYPE_NOT_FOUND) {
++ command_print(CMD,
+ "Cannot find type `%s' for register `%s'.",
+ type_name, reg->name);
++ return retval;
++ }
++
++ return ERROR_OK;
++}
++
++COMMAND_HANDLER(arc_handle_add_reg)
++{
++ struct arc_reg_desc *reg = calloc(1, sizeof(*reg));
++ if (!reg) {
++ LOG_ERROR("Out of memory");
++ return ERROR_FAIL;
++ }
++
++ int retval = CALL_COMMAND_HANDLER(arc_handle_add_reg_do, reg);
++ if (retval != ERROR_OK) {
+ free_reg_desc(reg);
+- return JIM_ERR;
++ return retval;
+ }
+
+- return e;
++ return ERROR_OK;
+ }
+
+ /* arc set-reg-exists ($reg_name)+
+@@ -887,7 +850,7 @@ static const struct command_registration arc_core_command_handlers[] = {
+ },
+ {
+ .name = "add-reg",
+- .jim_handler = jim_arc_add_reg,
++ .handler = arc_handle_add_reg,
+ .mode = COMMAND_CONFIG,
+ .usage = "-name <string> -num <int> -feature <string> [-gdbnum <int>] "
+ "[-core|-bcr] [-type <type_name>] [-g]",
new file mode 100644
@@ -0,0 +1,28 @@
+From b6021e856a9259aac5dcba45bb3a5d8ae307886b Mon Sep 17 00:00:00 2001
+From: Marc Schink <dev@zapb.de>
+Date: Mon, 30 Jan 2023 16:38:45 +0100
+Subject: [PATCH] flash/nor/stm32l4x: Add revision 'Z' for STM32L552/562
+ devices
+
+Change-Id: Icc6058ef1f43e969a2a9baadfaf382ac820a7b76
+Signed-off-by: Marc Schink <dev@zapb.de>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7468
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/stm32l4x.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c
+index c67dbf75d..02e737b87 100644
+--- a/src/flash/nor/stm32l4x.c
++++ b/src/flash/nor/stm32l4x.c
+@@ -318,7 +318,7 @@ static const struct stm32l4_rev stm32l4p_l4qxx_revs[] = {
+ };
+
+ static const struct stm32l4_rev stm32l55_l56xx_revs[] = {
+- { 0x1000, "A" }, { 0x2000, "B" },
++ { 0x1000, "A" }, { 0x2000, "B" }, { 0x2001, "Z" },
+ };
+
+ static const struct stm32l4_rev stm32g49_g4axx_revs[] = {
new file mode 100644
@@ -0,0 +1,28 @@
+From 1998b1e5a89e57b2d1109bc36d6af916106103ff Mon Sep 17 00:00:00 2001
+From: Marc Schink <dev@zapb.de>
+Date: Thu, 2 Feb 2023 14:25:27 +0100
+Subject: [PATCH] README: Remove statement about libjaylink Git submodule
+
+Change-Id: I552c08979849c66d7f8f559ccfd49d27f8b68bb8
+Signed-off-by: Marc Schink <dev@zapb.de>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7470
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ README | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/README b/README
+index 2f71cfc6a..7d3f10def 100644
+--- a/README
++++ b/README
+@@ -240,8 +240,7 @@ Optional CMSIS-DAP adapter driver needs HIDAPI library.
+
+ Optional linuxgpiod adapter driver needs libgpiod library.
+
+-Optional JLink adapter driver needs libjaylink; build from git can
+-retrieve libjaylink as git submodule.
++Optional J-Link adapter driver needs libjaylink library.
+
+ Optional ARM disassembly needs capstone library.
+
new file mode 100644
@@ -0,0 +1,156 @@
+From 85ae73de03ebcc723842b7978a6c94b73166f027 Mon Sep 17 00:00:00 2001
+From: Andreas Bolsch <hyphen0break@gmail.com>
+Date: Wed, 9 Mar 2022 17:22:50 +0100
+Subject: [PATCH] new SPI memory devices, continuation code for manufacturer id
+
+A bunch of new SPI flash (Adesto, Cypress, XTX Tech, mainly octal)
+IDs and SPI FRAM (Infineon) IDs added. Backward compatible change
+of ID interpretation: The previously unused 4th byte now acts
+as continuation code (0x7F) count for manufacturer id, cf.
+JEDEC JEP106BC. Currently this affects only some recent octal flash
+and FRAM devices, which are only supported by stmqspi and cmspi
+flash drivers.
+
+Change-Id: Ibdcac81a84c636dc68439add4461b959df429bca
+Signed-off-by: Andreas Bolsch <hyphen0break@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/6929
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/spi.c | 73 +++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 64 insertions(+), 9 deletions(-)
+
+diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c
+index 9a606d545..b83df9677 100644
+--- a/src/flash/nor/spi.c
++++ b/src/flash/nor/spi.c
+@@ -23,7 +23,9 @@
+ * from device datasheets and Linux SPI flash drivers. */
+ const struct flash_device flash_devices[] = {
+ /* name, read_cmd, qread_cmd, pprog_cmd, erase_cmd, chip_erase_cmd, device_id,
+- * pagesize, sectorsize, size_in_bytes */
++ * pagesize, sectorsize, size_in_bytes
++ * note: device id is usually 3 bytes long, however the unused highest byte counts
++ * continuation codes for manufacturer id as per JEP106xx */
+ FLASH_ID("st m25p05", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00102020, 0x80, 0x8000, 0x10000),
+ FLASH_ID("st m25p10", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00112020, 0x80, 0x8000, 0x20000),
+ FLASH_ID("st m25p20", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000),
+@@ -51,12 +53,28 @@ const struct flash_device flash_devices[] = {
+ FLASH_ID("cyp s25fl064l", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00176001, 0x100, 0x10000, 0x800000),
+ FLASH_ID("cyp s25fl128l", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00186001, 0x100, 0x10000, 0x1000000),
+ FLASH_ID("cyp s25fl256l", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x00196001, 0x100, 0x10000, 0x2000000),
++ FLASH_ID("cyp s28hl256t", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x00195a34, 0x100, 0x40000, 0x2000000), /* page! */
++ FLASH_ID("cyp s28hs256t", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x00195b34, 0x100, 0x40000, 0x2000000), /* page! */
++ FLASH_ID("cyp s28hl512t", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a5a34, 0x100, 0x40000, 0x4000000), /* page! */
++ FLASH_ID("cyp s28hs512t", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a5b34, 0x100, 0x40000, 0x4000000), /* page! */
++ FLASH_ID("cyp s28hl01gt", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001b5a34, 0x100, 0x40000, 0x8000000), /* page! */
++ FLASH_ID("cyp s28hs01gt", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001b5b34, 0x100, 0x40000, 0x8000000), /* page! */
+ FLASH_ID("atmel 25f512", 0x03, 0x00, 0x02, 0x52, 0xc7, 0x0065001f, 0x80, 0x8000, 0x10000),
+ FLASH_ID("atmel 25f1024", 0x03, 0x00, 0x02, 0x52, 0x62, 0x0060001f, 0x100, 0x8000, 0x20000),
+ FLASH_ID("atmel 25f2048", 0x03, 0x00, 0x02, 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000),
+ FLASH_ID("atmel 25f4096", 0x03, 0x00, 0x02, 0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000),
+ FLASH_ID("atmel 25fs040", 0x03, 0x00, 0x02, 0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000),
++ FLASH_ID("adesto 25sf041b", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0001841f, 0x100, 0x10000, 0x80000),
+ FLASH_ID("adesto 25df081a", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0001451f, 0x100, 0x10000, 0x100000),
++ FLASH_ID("adesto 25sf081b", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0001851f, 0x100, 0x10000, 0x100000),
++ FLASH_ID("adesto 25sf161b", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0001861f, 0x100, 0x10000, 0x200000),
++ FLASH_ID("adesto 25df321b", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0001471f, 0x100, 0x10000, 0x400000),
++ FLASH_ID("adesto 25sf321b", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0001871f, 0x100, 0x10000, 0x400000),
++ FLASH_ID("adesto 25xf641b", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0001881f, 0x100, 0x10000, 0x800000), /* sf/qf */
++ FLASH_ID("adesto 25xf128a", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0001891f, 0x100, 0x10000, 0x1000000), /* sf/qf */
++ FLASH_ID("adesto xp032", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0700a743, 0x100, 0x10000, 0x400000), /* 4-byte */
++ FLASH_ID("adesto xp064b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0001a81f, 0x100, 0x10000, 0x800000), /* 4-byte */
++ FLASH_ID("adesto xp128", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0000a91f, 0x100, 0x10000, 0x1000000), /* 4-byte */
+ FLASH_ID("mac 25l512", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000),
+ FLASH_ID("mac 25l1005", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001120c2, 0x010, 0x10000, 0x20000),
+ FLASH_ID("mac 25l2005", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000),
+@@ -78,6 +96,9 @@ const struct flash_device flash_devices[] = {
+ FLASH_ID("mac 25r3235f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001628c2, 0x100, 0x10000, 0x400000),
+ FLASH_ID("mac 25r6435f", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001728c2, 0x100, 0x10000, 0x800000),
+ FLASH_ID("mac 25u1635e", 0x03, 0xeb, 0x02, 0x20, 0xc7, 0x003525c2, 0x100, 0x1000, 0x100000),
++ FLASH_ID("mac 66l1g45g", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001b20c2, 0x100, 0x10000, 0x8000000),
++ FLASH_ID("mac 66um1g45g", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x003b80c2, 0x100, 0x10000, 0x8000000),
++ FLASH_ID("mac 66lm1g45g", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x003b85c2, 0x100, 0x10000, 0x8000000),
+ FLASH_ID("micron n25q032", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0016ba20, 0x100, 0x10000, 0x400000),
+ FLASH_ID("micron n25q064", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000),
+ FLASH_ID("micron n25q128", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000),
+@@ -102,6 +123,10 @@ const struct flash_device flash_devices[] = {
+ FLASH_ID("win w25q256fv/jv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001940ef, 0x100, 0x10000, 0x2000000),
+ FLASH_ID("win w25q256fv", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001960ef, 0x100, 0x10000, 0x2000000), /* QPI mode */
+ FLASH_ID("win w25q256jv", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001970ef, 0x100, 0x10000, 0x2000000),
++ FLASH_ID("win w25q512jv", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x002040ef, 0x100, 0x10000, 0x4000000),
++ FLASH_ID("win w25q01jv", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x002140ef, 0x100, 0x10000, 0x8000000),
++ FLASH_ID("win w25q01jv-dtr", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x002170ef, 0x100, 0x10000, 0x8000000),
++ FLASH_ID("win w25q02jv-dtr", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x002270ef, 0x100, 0x10000, 0x10000000),
+ FLASH_ID("gd gd25q512", 0x03, 0x00, 0x02, 0x20, 0xc7, 0x001040c8, 0x100, 0x1000, 0x10000),
+ FLASH_ID("gd gd25q10", 0x03, 0x00, 0x02, 0x20, 0xc7, 0x001140c8, 0x100, 0x1000, 0x20000),
+ FLASH_ID("gd gd25q20", 0x03, 0x00, 0x02, 0x20, 0xc7, 0x001240c8, 0x100, 0x1000, 0x40000),
+@@ -109,9 +134,10 @@ const struct flash_device flash_devices[] = {
+ FLASH_ID("gd gd25q16c", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000),
+ FLASH_ID("gd gd25q32c", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000),
+ FLASH_ID("gd gd25q64c", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001740c8, 0x100, 0x10000, 0x800000),
+- FLASH_ID("gd gd25q128c", 0x03, 0xeb, 0x02, 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
++ FLASH_ID("gd gd25q128c", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000),
+ FLASH_ID("gd gd25q256c", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x001940c8, 0x100, 0x10000, 0x2000000),
+ FLASH_ID("gd gd25q512mc", 0x13, 0x00, 0x12, 0xdc, 0xc7, 0x002040c8, 0x100, 0x10000, 0x4000000),
++ FLASH_ID("gd gd25lx256e", 0x13, 0x0c, 0x12, 0xdc, 0xc7, 0x001968c8, 0x100, 0x10000, 0x2000000),
+ FLASH_ID("zbit zb25vq16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0015605e, 0x100, 0x10000, 0x200000),
+ FLASH_ID("zbit zb25vq32", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0016405e, 0x100, 0x10000, 0x400000),
+ FLASH_ID("zbit zb25vq32", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0016605e, 0x100, 0x10000, 0x400000), /* QPI mode */
+@@ -128,6 +154,18 @@ const struct flash_device flash_devices[] = {
+ FLASH_ID("issi is25wp256d", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x0019709d, 0x100, 0x10000, 0x2000000),
+ FLASH_ID("issi is25lp512m", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a609d, 0x100, 0x10000, 0x4000000),
+ FLASH_ID("issi is25wp512m", 0x13, 0xec, 0x12, 0xdc, 0xc7, 0x001a709d, 0x100, 0x10000, 0x4000000),
++ FLASH_ID("xtx xt25f02e", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0012400b, 0x100, 0x10000, 0x40000),
++ FLASH_ID("xtx xt25f04d", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0013400b, 0x100, 0x10000, 0x80000),
++ FLASH_ID("xtx xt25f08b", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0014400b, 0x100, 0x10000, 0x100000),
++ FLASH_ID("xtx xt25f16b", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x0015400b, 0x100, 0x10000, 0x200000),
++ FLASH_ID("xtx xt25f32b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0016400b, 0x100, 0x10000, 0x200000),
++ FLASH_ID("xtx xt25f64b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0017400b, 0x100, 0x10000, 0x400000),
++ FLASH_ID("xtx xt25f128b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0018400b, 0x100, 0x10000, 0x800000),
++ FLASH_ID("xtx xt25q08d", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0014600b, 0x100, 0x10000, 0x100000),
++ FLASH_ID("xtx xt25q16b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0015600b, 0x100, 0x10000, 0x200000),
++ FLASH_ID("xtx xt25q32b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0016600b, 0x100, 0x10000, 0x400000), /* exists ? */
++ FLASH_ID("xtx xt25q64b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0017600b, 0x100, 0x10000, 0x800000),
++ FLASH_ID("xtx xt25q128b", 0x03, 0x0b, 0x02, 0xd8, 0xc7, 0x0018600b, 0x100, 0x10000, 0x1000000),
+
+ /* FRAM, no erase commands, no write page or sectors */
+ FRAM_ID("fu mb85rs16n", 0x03, 0, 0x02, 0x00010104, 0x800),
+@@ -138,13 +176,30 @@ const struct flash_device flash_devices[] = {
+ FRAM_ID("fu mb85rs512t", 0x03, 0, 0x02, 0x00032604, 0x10000),
+ FRAM_ID("fu mb85rs1mt", 0x03, 0, 0x02, 0x00032704, 0x20000),
+ FRAM_ID("fu mb85rs2mta", 0x03, 0, 0x02, 0x00034804, 0x40000),
+- FRAM_ID("cyp fm25v01a", 0x03, 0, 0x02, 0x000821c2, 0x4000),
+- FRAM_ID("cyp fm25v02", 0x03, 0, 0x02, 0x000022c2, 0x8000),
+- FRAM_ID("cyp fm25v02a", 0x03, 0, 0x02, 0x000822c2, 0x8000),
+- FRAM_ID("cyp fm25v05", 0x03, 0, 0x02, 0x000023c2, 0x10000),
+- FRAM_ID("cyp fm25v10", 0x03, 0, 0x02, 0x000024c2, 0x20000),
+- FRAM_ID("cyp fm25v20a", 0x03, 0, 0x02, 0x000825c2, 0x40000),
+- FRAM_ID("cyp fm25v40", 0x03, 0, 0x02, 0x004026c2, 0x80000),
++ FRAM_ID("cyp fm25v01a", 0x03, 0, 0x02, 0x060821c2, 0x4000),
++ FRAM_ID("cyp fm25v02", 0x03, 0, 0x02, 0x060022c2, 0x8000),
++ FRAM_ID("cyp fm25v02a", 0x03, 0, 0x02, 0x060822c2, 0x8000),
++ FRAM_ID("cyp fm25v05", 0x03, 0, 0x02, 0x060023c2, 0x10000),
++ FRAM_ID("cyp fm25v10", 0x03, 0, 0x02, 0x060024c2, 0x20000),
++ FRAM_ID("cyp fm25v20a", 0x03, 0, 0x02, 0x060825c2, 0x40000),
++ FRAM_ID("cyp fm25v40", 0x03, 0, 0x02, 0x064026c2, 0x80000),
++ FRAM_ID("cyp cy15b102qn", 0x03, 0, 0x02, 0x06002ac2, 0x40000),
++ FRAM_ID("cyp cy15v102qn", 0x03, 0, 0x02, 0x06042ac2, 0x40000),
++ FRAM_ID("cyp cy15b104qi", 0x03, 0, 0x02, 0x06012dc2, 0x80000),
++ FRAM_ID("cyp cy15b104qi", 0x03, 0, 0x02, 0x06a12dc2, 0x80000),
++ FRAM_ID("cyp cy15v104qi", 0x03, 0, 0x02, 0x06052dc2, 0x80000),
++ FRAM_ID("cyp cy15v104qi", 0x03, 0, 0x02, 0x06a52dc2, 0x80000),
++ FRAM_ID("cyp cy15b104qn", 0x03, 0, 0x02, 0x06402cc2, 0x80000),
++ FRAM_ID("cyp cy15b108qi", 0x03, 0, 0x02, 0x06012fc2, 0x100000),
++ FRAM_ID("cyp cy15b108qi", 0x03, 0, 0x02, 0x06a12fc2, 0x100000),
++ FRAM_ID("cyp cy15v108qi", 0x03, 0, 0x02, 0x06052fc2, 0x100000),
++ FRAM_ID("cyp cy15v108qi", 0x03, 0, 0x02, 0x06a52fc2, 0x100000),
++ FRAM_ID("cyp cy15b108qn", 0x03, 0, 0x02, 0x06012ec2, 0x100000),
++ FRAM_ID("cyp cy15b108qn", 0x03, 0, 0x02, 0x06032ec2, 0x100000),
++ FRAM_ID("cyp cy15b108qn", 0x03, 0, 0x02, 0x06a12ec2, 0x100000),
++ FRAM_ID("cyp cy15v108qn", 0x03, 0, 0x02, 0x06052ec2, 0x100000),
++ FRAM_ID("cyp cy15v108qn", 0x03, 0, 0x02, 0x06072ec2, 0x100000),
++ FRAM_ID("cyp cy15v108qn", 0x03, 0, 0x02, 0x06a52ec2, 0x100000),
+
+ FLASH_ID(NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ };
new file mode 100644
@@ -0,0 +1,31 @@
+From 79caea8745284ac1d2e8931335b58c679cd11882 Mon Sep 17 00:00:00 2001
+From: Daniel Anselmi <danselmi@gmx.ch>
+Date: Thu, 22 Dec 2022 22:28:21 +0100
+Subject: [PATCH] flash/nor/spi: add 25pe{10/20/40/80/16}
+
+Change-Id: Ic5660bff83b8636ef397482a3313971ecdff72c0
+Signed-off-by: Daniel Anselmi <danselmi@gmx.ch>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7416
+Tested-by: jenkins
+Reviewed-by: Andreas Bolsch <hyphen0break@gmail.com>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/flash/nor/spi.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c
+index b83df9677..3bcaa9f61 100644
+--- a/src/flash/nor/spi.c
++++ b/src/flash/nor/spi.c
+@@ -26,6 +26,11 @@ const struct flash_device flash_devices[] = {
+ * pagesize, sectorsize, size_in_bytes
+ * note: device id is usually 3 bytes long, however the unused highest byte counts
+ * continuation codes for manufacturer id as per JEP106xx */
++ FLASH_ID("st m25pe10", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00118020, 0x100, 0x10000, 0x20000),
++ FLASH_ID("st m25pe20", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00128020, 0x100, 0x10000, 0x40000),
++ FLASH_ID("st m25pe40", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00138020, 0x100, 0x10000, 0x80000),
++ FLASH_ID("st m25pe80", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00148020, 0x100, 0x10000, 0x100000),
++ FLASH_ID("st m25pe16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00158020, 0x100, 0x10000, 0x200000),
+ FLASH_ID("st m25p05", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00102020, 0x80, 0x8000, 0x10000),
+ FLASH_ID("st m25p10", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00112020, 0x80, 0x8000, 0x20000),
+ FLASH_ID("st m25p20", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x00122020, 0x100, 0x10000, 0x40000),
new file mode 100644
@@ -0,0 +1,83 @@
+From c99c043f3f6e79e391debee29371360b0965b2d6 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 19:41:46 +0100
+Subject: [PATCH] helper: command: drop last LF ('\n') from sequence of
+ command_print()
+
+The OpenOCD commands produce their TCL text result through the
+pair command_print() and command_print_sameline().
+The latter is used to concatenate output in a single line.
+
+At the end of a sequence of command_print(), the last LF is taken
+as part of the command result, while it is not always needed, and
+it is even annoying when the output of two commands needs to be
+concatenate in a single line.
+
+Using command_print_sameline() in place of the last call to
+command_print() would solve the problem but it's quite expensive
+in term of coding to fix all the existing commands.
+
+Drop the last LF, if present.
+Commands that would specifically need a LF as last char, can add
+an extra LF at the end of the output.
+Document this behavior in command.h.
+
+Change-Id: I6757c20fbfce923dd393083146e8d5a1f3b790b4
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7471
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/helper/command.c | 12 ++++++++++--
+ src/helper/command.h | 11 +++++++++++
+ 2 files changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/src/helper/command.c b/src/helper/command.c
+index ca66cf7dd..12434ec90 100644
+--- a/src/helper/command.c
++++ b/src/helper/command.c
+@@ -543,8 +543,16 @@ static int run_command(struct command_context *context,
+ if (retval != ERROR_OK)
+ LOG_DEBUG("Command '%s' failed with error code %d",
+ words[0], retval);
+- /* Use the command output as the Tcl result */
+- Jim_SetResult(context->interp, cmd.output);
++ /*
++ * Use the command output as the Tcl result.
++ * Drop last '\n' to allow command output concatenation
++ * while keep using command_print() everywhere.
++ */
++ const char *output_txt = Jim_String(cmd.output);
++ int len = strlen(output_txt);
++ if (len && output_txt[len - 1] == '\n')
++ --len;
++ Jim_SetResultString(context->interp, output_txt, len);
+ }
+ Jim_DecrRefCount(context->interp, cmd.output);
+
+diff --git a/src/helper/command.h b/src/helper/command.h
+index 478e5c8ad..42cb9cb7d 100644
+--- a/src/helper/command.h
++++ b/src/helper/command.h
+@@ -370,10 +370,21 @@ struct command_context *copy_command_context(struct command_context *cmd_ctx);
+ */
+ void command_done(struct command_context *context);
+
++/*
++ * command_print() and command_print_sameline() are used to produce the TCL
++ * output of OpenOCD commands. command_print() automatically adds a '\n' at
++ * the end or the format string. Use command_print_sameline() to avoid the
++ * trailing '\n', e.g. to concatenate the command output in the same line.
++ * The very last '\n' of the command is stripped away (see run_command()).
++ * For commands that strictly require a '\n' as last output character, add
++ * it explicitly with either an empty command_print() or with a '\n' in the
++ * last command_print() and add a comment to document it.
++ */
+ void command_print(struct command_invocation *cmd, const char *format, ...)
+ __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)));
+ void command_print_sameline(struct command_invocation *cmd, const char *format, ...)
+ __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)));
++
+ int command_run_line(struct command_context *context, char *line);
+ int command_run_linef(struct command_context *context, const char *format, ...)
+ __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 2, 3)));
new file mode 100644
@@ -0,0 +1,47 @@
+From 0a20e78b759efa86a676b4a9fed4027fdd84e90c Mon Sep 17 00:00:00 2001
+From: Peter Collingbourne <pcc@google.com>
+Date: Fri, 17 Feb 2023 18:26:05 -0800
+Subject: [PATCH] jtag/drivers/cmsis_dap: run queue on reaching transaction
+ limit
+
+We currently fail the transfer when issuing more than 255 transactions
+at once, e.g.
+
+> read_memory 0x10000000 32 256
+CMSIS-DAP transfer count mismatch: expected 257, got 1
+
+This is because the protocol only supports 255 transactions per packet
+(65535 for block transactions), and as a result we truncate the
+transaction count when assembling the packet. Fix it by running the
+queue when we hit the limit.
+
+Change-Id: Ia9e01e3af5ad035f2cf2a32292c9d66e57eafae9
+Signed-off-by: Peter Collingbourne <pcc@google.com>
+Fixes: 40bac8e8c4e5 ("jtag/drivers/cmsis_dap: improve USB packets filling")
+Reviewed-on: https://review.openocd.org/c/openocd/+/7483
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/jtag/drivers/cmsis_dap.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c
+index 0c42a7f1e..1e7a851e4 100644
+--- a/src/jtag/drivers/cmsis_dap.c
++++ b/src/jtag/drivers/cmsis_dap.c
+@@ -1001,12 +1001,14 @@ static void cmsis_dap_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
+ block_cmd);
+ unsigned int resp_size = cmsis_dap_tfer_resp_size(write_count, read_count,
+ block_cmd);
++ unsigned int max_transfer_count = block_cmd ? 65535 : 255;
+
+ /* Does the DAP Transfer command and the expected response fit into one packet?
+ * Run the queue also before a targetsel - it cannot be queued */
+ if (cmd_size > tfer_max_command_size
+ || resp_size > tfer_max_response_size
+- || targetsel_cmd) {
++ || targetsel_cmd
++ || write_count + read_count > max_transfer_count) {
+ if (cmsis_dap_handle->pending_fifo_block_count)
+ cmsis_dap_swd_read_process(cmsis_dap_handle, 0);
+
new file mode 100644
@@ -0,0 +1,27 @@
+From fc30feb51a76e893646e2794c99a78dbdc0d251f Mon Sep 17 00:00:00 2001
+From: Tomas Deingruber <Deingruber.Tomas@gmail.com>
+Date: Tue, 28 Feb 2023 23:17:56 +0000
+Subject: [PATCH] tlc/interface: does fix source of
+ raspberrypi-gpio-connector.cfg in raspberrypi-native.cfg
+
+Fixes: bec6c0eb094f (tcl/interface: universal config for all Raspberry Pi models)
+Signed-off-by: Tomas Deingruber <Deingruber.Tomas@gmail.com>
+Change-Id: I632c8acd84974937849b5fdf2943239def17bd6d
+Reviewed-on: https://review.openocd.org/c/openocd/+/7512
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ tcl/interface/raspberrypi-native.cfg | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tcl/interface/raspberrypi-native.cfg b/tcl/interface/raspberrypi-native.cfg
+index 95426c226..7224723d6 100644
+--- a/tcl/interface/raspberrypi-native.cfg
++++ b/tcl/interface/raspberrypi-native.cfg
+@@ -68,4 +68,4 @@ set speed_coeff [expr { $clock / $clocks_per_timing_loop }]
+ # The coefficients depend on system clock and CPU frequency scaling.
+ bcm2835gpio speed_coeffs $speed_coeff $speed_offset
+
+-source raspberrypi-gpio-connector.cfg
++source [find interface/raspberrypi-gpio-connector.cfg]
new file mode 100644
@@ -0,0 +1,31 @@
+From e1b0d5759a1e9221d534400505c6eb7e43abd051 Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa@kernel.org>
+Date: Fri, 3 Mar 2023 16:50:38 +0100
+Subject: [PATCH] tcl/board/at91sam9g20-ek: remove outdated FIXME
+
+It was fixed by e94180571 ("at91sam9: factorise cpu support") in 2011.
+
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Change-Id: I95ea149b45a9902424bf9068b4a2830c17ddc6be
+Reviewed-on: https://review.openocd.org/c/openocd/+/7525
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ tcl/board/at91sam9g20-ek.cfg | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/tcl/board/at91sam9g20-ek.cfg b/tcl/board/at91sam9g20-ek.cfg
+index a5831cd91..4740471c8 100644
+--- a/tcl/board/at91sam9g20-ek.cfg
++++ b/tcl/board/at91sam9g20-ek.cfg
+@@ -7,10 +7,6 @@
+ # #
+ #################################################################################################
+
+-# FIXME use some standard target config, maybe create one from this
+-#
+-# source [find target/...cfg]
+-
+ source [find target/at91sam9g20.cfg]
+
+ set _FLASHTYPE nandflash_cs3
new file mode 100644
@@ -0,0 +1,31 @@
+From c8f56b4f00a1b8d7cc74f08b34466b2017c1f1dc Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa@kernel.org>
+Date: Fri, 3 Mar 2023 17:00:19 +0100
+Subject: [PATCH] TODO: remove outdated AT91SAM92xx entry
+
+SAM9260 gained good generic infrastructure since 2009. And we always
+want "improvements", no need for a TODO item.
+
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Change-Id: I92551ef9d42ee47ad7441f2354587bbb45edc97e
+Reviewed-on: https://review.openocd.org/c/openocd/+/7526
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ TODO | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/TODO b/TODO
+index ebb6c9980..e4dded0ce 100644
+--- a/TODO
++++ b/TODO
+@@ -202,8 +202,6 @@ https://lists.berlios.de/pipermail/openocd-development/2009-October/011506.html
+ - MC1322x support (JW/DE?)
+ - integrate and test support from JW (and DE?)
+ - get working with a known good interface (i.e. not today's jlink)
+-- AT91SAM92xx:
+- - improvements for unknown-board-atmel-at91sam9260.cfg (RD)
+ - STR9x: (ZW)
+ - improvements to str912.cfg to be more general purpose
+ - AVR: (SQ)
new file mode 100644
@@ -0,0 +1,45 @@
+From c7e0040689db1fc2673c117e038ffb3a88f6562b Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Mon, 6 Mar 2023 15:31:08 +0100
+Subject: [PATCH] drivers/libusb_helper: allow external use of
+ jtag_libusb_match_ids()
+
+Can be employed by a driver with custom libusb open.
+
+Change-Id: I00c8a01df8780891a8b7c30e2e34ab191acdf9a8
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7528
+Tested-by: jenkins
+Reviewed-by: Wolfram Sang <wsa@kernel.org>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/jtag/drivers/libusb_helper.c | 2 +-
+ src/jtag/drivers/libusb_helper.h | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c
+index 53dfd502d..4b098b482 100644
+--- a/src/jtag/drivers/libusb_helper.c
++++ b/src/jtag/drivers/libusb_helper.c
+@@ -50,7 +50,7 @@ static int jtag_libusb_error(int err)
+ }
+ }
+
+-static bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
++bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
+ const uint16_t vids[], const uint16_t pids[])
+ {
+ for (unsigned i = 0; vids[i]; i++) {
+diff --git a/src/jtag/drivers/libusb_helper.h b/src/jtag/drivers/libusb_helper.h
+index 172c34598..799e3e6a9 100644
+--- a/src/jtag/drivers/libusb_helper.h
++++ b/src/jtag/drivers/libusb_helper.h
+@@ -30,6 +30,8 @@
+ typedef char * (*adapter_get_alternate_serial_fn)(struct libusb_device_handle *device,
+ struct libusb_device_descriptor *dev_desc);
+
++bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
++ const uint16_t vids[], const uint16_t pids[]);
+ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
+ struct libusb_device_handle **out,
+ adapter_get_alternate_serial_fn adapter_get_alternate_serial);
new file mode 100644
@@ -0,0 +1,111 @@
+From a8bc4e75b3dda3d32345fa310a3be724235d8fa8 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Mon, 6 Mar 2023 15:37:43 +0100
+Subject: [PATCH] drivers/ftdi: prevent misleading error msg when more vid/pids
+ configured
+
+The driver tries to open mpsse engine for each vid pid
+pair in sequence. If more vid/pid pairs are configured and
+the USB device does not correspond to the first pair,
+the driver shows 'unable to open ftdi device ...' error.
+
+Match vid pid with the whole list as used in jtag_libusb_open()
+instead of multiple mpsse_open() in for loop over vid/pid pairs.
+
+Change-Id: I8ef55205be221c727607fe25b81ae21de0d96f02
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7529
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-by: Wolfram Sang <wsa@kernel.org>
+---
+ src/jtag/drivers/ftdi.c | 7 +------
+ src/jtag/drivers/mpsse.c | 20 +++++++-------------
+ 2 files changed, 8 insertions(+), 19 deletions(-)
+
+diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c
+index 3097d4129..6356a4929 100644
+--- a/src/jtag/drivers/ftdi.c
++++ b/src/jtag/drivers/ftdi.c
+@@ -658,13 +658,8 @@ static int ftdi_initialize(void)
+ return ERROR_JTAG_INIT_FAILED;
+ }
+
+- for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) {
+- mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc,
++ mpsse_ctx = mpsse_open(ftdi_vid, ftdi_pid, ftdi_device_desc,
+ adapter_get_required_serial(), adapter_usb_get_location(), ftdi_channel);
+- if (mpsse_ctx)
+- break;
+- }
+-
+ if (!mpsse_ctx)
+ return ERROR_JTAG_INIT_FAILED;
+
+diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c
+index 18aeb38a4..9f2fdde9f 100644
+--- a/src/jtag/drivers/mpsse.c
++++ b/src/jtag/drivers/mpsse.c
+@@ -13,6 +13,7 @@
+ #include "helper/log.h"
+ #include "helper/replacements.h"
+ #include "helper/time_support.h"
++#include "libusb_helper.h"
+ #include <libusb.h>
+
+ /* Compatibility define for older libusb-1.0 */
+@@ -148,7 +149,7 @@ static bool device_location_equal(struct libusb_device *device, const char *loca
+ * Set any field to 0 as a wildcard. If the device is found true is returned, with ctx containing
+ * the already opened handle. ctx->interface must be set to the desired interface (channel) number
+ * prior to calling this function. */
+-static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, const uint16_t *pid,
++static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t vids[], const uint16_t pids[],
+ const char *product, const char *serial, const char *location)
+ {
+ struct libusb_device **list;
+@@ -169,9 +170,7 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con
+ continue;
+ }
+
+- if (vid && *vid != desc.idVendor)
+- continue;
+- if (pid && *pid != desc.idProduct)
++ if (!jtag_libusb_match_ids(&desc, vids, pids))
+ continue;
+
+ err = libusb_open(device, &ctx->usb_dev);
+@@ -203,7 +202,7 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con
+ libusb_free_device_list(list, 1);
+
+ if (!found) {
+- LOG_ERROR("no device found");
++ /* The caller reports detailed error desc */
+ return false;
+ }
+
+@@ -307,7 +306,7 @@ error:
+ return false;
+ }
+
+-struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description,
++struct mpsse_ctx *mpsse_open(const uint16_t vids[], const uint16_t pids[], const char *description,
+ const char *serial, const char *location, int channel)
+ {
+ struct mpsse_ctx *ctx = calloc(1, sizeof(*ctx));
+@@ -343,14 +342,9 @@ struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const cha
+ goto error;
+ }
+
+- if (!open_matching_device(ctx, vid, pid, description, serial, location)) {
+- /* Four hex digits plus terminating zero each */
+- char vidstr[5];
+- char pidstr[5];
+- LOG_ERROR("unable to open ftdi device with vid %s, pid %s, description '%s', "
++ if (!open_matching_device(ctx, vids, pids, description, serial, location)) {
++ LOG_ERROR("unable to open ftdi device with description '%s', "
+ "serial '%s' at bus location '%s'",
+- vid ? sprintf(vidstr, "%04x", *vid), vidstr : "*",
+- pid ? sprintf(pidstr, "%04x", *pid), pidstr : "*",
+ description ? description : "*",
+ serial ? serial : "*",
+ location ? location : "*");
new file mode 100644
@@ -0,0 +1,31 @@
+From 70d771c7b7d488c76452191fb1a2a8bdfa9a2f25 Mon Sep 17 00:00:00 2001
+From: Andrew Lalaev <andrey.lalaev@gmail.com>
+Date: Sun, 5 Mar 2023 20:36:32 +0100
+Subject: [PATCH] flash/nor/at91samd: fix RAM size for SAMR34/35
+
+According to the datasheets these MCUs have 40Kb RAM.
+
+Signed-off-by: Andrew Lalaev <andrey.lalaev@gmail.com>
+Change-Id: I52b8a0c86035bccd6f3c1a478bb2e558bca4ae86
+Reviewed-on: https://review.openocd.org/c/openocd/+/7520
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/flash/nor/at91samd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c
+index 33e86c76e..b3252e870 100644
+--- a/src/flash/nor/at91samd.c
++++ b/src/flash/nor/at91samd.c
+@@ -243,8 +243,8 @@ static const struct samd_part saml21_parts[] = {
+ { 0x1F, "SAMR30E18A", 256, 32 },
+
+ /* SAMR34/R35 parts have integrated SAML21 with a lora radio */
+- { 0x28, "SAMR34J18", 256, 32 },
+- { 0x2B, "SAMR35J18", 256, 32 },
++ { 0x28, "SAMR34J18", 256, 40 },
++ { 0x2B, "SAMR35J18", 256, 40 },
+ };
+
+ /* Known SAML22 parts. */
new file mode 100644
@@ -0,0 +1,32 @@
+From 8d1261c248796d5eee9ec8e646d16d653be984a6 Mon Sep 17 00:00:00 2001
+From: Andrew Lalaev <andrey.lalaev@gmail.com>
+Date: Sun, 5 Mar 2023 20:41:14 +0100
+Subject: [PATCH] flash/nor/at91samd: add missing SAMR34/35 part numbers
+
+All DIDs are taken from "SAM R34/R35 Errata Sheet" (DS80000834A).
+
+Signed-off-by: Andrew Lalaev <andrey.lalaev@gmail.com>
+Change-Id: Ie35f58e61bb02919c0676c91938c90192481d995
+Reviewed-on: https://review.openocd.org/c/openocd/+/7521
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/flash/nor/at91samd.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c
+index b3252e870..416f07778 100644
+--- a/src/flash/nor/at91samd.c
++++ b/src/flash/nor/at91samd.c
+@@ -244,7 +244,11 @@ static const struct samd_part saml21_parts[] = {
+
+ /* SAMR34/R35 parts have integrated SAML21 with a lora radio */
+ { 0x28, "SAMR34J18", 256, 40 },
++ { 0x29, "SAMR34J17", 128, 24 },
++ { 0x2A, "SAMR34J16", 64, 12 },
+ { 0x2B, "SAMR35J18", 256, 40 },
++ { 0x2C, "SAMR35J17", 128, 24 },
++ { 0x2D, "SAMR35J16", 64, 12 },
+ };
+
+ /* Known SAML22 parts. */
new file mode 100644
@@ -0,0 +1,31 @@
+From a7f8a1d7fb8e6628f34340a5777ce600dc27f8d8 Mon Sep 17 00:00:00 2001
+From: Chao Du <duchao@eswincomputing.com>
+Date: Wed, 8 Mar 2023 07:17:13 +0000
+Subject: [PATCH] doc: add missing FreeRTOS symbol
+
+A new FreeRTOS symbol xSchedulerRunning was added into the symbol list.
+But the doc was not updated accordingly.
+
+Signed-off-by: Chao Du <duchao@eswincomputing.com>
+Change-Id: If1b18591e2681477ad96f1dea566cc2547097767
+Reviewed-on: https://review.openocd.org/c/openocd/+/7531
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ doc/openocd.texi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index 6c853f2ce..414b4c405 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -11887,7 +11887,7 @@ _tx_thread_current_ptr, _tx_thread_created_ptr, _tx_thread_created_count.
+ @raggedright
+ pxCurrentTCB, pxReadyTasksLists, xDelayedTaskList1, xDelayedTaskList2,
+ pxDelayedTaskList, pxOverflowDelayedTaskList, xPendingReadyList,
+-uxCurrentNumberOfTasks, uxTopUsedPriority.
++uxCurrentNumberOfTasks, uxTopUsedPriority, xSchedulerRunning.
+ @end raggedright
+ @item linux symbols
+ init_task.
new file mode 100644
@@ -0,0 +1,166 @@
+From 047b1a8fc237af480e3bab66a9827a358afd7547 Mon Sep 17 00:00:00 2001
+From: Peter Collingbourne <pcc@google.com>
+Date: Wed, 1 Mar 2023 20:20:29 -0800
+Subject: [PATCH] target/image: zero-initialize ELF segments up to p_memsz
+
+We were previously not zero-initializing ELF segments between p_filesz
+and p_memsz (aka BSS). However, this may be necessary depending on the
+user's application. Therefore, start doing so.
+
+Change-Id: I5a743390069583aca7ee276f53afeccf2cac0855
+Signed-off-by: Peter Collingbourne <pcc@google.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7513
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/image.c | 54 +++++++++++++++++++++++++++++-----------------
+ 1 file changed, 34 insertions(+), 20 deletions(-)
+
+diff --git a/src/target/image.c b/src/target/image.c
+index f8de7a23e..6aa609d39 100644
+--- a/src/target/image.c
++++ b/src/target/image.c
+@@ -407,12 +407,10 @@ static int image_elf32_read_headers(struct image *image)
+ return ERROR_FILEIO_OPERATION_FAILED;
+ }
+
+- /* count useful segments (loadable), ignore BSS section */
++ /* count useful segments (loadable) */
+ image->num_sections = 0;
+ for (i = 0; i < elf->segment_count; i++)
+- if ((field32(elf,
+- elf->segments32[i].p_type) == PT_LOAD) &&
+- (field32(elf, elf->segments32[i].p_filesz) != 0))
++ if (field32(elf, elf->segments32[i].p_type) == PT_LOAD)
+ image->num_sections++;
+
+ if (image->num_sections == 0) {
+@@ -449,10 +447,8 @@ static int image_elf32_read_headers(struct image *image)
+ }
+
+ for (i = 0, j = 0; i < elf->segment_count; i++) {
+- if ((field32(elf,
+- elf->segments32[i].p_type) == PT_LOAD) &&
+- (field32(elf, elf->segments32[i].p_filesz) != 0)) {
+- image->sections[j].size = field32(elf, elf->segments32[i].p_filesz);
++ if (field32(elf, elf->segments32[i].p_type) == PT_LOAD) {
++ image->sections[j].size = field32(elf, elf->segments32[i].p_memsz);
+ if (load_to_vaddr)
+ image->sections[j].base_address = field32(elf,
+ elf->segments32[i].p_vaddr);
+@@ -532,12 +528,10 @@ static int image_elf64_read_headers(struct image *image)
+ return ERROR_FILEIO_OPERATION_FAILED;
+ }
+
+- /* count useful segments (loadable), ignore BSS section */
++ /* count useful segments (loadable) */
+ image->num_sections = 0;
+ for (i = 0; i < elf->segment_count; i++)
+- if ((field32(elf,
+- elf->segments64[i].p_type) == PT_LOAD) &&
+- (field64(elf, elf->segments64[i].p_filesz) != 0))
++ if (field32(elf, elf->segments64[i].p_type) == PT_LOAD)
+ image->num_sections++;
+
+ if (image->num_sections == 0) {
+@@ -574,10 +568,8 @@ static int image_elf64_read_headers(struct image *image)
+ }
+
+ for (i = 0, j = 0; i < elf->segment_count; i++) {
+- if ((field32(elf,
+- elf->segments64[i].p_type) == PT_LOAD) &&
+- (field64(elf, elf->segments64[i].p_filesz) != 0)) {
+- image->sections[j].size = field64(elf, elf->segments64[i].p_filesz);
++ if (field32(elf, elf->segments64[i].p_type) == PT_LOAD) {
++ image->sections[j].size = field64(elf, elf->segments64[i].p_memsz);
+ if (load_to_vaddr)
+ image->sections[j].base_address = field64(elf,
+ elf->segments64[i].p_vaddr);
+@@ -651,6 +643,8 @@ static int image_elf32_read_section(struct image *image,
+ {
+ struct image_elf *elf = image->type_private;
+ Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private;
++ uint32_t filesz = field32(elf, segment->p_filesz);
++ uint32_t memsz = field32(elf, segment->p_memsz);
+ size_t read_size, really_read;
+ int retval;
+
+@@ -659,9 +653,9 @@ static int image_elf32_read_section(struct image *image,
+ LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size);
+
+ /* read initialized data in current segment if any */
+- if (offset < field32(elf, segment->p_filesz)) {
++ if (offset < filesz) {
+ /* maximal size present in file for the current segment */
+- read_size = MIN(size, field32(elf, segment->p_filesz) - offset);
++ read_size = MIN(size, filesz - offset);
+ LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size,
+ field32(elf, segment->p_offset) + offset);
+ /* read initialized area of the segment */
+@@ -675,6 +669,8 @@ static int image_elf32_read_section(struct image *image,
+ LOG_ERROR("cannot read ELF segment content, read failed");
+ return retval;
+ }
++ buffer += read_size;
++ offset += read_size;
+ size -= read_size;
+ *size_read += read_size;
+ /* need more data ? */
+@@ -682,6 +678,13 @@ static int image_elf32_read_section(struct image *image,
+ return ERROR_OK;
+ }
+
++ /* clear bss in current segment if any */
++ if (offset >= filesz) {
++ uint32_t memset_size = MIN(size, memsz - filesz);
++ memset(buffer, 0, memset_size);
++ *size_read += memset_size;
++ }
++
+ return ERROR_OK;
+ }
+
+@@ -694,6 +697,8 @@ static int image_elf64_read_section(struct image *image,
+ {
+ struct image_elf *elf = image->type_private;
+ Elf64_Phdr *segment = (Elf64_Phdr *)image->sections[section].private;
++ uint64_t filesz = field64(elf, segment->p_filesz);
++ uint64_t memsz = field64(elf, segment->p_memsz);
+ size_t read_size, really_read;
+ int retval;
+
+@@ -702,9 +707,9 @@ static int image_elf64_read_section(struct image *image,
+ LOG_DEBUG("load segment %d at 0x%" TARGET_PRIxADDR " (sz = 0x%" PRIx32 ")", section, offset, size);
+
+ /* read initialized data in current segment if any */
+- if (offset < field64(elf, segment->p_filesz)) {
++ if (offset < filesz) {
+ /* maximal size present in file for the current segment */
+- read_size = MIN(size, field64(elf, segment->p_filesz) - offset);
++ read_size = MIN(size, filesz - offset);
+ LOG_DEBUG("read elf: size = 0x%zx at 0x%" TARGET_PRIxADDR "", read_size,
+ field64(elf, segment->p_offset) + offset);
+ /* read initialized area of the segment */
+@@ -718,6 +723,8 @@ static int image_elf64_read_section(struct image *image,
+ LOG_ERROR("cannot read ELF segment content, read failed");
+ return retval;
+ }
++ buffer += read_size;
++ offset += read_size;
+ size -= read_size;
+ *size_read += read_size;
+ /* need more data ? */
+@@ -725,6 +732,13 @@ static int image_elf64_read_section(struct image *image,
+ return ERROR_OK;
+ }
+
++ /* clear bss in current segment if any */
++ if (offset >= filesz) {
++ uint64_t memset_size = MIN(size, memsz - filesz);
++ memset(buffer, 0, memset_size);
++ *size_read += memset_size;
++ }
++
+ return ERROR_OK;
+ }
+
new file mode 100644
@@ -0,0 +1,806 @@
+From 904d58c208ab03f09f8d8e7184d49f42f6e16533 Mon Sep 17 00:00:00 2001
+From: Ian Thompson <ianst@cadence.com>
+Date: Fri, 4 Nov 2022 14:54:24 -0700
+Subject: [PATCH] target/xtensa: add NX support
+
+- Manual integration of NX support from xt0.2 release
+- No new clang static analysis warnings
+
+Signed-off-by: Ian Thompson <ianst@cadence.com>
+Change-Id: I95b51ccc83e56c0d4dbf09e01969ed6a4a93d497
+Reviewed-on: https://review.openocd.org/c/openocd/+/7356
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/xtensa/xtensa.c | 367 ++++++++++++++++++++----
+ src/target/xtensa/xtensa.h | 40 +++
+ src/target/xtensa/xtensa_debug_module.h | 15 +
+ 3 files changed, 370 insertions(+), 52 deletions(-)
+
+diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c
+index b57e2d660..fcd00487c 100644
+--- a/src/target/xtensa/xtensa.c
++++ b/src/target/xtensa/xtensa.c
+@@ -165,6 +165,7 @@
+ #define XT_SR_DDR (xtensa_regs[XT_REG_IDX_DDR].reg_num)
+ #define XT_SR_PS (xtensa_regs[XT_REG_IDX_PS].reg_num)
+ #define XT_SR_WB (xtensa_regs[XT_REG_IDX_WINDOWBASE].reg_num)
++#define XT_REG_A0 (xtensa_regs[XT_REG_IDX_AR0].reg_num)
+ #define XT_REG_A3 (xtensa_regs[XT_REG_IDX_AR3].reg_num)
+ #define XT_REG_A4 (xtensa_regs[XT_REG_IDX_AR4].reg_num)
+
+@@ -173,6 +174,7 @@
+ #define XT_EPC_REG_NUM_BASE (0xb0U) /* (EPC1 - 1), for adding DBGLEVEL */
+ #define XT_PC_REG_NUM_VIRTUAL (0xffU) /* Marker for computing PC (EPC[DBGLEVEL) */
+ #define XT_PC_DBREG_NUM_BASE (0x20U) /* External (i.e., GDB) access */
++#define XT_NX_IBREAKC_BASE (0xc0U) /* (IBREAKC0..IBREAKC1) for NX */
+
+ #define XT_SW_BREAKPOINTS_MAX_NUM 32
+ #define XT_HW_IBREAK_MAX_NUM 2
+@@ -476,7 +478,9 @@ static enum xtensa_reg_id xtensa_windowbase_offset_to_canonical(struct xtensa *x
+ LOG_ERROR("Error: can't convert register %d to non-windowbased register!", reg_idx);
+ return -1;
+ }
+- return ((idx + windowbase * 4) & (xtensa->core_config->aregs_num - 1)) + XT_REG_IDX_AR0;
++ /* Each windowbase value represents 4 registers on LX and 8 on NX */
++ int base_inc = (xtensa->core_config->core_type == XT_LX) ? 4 : 8;
++ return ((idx + windowbase * base_inc) & (xtensa->core_config->aregs_num - 1)) + XT_REG_IDX_AR0;
+ }
+
+ static enum xtensa_reg_id xtensa_canonical_to_windowbase_offset(struct xtensa *xtensa,
+@@ -526,26 +530,29 @@ static int xtensa_queue_pwr_reg_write(struct xtensa *xtensa, unsigned int reg, u
+ static int xtensa_window_state_save(struct target *target, uint32_t *woe)
+ {
+ struct xtensa *xtensa = target_to_xtensa(target);
+- int woe_dis;
++ unsigned int woe_sr = (xtensa->core_config->core_type == XT_LX) ? XT_SR_PS : XT_SR_WB;
++ uint32_t woe_dis;
+ uint8_t woe_buf[4];
+
+ if (xtensa->core_config->windowed) {
+- /* Save PS (LX) and disable window overflow exceptions prior to AR save */
+- xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_PS, XT_REG_A3));
++ /* Save PS (LX) or WB (NX) and disable window overflow exceptions prior to AR save */
++ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, woe_sr, XT_REG_A3));
+ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_DDR, XT_REG_A3));
+ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DDR, woe_buf);
+ int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
+ if (res != ERROR_OK) {
+- LOG_ERROR("Failed to read PS (%d)!", res);
++ LOG_TARGET_ERROR(target, "Failed to read %s (%d)!",
++ (woe_sr == XT_SR_PS) ? "PS" : "WB", res);
+ return res;
+ }
+ xtensa_core_status_check(target);
+ *woe = buf_get_u32(woe_buf, 0, 32);
+- woe_dis = *woe & ~XT_PS_WOE_MSK;
+- LOG_DEBUG("Clearing PS.WOE (0x%08" PRIx32 " -> 0x%08" PRIx32 ")", *woe, woe_dis);
++ woe_dis = *woe & ~((woe_sr == XT_SR_PS) ? XT_PS_WOE_MSK : XT_WB_S_MSK);
++ LOG_TARGET_DEBUG(target, "Clearing %s (0x%08" PRIx32 " -> 0x%08" PRIx32 ")",
++ (woe_sr == XT_SR_PS) ? "PS.WOE" : "WB.S", *woe, woe_dis);
+ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, woe_dis);
+ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3));
+- xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_PS, XT_REG_A3));
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, woe_sr, XT_REG_A3));
+ }
+ return ERROR_OK;
+ }
+@@ -554,12 +561,14 @@ static int xtensa_window_state_save(struct target *target, uint32_t *woe)
+ static void xtensa_window_state_restore(struct target *target, uint32_t woe)
+ {
+ struct xtensa *xtensa = target_to_xtensa(target);
++ unsigned int woe_sr = (xtensa->core_config->core_type == XT_LX) ? XT_SR_PS : XT_SR_WB;
+ if (xtensa->core_config->windowed) {
+ /* Restore window overflow exception state */
+ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, woe);
+ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3));
+- xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_PS, XT_REG_A3));
+- LOG_DEBUG("Restored PS.WOE (0x%08" PRIx32 ")", woe);
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, woe_sr, XT_REG_A3));
++ LOG_TARGET_DEBUG(target, "Restored %s (0x%08" PRIx32 ")",
++ (woe_sr == XT_SR_PS) ? "PS.WOE" : "WB", woe);
+ }
+ }
+
+@@ -596,6 +605,10 @@ static int xtensa_write_dirty_registers(struct target *target)
+ bool preserve_a3 = false;
+ uint8_t a3_buf[4];
+ xtensa_reg_val_t a3 = 0, woe;
++ unsigned int ms_idx = (xtensa->core_config->core_type == XT_NX) ?
++ xtensa->nx_reg_idx[XT_NX_REG_IDX_MS] : reg_list_size;
++ xtensa_reg_val_t ms;
++ bool restore_ms = false;
+
+ LOG_TARGET_DEBUG(target, "start");
+
+@@ -627,13 +640,25 @@ 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_EPC_REG_NUM_BASE +
+- xtensa->core_config->debug.irq_level);
+- xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, reg_num, XT_REG_A3));
++ if (reg_num == XT_PC_REG_NUM_VIRTUAL) {
++ if (xtensa->core_config->core_type == XT_LX) {
++ /* reg number of PC for debug interrupt depends on NDEBUGLEVEL */
++ reg_num = (XT_EPC_REG_NUM_BASE + xtensa->core_config->debug.irq_level);
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, reg_num, XT_REG_A3));
++ } else {
++ /* NX PC set through issuing a jump instruction */
++ xtensa_queue_exec_ins(xtensa, XT_INS_JX(xtensa, XT_REG_A3));
++ }
++ } else if (i == ms_idx) {
++ /* MS must be restored after ARs. This ensures ARs remain in correct
++ * order even for reversed register groups (overflow/underflow).
++ */
++ ms = regval;
++ restore_ms = true;
++ LOG_TARGET_DEBUG(target, "Delaying MS write: 0x%x", ms);
++ } else {
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, reg_num, XT_REG_A3));
++ }
+ }
+ }
+ reg_list[i].dirty = false;
+@@ -648,12 +673,12 @@ static int xtensa_write_dirty_registers(struct target *target)
+ xtensa_queue_dbg_reg_write(xtensa, XDMREG_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;
+ }
+
+- preserve_a3 = (xtensa->core_config->windowed);
++ preserve_a3 = (xtensa->core_config->windowed) || (xtensa->core_config->core_type == XT_NX);
+ if (preserve_a3) {
+ /* Save (windowed) A3 for scratch use */
+ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_DDR, XT_REG_A3));
+@@ -670,7 +695,12 @@ static int xtensa_write_dirty_registers(struct target *target)
+ if (res != ERROR_OK)
+ return res;
+ /* Grab the windowbase, we need it. */
+- windowbase = xtensa_reg_get(target, XT_REG_IDX_WINDOWBASE);
++ uint32_t wb_idx = (xtensa->core_config->core_type == XT_LX) ?
++ XT_REG_IDX_WINDOWBASE : xtensa->nx_reg_idx[XT_NX_REG_IDX_WB];
++ windowbase = xtensa_reg_get(target, wb_idx);
++ if (xtensa->core_config->core_type == XT_NX)
++ windowbase = (windowbase & XT_WB_P_MSK) >> XT_WB_P_SHIFT;
++
+ /* Check if there are mismatches between the ARx and corresponding Ax registers.
+ * When the user sets a register on a windowed config, xt-gdb may set the ARx
+ * register directly. Thus we take ARx as priority over Ax if both are dirty
+@@ -748,10 +778,12 @@ static int xtensa_write_dirty_registers(struct target *target)
+ }
+ }
+ }
+- /*Now rotate the window so we'll see the next 16 registers. The final rotate
+- * will wraparound, */
+- /*leaving us in the state we were. */
+- xtensa_queue_exec_ins(xtensa, XT_INS_ROTW(xtensa, 4));
++
++ /* Now rotate the window so we'll see the next 16 registers. The final rotate
++ * will wraparound, leaving us in the state we were.
++ * Each ROTW rotates 4 registers on LX and 8 on NX */
++ int rotw_arg = (xtensa->core_config->core_type == XT_LX) ? 4 : 2;
++ xtensa_queue_exec_ins(xtensa, XT_INS_ROTW(xtensa, rotw_arg));
+ }
+
+ xtensa_window_state_restore(target, woe);
+@@ -760,6 +792,14 @@ static int xtensa_write_dirty_registers(struct target *target)
+ xtensa->scratch_ars[s].intval = false;
+ }
+
++ if (restore_ms) {
++ uint32_t ms_regno = xtensa->optregs[ms_idx - XT_NUM_REGS].reg_num;
++ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, ms);
++ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3));
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, ms_regno, XT_REG_A3));
++ LOG_TARGET_DEBUG(target, "Delayed MS (0x%x) write complete: 0x%x", ms_regno, ms);
++ }
++
+ if (preserve_a3) {
+ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, a3);
+ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3));
+@@ -877,10 +917,41 @@ static inline void xtensa_reg_set_value(struct reg *reg, xtensa_reg_val_t value)
+ reg->dirty = true;
+ }
+
++static int xtensa_imprecise_exception_occurred(struct target *target)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++ for (enum xtensa_nx_reg_idx idx = XT_NX_REG_IDX_IEVEC; idx <= XT_NX_REG_IDX_MESR; idx++) {
++ enum xtensa_reg_id ridx = xtensa->nx_reg_idx[idx];
++ if (xtensa->nx_reg_idx[idx]) {
++ xtensa_reg_val_t reg = xtensa_reg_get(target, xtensa->nx_reg_idx[idx]);
++ if (reg & XT_IMPR_EXC_MSK) {
++ LOG_TARGET_DEBUG(target, "Imprecise exception: %s: 0x%x",
++ xtensa->core_cache->reg_list[ridx].name, reg);
++ return true;
++ }
++ }
++ }
++ return false;
++}
++
++static void xtensa_imprecise_exception_clear(struct target *target)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++ for (enum xtensa_nx_reg_idx idx = XT_NX_REG_IDX_IEVEC; idx <= XT_NX_REG_IDX_MESRCLR; idx++) {
++ enum xtensa_reg_id ridx = xtensa->nx_reg_idx[idx];
++ if (ridx && idx != XT_NX_REG_IDX_MESR) {
++ xtensa_reg_val_t value = (idx == XT_NX_REG_IDX_MESRCLR) ? XT_MESRCLR_IMPR_EXC_MSK : 0;
++ xtensa_reg_set(target, ridx, value);
++ LOG_TARGET_DEBUG(target, "Imprecise exception: clearing %s (0x%x)",
++ xtensa->core_cache->reg_list[ridx].name, value);
++ }
++ }
++}
++
+ int xtensa_core_status_check(struct target *target)
+ {
+ struct xtensa *xtensa = target_to_xtensa(target);
+- int res, needclear = 0;
++ int res, needclear = 0, needimprclear = 0;
+
+ xtensa_dm_core_status_read(&xtensa->dbg_mod);
+ xtensa_dsr_t dsr = xtensa_dm_core_status_get(&xtensa->dbg_mod);
+@@ -904,11 +975,20 @@ int xtensa_core_status_check(struct target *target)
+ dsr);
+ needclear = 1;
+ }
++ if (xtensa->core_config->core_type == XT_NX && (xtensa_imprecise_exception_occurred(target))) {
++ if (!xtensa->suppress_dsr_errors)
++ LOG_TARGET_ERROR(target,
++ "%s: Imprecise exception occurred!", target_name(target));
++ needclear = 1;
++ needimprclear = 1;
++ }
+ if (needclear) {
+ res = xtensa_dm_core_status_clear(&xtensa->dbg_mod,
+ OCDDSR_EXECEXCEPTION | OCDDSR_EXECOVERRUN);
+ if (res != ERROR_OK && !xtensa->suppress_dsr_errors)
+ LOG_TARGET_ERROR(target, "clearing DSR failed!");
++ if (xtensa->core_config->core_type == XT_NX && needimprclear)
++ xtensa_imprecise_exception_clear(target);
+ return ERROR_FAIL;
+ }
+ return ERROR_OK;
+@@ -934,8 +1014,12 @@ void xtensa_reg_set(struct target *target, enum xtensa_reg_id reg_id, xtensa_reg
+ void xtensa_reg_set_deep_relgen(struct target *target, enum xtensa_reg_id a_idx, xtensa_reg_val_t value)
+ {
+ struct xtensa *xtensa = target_to_xtensa(target);
++ uint32_t wb_idx = (xtensa->core_config->core_type == XT_LX) ?
++ XT_REG_IDX_WINDOWBASE : xtensa->nx_reg_idx[XT_NX_REG_IDX_WB];
+ uint32_t windowbase = (xtensa->core_config->windowed ?
+- xtensa_reg_get(target, XT_REG_IDX_WINDOWBASE) : 0);
++ xtensa_reg_get(target, wb_idx) : 0);
++ if (xtensa->core_config->core_type == XT_NX)
++ windowbase = (windowbase & XT_WB_P_MSK) >> XT_WB_P_SHIFT;
+ 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);
+@@ -944,14 +1028,68 @@ void xtensa_reg_set_deep_relgen(struct target *target, enum xtensa_reg_id a_idx,
+ /* Read cause for entering halted state; return bitmask in DEBUGCAUSE_* format */
+ uint32_t xtensa_cause_get(struct target *target)
+ {
+- return xtensa_reg_get(target, XT_REG_IDX_DEBUGCAUSE);
++ struct xtensa *xtensa = target_to_xtensa(target);
++ if (xtensa->core_config->core_type == XT_LX) {
++ /* LX cause in DEBUGCAUSE */
++ return xtensa_reg_get(target, XT_REG_IDX_DEBUGCAUSE);
++ }
++ if (xtensa->nx_stop_cause & DEBUGCAUSE_VALID)
++ return xtensa->nx_stop_cause;
++
++ /* NX cause determined from DSR.StopCause */
++ if (xtensa_dm_core_status_read(&xtensa->dbg_mod) != ERROR_OK) {
++ LOG_TARGET_ERROR(target, "Read DSR error");
++ } else {
++ uint32_t dsr = xtensa_dm_core_status_get(&xtensa->dbg_mod);
++ /* NX causes are prioritized; only 1 bit can be set */
++ switch ((dsr & OCDDSR_STOPCAUSE) >> OCDDSR_STOPCAUSE_SHIFT) {
++ case OCDDSR_STOPCAUSE_DI:
++ xtensa->nx_stop_cause = DEBUGCAUSE_DI;
++ break;
++ case OCDDSR_STOPCAUSE_SS:
++ xtensa->nx_stop_cause = DEBUGCAUSE_IC;
++ break;
++ case OCDDSR_STOPCAUSE_IB:
++ xtensa->nx_stop_cause = DEBUGCAUSE_IB;
++ break;
++ case OCDDSR_STOPCAUSE_B:
++ case OCDDSR_STOPCAUSE_B1:
++ xtensa->nx_stop_cause = DEBUGCAUSE_BI;
++ break;
++ case OCDDSR_STOPCAUSE_BN:
++ xtensa->nx_stop_cause = DEBUGCAUSE_BN;
++ break;
++ case OCDDSR_STOPCAUSE_DB0:
++ case OCDDSR_STOPCAUSE_DB1:
++ xtensa->nx_stop_cause = DEBUGCAUSE_DB;
++ break;
++ default:
++ LOG_TARGET_ERROR(target, "Unknown stop cause (DSR: 0x%08x)", dsr);
++ break;
++ }
++ if (xtensa->nx_stop_cause)
++ xtensa->nx_stop_cause |= DEBUGCAUSE_VALID;
++ }
++ return xtensa->nx_stop_cause;
+ }
+
+ void xtensa_cause_clear(struct target *target)
+ {
+ struct xtensa *xtensa = target_to_xtensa(target);
+- xtensa_reg_set(target, XT_REG_IDX_DEBUGCAUSE, 0);
+- xtensa->core_cache->reg_list[XT_REG_IDX_DEBUGCAUSE].dirty = false;
++ if (xtensa->core_config->core_type == XT_LX) {
++ xtensa_reg_set(target, XT_REG_IDX_DEBUGCAUSE, 0);
++ xtensa->core_cache->reg_list[XT_REG_IDX_DEBUGCAUSE].dirty = false;
++ } else {
++ /* NX DSR.STOPCAUSE is not writeable; clear cached copy but leave it valid */
++ xtensa->nx_stop_cause = DEBUGCAUSE_VALID;
++ }
++}
++
++void xtensa_cause_reset(struct target *target)
++{
++ /* Clear DEBUGCAUSE_VALID to trigger re-read (on NX) */
++ struct xtensa *xtensa = target_to_xtensa(target);
++ xtensa->nx_stop_cause = 0;
+ }
+
+ int xtensa_assert_reset(struct target *target)
+@@ -1008,9 +1146,11 @@ int xtensa_fetch_all_regs(struct target *target)
+ struct xtensa *xtensa = target_to_xtensa(target);
+ struct reg *reg_list = xtensa->core_cache->reg_list;
+ unsigned int reg_list_size = xtensa->core_cache->num_regs;
+- xtensa_reg_val_t cpenable = 0, windowbase = 0, a3;
++ xtensa_reg_val_t cpenable = 0, windowbase = 0, a0 = 0, a3;
++ unsigned int ms_idx = reg_list_size;
++ uint32_t ms = 0;
+ uint32_t woe;
+- uint8_t a3_buf[4];
++ uint8_t a0_buf[4], a3_buf[4], ms_buf[4];
+ bool debug_dsrs = !xtensa->regs_fetched || LOG_LEVEL_IS(LOG_LVL_DEBUG);
+
+ union xtensa_reg_val_u *regvals = calloc(reg_list_size, sizeof(*regvals));
+@@ -1030,6 +1170,25 @@ int xtensa_fetch_all_regs(struct target *target)
+ /* Save (windowed) A3 so cache matches physical AR3; A3 usable as scratch */
+ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_DDR, XT_REG_A3));
+ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DDR, a3_buf);
++ if (xtensa->core_config->core_type == XT_NX) {
++ /* Save (windowed) A0 as well--it will be required for reading PC */
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_DDR, XT_REG_A0));
++ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DDR, a0_buf);
++
++ /* Set MS.DispSt, clear MS.DE prior to accessing ARs. This ensures ARs remain
++ * in correct order even for reversed register groups (overflow/underflow).
++ */
++ ms_idx = xtensa->nx_reg_idx[XT_NX_REG_IDX_MS];
++ uint32_t ms_regno = xtensa->optregs[ms_idx - XT_NUM_REGS].reg_num;
++ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, ms_regno, XT_REG_A3));
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_DDR, XT_REG_A3));
++ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DDR, ms_buf);
++ LOG_TARGET_DEBUG(target, "Overriding MS (0x%x): 0x%x", ms_regno, XT_MS_DISPST_DBG);
++ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, XT_MS_DISPST_DBG);
++ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3));
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, ms_regno, XT_REG_A3));
++ }
++
+ int res = xtensa_window_state_save(target, &woe);
+ if (res != ERROR_OK)
+ goto xtensa_fetch_all_regs_done;
+@@ -1052,11 +1211,13 @@ int xtensa_fetch_all_regs(struct target *target)
+ dsrs[XT_REG_IDX_AR0 + i + j].buf);
+ }
+ }
+- if (xtensa->core_config->windowed)
++ if (xtensa->core_config->windowed) {
+ /* Now rotate the window so we'll see the next 16 registers. The final rotate
+- * will wraparound, */
+- /* leaving us in the state we were. */
+- xtensa_queue_exec_ins(xtensa, XT_INS_ROTW(xtensa, 4));
++ * will wraparound, leaving us in the state we were.
++ * Each ROTW rotates 4 registers on LX and 8 on NX */
++ int rotw_arg = (xtensa->core_config->core_type == XT_LX) ? 4 : 2;
++ xtensa_queue_exec_ins(xtensa, XT_INS_ROTW(xtensa, rotw_arg));
++ }
+ }
+ xtensa_window_state_restore(target, woe);
+
+@@ -1074,6 +1235,10 @@ int xtensa_fetch_all_regs(struct target *target)
+ xtensa_core_status_check(target);
+
+ a3 = buf_get_u32(a3_buf, 0, 32);
++ if (xtensa->core_config->core_type == XT_NX) {
++ a0 = buf_get_u32(a0_buf, 0, 32);
++ ms = buf_get_u32(ms_buf, 0, 32);
++ }
+
+ if (xtensa->core_config->coproc) {
+ cpenable = buf_get_u32(regvals[XT_REG_IDX_CPENABLE].buf, 0, 32);
+@@ -1104,17 +1269,30 @@ int xtensa_fetch_all_regs(struct target *target)
+ break;
+ case XT_REG_SPECIAL:
+ if (reg_num == XT_PC_REG_NUM_VIRTUAL) {
+- /* reg number of PC for debug interrupt depends on NDEBUGLEVEL */
+- reg_num = XT_EPC_REG_NUM_BASE + xtensa->core_config->debug.irq_level;
+- } else if (reg_num == xtensa_regs[XT_REG_IDX_PS].reg_num) {
++ if (xtensa->core_config->core_type == XT_LX) {
++ /* reg number of PC for debug interrupt depends on NDEBUGLEVEL */
++ reg_num = XT_EPC_REG_NUM_BASE + xtensa->core_config->debug.irq_level;
++ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, reg_num, XT_REG_A3));
++ } else {
++ /* NX PC read through CALL0(0) and reading A0 */
++ xtensa_queue_exec_ins(xtensa, XT_INS_CALL0(xtensa, 0));
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_DDR, XT_REG_A0));
++ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DDR, regvals[i].buf);
++ xtensa_queue_dbg_reg_read(xtensa, XDMREG_DSR, dsrs[i].buf);
++ reg_fetched = false;
++ }
++ } else if ((xtensa->core_config->core_type == XT_LX)
++ && (reg_num == xtensa_regs[XT_REG_IDX_PS].reg_num)) {
+ /* reg number of PS for debug interrupt depends on NDEBUGLEVEL */
+ reg_num = XT_EPS_REG_NUM_BASE + xtensa->core_config->debug.irq_level;
++ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, reg_num, XT_REG_A3));
+ } else if (reg_num == xtensa_regs[XT_REG_IDX_CPENABLE].reg_num) {
+ /* CPENABLE already read/updated; don't re-read */
+ reg_fetched = false;
+ break;
++ } else {
++ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, reg_num, XT_REG_A3));
+ }
+- xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, reg_num, XT_REG_A3));
+ break;
+ default:
+ reg_fetched = false;
+@@ -1154,9 +1332,15 @@ int xtensa_fetch_all_regs(struct target *target)
+ }
+ }
+
+- if (xtensa->core_config->windowed)
++ if (xtensa->core_config->windowed) {
+ /* We need the windowbase to decode the general addresses. */
+- windowbase = buf_get_u32(regvals[XT_REG_IDX_WINDOWBASE].buf, 0, 32);
++ uint32_t wb_idx = (xtensa->core_config->core_type == XT_LX) ?
++ XT_REG_IDX_WINDOWBASE : xtensa->nx_reg_idx[XT_NX_REG_IDX_WB];
++ windowbase = buf_get_u32(regvals[wb_idx].buf, 0, 32);
++ if (xtensa->core_config->core_type == XT_NX)
++ windowbase = (windowbase & XT_WB_P_MSK) >> XT_WB_P_SHIFT;
++ }
++
+ /* Decode the result and update the cache. */
+ for (unsigned int i = 0; i < reg_list_size; i++) {
+ struct xtensa_reg_desc *rlist = (i < XT_NUM_REGS) ? xtensa_regs : xtensa->optregs;
+@@ -1180,6 +1364,16 @@ int xtensa_fetch_all_regs(struct target *target)
+ bool is_dirty = (i == XT_REG_IDX_CPENABLE);
+ if (xtensa_extra_debug_log)
+ LOG_INFO("Register %s: 0x%X", reg_list[i].name, regval);
++ if (rlist[ridx].reg_num == XT_PC_REG_NUM_VIRTUAL &&
++ xtensa->core_config->core_type == XT_NX) {
++ /* A0 from prior CALL0 points to next instruction; decrement it */
++ regval -= 3;
++ is_dirty = 1;
++ } else if (i == ms_idx) {
++ LOG_TARGET_DEBUG(target, "Caching MS: 0x%x", ms);
++ regval = ms;
++ is_dirty = 1;
++ }
+ xtensa_reg_set(target, i, regval);
+ reg_list[i].dirty = is_dirty; /*always do this _after_ xtensa_reg_set! */
+ }
+@@ -1214,6 +1408,11 @@ int xtensa_fetch_all_regs(struct target *target)
+ /* We have used A3 (XT_REG_RELGEN) as a scratch register. Restore and flag for write-back. */
+ xtensa_reg_set(target, XT_REG_IDX_A3, a3);
+ xtensa_mark_register_dirty(xtensa, XT_REG_IDX_A3);
++ if (xtensa->core_config->core_type == XT_NX) {
++ xtensa_reg_set(target, XT_REG_IDX_A0, a0);
++ xtensa_mark_register_dirty(xtensa, XT_REG_IDX_A0);
++ }
++
+ xtensa->regs_fetched = true;
+ xtensa_fetch_all_regs_done:
+ free(regvals);
+@@ -1262,7 +1461,7 @@ int xtensa_get_gdb_reg_list(struct target *target,
+ struct xtensa_reg_desc *rlist = (i < XT_NUM_REGS) ? xtensa_regs : xtensa->optregs;
+ unsigned int ridx = (i < XT_NUM_REGS) ? i : i - XT_NUM_REGS;
+ int sparse_idx = rlist[ridx].dbreg_num;
+- if (i == XT_REG_IDX_PS) {
++ if (i == XT_REG_IDX_PS && xtensa->core_config->core_type == XT_LX) {
+ if (xtensa->eps_dbglevel_idx == 0) {
+ LOG_ERROR("eps_dbglevel_idx not set\n");
+ return ERROR_FAIL;
+@@ -1372,10 +1571,13 @@ int xtensa_prepare_resume(struct target *target,
+ if (xtensa->hw_brps[slot]) {
+ /* Write IBREAKA[slot] and set bit #slot in IBREAKENABLE */
+ xtensa_reg_set(target, XT_REG_IDX_IBREAKA0 + slot, xtensa->hw_brps[slot]->address);
++ if (xtensa->core_config->core_type == XT_NX)
++ xtensa_reg_set(target, xtensa->nx_reg_idx[XT_NX_REG_IDX_IBREAKC0] + slot, XT_IBREAKC_FB);
+ bpena |= BIT(slot);
+ }
+ }
+- xtensa_reg_set(target, XT_REG_IDX_IBREAKENABLE, bpena);
++ if (xtensa->core_config->core_type == XT_LX)
++ xtensa_reg_set(target, XT_REG_IDX_IBREAKENABLE, bpena);
+
+ /* Here we write all registers to the targets */
+ int res = xtensa_write_dirty_registers(target);
+@@ -1390,6 +1592,7 @@ int xtensa_do_resume(struct target *target)
+
+ LOG_TARGET_DEBUG(target, "start");
+
++ xtensa_cause_reset(target);
+ xtensa_queue_exec_ins(xtensa, XT_INS_RFDO(xtensa));
+ int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
+ if (res != ERROR_OK) {
+@@ -1467,13 +1670,14 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+- if (xtensa->eps_dbglevel_idx == 0) {
+- LOG_ERROR("eps_dbglevel_idx not set\n");
++ if (xtensa->eps_dbglevel_idx == 0 && xtensa->core_config->core_type == XT_LX) {
++ LOG_TARGET_ERROR(target, "eps_dbglevel_idx not set\n");
+ return ERROR_FAIL;
+ }
+
+ /* Save old ps (EPS[dbglvl] on LX), pc */
+- oldps = xtensa_reg_get(target, xtensa->eps_dbglevel_idx);
++ oldps = xtensa_reg_get(target, (xtensa->core_config->core_type == XT_LX) ?
++ xtensa->eps_dbglevel_idx : XT_REG_IDX_PS);
+ oldpc = xtensa_reg_get(target, XT_REG_IDX_PC);
+
+ cause = xtensa_cause_get(target);
+@@ -1542,7 +1746,7 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in
+ if (!handle_breakpoints && (cause & (DEBUGCAUSE_BI | DEBUGCAUSE_BN)))
+ /* handle normal SW breakpoint */
+ xtensa_cause_clear(target); /* so we don't recurse into the same routine */
+- if ((oldps & 0xf) >= icountlvl) {
++ if (xtensa->core_config->core_type == XT_LX && ((oldps & 0xf) >= icountlvl)) {
+ /* Lower interrupt level to allow stepping, but flag eps[dbglvl] to be restored */
+ ps_lowered = true;
+ uint32_t newps = (oldps & ~0xf) | (icountlvl - 1);
+@@ -1554,10 +1758,16 @@ int xtensa_do_step(struct target *target, int current, target_addr_t address, in
+ oldps);
+ }
+ do {
+- xtensa_reg_set(target, XT_REG_IDX_ICOUNTLEVEL, icountlvl);
+- xtensa_reg_set(target, XT_REG_IDX_ICOUNT, icount_val);
++ if (xtensa->core_config->core_type == XT_LX) {
++ xtensa_reg_set(target, XT_REG_IDX_ICOUNTLEVEL, icountlvl);
++ xtensa_reg_set(target, XT_REG_IDX_ICOUNT, icount_val);
++ } else {
++ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DCRSET, OCDDCR_STEPREQUEST);
++ }
+
+- /* Now ICOUNT is set, we can resume as if we were going to run */
++ /* Now that ICOUNT (LX) or DCR.StepRequest (NX) is set,
++ * we can resume as if we were going to run
++ */
+ res = xtensa_prepare_resume(target, current, address, 0, 0);
+ if (res != ERROR_OK) {
+ LOG_TARGET_ERROR(target, "Failed to prepare resume for single step");
+@@ -2108,6 +2318,22 @@ int xtensa_poll(struct target *target)
+ OCDDSR_DEBUGPENDBREAK | OCDDSR_DEBUGINTBREAK | OCDDSR_DEBUGPENDTRAX |
+ OCDDSR_DEBUGINTTRAX |
+ OCDDSR_DEBUGPENDHOST | OCDDSR_DEBUGINTHOST);
++ if (xtensa->core_config->core_type == XT_NX) {
++ /* Enable imprecise exceptions while in halted state */
++ xtensa_reg_val_t ps = xtensa_reg_get(target, XT_REG_IDX_PS);
++ xtensa_reg_val_t newps = ps & ~(XT_PS_DIEXC_MSK);
++ xtensa_mark_register_dirty(xtensa, XT_REG_IDX_PS);
++ LOG_TARGET_DEBUG(target, "Enabling PS.DIEXC: 0x%08x -> 0x%08x", ps, newps);
++ xtensa_queue_dbg_reg_write(xtensa, XDMREG_DDR, newps);
++ xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa, XT_SR_DDR, XT_REG_A3));
++ xtensa_queue_exec_ins(xtensa, XT_INS_WSR(xtensa, XT_SR_PS, XT_REG_A3));
++ res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
++ if (res != ERROR_OK) {
++ LOG_TARGET_ERROR(target, "Failed to write PS.DIEXC (%d)!", res);
++ return res;
++ }
++ xtensa_core_status_check(target);
++ }
+ }
+ } else {
+ target->debug_reason = DBG_REASON_NOTHALTED;
+@@ -2326,6 +2552,8 @@ int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoin
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+ xtensa->hw_brps[slot] = NULL;
++ if (xtensa->core_config->core_type == XT_NX)
++ xtensa_reg_set(target, xtensa->nx_reg_idx[XT_NX_REG_IDX_IBREAKC0] + slot, 0);
+ LOG_TARGET_DEBUG(target, "cleared HW breakpoint %u @ " TARGET_ADDR_FMT, slot, breakpoint->address);
+ return ERROR_OK;
+ }
+@@ -3073,8 +3301,10 @@ COMMAND_HELPER(xtensa_cmd_xtdef_do, struct xtensa *xtensa)
+ const char *core_name = CMD_ARGV[0];
+ if (strcasecmp(core_name, "LX") == 0) {
+ xtensa->core_config->core_type = XT_LX;
++ } else if (strcasecmp(core_name, "NX") == 0) {
++ xtensa->core_config->core_type = XT_NX;
+ } else {
+- LOG_ERROR("xtdef [LX]\n");
++ LOG_ERROR("xtdef [LX|NX]\n");
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+ return ERROR_OK;
+@@ -3456,6 +3686,33 @@ 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);
+ }
++ if (xtensa->core_config->core_type == XT_NX) {
++ enum xtensa_nx_reg_idx idx = XT_NX_REG_IDX_NUM;
++ if (strcmp(rptr->name, "ibreakc0") == 0)
++ idx = XT_NX_REG_IDX_IBREAKC0;
++ else if (strcmp(rptr->name, "wb") == 0)
++ idx = XT_NX_REG_IDX_WB;
++ else if (strcmp(rptr->name, "ms") == 0)
++ idx = XT_NX_REG_IDX_MS;
++ else if (strcmp(rptr->name, "ievec") == 0)
++ idx = XT_NX_REG_IDX_IEVEC;
++ else if (strcmp(rptr->name, "ieextern") == 0)
++ idx = XT_NX_REG_IDX_IEEXTERN;
++ else if (strcmp(rptr->name, "mesr") == 0)
++ idx = XT_NX_REG_IDX_MESR;
++ else if (strcmp(rptr->name, "mesrclr") == 0)
++ idx = XT_NX_REG_IDX_MESRCLR;
++ if (idx < XT_NX_REG_IDX_NUM) {
++ if (xtensa->nx_reg_idx[idx] != 0) {
++ LOG_ERROR("nx_reg_idx[%d] previously set to %d",
++ idx, xtensa->nx_reg_idx[idx]);
++ return ERROR_FAIL;
++ }
++ xtensa->nx_reg_idx[idx] = XT_NUM_REGS + xtensa->num_optregs - 1;
++ LOG_DEBUG("NX reg %s: index %d (%d)",
++ rptr->name, xtensa->nx_reg_idx[idx], idx);
++ }
++ }
+ } else if (strcmp(rptr->name, "cpenable") == 0) {
+ xtensa->core_config->coproc = true;
+ }
+@@ -3640,6 +3897,12 @@ COMMAND_HELPER(xtensa_cmd_mask_interrupts_do, struct xtensa *xtensa)
+ command_print(CMD, "Current ISR step mode: %s", st);
+ return ERROR_OK;
+ }
++
++ if (xtensa->core_config->core_type == XT_NX) {
++ command_print(CMD, "ERROR: ISR step mode only supported on Xtensa LX");
++ return ERROR_FAIL;
++ }
++
+ /* Masking is ON -> interrupts during stepping are OFF, and vice versa */
+ if (!strcasecmp(CMD_ARGV[0], "off"))
+ state = XT_STEPPING_ISR_ON;
+diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h
+index 4d98f3a36..4216ae24f 100644
+--- a/src/target/xtensa/xtensa.h
++++ b/src/target/xtensa/xtensa.h
+@@ -35,6 +35,7 @@
+
+ #define XT_ISNS_SZ_MAX 3
+
++/* PS register bits (LX) */
+ #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)
+@@ -42,6 +43,31 @@
+ #define XT_PS_OWB_MSK (0xF << 8)
+ #define XT_PS_WOE_MSK BIT(18)
+
++/* PS register bits (NX) */
++#define XT_PS_DIEXC_MSK BIT(2)
++
++/* MS register bits (NX) */
++#define XT_MS_DE_MSK BIT(5)
++#define XT_MS_DISPST_MSK (0x1f)
++#define XT_MS_DISPST_DBG (0x10)
++
++/* WB register bits (NX) */
++#define XT_WB_P_SHIFT (0)
++#define XT_WB_P_MSK (0x7U << XT_WB_P_SHIFT)
++#define XT_WB_C_SHIFT (4)
++#define XT_WB_C_MSK (0x7U << XT_WB_C_SHIFT)
++#define XT_WB_N_SHIFT (8)
++#define XT_WB_N_MSK (0x7U << XT_WB_N_SHIFT)
++#define XT_WB_S_SHIFT (30)
++#define XT_WB_S_MSK (0x3U << XT_WB_S_SHIFT)
++
++/* IBREAKC register bits (NX) */
++#define XT_IBREAKC_FB (0x80000000)
++
++/* Definitions for imprecise exception registers (NX) */
++#define XT_IMPR_EXC_MSK (0x00000013)
++#define XT_MESRCLR_IMPR_EXC_MSK (0x00000090)
++
+ #define XT_LOCAL_MEM_REGIONS_NUM_MAX 8
+
+ #define XT_AREGS_NUM_MAX 64
+@@ -79,6 +105,7 @@ struct xtensa_keyval_info_s {
+ enum xtensa_type {
+ XT_UNDEF = 0,
+ XT_LX,
++ XT_NX,
+ };
+
+ struct xtensa_cache_config {
+@@ -167,6 +194,17 @@ enum xtensa_stepping_isr_mode {
+ XT_STEPPING_ISR_ON, /* interrupts are enabled during stepping */
+ };
+
++enum xtensa_nx_reg_idx {
++ XT_NX_REG_IDX_IBREAKC0 = 0,
++ XT_NX_REG_IDX_WB,
++ XT_NX_REG_IDX_MS,
++ XT_NX_REG_IDX_IEVEC, /* IEVEC, IEEXTERN, and MESR must be contiguous */
++ XT_NX_REG_IDX_IEEXTERN,
++ XT_NX_REG_IDX_MESR,
++ XT_NX_REG_IDX_MESRCLR,
++ XT_NX_REG_IDX_NUM
++};
++
+ /* Only supported in cores with in-CPU MMU. None of Espressif chips as of now. */
+ enum xtensa_mode {
+ XT_MODE_RING0,
+@@ -232,6 +270,8 @@ struct xtensa {
+ uint8_t come_online_probes_num;
+ bool proc_syscall;
+ bool halt_request;
++ uint32_t nx_stop_cause;
++ uint32_t nx_reg_idx[XT_NX_REG_IDX_NUM];
+ struct xtensa_keyval_info_s scratch_ars[XT_AR_SCRATCH_NUM];
+ bool regs_fetched; /* true after first register fetch completed successfully */
+ };
+diff --git a/src/target/xtensa/xtensa_debug_module.h b/src/target/xtensa/xtensa_debug_module.h
+index b382e03db..46b29354c 100644
+--- a/src/target/xtensa/xtensa_debug_module.h
++++ b/src/target/xtensa/xtensa_debug_module.h
+@@ -246,6 +246,7 @@ struct xtensa_dm_reg_offsets {
+ #define OCDDCR_ENABLEOCD BIT(0)
+ #define OCDDCR_DEBUGINTERRUPT BIT(1)
+ #define OCDDCR_INTERRUPTALLCONDS BIT(2)
++#define OCDDCR_STEPREQUEST BIT(3) /* NX only */
+ #define OCDDCR_BREAKINEN BIT(16)
+ #define OCDDCR_BREAKOUTEN BIT(17)
+ #define OCDDCR_DEBUGSWACTIVE BIT(20)
+@@ -259,6 +260,8 @@ struct xtensa_dm_reg_offsets {
+ #define OCDDSR_EXECBUSY BIT(2)
+ #define OCDDSR_EXECOVERRUN BIT(3)
+ #define OCDDSR_STOPPED BIT(4)
++#define OCDDSR_STOPCAUSE (0xF << 5) /* NX only */
++#define OCDDSR_STOPCAUSE_SHIFT (5) /* NX only */
+ #define OCDDSR_COREWROTEDDR BIT(10)
+ #define OCDDSR_COREREADDDR BIT(11)
+ #define OCDDSR_HOSTWROTEDDR BIT(14)
+@@ -275,12 +278,24 @@ struct xtensa_dm_reg_offsets {
+ #define OCDDSR_BREAKINITI BIT(26)
+ #define OCDDSR_DBGMODPOWERON BIT(31)
+
++/* NX stop cause */
++#define OCDDSR_STOPCAUSE_DI (0) /* Debug Interrupt */
++#define OCDDSR_STOPCAUSE_SS (1) /* Single-step completed */
++#define OCDDSR_STOPCAUSE_IB (2) /* HW breakpoint (IBREAKn match) */
++#define OCDDSR_STOPCAUSE_B1 (4) /* SW breakpoint (BREAK.1 instruction) */
++#define OCDDSR_STOPCAUSE_BN (5) /* SW breakpoint (BREAK.N instruction) */
++#define OCDDSR_STOPCAUSE_B (6) /* SW breakpoint (BREAK instruction) */
++#define OCDDSR_STOPCAUSE_DB0 (8) /* HW watchpoint (DBREAK0 match) */
++#define OCDDSR_STOPCAUSE_DB1 (9) /* HW watchpoint (DBREAK0 match) */
++
++/* LX stop cause */
+ #define DEBUGCAUSE_IC BIT(0) /* ICOUNT exception */
+ #define DEBUGCAUSE_IB BIT(1) /* IBREAK exception */
+ #define DEBUGCAUSE_DB BIT(2) /* DBREAK exception */
+ #define DEBUGCAUSE_BI BIT(3) /* BREAK instruction encountered */
+ #define DEBUGCAUSE_BN BIT(4) /* BREAK.N instruction encountered */
+ #define DEBUGCAUSE_DI BIT(5) /* Debug Interrupt */
++#define DEBUGCAUSE_VALID BIT(31) /* Pseudo-value to trigger reread (NX only) */
+
+ #define TRAXCTRL_TREN BIT(0) /* Trace enable. Tracing starts on 0->1 */
+ #define TRAXCTRL_TRSTP BIT(1) /* Trace Stop. Make 1 to stop trace. */
new file mode 100644
@@ -0,0 +1,111 @@
+From e8f376e3c1874ccd14e148164d9695a93c575def Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sat, 4 Mar 2023 23:56:35 +0100
+Subject: [PATCH] helper: add compiler.h to handle compiler specific
+ workarounds
+
+Not all compilers nor compiler versions supports the attributes
+used in OpenOCD code.
+Collect in a single file the workaround to handle them.
+
+Change-Id: I92d871337281169134ce8e40b2064591518be71f
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7519
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/helper/Makefile.am | 3 ++-
+ src/helper/compiler.h | 44 ++++++++++++++++++++++++++++++++++++++++++
+ src/helper/nvp.h | 6 ++++--
+ 3 files changed, 50 insertions(+), 3 deletions(-)
+ create mode 100644 src/helper/compiler.h
+
+diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am
+index e9c05cfc5..e0fa331ea 100644
+--- a/src/helper/Makefile.am
++++ b/src/helper/Makefile.am
+@@ -34,7 +34,8 @@ noinst_LTLIBRARIES += %D%/libhelper.la
+ %D%/jep106.h \
+ %D%/jep106.inc \
+ %D%/jim-nvp.h \
+- %D%/nvp.h
++ %D%/nvp.h \
++ %D%/compiler.h
+
+ STARTUP_TCL_SRCS += %D%/startup.tcl
+ EXTRA_DIST += \
+diff --git a/src/helper/compiler.h b/src/helper/compiler.h
+new file mode 100644
+index 000000000..8f6c09950
+--- /dev/null
++++ b/src/helper/compiler.h
+@@ -0,0 +1,44 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++/*
++ * This file contains compiler specific workarounds to handle different
++ * compilers and different compiler versions.
++ * Inspired by Linux's include/linux/compiler_attributes.h
++ * and file sys/cdefs.h in libc and newlib.
++ */
++
++#ifndef OPENOCD_HELPER_COMPILER_H
++#define OPENOCD_HELPER_COMPILER_H
++
++/*
++ * __has_attribute is supported on gcc >= 5, clang >= 2.9 and icc >= 17.
++ */
++#ifndef __has_attribute
++# define __has_attribute(x) 0
++#endif
++
++/*
++ * The __returns_nonnull function attribute marks the return type of the function
++ * as always being non-null.
++ */
++#ifndef __returns_nonnull
++# if __has_attribute(__returns_nonnull__)
++# define __returns_nonnull __attribute__((__returns_nonnull__))
++# else
++# define __returns_nonnull
++# endif
++#endif
++
++/*
++ * The __nonnull function attribute marks pointer parameters that
++ * must not be NULL.
++ */
++#ifndef __nonnull
++# if __has_attribute(__nonnull__)
++# define __nonnull(params) __attribute__ ((__nonnull__ params))
++# else
++# define __nonnull(params)
++# endif
++#endif
++
++#endif /* OPENOCD_HELPER_COMPILER_H */
+diff --git a/src/helper/nvp.h b/src/helper/nvp.h
+index 125164e4e..14bd9b028 100644
+--- a/src/helper/nvp.h
++++ b/src/helper/nvp.h
+@@ -20,6 +20,8 @@
+ #ifndef OPENOCD_HELPER_NVP_H
+ #define OPENOCD_HELPER_NVP_H
+
++#include <helper/compiler.h>
++
+ /** Name Value Pairs, aka: NVP
+ * - Given a string - return the associated int.
+ * - Given a number - return the associated string.
+@@ -65,9 +67,9 @@ struct command_invocation;
+
+ /* Name Value Pairs Operations */
+ const struct nvp *nvp_name2value(const struct nvp *nvp_table, const char *name)
+- __attribute__((returns_nonnull, nonnull(1)));
++ __returns_nonnull __nonnull((1));
+ const struct nvp *nvp_value2name(const struct nvp *nvp_table, int v)
+- __attribute__((returns_nonnull, nonnull(1)));
++ __returns_nonnull __nonnull((1));
+
+ void nvp_unknown_command_print(struct command_invocation *cmd, const struct nvp *nvp,
+ const char *param_name, const char *param_value);
new file mode 100644
@@ -0,0 +1,35 @@
+From 642735449a3a7297126a3dd9b76ffaaca74a1752 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sat, 4 Mar 2023 19:19:16 +0100
+Subject: [PATCH] openocd: drop JIM_EMBEDDED macro
+
+The macro JIM_EMBEDDED was required to be defined before including
+jim.h in applications that embed jimtcl.
+This requirement has been dropped in 2010 by removing the file
+dos/Embedder-HOWTO.txt from jimtcl in
+https://github.com/msteveb/jimtcl/commit/2d8564100c86#diff-3e93fa55e666
+
+Drop the macro definition and the comment that mandates it.
+
+Change-Id: I36883f60f25bb25839e4ebf908159569659764dd
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7518
+Tested-by: jenkins
+---
+ src/helper/command.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/src/helper/command.c b/src/helper/command.c
+index 12434ec90..b358e18aa 100644
+--- a/src/helper/command.c
++++ b/src/helper/command.c
+@@ -18,9 +18,6 @@
+ #include "config.h"
+ #endif
+
+-/* see Embedded-HOWTO.txt in Jim Tcl project hosted on BerliOS*/
+-#define JIM_EMBEDDED
+-
+ /* @todo the inclusion of target.h here is a layering violation */
+ #include <jtag/jtag.h>
+ #include <target/target.h>
new file mode 100644
@@ -0,0 +1,81 @@
+From 45eeeab3080991168a07854af5dded926a22253c Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 6 Mar 2023 00:27:58 +0100
+Subject: [PATCH] build: fix distcheck for jimtcl
+
+The issues have been highlighted while integrated jimtcl 0.82,
+but were already present.
+
+While building jimtcl as submodule, OpenOCD generates the file
+jimtcl/configure.gnu to pass specific configure flags.
+Issue 1: this file is not included in the distribution.
+This causes the rebuild from the distribution to have a jimtcl
+built with different (the default) configure flags.
+With jimtcl 0.82 the new default is to enable all the features,
+but a bug causes the build to fail when openssl is not installed
+in the build system (the bug is already fixed but after 0.82 [1]).
+All these together cause OpenOCD Jenkins to fail the build for
+target 'distcheck' with jimtcl 0.82.
+
+Add jimtcl/configure.gnu to OpenOCD distribution's file list.
+
+The build system considers jimtcl/configure.gnu as a temporarily
+file that should be removed during 'distclean'.
+Issue 2: 'distcheck' set read-only permission to the source files,
+including jimtcl/configure.gnu, so 'distclean' fails removing it.
+
+Add a leading '-' to ignore errors while trying to remove the
+file.
+
+Issue 3: Now that 'distcheck' properly configures and builds
+jimtcl, 'distcheck' still fails because we have enabled jimtcl
+json support in [2] and jimtcl 'distclean' fails to properly
+remove one object file (fixed after 0.82 [3]).
+
+Make OpenOCD removing the file jimtcl/jsmn/jsmn.o to complete
+the execution of 'distcheck'. Add a comment specifying which of
+the jimtcl versions are affected.
+
+Change-Id: I2f9153c5a41ba66b989b27c7bc57b38d1744cc29
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Link: [1] https://github.com/msteveb/jimtcl/commit/22277943a19c
+Link: [2] 0a36acbf6ac6 ("configure: build jimtcl with json extension")
+Link: [3] https://github.com/msteveb/jimtcl/commit/32a488587a3e
+Reviewed-on: https://review.openocd.org/c/openocd/+/7527
+Tested-by: jenkins
+Reviewed-by: zapb <dev@zapb.de>
+---
+ Makefile.am | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 41daf9522..fa92da912 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -26,10 +26,14 @@ noinst_LTLIBRARIES =
+ info_TEXINFOS =
+ dist_man_MANS =
+ EXTRA_DIST =
++DISTCLEANFILES =
+
+ if INTERNAL_JIMTCL
+ SUBDIRS += jimtcl
+ DIST_SUBDIRS += jimtcl
++EXTRA_DIST += jimtcl/configure.gnu
++# jimtcl from 0.79 to 0.82 miss cleaning jsmn.o
++DISTCLEANFILES += jimtcl/jsmn/jsmn.o
+ endif
+
+ # common flags used in openocd build
+@@ -129,9 +133,9 @@ uninstall-hook:
+
+ distclean-local:
+ rm -rf Doxyfile doxygen
+- rm -f $(srcdir)/jimtcl/configure.gnu
++ -rm -f $(srcdir)/jimtcl/configure.gnu
+
+-DISTCLEANFILES = doxygen.log
++DISTCLEANFILES += doxygen.log
+
+ METASOURCES = AUTO
+
new file mode 100644
@@ -0,0 +1,53 @@
+From dccf323c1f78d015f75db4cef8cdc33523e1abd6 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sat, 4 Mar 2023 12:08:58 +0100
+Subject: [PATCH] jimtcl: update to version 0.82
+
+The new version modifies it's auto configure in change
+ https://github.com/msteveb/jimtcl/commit/ccd47be13019
+stating:
+ configure: Default to --full
+ Now use --minimal and/or --without-ext to disable things.
+
+With such change jimtcl doesn't build anymore as OpenOCD submodule
+because of errors linking with new dependencies openssl and zlib.
+
+Use option --minimal to keep the same build configuration as with
+former jimtcl 0.81.
+Add option --disable-ssl to avoid a build error on system with no
+ssl libraries installed. This is already fixed in jimtcl upstream
+but not part of 0.82. Note that ssl is not currently used by
+OpenOCD.
+
+Change-Id: I0879891dbd083bfbff1e904daf6cd549c3329bbf
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7517
+Tested-by: jenkins
+---
+ configure.ac | 4 ++--
+ jimtcl | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index cc7139c7c..ac2808e1f 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -571,9 +571,9 @@ AS_IF([test "x$enable_buspirate" != "xno"], [
+ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [
+ AS_IF([test -f "$srcdir/jimtcl/configure"], [
+ AS_IF([test "x$use_internal_jimtcl_maintainer" = "xyes"], [
+- jimtcl_config_options="--disable-install-jim --with-ext=json --maintainer"
++ jimtcl_config_options="--disable-install-jim --with-ext=json --minimal --disable-ssl --maintainer"
+ ], [
+- jimtcl_config_options="--disable-install-jim --with-ext=json"
++ jimtcl_config_options="--disable-install-jim --with-ext=json --minimal --disable-ssl"
+ ])
+ AX_CONFIG_SUBDIR_OPTION([jimtcl], [$jimtcl_config_options])
+ ], [
+diff --git a/jimtcl b/jimtcl
+index a77ef1a62..1933e5457 160000
+--- a/jimtcl
++++ b/jimtcl
+@@ -1 +1 @@
+-Subproject commit a77ef1a6218fad4c928ddbdc03c1aedc41007e70
++Subproject commit 1933e5457b9512d39ebbe11ed32578aada149f49
new file mode 100644
@@ -0,0 +1,30 @@
+From 1528845331ad260bebda6b88b880baf725ffb3c3 Mon Sep 17 00:00:00 2001
+From: Marc Schink <dev@zapb.de>
+Date: Thu, 9 Feb 2023 11:23:28 +0100
+Subject: [PATCH] tcl/tools/test_cpu_speed: Fix register name
+
+Use correct register name after it has beed changed
+in commit 11ee500bffe4 ("target/armv7m: Rename xPSR to xpsr")
+
+Change-Id: I3648848f4b47af2d20d60c3e0ecef78f75f6d605
+Signed-off-by: Marc Schink <dev@zapb.de>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7473
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ tcl/tools/test_cpu_speed.tcl | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tcl/tools/test_cpu_speed.tcl b/tcl/tools/test_cpu_speed.tcl
+index cef2bbbd7..f1a3fb30e 100644
+--- a/tcl/tools/test_cpu_speed.tcl
++++ b/tcl/tools/test_cpu_speed.tcl
+@@ -18,7 +18,7 @@ proc cortex_m_test_cpu_speed { address { timeout 200 } { cycles_per_loop 4 } } {
+ halt
+
+ # Backup registers and memory.
+- set backup_regs [get_reg -force {pc r0 xPSR}]
++ set backup_regs [get_reg -force {pc r0 xpsr}]
+ set backup_mem [read_memory $address 16 3]
+
+ # We place the following code at the given address to measure the
new file mode 100644
@@ -0,0 +1,28 @@
+From b4e28446b8f2a116b088eef78744c8b529c1a747 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 6 Mar 2023 23:18:35 +0100
+Subject: [PATCH] tcl: remove exec permission to tcl config files
+
+With the new checkpatch we will not get this type of issues
+anymore.
+In mean time, let's fix what we have missed during the review
+process.
+
+Change-Id: Iecebf9d43f51a29ee09505d360792793afd24b40
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Fixes: 53556fcded05 ("tcl/interface: add Ashling Opella-LD FTDI config files")
+Reviewed-on: https://review.openocd.org/c/openocd/+/7530
+Tested-by: jenkins
+---
+ tcl/interface/ftdi/ashling-opella-ld-jtag.cfg | 0
+ tcl/interface/ftdi/ashling-opella-ld-swd.cfg | 0
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+ mode change 100755 => 100644 tcl/interface/ftdi/ashling-opella-ld-jtag.cfg
+ mode change 100755 => 100644 tcl/interface/ftdi/ashling-opella-ld-swd.cfg
+
+diff --git a/tcl/interface/ftdi/ashling-opella-ld-jtag.cfg b/tcl/interface/ftdi/ashling-opella-ld-jtag.cfg
+old mode 100755
+new mode 100644
+diff --git a/tcl/interface/ftdi/ashling-opella-ld-swd.cfg b/tcl/interface/ftdi/ashling-opella-ld-swd.cfg
+old mode 100755
+new mode 100644
new file mode 100644
@@ -0,0 +1,145 @@
+From b6b4f9d46a48aadc1de6bb5152ff4913661c9059 Mon Sep 17 00:00:00 2001
+From: Kai Schmitz <kai.schmitz@advantest.com>
+Date: Thu, 5 Jan 2023 13:50:53 +0100
+Subject: [PATCH] svf: new command line options -noreset and -addcycles
+
+-noreset: when using several SVF input files in a sequence it is not always
+ desireable to have a JTAG reset between the execution of the files.
+ The -noreset option skips this unwanted reset.
+
+-addcycles <x>: some tests rely on a certain number of extra clock cycles
+ between the actual JTAG commands. The -addcycles option injects a number
+ x cycles after each SDR instruction.
+
+Signed-off-by: Kai Schmitz <kai.schmitz@advantest.com>
+Change-Id: I31932d6041dbc803be00016cd0a4f23fb2e7dbe1
+Reviewed-on: https://review.openocd.org/c/openocd/+/7433
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ doc/openocd.texi | 7 ++++++-
+ src/svf/svf.c | 29 +++++++++++++++++++++++++----
+ 2 files changed, 31 insertions(+), 5 deletions(-)
+
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index 414b4c405..0de101b6d 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -11433,7 +11433,8 @@ In a debug session using JTAG for its transport protocol,
+ OpenOCD supports running such test files.
+
+ @deffn {Command} {svf} @file{filename} [@option{-tap @var{tapname}}] [@option{[-]quiet}] @
+- [@option{[-]nil}] [@option{[-]progress}] [@option{[-]ignore_error}]
++ [@option{[-]nil}] [@option{[-]progress}] [@option{[-]ignore_error}] @
++ [@option{-noreset}] [@option{-addcycles @var{cyclecount}}]
+ This issues a JTAG reset (Test-Logic-Reset) and then
+ runs the SVF script from @file{filename}.
+
+@@ -11452,6 +11453,10 @@ on the real interface;
+ @item @option{[-]progress} enable progress indication;
+ @item @option{[-]ignore_error} continue execution despite TDO check
+ errors.
++@item @option{-noreset} omit JTAG reset (Test-Logic-Reset) before executing
++content of the SVF file;
++@item @option{-addcycles @var{cyclecount}} inject @var{cyclecount} number of
++additional TCLK cycles after each SDR scan instruction;
+ @end itemize
+ @end deffn
+
+diff --git a/src/svf/svf.c b/src/svf/svf.c
+index a5374316e..719588067 100644
+--- a/src/svf/svf.c
++++ b/src/svf/svf.c
+@@ -22,6 +22,7 @@
+ #include "svf.h"
+ #include "helper/system.h"
+ #include <helper/time_support.h>
++#include <stdbool.h>
+
+ /* SVF command */
+ enum svf_command {
+@@ -139,6 +140,9 @@ static const struct svf_statemove svf_statemoves[] = {
+ #define XXR_TDO (1 << 1)
+ #define XXR_MASK (1 << 2)
+ #define XXR_SMASK (1 << 3)
++
++#define SVF_MAX_ADDCYCLES 255
++
+ struct svf_xxr_para {
+ int len;
+ int data_mask;
+@@ -220,6 +224,8 @@ static int svf_buffer_index, svf_buffer_size;
+ static int svf_quiet;
+ static int svf_nil;
+ static int svf_ignore_error;
++static bool svf_noreset;
++static int svf_addcycles;
+
+ /* Targeting particular tap */
+ static int svf_tap_is_specified;
+@@ -343,7 +349,7 @@ int svf_add_statemove(tap_state_t state_to)
+ COMMAND_HANDLER(handle_svf_command)
+ {
+ #define SVF_MIN_NUM_OF_OPTIONS 1
+-#define SVF_MAX_NUM_OF_OPTIONS 5
++#define SVF_MAX_NUM_OF_OPTIONS 8
+ int command_num = 0;
+ int ret = ERROR_OK;
+ int64_t time_measure_ms;
+@@ -363,8 +369,18 @@ COMMAND_HANDLER(handle_svf_command)
+ svf_nil = 0;
+ svf_progress_enabled = 0;
+ svf_ignore_error = 0;
++ svf_noreset = false;
++ svf_addcycles = 0;
++
+ for (unsigned int i = 0; i < CMD_ARGC; i++) {
+- if (strcmp(CMD_ARGV[i], "-tap") == 0) {
++ if (strcmp(CMD_ARGV[i], "-addcycles") == 0) {
++ svf_addcycles = atoi(CMD_ARGV[i + 1]);
++ if (svf_addcycles > SVF_MAX_ADDCYCLES) {
++ command_print(CMD, "addcycles: %s out of range", CMD_ARGV[i + 1]);
++ return ERROR_FAIL;
++ }
++ i++;
++ } else if (strcmp(CMD_ARGV[i], "-tap") == 0) {
+ tap = jtag_tap_by_string(CMD_ARGV[i+1]);
+ if (!tap) {
+ command_print(CMD, "Tap: %s unknown", CMD_ARGV[i+1]);
+@@ -382,6 +398,8 @@ COMMAND_HANDLER(handle_svf_command)
+ else if ((strcmp(CMD_ARGV[i],
+ "ignore_error") == 0) || (strcmp(CMD_ARGV[i], "-ignore_error") == 0))
+ svf_ignore_error = 1;
++ else if (strcmp(CMD_ARGV[i], "-noreset") == 0)
++ svf_noreset = true;
+ else {
+ svf_fd = fopen(CMD_ARGV[i], "r");
+ if (!svf_fd) {
+@@ -424,7 +442,7 @@ COMMAND_HANDLER(handle_svf_command)
+
+ memcpy(&svf_para, &svf_para_init, sizeof(svf_para));
+
+- if (!svf_nil) {
++ if (!svf_nil && !svf_noreset) {
+ /* TAP_RESET */
+ jtag_add_tlr();
+ }
+@@ -1189,6 +1207,9 @@ xxr_common:
+ svf_para.dr_end_state);
+ }
+
++ if (svf_addcycles)
++ jtag_add_clocks(svf_addcycles);
++
+ svf_buffer_index += (i + 7) >> 3;
+ } else if (command == SIR) {
+ /* check buffer size first, reallocate if necessary */
+@@ -1545,7 +1566,7 @@ static const struct command_registration svf_command_handlers[] = {
+ .handler = handle_svf_command,
+ .mode = COMMAND_EXEC,
+ .help = "Runs a SVF file.",
+- .usage = "[-tap device.tap] <file> [quiet] [nil] [progress] [ignore_error]",
++ .usage = "[-tap device.tap] <file> [quiet] [nil] [progress] [ignore_error] [-noreset] [-addcycles numcycles]",
+ },
+ COMMAND_REGISTRATION_DONE
+ };
new file mode 100644
@@ -0,0 +1,41 @@
+From 9ce6b0898e5c0b2d6b6928b93b18137fecd6a32d Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 19 Mar 2023 10:57:04 +0100
+Subject: [PATCH] helper/compiler: fix build on MacOS
+
+On MacOS, clang defines [1]:
+ #define __nonnull _Nonnull
+that creates incompatibility with GCC and with the macro __nonnull
+defined in some libc.
+
+Detect clang on MacOS and undefine __nonnull.
+
+Change-Id: I64fcf51b102ea91c196e657debd8c267943a2b08
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Links: [1] https://github.com/llvm/llvm-project/blob/llvmorg-16.0.0/clang/lib/Frontend/InitPreprocessor.cpp#L1226
+Reviewed-on: https://review.openocd.org/c/openocd/+/7544
+Tested-by: jenkins
+---
+ src/helper/compiler.h | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/src/helper/compiler.h b/src/helper/compiler.h
+index 8f6c09950..33a075d64 100644
+--- a/src/helper/compiler.h
++++ b/src/helper/compiler.h
+@@ -32,7 +32,15 @@
+ /*
+ * The __nonnull function attribute marks pointer parameters that
+ * must not be NULL.
++ *
++ * clang for Apple defines
++ * #define __nonnull _Nonnull
++ * that is a per argument attribute, incompatible with the gcc per function attribute __nonnull__.
++ * Undefine it to keep compatibility among compilers.
+ */
++#if defined(__clang__) && defined(__APPLE__)
++# undef __nonnull
++#endif
+ #ifndef __nonnull
+ # if __has_attribute(__nonnull__)
+ # define __nonnull(params) __attribute__ ((__nonnull__ params))
new file mode 100644
@@ -0,0 +1,758 @@
+From ee31f1578a333a75737bc5b183cd4ae98cdaf798 Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Sun, 22 Jan 2023 23:43:03 +0100
+Subject: [PATCH] rtos/nuttx: add Espressif target support and refactoring
+
+Almost written from the beginning in a modern OpenOCD way.
+- Endiannes support
+- Proper variable types
+- Align with the other rtos implementations
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: I0868a22da2ed2ab664c82b17c171dc59ede78d10
+Reviewed-on: https://review.openocd.org/c/openocd/+/7444
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/rtos/Makefile.am | 3 +-
+ src/rtos/nuttx.c | 541 +++++++++++++++++++-------------
+ src/rtos/nuttx_header.h | 60 ----
+ src/rtos/rtos_nuttx_stackings.h | 3 +
+ 4 files changed, 329 insertions(+), 278 deletions(-)
+ delete mode 100644 src/rtos/nuttx_header.h
+
+diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am
+index b0f7daf5f..0796910de 100644
+--- a/src/rtos/Makefile.am
++++ b/src/rtos/Makefile.am
+@@ -34,5 +34,4 @@ noinst_LTLIBRARIES += %D%/librtos.la
+ %D%/rtos_mqx_stackings.h \
+ %D%/rtos_riot_stackings.h \
+ %D%/rtos_ucos_iii_stackings.h \
+- %D%/rtos_nuttx_stackings.h \
+- %D%/nuttx_header.h
++ %D%/rtos_nuttx_stackings.h
+diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c
+index 78271181e..0616af0f4 100644
+--- a/src/rtos/nuttx.c
++++ b/src/rtos/nuttx.c
+@@ -18,53 +18,60 @@
+ #include "rtos.h"
+ #include "helper/log.h"
+ #include "helper/types.h"
+-#include "server/gdb_server.h"
+-
+-#include "nuttx_header.h"
++#include "target/register.h"
+ #include "rtos_nuttx_stackings.h"
+
+-int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
+-
+-#ifdef CONFIG_DISABLE_SIGNALS
+-#define SIG_QUEUE_NUM 0
+-#else
+-#define SIG_QUEUE_NUM 1
+-#endif /* CONFIG_DISABLE_SIGNALS */
+-
+-#ifdef CONFIG_DISABLE_MQUEUE
+-#define M_QUEUE_NUM 0
+-#else
+-#define M_QUEUE_NUM 2
+-#endif /* CONFIG_DISABLE_MQUEUE */
+-
+-#ifdef CONFIG_PAGING
+-#define PAGING_QUEUE_NUM 1
+-#else
+-#define PAGING_QUEUE_NUM 0
+-#endif /* CONFIG_PAGING */
++#define NAME_SIZE 32
++#define EXTRAINFO_SIZE 256
+
++/* Only 32-bit CPUs are supported by the current implementation. Supporting
++ * other CPUs will require reading this information from the target and
++ * adapting the code accordingly.
++ */
++#define PTR_WIDTH 4
+
+-#define TASK_QUEUE_NUM (6 + SIG_QUEUE_NUM + M_QUEUE_NUM + PAGING_QUEUE_NUM)
++struct nuttx_params {
++ const char *target_name;
++ const struct rtos_register_stacking *stacking;
++ const struct rtos_register_stacking *(*select_stackinfo)(struct target *target);
++};
+
++/*
++ * struct tcbinfo_s is located in the sched.h
++ * https://github.com/apache/nuttx/blob/master/include/nuttx/sched.h
++ */
++#define TCBINFO_TARGET_SIZE 22
++struct tcbinfo {
++ uint16_t pid_off; /* Offset of tcb.pid */
++ uint16_t state_off; /* Offset of tcb.task_state */
++ uint16_t pri_off; /* Offset of tcb.sched_priority */
++ uint16_t name_off; /* Offset of tcb.name */
++ uint16_t regs_off; /* Offset of tcb.regs */
++ uint16_t basic_num; /* Num of genernal regs */
++ uint16_t total_num; /* Num of regs in tcbinfo.reg_offs */
++ target_addr_t xcpreg_off; /* Offset pointer of xcp.regs */
++};
+
+-/* see nuttx/sched/os_start.c */
+-static char *nuttx_symbol_list[] = {
+- "g_readytorun", /* 0: must be top of this array */
+- "g_tasklisttable",
+- NULL
++struct symbols {
++ const char *name;
++ bool optional;
+ };
+
+-/* see nuttx/include/nuttx/sched.h */
+-struct tcb {
+- uint32_t flink;
+- uint32_t blink;
+- uint8_t dat[512];
++/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */
++enum nuttx_symbol_vals {
++ NX_SYM_READYTORUN = 0,
++ NX_SYM_PIDHASH,
++ NX_SYM_NPIDHASH,
++ NX_SYM_TCB_INFO,
+ };
+
+-static struct {
+- uint32_t addr;
+- uint32_t prio;
+-} g_tasklist[TASK_QUEUE_NUM];
++static const struct symbols nuttx_symbol_list[] = {
++ { "g_readytorun", false },
++ { "g_pidhash", false },
++ { "g_npidhash", false },
++ { "g_tcbinfo", false },
++ { NULL, false }
++};
+
+ static char *task_state_str[] = {
+ "INVALID",
+@@ -73,261 +80,363 @@ static char *task_state_str[] = {
+ "RUNNING",
+ "INACTIVE",
+ "WAIT_SEM",
+-#ifndef CONFIG_DISABLE_SIGNALS
+ "WAIT_SIG",
+-#endif /* CONFIG_DISABLE_SIGNALS */
+-#ifndef CONFIG_DISABLE_MQUEUE
+ "WAIT_MQNOTEMPTY",
+ "WAIT_MQNOTFULL",
+-#endif /* CONFIG_DISABLE_MQUEUE */
+-#ifdef CONFIG_PAGING
+ "WAIT_PAGEFILL",
+-#endif /* CONFIG_PAGING */
++ "STOPPED",
+ };
+
+-static int pid_offset = PID;
+-static int state_offset = STATE;
+-static int name_offset = NAME;
+-static int xcpreg_offset = XCPREG;
+-static int name_size = NAME_SIZE;
++static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target);
++
++static const struct nuttx_params nuttx_params_list[] = {
++ {
++ .target_name = "cortex_m",
++ .stacking = NULL,
++ .select_stackinfo = cortexm_select_stackinfo,
++ },
++ {
++ .target_name = "hla_target",
++ .stacking = NULL,
++ .select_stackinfo = cortexm_select_stackinfo,
++ },
++ {
++ .target_name = "esp32",
++ .stacking = &nuttx_esp32_stacking,
++ },
++ {
++ .target_name = "esp32s2",
++ .stacking = &nuttx_esp32s2_stacking,
++ },
++ {
++ .target_name = "esp32s3",
++ .stacking = &nuttx_esp32s3_stacking,
++ },
++ {
++ .target_name = "esp32c3",
++ .stacking = &nuttx_riscv_stacking,
++ },
++};
+
+-static int rcmd_offset(const char *cmd, const char *name)
++static bool cortexm_hasfpu(struct target *target)
+ {
+- if (strncmp(cmd, name, strlen(name)))
+- return -1;
++ uint32_t cpacr;
++ struct armv7m_common *armv7m_target = target_to_armv7m(target);
+
+- if (strlen(cmd) <= strlen(name) + 1)
+- return -1;
++ if (!is_armv7m(armv7m_target) || armv7m_target->fp_feature == FP_NONE)
++ return false;
+
+- return atoi(cmd + strlen(name));
++ int retval = target_read_u32(target, FPU_CPACR, &cpacr);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("Could not read CPACR register to check FPU state");
++ return false;
++ }
++
++ return cpacr & 0x00F00000;
+ }
+
+-static int nuttx_thread_packet(struct connection *connection,
+- char const *packet, int packet_size)
++static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target)
+ {
+- char cmd[GDB_BUFFER_SIZE / 2 + 1] = ""; /* Extra byte for null-termination */
+-
+- if (!strncmp(packet, "qRcmd", 5)) {
+- size_t len = unhexify((uint8_t *)cmd, packet + 6, sizeof(cmd));
+- int offset;
+-
+- if (len <= 0)
+- goto pass;
+-
+- offset = rcmd_offset(cmd, "nuttx.pid_offset");
+-
+- if (offset >= 0) {
+- LOG_INFO("pid_offset: %d", offset);
+- pid_offset = offset;
+- goto retok;
+- }
+-
+- offset = rcmd_offset(cmd, "nuttx.state_offset");
++ return cortexm_hasfpu(target) ? &nuttx_stacking_cortex_m_fpu : &nuttx_stacking_cortex_m;
++}
+
+- if (offset >= 0) {
+- LOG_INFO("state_offset: %d", offset);
+- state_offset = offset;
+- goto retok;
+- }
++static bool nuttx_detect_rtos(struct target *target)
++{
++ if (target->rtos->symbols &&
++ target->rtos->symbols[NX_SYM_READYTORUN].address != 0 &&
++ target->rtos->symbols[NX_SYM_PIDHASH].address != 0)
++ return true;
++ return false;
++}
+
+- offset = rcmd_offset(cmd, "nuttx.name_offset");
++static int nuttx_create(struct target *target)
++{
++ const struct nuttx_params *param;
++ unsigned int i;
+
+- if (offset >= 0) {
+- LOG_INFO("name_offset: %d", offset);
+- name_offset = offset;
+- goto retok;
++ for (i = 0; i < ARRAY_SIZE(nuttx_params_list); i++) {
++ param = &nuttx_params_list[i];
++ if (strcmp(target_type_name(target), param->target_name) == 0) {
++ LOG_INFO("Detected target \"%s\"", param->target_name);
++ break;
+ }
++ }
+
+- offset = rcmd_offset(cmd, "nuttx.xcpreg_offset");
+-
+- if (offset >= 0) {
+- LOG_INFO("xcpreg_offset: %d", offset);
+- xcpreg_offset = offset;
+- goto retok;
+- }
++ if (i >= ARRAY_SIZE(nuttx_params_list)) {
++ LOG_ERROR("Could not find \"%s\" target in NuttX compatibility list", target_type_name(target));
++ return JIM_ERR;
++ }
+
+- offset = rcmd_offset(cmd, "nuttx.name_size");
++ /* We found a target in our list, copy its reference. */
++ target->rtos->rtos_specific_params = (void *)param;
+
+- if (offset >= 0) {
+- LOG_INFO("name_size: %d", offset);
+- name_size = offset;
+- goto retok;
+- }
+- }
+-pass:
+- return rtos_thread_packet(connection, packet, packet_size);
+-retok:
+- gdb_put_packet(connection, "OK", 2);
+- return ERROR_OK;
++ return JIM_OK;
+ }
+
+-
+-static bool nuttx_detect_rtos(struct target *target)
++static int nuttx_smp_init(struct target *target)
+ {
+- if ((target->rtos->symbols) &&
+- (target->rtos->symbols[0].address != 0) &&
+- (target->rtos->symbols[1].address != 0)) {
+- return true;
+- }
+- return false;
++ /* Return OK for now so that the initialisation sequence doesn't stop.
++ * SMP case will be implemented later. */
++ return ERROR_OK;
+ }
+
+-static int nuttx_create(struct target *target)
++static target_addr_t target_buffer_get_addr(struct target *target, const uint8_t *buffer)
+ {
+-
+- target->rtos->gdb_thread_packet = nuttx_thread_packet;
+- LOG_INFO("target type name = %s", target->type->name);
+- return 0;
++#if PTR_WIDTH == 8
++ return target_buffer_get_u64(target, buffer);
++#else
++ return target_buffer_get_u32(target, buffer);
++#endif
+ }
+
+ static int nuttx_update_threads(struct rtos *rtos)
+ {
+- uint32_t thread_count;
+- struct tcb tcb;
+- int ret;
+- uint32_t head;
+- uint32_t tcb_addr;
+- uint32_t i;
++ struct tcbinfo tcbinfo;
++ uint32_t pidhashaddr, npidhash, tcbaddr;
++ uint16_t pid;
+ uint8_t state;
+
+ if (!rtos->symbols) {
+- LOG_ERROR("No symbols for NuttX");
+- return -3;
++ LOG_ERROR("No symbols for nuttx");
++ return ERROR_FAIL;
+ }
+
+- /* free previous thread details */
++ /* Free previous thread details */
+ rtos_free_threadlist(rtos);
+
+- ret = target_read_buffer(rtos->target, rtos->symbols[1].address,
+- sizeof(g_tasklist), (uint8_t *)&g_tasklist);
+- if (ret) {
+- LOG_ERROR("target_read_buffer : ret = %d\n", ret);
++ /* NuttX provides a hash table that keeps track of all the TCBs.
++ * We first read its size from g_npidhash and its address from g_pidhash.
++ * Its content is then read from these values.
++ */
++ int ret = target_read_u32(rtos->target, rtos->symbols[NX_SYM_NPIDHASH].address, &npidhash);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read g_npidhash: ret = %d", ret);
+ return ERROR_FAIL;
+ }
+
+- thread_count = 0;
++ LOG_DEBUG("Hash table size (g_npidhash) = %" PRId32, npidhash);
++
++ ret = target_read_u32(rtos->target, rtos->symbols[NX_SYM_PIDHASH].address, &pidhashaddr);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read g_pidhash address: ret = %d", ret);
++ return ERROR_FAIL;
++ }
+
+- for (i = 0; i < TASK_QUEUE_NUM; i++) {
++ LOG_DEBUG("Hash table address (g_pidhash) = %" PRIx32, pidhashaddr);
++
++ uint8_t *pidhash = malloc(npidhash * PTR_WIDTH);
++ if (!pidhash) {
++ LOG_ERROR("Failed to allocate pidhash");
++ return ERROR_FAIL;
++ }
+
+- if (g_tasklist[i].addr == 0)
++ ret = target_read_buffer(rtos->target, pidhashaddr, PTR_WIDTH * npidhash, pidhash);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read tcbhash: ret = %d", ret);
++ goto errout;
++ }
++
++ /* NuttX provides a struct that contains TCB offsets for required members.
++ * Read its content from g_tcbinfo.
++ */
++ uint8_t buff[TCBINFO_TARGET_SIZE];
++ ret = target_read_buffer(rtos->target, rtos->symbols[NX_SYM_TCB_INFO].address, sizeof(buff), buff);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read tcbinfo: ret = %d", ret);
++ goto errout;
++ }
++ tcbinfo.pid_off = target_buffer_get_u16(rtos->target, buff);
++ tcbinfo.state_off = target_buffer_get_u16(rtos->target, buff + 2);
++ tcbinfo.pri_off = target_buffer_get_u16(rtos->target, buff + 4);
++ tcbinfo.name_off = target_buffer_get_u16(rtos->target, buff + 6);
++ tcbinfo.regs_off = target_buffer_get_u16(rtos->target, buff + 8);
++ tcbinfo.basic_num = target_buffer_get_u16(rtos->target, buff + 10);
++ tcbinfo.total_num = target_buffer_get_u16(rtos->target, buff + 12);
++ tcbinfo.xcpreg_off = target_buffer_get_addr(rtos->target, buff + 14);
++
++ /* The head of the g_readytorun list is the currently running task.
++ * Reading in a temporary variable first to avoid endianness issues,
++ * rtos->current_thread is int64_t. */
++ uint32_t current_thread;
++ ret = target_read_u32(rtos->target, rtos->symbols[NX_SYM_READYTORUN].address, ¤t_thread);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read g_readytorun: ret = %d", ret);
++ goto errout;
++ }
++ rtos->current_thread = current_thread;
++
++ uint32_t thread_count = 0;
++
++ for (unsigned int i = 0; i < npidhash; i++) {
++ tcbaddr = target_buffer_get_u32(rtos->target, &pidhash[i * PTR_WIDTH]);
++
++ if (!tcbaddr)
+ continue;
+
+- ret = target_read_u32(rtos->target, g_tasklist[i].addr,
+- &head);
++ ret = target_read_u16(rtos->target, tcbaddr + tcbinfo.pid_off, &pid);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read PID of TCB@0x%x from pidhash[%d]: ret = %d",
++ tcbaddr, i, ret);
++ goto errout;
++ }
+
+- if (ret) {
+- LOG_ERROR("target_read_u32 : ret = %d\n", ret);
+- return ERROR_FAIL;
++ ret = target_read_u8(rtos->target, tcbaddr + tcbinfo.state_off, &state);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read state of TCB@0x%x from pidhash[%d]: ret = %d",
++ tcbaddr, i, ret);
++ goto errout;
+ }
+
+- /* readytorun head is current thread */
+- if (g_tasklist[i].addr == rtos->symbols[0].address)
+- rtos->current_thread = head;
++ struct thread_detail *new_thread_details = realloc(rtos->thread_details,
++ sizeof(struct thread_detail) * (thread_count + 1));
++ if (!new_thread_details) {
++ ret = ERROR_FAIL;
++ goto errout;
++ }
+
++ struct thread_detail *thread = &new_thread_details[thread_count];
++ thread->threadid = tcbaddr;
++ thread->exists = true;
++ thread->extra_info_str = NULL;
+
+- tcb_addr = head;
+- while (tcb_addr) {
+- struct thread_detail *thread;
+- ret = target_read_buffer(rtos->target, tcb_addr,
+- sizeof(tcb), (uint8_t *)&tcb);
+- if (ret) {
+- LOG_ERROR("target_read_buffer : ret = %d\n",
+- ret);
+- return ERROR_FAIL;
+- }
+- thread_count++;
+-
+- rtos->thread_details = realloc(rtos->thread_details,
+- sizeof(struct thread_detail) * thread_count);
+- thread = &rtos->thread_details[thread_count - 1];
+- thread->threadid = tcb_addr;
+- thread->exists = true;
+-
+- state = tcb.dat[state_offset - 8];
+- thread->extra_info_str = NULL;
+- if (state < ARRAY_SIZE(task_state_str)) {
+- thread->extra_info_str = malloc(256);
+- snprintf(thread->extra_info_str, 256, "pid:%d, %s",
+- tcb.dat[pid_offset - 8] |
+- tcb.dat[pid_offset - 8 + 1] << 8,
+- task_state_str[state]);
+- }
++ rtos->thread_details = new_thread_details;
++ thread_count++;
+
+- if (name_offset) {
+- thread->thread_name_str = malloc(name_size + 1);
+- snprintf(thread->thread_name_str, name_size,
+- "%s", (char *)&tcb.dat[name_offset - 8]);
+- } else {
+- thread->thread_name_str = malloc(sizeof("None"));
+- strcpy(thread->thread_name_str, "None");
++ if (state < ARRAY_SIZE(task_state_str)) {
++ thread->extra_info_str = malloc(EXTRAINFO_SIZE);
++ if (!thread->extra_info_str) {
++ ret = ERROR_FAIL;
++ goto errout;
+ }
++ snprintf(thread->extra_info_str, EXTRAINFO_SIZE, "pid:%d, %s",
++ pid,
++ task_state_str[state]);
++ }
+
+- tcb_addr = tcb.flink;
++ if (tcbinfo.name_off) {
++ thread->thread_name_str = calloc(NAME_SIZE + 1, sizeof(char));
++ if (!thread->thread_name_str) {
++ ret = ERROR_FAIL;
++ goto errout;
++ }
++ ret = target_read_buffer(rtos->target, tcbaddr + tcbinfo.name_off,
++ sizeof(char) * NAME_SIZE, (uint8_t *)thread->thread_name_str);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read thread's name: ret = %d", ret);
++ goto errout;
++ }
++ } else {
++ thread->thread_name_str = strdup("None");
+ }
+ }
+- rtos->thread_count = thread_count;
+
+- return 0;
++ ret = ERROR_OK;
++ rtos->thread_count = thread_count;
++errout:
++ free(pidhash);
++ return ret;
+ }
+
+-
+-/*
+- * thread_id = tcb address;
+- */
+-static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
++static int nuttx_getreg_current_thread(struct rtos *rtos,
+ struct rtos_reg **reg_list, int *num_regs)
+ {
+- int retval;
+-
+- /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
+- bool cm4_fpu_enabled = false;
+- struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
+- if (is_armv7m(armv7m_target)) {
+- if (armv7m_target->fp_feature == FPV4_SP) {
+- /* Found ARM v7m target which includes a FPU */
+- uint32_t cpacr;
+-
+- retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr);
+- if (retval != ERROR_OK) {
+- LOG_ERROR("Could not read CPACR register to check FPU state");
+- return -1;
+- }
++ struct reg **gdb_reg_list;
++
++ /* Registers for currently running thread are not on task's stack and
++ * should be retrieved from reg caches via target_get_gdb_reg_list */
++ int ret = target_get_gdb_reg_list(rtos->target, &gdb_reg_list, num_regs,
++ REG_CLASS_GENERAL);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("target_get_gdb_reg_list failed %d", ret);
++ return ret;
++ }
+
+- /* Check if CP10 and CP11 are set to full access. */
+- if (cpacr & 0x00F00000) {
+- /* Found target with enabled FPU */
+- cm4_fpu_enabled = 1;
+- }
++ *reg_list = calloc(*num_regs, sizeof(struct rtos_reg));
++ if (!(*reg_list)) {
++ LOG_ERROR("Failed to alloc memory for %d", *num_regs);
++ free(gdb_reg_list);
++ return ERROR_FAIL;
++ }
++
++ for (int i = 0; i < *num_regs; i++) {
++ (*reg_list)[i].number = gdb_reg_list[i]->number;
++ (*reg_list)[i].size = gdb_reg_list[i]->size;
++ memcpy((*reg_list)[i].value, gdb_reg_list[i]->value, ((*reg_list)[i].size + 7) / 8);
++ }
++
++ free(gdb_reg_list);
++
++ return ERROR_OK;
++}
++
++static int nuttx_getregs_fromstack(struct rtos *rtos, int64_t thread_id,
++ struct rtos_reg **reg_list, int *num_regs)
++{
++ uint16_t xcpreg_off;
++ uint32_t regsaddr;
++ const struct nuttx_params *priv = rtos->rtos_specific_params;
++ const struct rtos_register_stacking *stacking = priv->stacking;
++
++ if (!stacking) {
++ if (priv->select_stackinfo) {
++ stacking = priv->select_stackinfo(rtos->target);
++ } else {
++ LOG_ERROR("Can't find a way to get stacking info");
++ return ERROR_FAIL;
+ }
+ }
+
+- const struct rtos_register_stacking *stacking;
+- if (cm4_fpu_enabled)
+- stacking = &nuttx_stacking_cortex_m_fpu;
+- else
+- stacking = &nuttx_stacking_cortex_m;
++ int ret = target_read_u16(rtos->target,
++ rtos->symbols[NX_SYM_TCB_INFO].address + offsetof(struct tcbinfo, regs_off),
++ &xcpreg_off);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read registers' offset: ret = %d", ret);
++ return ERROR_FAIL;
++ }
++
++ ret = target_read_u32(rtos->target, thread_id + xcpreg_off, ®saddr);
++ if (ret != ERROR_OK) {
++ LOG_ERROR("Failed to read registers' address: ret = %d", ret);
++ return ERROR_FAIL;
++ }
+
+- return rtos_generic_stack_read(rtos->target, stacking,
+- (uint32_t)thread_id + xcpreg_offset, reg_list, num_regs);
++ return rtos_generic_stack_read(rtos->target, stacking, regsaddr, reg_list, num_regs);
+ }
+
+-static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
++static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
++ struct rtos_reg **reg_list, int *num_regs)
+ {
+- unsigned int i;
++ if (!rtos) {
++ LOG_ERROR("NUTTX: out of memory");
++ return ERROR_FAIL;
++ }
++
++ if (thread_id == rtos->current_thread)
++ return nuttx_getreg_current_thread(rtos, reg_list, num_regs);
++ return nuttx_getregs_fromstack(rtos, thread_id, reg_list, num_regs);
++}
+
+- *symbol_list = (struct symbol_table_elem *) calloc(1,
+- sizeof(struct symbol_table_elem) * ARRAY_SIZE(nuttx_symbol_list));
++static int nuttx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
++{
++ *symbol_list = calloc(ARRAY_SIZE(nuttx_symbol_list), sizeof(**symbol_list));
++ if (!*symbol_list) {
++ LOG_ERROR("NUTTX: out of memory");
++ return ERROR_FAIL;
++ }
+
+- for (i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++)
+- (*symbol_list)[i].symbol_name = nuttx_symbol_list[i];
++ for (unsigned int i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++) {
++ (*symbol_list)[i].symbol_name = nuttx_symbol_list[i].name;
++ (*symbol_list)[i].optional = nuttx_symbol_list[i].optional;
++ }
+
+- return 0;
++ return ERROR_OK;
+ }
+
+ const struct rtos_type nuttx_rtos = {
+ .name = "nuttx",
+ .detect_rtos = nuttx_detect_rtos,
+ .create = nuttx_create,
++ .smp_init = nuttx_smp_init,
+ .update_threads = nuttx_update_threads,
+ .get_thread_reg_list = nuttx_get_thread_reg_list,
+ .get_symbol_list_to_lookup = nuttx_get_symbol_list_to_lookup,
+diff --git a/src/rtos/nuttx_header.h b/src/rtos/nuttx_header.h
+deleted file mode 100644
+index 3436df1eb..000000000
+--- a/src/rtos/nuttx_header.h
++++ /dev/null
+@@ -1,60 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-or-later */
+-
+-/***************************************************************************
+- * Copyright 2016,2017 Sony Video & Sound Products Inc. *
+- * Masatoshi Tateishi - Masatoshi.Tateishi@jp.sony.com *
+- * Masayuki Ishikawa - Masayuki.Ishikawa@jp.sony.com *
+- ***************************************************************************/
+-
+-#ifndef OPENOCD_RTOS_NUTTX_HEADER_H
+-#define OPENOCD_RTOS_NUTTX_HEADER_H
+-
+-/* gdb script to update the header file
+- according to kernel version and build option
+- before executing function awareness
+- kernel symbol must be loaded : symbol nuttx
+-
+-define awareness
+- set logging off
+- set logging file nuttx_header.h
+- set logging on
+-
+- printf "#define PID %p\n",&((struct tcb_s *)(0))->pid
+- printf "#define XCPREG %p\n",&((struct tcb_s *)(0))->xcp.regs
+- printf "#define STATE %p\n",&((struct tcb_s *)(0))->task_state
+- printf "#define NAME %p\n",&((struct tcb_s *)(0))->name
+- printf "#define NAME_SIZE %d\n",sizeof(((struct tcb_s *)(0))->name)
+- end
+-
+-
+- OR ~/.gdbinit
+-
+-
+-define hookpost-file
+-
+- if &g_readytorun != 0
+- eval "monitor nuttx.pid_offset %d", &((struct tcb_s *)(0))->pid
+- eval "monitor nuttx.xcpreg_offset %d", &((struct tcb_s *)(0))->xcp.regs
+- eval "monitor nuttx.state_offset %d", &((struct tcb_s *)(0))->task_state
+- eval "monitor nuttx.name_offset %d", &((struct tcb_s *)(0))->name
+- eval "monitor nuttx.name_size %d", sizeof(((struct tcb_s *)(0))->name)
+- end
+-
+-end
+-
+-*/
+-
+-/* default offset */
+-#define PID 0xc
+-#define XCPREG 0x70
+-#define STATE 0x19
+-#define NAME 0xb8
+-#define NAME_SIZE 32
+-
+-/* defconfig of nuttx */
+-/* #define CONFIG_DISABLE_SIGNALS */
+-#define CONFIG_DISABLE_MQUEUE
+-/* #define CONFIG_PAGING */
+-
+-
+-#endif /* OPENOCD_RTOS_NUTTX_HEADER_H */
+diff --git a/src/rtos/rtos_nuttx_stackings.h b/src/rtos/rtos_nuttx_stackings.h
+index 2e5f09212..213a06033 100644
+--- a/src/rtos/rtos_nuttx_stackings.h
++++ b/src/rtos/rtos_nuttx_stackings.h
+@@ -8,5 +8,8 @@
+ extern const struct rtos_register_stacking nuttx_stacking_cortex_m;
+ extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu;
+ extern const struct rtos_register_stacking nuttx_riscv_stacking;
++extern const struct rtos_register_stacking nuttx_esp32_stacking;
++extern const struct rtos_register_stacking nuttx_esp32s2_stacking;
++extern const struct rtos_register_stacking nuttx_esp32s3_stacking;
+
+ #endif /* INCLUDED_RTOS_NUTTX_STACKINGS_H */
new file mode 100644
@@ -0,0 +1,42 @@
+From faeae51d7f497d83ab166329abb1f06aa5903774 Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Wed, 15 Mar 2023 01:22:10 +0300
+Subject: [PATCH] target/espressif: check common_magic instead of gdb_arch
+ string
+
+The value returned by target_get_gdb_arch() is something specific for GDB.
+There could be several variants of the same CPU.
+If we start implementing all the variants, checking the string value,
+could become incorrect.
+It's better to check for xtensa->common_magic == XTENSA_COMMON_MAGIC
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: I20f3fdced176c3b9ab00f889743161ecad7280f9
+Reviewed-on: https://review.openocd.org/c/openocd/+/7536
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/espressif/esp_semihosting.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/src/target/espressif/esp_semihosting.c b/src/target/espressif/esp_semihosting.c
+index 5e9cb9457..51d499866 100644
+--- a/src/target/espressif/esp_semihosting.c
++++ b/src/target/espressif/esp_semihosting.c
+@@ -17,12 +17,10 @@
+
+ static struct esp_semihost_data __attribute__((unused)) *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 */
+- }
++ struct xtensa *xtensa = target->arch_info;
++ if (xtensa->common_magic == XTENSA_COMMON_MAGIC)
++ return &target_to_esp_xtensa(target)->semihost;
++ /* TODO: add riscv */
+ LOG_ERROR("Unknown target arch!");
+ return NULL;
+ }
new file mode 100644
@@ -0,0 +1,29 @@
+From 6ecd99ff9b98778d5655d6b6fc245dd8f344d365 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Tue, 14 Mar 2023 19:43:21 +0100
+Subject: [PATCH] target/adi_v5_swd: update comment about SWD capability
+
+The multidrop SWD is also supported.
+
+Change-Id: I9fefc54fc9d40a75194285cd6e0f10c5c347d9b6
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7537
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/adi_v5_swd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
+index aea730d4d..653f91f13 100644
+--- a/src/target/adi_v5_swd.c
++++ b/src/target/adi_v5_swd.c
+@@ -13,7 +13,7 @@
+ * is a transport level interface, with "target/arm_adi_v5.[hc]" code
+ * understanding operation semantics, shared with the JTAG transport.
+ *
+- * Single-DAP support only.
++ * Single DAP and multidrop-SWD support.
+ *
+ * for details, see "ARM IHI 0031A"
+ * ARM Debug Interface v5 Architecture Specification
new file mode 100644
@@ -0,0 +1,46 @@
+From 415715d91a11ea4ed6db3a1fd760741a22b6e098 Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Tue, 14 Mar 2023 15:11:14 +0100
+Subject: [PATCH] target/adi_v5_jtag: fix endianness error in transaction
+ replay
+
+The code for JTAG WAIT recovery did not handle DP_SELECT
+endianness.
+
+While on it, mark missing ADIv6 DP SELECT1 handling as TODO.
+
+Change-Id: I44f3bc8fc9fd2483c0293b6d4f2c51a60ca01873
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7540
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/adi_v5_jtag.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c
+index eeb796be4..9f66adc68 100644
+--- a/src/target/adi_v5_jtag.c
++++ b/src/target/adi_v5_jtag.c
+@@ -566,14 +566,20 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap)
+ /* restore SELECT register first */
+ if (!list_empty(&replay_list)) {
+ el = list_first_entry(&replay_list, struct dap_cmd, lh);
++
++ uint8_t out_value_buf[4];
++ buf_set_u32(out_value_buf, 0, 32, (uint32_t)(el->dp_select));
++
+ tmp = dap_cmd_new(dap, JTAG_DP_DPACC,
+- DP_SELECT, DPAP_WRITE, (uint8_t *)&el->dp_select, NULL, 0);
++ DP_SELECT, DPAP_WRITE, out_value_buf, NULL, 0);
+ if (!tmp) {
+ retval = ERROR_JTAG_DEVICE_ERROR;
+ goto done;
+ }
+ list_add(&tmp->lh, &replay_list);
+
++ /* TODO: ADIv6 DP SELECT1 handling */
++
+ dap->select = DP_SELECT_INVALID;
+ }
+
new file mode 100644
@@ -0,0 +1,54 @@
+From 86827a961a22815ebd5fa367468ca7444f0ee2e1 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Fri, 10 Mar 2023 11:50:08 +0100
+Subject: [PATCH] svf: fix leaking file descriptor
+
+The file descriptor svf_fd is not closed on command error, thus
+leaking memory.
+
+Close svf_fd on errors.
+While there, properly initialize svf_fd using NULL instead of 0.
+
+Change-Id: I5efe9ce576a3a50588b30000222665e26161dfdc
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7532
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-by: <kai.schmitz@advantest.com>
+---
+ src/svf/svf.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/svf/svf.c b/src/svf/svf.c
+index 719588067..05fb21d63 100644
+--- a/src/svf/svf.c
++++ b/src/svf/svf.c
+@@ -377,6 +377,9 @@ COMMAND_HANDLER(handle_svf_command)
+ svf_addcycles = atoi(CMD_ARGV[i + 1]);
+ if (svf_addcycles > SVF_MAX_ADDCYCLES) {
+ command_print(CMD, "addcycles: %s out of range", CMD_ARGV[i + 1]);
++ if (svf_fd)
++ fclose(svf_fd);
++ svf_fd = NULL;
+ return ERROR_FAIL;
+ }
+ i++;
+@@ -384,6 +387,9 @@ COMMAND_HANDLER(handle_svf_command)
+ tap = jtag_tap_by_string(CMD_ARGV[i+1]);
+ if (!tap) {
+ command_print(CMD, "Tap: %s unknown", CMD_ARGV[i+1]);
++ if (svf_fd)
++ fclose(svf_fd);
++ svf_fd = NULL;
+ return ERROR_FAIL;
+ }
+ i++;
+@@ -546,7 +552,7 @@ COMMAND_HANDLER(handle_svf_command)
+ free_all:
+
+ fclose(svf_fd);
+- svf_fd = 0;
++ svf_fd = NULL;
+
+ /* free buffers */
+ free(svf_command_buffer);
new file mode 100644
@@ -0,0 +1,68 @@
+From f8631c3650c0e3a3c3e16726f1ca3748d163cc69 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Fri, 10 Mar 2023 12:01:03 +0100
+Subject: [PATCH] svf: fix memory leak on error during command execution
+
+If svf_set_padding() returns error, jump to free_all label to
+prevent any memory leak.
+Propagate the error reported by svf_set_padding() instead of
+overwriting it.
+Use command_print() instead of LOG_ERROR() for command output.
+
+Change-Id: I61fd89cad10652f2f9ef1f9d48a040e35253c3d4
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7533
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/svf/svf.c | 28 ++++++++++++++++------------
+ 1 file changed, 16 insertions(+), 12 deletions(-)
+
+diff --git a/src/svf/svf.c b/src/svf/svf.c
+index 05fb21d63..2a1331280 100644
+--- a/src/svf/svf.c
++++ b/src/svf/svf.c
+@@ -473,27 +473,31 @@ COMMAND_HANDLER(handle_svf_command)
+ }
+
+ /* HDR %d TDI (0) */
+- if (svf_set_padding(&svf_para.hdr_para, header_dr_len, 0) != ERROR_OK) {
+- LOG_ERROR("failed to set data header");
+- return ERROR_FAIL;
++ ret = svf_set_padding(&svf_para.hdr_para, header_dr_len, 0);
++ if (ret != ERROR_OK) {
++ command_print(CMD, "failed to set data header");
++ goto free_all;
+ }
+
+ /* HIR %d TDI (0xFF) */
+- if (svf_set_padding(&svf_para.hir_para, header_ir_len, 0xFF) != ERROR_OK) {
+- LOG_ERROR("failed to set instruction header");
+- return ERROR_FAIL;
++ ret = svf_set_padding(&svf_para.hir_para, header_ir_len, 0xFF);
++ if (ret != ERROR_OK) {
++ command_print(CMD, "failed to set instruction header");
++ goto free_all;
+ }
+
+ /* TDR %d TDI (0) */
+- if (svf_set_padding(&svf_para.tdr_para, trailer_dr_len, 0) != ERROR_OK) {
+- LOG_ERROR("failed to set data trailer");
+- return ERROR_FAIL;
++ ret = svf_set_padding(&svf_para.tdr_para, trailer_dr_len, 0);
++ if (ret != ERROR_OK) {
++ command_print(CMD, "failed to set data trailer");
++ goto free_all;
+ }
+
+ /* TIR %d TDI (0xFF) */
+- if (svf_set_padding(&svf_para.tir_para, trailer_ir_len, 0xFF) != ERROR_OK) {
+- LOG_ERROR("failed to set instruction trailer");
+- return ERROR_FAIL;
++ ret = svf_set_padding(&svf_para.tir_para, trailer_ir_len, 0xFF);
++ if (ret != ERROR_OK) {
++ command_print(CMD, "failed to set instruction trailer");
++ goto free_all;
+ }
+ }
+
new file mode 100644
@@ -0,0 +1,218 @@
+From 5f6ceebbba3a34fc4bfcf56e963739dd2e9cf056 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Fri, 10 Mar 2023 11:41:54 +0100
+Subject: [PATCH] svf: make command 'svf' syntax consistent
+
+The command 'svf' is the only command in OpenOCD that accepts
+options in both forms 'option' and '-option'.
+
+Deprecate the option format without the leading '-'.
+Update the documentation and fix the on-line help.
+While there:
+- switch to use the new nvp.h helper;
+- return ERROR_COMMAND_ARGUMENT_INVALID on invalid command args;
+- fix some minor coding style rule.
+
+Change-Id: I5b944403d92a3fa1e12d5faafc1d2a139bc16a7d
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7534
+Tested-by: jenkins
+---
+ doc/openocd.texi | 12 +++---
+ src/svf/svf.c | 95 +++++++++++++++++++++++++++++++++++++++---------
+ 2 files changed, 83 insertions(+), 24 deletions(-)
+
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index 0de101b6d..26a59e6a7 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -11432,8 +11432,8 @@ way to represent JTAG test patterns in text files.
+ In a debug session using JTAG for its transport protocol,
+ OpenOCD supports running such test files.
+
+-@deffn {Command} {svf} @file{filename} [@option{-tap @var{tapname}}] [@option{[-]quiet}] @
+- [@option{[-]nil}] [@option{[-]progress}] [@option{[-]ignore_error}] @
++@deffn {Command} {svf} @file{filename} [@option{-tap @var{tapname}}] [@option{-quiet}] @
++ [@option{-nil}] [@option{-progress}] [@option{-ignore_error}] @
+ [@option{-noreset}] [@option{-addcycles @var{cyclecount}}]
+ This issues a JTAG reset (Test-Logic-Reset) and then
+ runs the SVF script from @file{filename}.
+@@ -11447,11 +11447,11 @@ Command options:
+ specified by the SVF file with HIR, TIR, HDR and TDR commands;
+ instead, calculate them automatically according to the current JTAG
+ chain configuration, targeting @var{tapname};
+-@item @option{[-]quiet} do not log every command before execution;
+-@item @option{[-]nil} ``dry run'', i.e., do not perform any operations
++@item @option{-quiet} do not log every command before execution;
++@item @option{-nil} ``dry run'', i.e., do not perform any operations
+ on the real interface;
+-@item @option{[-]progress} enable progress indication;
+-@item @option{[-]ignore_error} continue execution despite TDO check
++@item @option{-progress} enable progress indication;
++@item @option{-ignore_error} continue execution despite TDO check
+ errors.
+ @item @option{-noreset} omit JTAG reset (Test-Logic-Reset) before executing
+ content of the SVF file;
+diff --git a/src/svf/svf.c b/src/svf/svf.c
+index 2a1331280..dd3d5175c 100644
+--- a/src/svf/svf.c
++++ b/src/svf/svf.c
+@@ -22,6 +22,7 @@
+ #include "svf.h"
+ #include "helper/system.h"
+ #include <helper/time_support.h>
++#include <helper/nvp.h>
+ #include <stdbool.h>
+
+ /* SVF command */
+@@ -346,6 +347,37 @@ int svf_add_statemove(tap_state_t state_to)
+ return ERROR_FAIL;
+ }
+
++enum svf_cmd_param {
++ OPT_ADDCYCLES,
++ OPT_IGNORE_ERROR,
++ OPT_NIL,
++ OPT_NORESET,
++ OPT_PROGRESS,
++ OPT_QUIET,
++ OPT_TAP,
++ /* DEPRECATED */
++ DEPRECATED_OPT_IGNORE_ERROR,
++ DEPRECATED_OPT_NIL,
++ DEPRECATED_OPT_PROGRESS,
++ DEPRECATED_OPT_QUIET,
++};
++
++static const struct nvp svf_cmd_opts[] = {
++ { .name = "-addcycles", .value = OPT_ADDCYCLES },
++ { .name = "-ignore_error", .value = OPT_IGNORE_ERROR },
++ { .name = "-nil", .value = OPT_NIL },
++ { .name = "-noreset", .value = OPT_NORESET },
++ { .name = "-progress", .value = OPT_PROGRESS },
++ { .name = "-quiet", .value = OPT_QUIET },
++ { .name = "-tap", .value = OPT_TAP },
++ /* DEPRECATED */
++ { .name = "ignore_error", .value = DEPRECATED_OPT_IGNORE_ERROR },
++ { .name = "nil", .value = DEPRECATED_OPT_NIL },
++ { .name = "progress", .value = DEPRECATED_OPT_PROGRESS },
++ { .name = "quiet", .value = DEPRECATED_OPT_QUIET },
++ { .name = NULL, .value = -1 }
++};
++
+ COMMAND_HANDLER(handle_svf_command)
+ {
+ #define SVF_MIN_NUM_OF_OPTIONS 1
+@@ -355,10 +387,11 @@ COMMAND_HANDLER(handle_svf_command)
+ int64_t time_measure_ms;
+ int time_measure_s, time_measure_m;
+
+- /* use NULL to indicate a "plain" svf file which accounts for
++ /*
++ * use NULL to indicate a "plain" svf file which accounts for
+ * any additional devices in the scan chain, otherwise the device
+ * that should be affected
+- */
++ */
+ struct jtag_tap *tap = NULL;
+
+ if ((CMD_ARGC < SVF_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > SVF_MAX_NUM_OF_OPTIONS))
+@@ -373,48 +406,74 @@ COMMAND_HANDLER(handle_svf_command)
+ svf_addcycles = 0;
+
+ for (unsigned int i = 0; i < CMD_ARGC; i++) {
+- if (strcmp(CMD_ARGV[i], "-addcycles") == 0) {
++ const struct nvp *n = nvp_name2value(svf_cmd_opts, CMD_ARGV[i]);
++ switch (n->value) {
++ case OPT_ADDCYCLES:
+ svf_addcycles = atoi(CMD_ARGV[i + 1]);
+ if (svf_addcycles > SVF_MAX_ADDCYCLES) {
+ command_print(CMD, "addcycles: %s out of range", CMD_ARGV[i + 1]);
+ if (svf_fd)
+ fclose(svf_fd);
+ svf_fd = NULL;
+- return ERROR_FAIL;
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ i++;
+- } else if (strcmp(CMD_ARGV[i], "-tap") == 0) {
++ break;
++
++ case OPT_TAP:
+ tap = jtag_tap_by_string(CMD_ARGV[i+1]);
+ if (!tap) {
+ command_print(CMD, "Tap: %s unknown", CMD_ARGV[i+1]);
+ if (svf_fd)
+ fclose(svf_fd);
+ svf_fd = NULL;
+- return ERROR_FAIL;
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ i++;
+- } else if ((strcmp(CMD_ARGV[i],
+- "quiet") == 0) || (strcmp(CMD_ARGV[i], "-quiet") == 0))
++ break;
++
++ case DEPRECATED_OPT_QUIET:
++ LOG_INFO("DEPRECATED flag '%s'; use '-%s'", CMD_ARGV[i], CMD_ARGV[i]);
++ /* fallthrough */
++ case OPT_QUIET:
+ svf_quiet = 1;
+- else if ((strcmp(CMD_ARGV[i], "nil") == 0) || (strcmp(CMD_ARGV[i], "-nil") == 0))
++ break;
++
++ case DEPRECATED_OPT_NIL:
++ LOG_INFO("DEPRECATED flag '%s'; use '-%s'", CMD_ARGV[i], CMD_ARGV[i]);
++ /* fallthrough */
++ case OPT_NIL:
+ svf_nil = 1;
+- else if ((strcmp(CMD_ARGV[i],
+- "progress") == 0) || (strcmp(CMD_ARGV[i], "-progress") == 0))
++ break;
++
++ case DEPRECATED_OPT_PROGRESS:
++ LOG_INFO("DEPRECATED flag '%s'; use '-%s'", CMD_ARGV[i], CMD_ARGV[i]);
++ /* fallthrough */
++ case OPT_PROGRESS:
+ svf_progress_enabled = 1;
+- else if ((strcmp(CMD_ARGV[i],
+- "ignore_error") == 0) || (strcmp(CMD_ARGV[i], "-ignore_error") == 0))
++ break;
++
++ case DEPRECATED_OPT_IGNORE_ERROR:
++ LOG_INFO("DEPRECATED flag '%s'; use '-%s'", CMD_ARGV[i], CMD_ARGV[i]);
++ /* fallthrough */
++ case OPT_IGNORE_ERROR:
+ svf_ignore_error = 1;
+- else if (strcmp(CMD_ARGV[i], "-noreset") == 0)
++ break;
++
++ case OPT_NORESET:
+ svf_noreset = true;
+- else {
++ break;
++
++ default:
+ svf_fd = fopen(CMD_ARGV[i], "r");
+ if (!svf_fd) {
+ int err = errno;
+ command_print(CMD, "open(\"%s\"): %s", CMD_ARGV[i], strerror(err));
+ /* no need to free anything now */
+ return ERROR_COMMAND_SYNTAX_ERROR;
+- } else
+- LOG_USER("svf processing file: \"%s\"", CMD_ARGV[i]);
++ }
++ LOG_USER("svf processing file: \"%s\"", CMD_ARGV[i]);
++ break;
+ }
+ }
+
+@@ -1576,7 +1635,7 @@ static const struct command_registration svf_command_handlers[] = {
+ .handler = handle_svf_command,
+ .mode = COMMAND_EXEC,
+ .help = "Runs a SVF file.",
+- .usage = "[-tap device.tap] <file> [quiet] [nil] [progress] [ignore_error] [-noreset] [-addcycles numcycles]",
++ .usage = "[-tap device.tap] [-quiet] [-nil] [-progress] [-ignore_error] [-noreset] [-addcycles numcycles] file",
+ },
+ COMMAND_REGISTRATION_DONE
+ };
new file mode 100644
@@ -0,0 +1,62 @@
+From 1ec8b83cbdb407536966b4e455dbb39d1cb42b3a Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 00:01:00 +0100
+Subject: [PATCH] helper: command: rewrite command 'ocd_find' as
+ COMMAND_HANDLER
+
+The mixed use of jim commands and OpenOCD commands is error prone
+due to handling of errors through JIM_xx and ERROR_yy.
+
+Rewrite the jim command 'ocd_find' as OpenOCD command.
+
+Change-Id: Id775bccc12840bcf95d8c19787beda5e7c3107fc
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7484
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Tested-by: jenkins
+---
+ src/helper/command.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/helper/command.c b/src/helper/command.c
+index b358e18aa..235bec858 100644
+--- a/src/helper/command.c
++++ b/src/helper/command.c
+@@ -662,19 +662,19 @@ void command_done(struct command_context *cmd_ctx)
+ }
+
+ /* find full path to file */
+-static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_find)
+ {
+- if (argc != 2)
+- return JIM_ERR;
+- const char *file = Jim_GetString(argv[1], NULL);
+- char *full_path = find_file(file);
++ if (CMD_ARGC != 1)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ char *full_path = find_file(CMD_ARGV[0]);
+ if (!full_path)
+- return JIM_ERR;
+- Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++
++ command_print(CMD, "%s", full_path);
+ free(full_path);
+
+- Jim_SetResult(interp, result);
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ COMMAND_HANDLER(handle_echo)
+@@ -1165,7 +1165,7 @@ static const struct command_registration command_builtin_handlers[] = {
+ {
+ .name = "ocd_find",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_find,
++ .handler = handle_find,
+ .help = "find full path to file",
+ .usage = "file",
+ },
new file mode 100644
@@ -0,0 +1,149 @@
+From d05c68667129705ecfd42c6029a60e849518d50c Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 18 Dec 2022 15:26:56 +0100
+Subject: [PATCH] transport: rewrite command 'transport select' as
+ COMMAND_HANDLER
+
+The mixed use of jim commands and OpenOCD commands is error prone
+due to handling of errors through JIM_xx and ERROR_yy.
+
+Rewrite the jim command 'transport select' as OpenOCD command.
+This fixes and incorrect check for the return value of function
+transport_select(); it returns ERROR_yy but the check is on JIM_xx.
+While there, fix the coding style.
+
+Change-Id: I9f3e8394c1a0cc0312b414c58275e1220217bbed
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7485
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Tested-by: jenkins
+---
+ src/transport/transport.c | 100 +++++++++++++++++++-------------------
+ 1 file changed, 49 insertions(+), 51 deletions(-)
+
+diff --git a/src/transport/transport.c b/src/transport/transport.c
+index c05db3f00..81d3d583b 100644
+--- a/src/transport/transport.c
++++ b/src/transport/transport.c
+@@ -252,64 +252,62 @@ COMMAND_HANDLER(handle_transport_list)
+ * set supported by the debug adapter being used. Return value
+ * is scriptable (allowing "if swd then..." etc).
+ */
+-static int jim_transport_select(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(handle_transport_select)
+ {
+- int res;
+- switch (argc) {
+- case 1: /* autoselect if necessary, then return/display current config */
+- if (!session) {
+- if (!allowed_transports) {
+- LOG_ERROR("Debug adapter does not support any transports? Check config file order.");
+- return JIM_ERR;
+- }
+- LOG_INFO("auto-selecting first available session transport \"%s\". "
+- "To override use 'transport select <transport>'.", allowed_transports[0]);
+- res = transport_select(global_cmd_ctx, allowed_transports[0]);
+- if (res != JIM_OK)
+- return res;
+- }
+- Jim_SetResultString(interp, session->name, -1);
+- return JIM_OK;
+- case 2: /* assign */
+- if (session) {
+- if (!strcmp(session->name, argv[1]->bytes)) {
+- LOG_WARNING("Transport \"%s\" was already selected", session->name);
+- Jim_SetResultString(interp, session->name, -1);
+- return JIM_OK;
+- } else {
+- LOG_ERROR("Can't change session's transport after the initial selection was made");
+- return JIM_ERR;
+- }
+- }
++ if (CMD_ARGC > 1)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- /* Is this transport supported by our debug adapter?
+- * Example, "JTAG-only" means SWD is not supported.
+- *
+- * NOTE: requires adapter to have been set up, with
+- * transports declared via C.
+- */
++ if (CMD_ARGC == 0) {
++ /* autoselect if necessary, then return/display current config */
++ if (!session) {
+ if (!allowed_transports) {
+- LOG_ERROR("Debug adapter doesn't support any transports?");
+- return JIM_ERR;
++ command_print(CMD, "Debug adapter does not support any transports? Check config file order.");
++ return ERROR_FAIL;
+ }
++ LOG_INFO("auto-selecting first available session transport \"%s\". "
++ "To override use 'transport select <transport>'.", allowed_transports[0]);
++ int retval = transport_select(CMD_CTX, allowed_transports[0]);
++ if (retval != ERROR_OK)
++ return retval;
++ }
++ command_print(CMD, "%s", session->name);
++ return ERROR_OK;
++ }
+
+- for (unsigned i = 0; allowed_transports[i]; i++) {
++ /* assign transport */
++ if (session) {
++ if (!strcmp(session->name, CMD_ARGV[0])) {
++ LOG_WARNING("Transport \"%s\" was already selected", session->name);
++ command_print(CMD, "%s", session->name);
++ return ERROR_OK;
++ }
++ command_print(CMD, "Can't change session's transport after the initial selection was made");
++ return ERROR_FAIL;
++ }
+
+- if (strcmp(allowed_transports[i], argv[1]->bytes) == 0) {
+- if (transport_select(global_cmd_ctx, argv[1]->bytes) == ERROR_OK) {
+- Jim_SetResultString(interp, session->name, -1);
+- return JIM_OK;
+- }
+- return JIM_ERR;
+- }
+- }
++ /* Is this transport supported by our debug adapter?
++ * Example, "JTAG-only" means SWD is not supported.
++ *
++ * NOTE: requires adapter to have been set up, with
++ * transports declared via C.
++ */
++ if (!allowed_transports) {
++ command_print(CMD, "Debug adapter doesn't support any transports?");
++ return ERROR_FAIL;
++ }
+
+- LOG_ERROR("Debug adapter doesn't support '%s' transport", argv[1]->bytes);
+- return JIM_ERR;
+- default:
+- Jim_WrongNumArgs(interp, 1, argv, "[too many parameters]");
+- return JIM_ERR;
++ for (unsigned int i = 0; allowed_transports[i]; i++) {
++ if (!strcmp(allowed_transports[i], CMD_ARGV[0])) {
++ int retval = transport_select(CMD_CTX, CMD_ARGV[0]);
++ if (retval != ERROR_OK)
++ return retval;
++ command_print(CMD, "%s", session->name);
++ return ERROR_OK;
++ }
+ }
++
++ command_print(CMD, "Debug adapter doesn't support '%s' transport", CMD_ARGV[0]);
++ return ERROR_FAIL;
+ }
+
+ static const struct command_registration transport_commands[] = {
+@@ -333,7 +331,7 @@ static const struct command_registration transport_commands[] = {
+ },
+ {
+ .name = "select",
+- .jim_handler = jim_transport_select,
++ .handler = handle_transport_select,
+ .mode = COMMAND_ANY,
+ .help = "Select this session's transport",
+ .usage = "[transport_name]",
new file mode 100644
@@ -0,0 +1,95 @@
+From 80fc9fabc66a0bc767467fa14c703e5a9f340cd3 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 18 Dec 2022 16:09:02 +0100
+Subject: [PATCH] flash: nor: rewrite command 'flash list' as COMMAND_HANDLER
+
+The mixed use of jim commands and OpenOCD commands is error prone
+due to handling of errors through JIM_xx and ERROR_yy.
+
+Rewrite the jim command 'flash list' as OpenOCD command.
+While there:
+- format in a human readable way the output dictionary list, while
+ preserving the structure of its TCL data;
+- add the mandatory 'usage' field.
+
+Change-Id: I1ee69870d3ab3c1cfc46cd2b8ec03de6b2300bd6
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7486
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Tested-by: jenkins
+---
+ src/flash/nor/tcl.c | 48 +++++++++++++++++----------------------------
+ 1 file changed, 18 insertions(+), 30 deletions(-)
+
+diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
+index 4ff6d9838..ecbcf00aa 100644
+--- a/src/flash/nor/tcl.c
++++ b/src/flash/nor/tcl.c
+@@ -1324,40 +1324,27 @@ COMMAND_HANDLER(handle_flash_banks_command)
+ return ERROR_OK;
+ }
+
+-static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(handle_flash_list)
+ {
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv,
+- "no arguments to 'flash list' command");
+- return JIM_ERR;
+- }
+-
+- Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ for (struct flash_bank *p = flash_bank_list(); p; p = p->next) {
+- Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
+-
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->name, -1));
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "driver", -1));
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
+- Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
+- Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
+- Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
+- Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "target", -1));
+- Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, target_name(p->target), -1));
+-
+- Jim_ListAppendElement(interp, list, elem);
++ command_print(CMD,
++ "{\n"
++ " name %s\n"
++ " driver %s\n"
++ " base " TARGET_ADDR_FMT "\n"
++ " size 0x%" PRIx32 "\n"
++ " bus_width %u\n"
++ " chip_width %u\n"
++ " target %s\n"
++ "}",
++ p->name, p->driver->name, p->base, p->size, p->bus_width, p->chip_width,
++ target_name(p->target));
+ }
+
+- Jim_SetResult(interp, list);
+-
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ COMMAND_HANDLER(handle_flash_init_command)
+@@ -1404,8 +1391,9 @@ static const struct command_registration flash_config_command_handlers[] = {
+ {
+ .name = "list",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_flash_list,
++ .handler = handle_flash_list,
+ .help = "Returns a list of details about the flash banks.",
++ .usage = "",
+ },
+ COMMAND_REGISTRATION_DONE
+ };
new file mode 100644
@@ -0,0 +1,55 @@
+From 842a12f4caf307e756045c14011c402a20da30b6 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 18 Dec 2022 18:49:02 +0100
+Subject: [PATCH] helper: util: rewrite command 'ms' as COMMAND_HANDLER
+
+Use full 64 bits in output; no reason to truncate at 32 bits.
+
+Change-Id: I433815a381e147731ff0da2c805170649a9bcf38
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7487
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Tested-by: jenkins
+---
+ src/helper/util.c | 19 ++++++-------------
+ 1 file changed, 6 insertions(+), 13 deletions(-)
+
+diff --git a/src/helper/util.c b/src/helper/util.c
+index bf18f8e60..5e12021ff 100644
+--- a/src/helper/util.c
++++ b/src/helper/util.c
+@@ -13,28 +13,21 @@
+ #include "log.h"
+ #include "time_support.h"
+
+-static int jim_util_ms(Jim_Interp *interp,
+- int argc,
+- Jim_Obj * const *argv)
++COMMAND_HANDLER(handler_util_ms)
+ {
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "ls ?dir?");
+- return JIM_ERR;
+- }
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- /* Cast from 64 to 32 bit int works for 2's-compliment
+- * when calculating differences*/
+- Jim_SetResult(interp, Jim_NewIntObj(interp, (int)timeval_ms()));
++ command_print(CMD, "%" PRId64, timeval_ms());
+
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ static const struct command_registration util_command_handlers[] = {
+- /* jim handlers */
+ {
+ .name = "ms",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_util_ms,
++ .handler = handler_util_ms,
+ .help =
+ "Returns ever increasing milliseconds. Used to calculate differences in time.",
+ .usage = "",
new file mode 100644
@@ -0,0 +1,89 @@
+From 880ae3f07744a09e267bde00cf405c85a6f10482 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 18 Dec 2022 19:12:35 +0100
+Subject: [PATCH] openocd: rewrite command 'version' as COMMAND_HANDLER
+
+Trivial change.
+While there:
+- add the mandatory 'usage' field;
+- document the optional parameter 'git';
+- reword the documentation.
+
+Change-Id: I6be4d4423128fa026a62e2ef355f77b69d50397e
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7488
+Tested-by: jenkins
+---
+ doc/openocd.texi | 6 ++++--
+ src/openocd.c | 26 +++++++++++++-------------
+ 2 files changed, 17 insertions(+), 15 deletions(-)
+
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index 26a59e6a7..67661845d 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -9101,8 +9101,10 @@ format. Optional @option{start} and @option{end} parameters allow to
+ limit the address range.
+ @end deffn
+
+-@deffn {Command} {version}
+-Displays a string identifying the version of this OpenOCD server.
++@deffn {Command} {version} [git]
++Returns a string identifying the version of this OpenOCD server.
++With option @option{git}, it returns the git version obtained at compile time
++through ``git describe''.
+ @end deffn
+
+ @deffn {Command} {virt2phys} virtual_address
+diff --git a/src/openocd.c b/src/openocd.c
+index 875da5a62..54c5eb34f 100644
+--- a/src/openocd.c
++++ b/src/openocd.c
+@@ -51,24 +51,23 @@ static const char openocd_startup_tcl[] = {
+ };
+
+ /* Give scripts and TELNET a way to find out what version this is */
+-static int jim_version_command(Jim_Interp *interp, int argc,
+- Jim_Obj * const *argv)
++COMMAND_HANDLER(handler_version_command)
+ {
+- if (argc > 2)
+- return JIM_ERR;
+- const char *str = "";
+- char *version_str;
+- version_str = OPENOCD_VERSION;
++ char *version_str = OPENOCD_VERSION;
+
+- if (argc == 2)
+- str = Jim_GetString(argv[1], NULL);
++ if (CMD_ARGC > 1)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ if (CMD_ARGC == 1) {
++ if (strcmp("git", CMD_ARGV[0]))
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+
+- if (strcmp("git", str) == 0)
+ version_str = GITVERSION;
++ }
+
+- Jim_SetResult(interp, Jim_NewStringObj(interp, version_str, -1));
++ command_print(CMD, "%s", version_str);
+
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ static int log_target_callback_event_handler(struct target *target,
+@@ -194,9 +193,10 @@ COMMAND_HANDLER(handle_add_script_search_dir_command)
+ static const struct command_registration openocd_command_handlers[] = {
+ {
+ .name = "version",
+- .jim_handler = jim_version_command,
++ .handler = handler_version_command,
+ .mode = COMMAND_ANY,
+ .help = "show program version",
++ .usage = "[git]",
+ },
+ {
+ .name = "noinit",
new file mode 100644
@@ -0,0 +1,158 @@
+From 0332da1f1518b0cb4150965614c09fcc7319ddbe Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 18 Dec 2022 22:42:18 +0100
+Subject: [PATCH] rtt: rewrite command 'rtt channellist' as COMMAND_HANDLER
+
+This also fixes a mistake of the jim command returning ERROR_xx
+when function rtt_read_channel_info() returns error.
+While there:
+- format in a human readable way the output dictionary list, while
+ preserving the structure of its TCL data;
+- add check for the number of parameters.
+
+Change-Id: Ica2b623699d3a606d3992975c836dae96f74b26d
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7489
+Tested-by: jenkins
+---
+ src/rtt/tcl.c | 86 ++++++++++++++++-----------------------------------
+ 1 file changed, 26 insertions(+), 60 deletions(-)
+
+diff --git a/src/rtt/tcl.c b/src/rtt/tcl.c
+index 7cbdccf56..f949aa1c9 100644
+--- a/src/rtt/tcl.c
++++ b/src/rtt/tcl.c
+@@ -150,17 +150,17 @@ COMMAND_HANDLER(handle_rtt_channels_command)
+ return ERROR_OK;
+ }
+
+-static int jim_channel_list(Jim_Interp *interp, int argc,
+- Jim_Obj * const *argv)
++COMMAND_HANDLER(handle_channel_list)
+ {
+- Jim_Obj *list;
+- Jim_Obj *channel_list;
+ char channel_name[CHANNEL_NAME_SIZE];
+ const struct rtt_control *ctrl;
+ struct rtt_channel_info info;
+
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
+ if (!rtt_found_cb()) {
+- Jim_SetResultFormatted(interp, "rtt: Control block not available");
++ command_print(CMD, "rtt: Control block not available");
+ return ERROR_FAIL;
+ }
+
+@@ -169,81 +169,47 @@ static int jim_channel_list(Jim_Interp *interp, int argc,
+ info.name = channel_name;
+ info.name_length = sizeof(channel_name);
+
+- list = Jim_NewListObj(interp, NULL, 0);
+- channel_list = Jim_NewListObj(interp, NULL, 0);
++ command_print(CMD, "{");
+
+ for (unsigned int i = 0; i < ctrl->num_up_channels; i++) {
+- int ret;
+- Jim_Obj *tmp;
+-
+- ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_UP, &info);
+-
++ int ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_UP, &info);
+ if (ret != ERROR_OK)
+ return ret;
+
+ if (!info.size)
+ continue;
+
+- tmp = Jim_NewListObj(interp, NULL, 0);
+-
+- Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
+- "name", -1));
+- Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
+- info.name, -1));
+-
+- Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
+- "size", -1));
+- Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp,
+- info.size));
+-
+- Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
+- "flags", -1));
+- Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp,
+- info.flags));
+-
+- Jim_ListAppendElement(interp, channel_list, tmp);
++ command_print(CMD,
++ " {\n"
++ " name %s\n"
++ " size 0x%" PRIx32 "\n"
++ " flags 0x%" PRIx32 "\n"
++ " }",
++ info.name, info.size, info.flags);
+ }
+
+- Jim_ListAppendElement(interp, list, channel_list);
+-
+- channel_list = Jim_NewListObj(interp, NULL, 0);
++ command_print(CMD, "}\n{");
+
+ for (unsigned int i = 0; i < ctrl->num_down_channels; i++) {
+- int ret;
+- Jim_Obj *tmp;
+-
+- ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_DOWN, &info);
+-
++ int ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_DOWN, &info);
+ if (ret != ERROR_OK)
+ return ret;
+
+ if (!info.size)
+ continue;
+
+- tmp = Jim_NewListObj(interp, NULL, 0);
+-
+- Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
+- "name", -1));
+- Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
+- info.name, -1));
+-
+- Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
+- "size", -1));
+- Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp,
+- info.size));
+-
+- Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp,
+- "flags", -1));
+- Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp,
+- info.flags));
+-
+- Jim_ListAppendElement(interp, channel_list, tmp);
++ command_print(CMD,
++ " {\n"
++ " name %s\n"
++ " size 0x%" PRIx32 "\n"
++ " flags 0x%" PRIx32 "\n"
++ " }",
++ info.name, info.size, info.flags);
+ }
+
+- Jim_ListAppendElement(interp, list, channel_list);
+- Jim_SetResult(interp, list);
++ command_print(CMD, "}");
+
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ static const struct command_registration rtt_subcommand_handlers[] = {
+@@ -284,7 +250,7 @@ static const struct command_registration rtt_subcommand_handlers[] = {
+ },
+ {
+ .name = "channellist",
+- .jim_handler = jim_channel_list,
++ .handler = handle_channel_list,
+ .mode = COMMAND_EXEC,
+ .help = "list available channels",
+ .usage = ""
new file mode 100644
@@ -0,0 +1,224 @@
+From 21e6252965d8cf82660344a7d6c12d64269d7387 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 12:49:20 +0100
+Subject: [PATCH] target: aarch64: rewrite commands 'aarch64 mcr/mrc' as
+ COMMAND_HANDLER
+
+This also fixes an incorrect return ERROR_TARGET_NOT_HALTED from a
+jim command.
+
+Change-Id: I99a02a21bedb64e60944e295c7cf24356e07be60
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7490
+Tested-by: jenkins
+---
+ src/target/aarch64.c | 129 +++++++++++++++----------------------------
+ 1 file changed, 46 insertions(+), 83 deletions(-)
+
+diff --git a/src/target/aarch64.c b/src/target/aarch64.c
+index 8e90e6400..3c33032e9 100644
+--- a/src/target/aarch64.c
++++ b/src/target/aarch64.c
+@@ -2952,53 +2952,41 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command)
+ return ERROR_OK;
+ }
+
+-static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(aarch64_mcrmrc_command)
+ {
+- struct command *c = jim_to_command(interp);
+- struct command_context *context;
+- struct target *target;
+- struct arm *arm;
+- int retval;
+ bool is_mcr = false;
+- int arg_cnt = 0;
++ unsigned int arg_cnt = 5;
+
+- if (!strcmp(c->name, "mcr")) {
++ if (!strcmp(CMD_NAME, "mcr")) {
+ is_mcr = true;
+- arg_cnt = 7;
+- } else {
+ arg_cnt = 6;
+ }
+
+- context = current_command_context(interp);
+- assert(context);
++ if (arg_cnt != CMD_ARGC)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- target = get_current_target(context);
++ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+- LOG_ERROR("%s: no current target", __func__);
+- return JIM_ERR;
++ command_print(CMD, "no current target");
++ return ERROR_FAIL;
+ }
+ if (!target_was_examined(target)) {
+- LOG_ERROR("%s: not yet examined", target_name(target));
+- return JIM_ERR;
++ command_print(CMD, "%s: not yet examined", target_name(target));
++ return ERROR_TARGET_NOT_EXAMINED;
+ }
+
+- arm = target_to_arm(target);
++ struct arm *arm = target_to_arm(target);
+ if (!is_arm(arm)) {
+- LOG_ERROR("%s: not an ARM", target_name(target));
+- return JIM_ERR;
++ command_print(CMD, "%s: not an ARM", target_name(target));
++ return ERROR_FAIL;
+ }
+
+ if (target->state != TARGET_HALTED)
+ return ERROR_TARGET_NOT_HALTED;
+
+ if (arm->core_state == ARM_STATE_AARCH64) {
+- LOG_ERROR("%s: not 32-bit arm target", target_name(target));
+- return JIM_ERR;
+- }
+-
+- if (argc != arg_cnt) {
+- LOG_ERROR("%s: wrong number of arguments", __func__);
+- return JIM_ERR;
++ command_print(CMD, "%s: not 32-bit arm target", target_name(target));
++ return ERROR_FAIL;
+ }
+
+ int cpnum;
+@@ -3007,87 +2995,62 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+ uint32_t crn;
+ uint32_t crm;
+ uint32_t value;
+- long l;
+
+ /* NOTE: parameter sequence matches ARM instruction set usage:
+ * MCR pNUM, op1, rX, CRn, CRm, op2 ; write CP from rX
+ * MRC pNUM, op1, rX, CRn, CRm, op2 ; read CP into rX
+ * The "rX" is necessarily omitted; it uses Tcl mechanisms.
+ */
+- retval = Jim_GetLong(interp, argv[1], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0xf) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "coprocessor", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cpnum);
++ if (cpnum & ~0xf) {
++ command_print(CMD, "coprocessor %d out of range", cpnum);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- cpnum = l;
+
+- retval = Jim_GetLong(interp, argv[2], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0x7) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "op1", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], op1);
++ if (op1 & ~0x7) {
++ command_print(CMD, "op1 %d out of range", op1);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- op1 = l;
+
+- retval = Jim_GetLong(interp, argv[3], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0xf) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "CRn", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], crn);
++ if (crn & ~0xf) {
++ command_print(CMD, "CRn %d out of range", crn);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- crn = l;
+
+- retval = Jim_GetLong(interp, argv[4], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0xf) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "CRm", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], crm);
++ if (crm & ~0xf) {
++ command_print(CMD, "CRm %d out of range", crm);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- crm = l;
+
+- retval = Jim_GetLong(interp, argv[5], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0x7) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "op2", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], op2);
++ if (op2 & ~0x7) {
++ command_print(CMD, "op2 %d out of range", op2);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- op2 = l;
+
+- value = 0;
+-
+- if (is_mcr == true) {
+- retval = Jim_GetLong(interp, argv[6], &l);
+- if (retval != JIM_OK)
+- return retval;
+- value = l;
++ if (is_mcr) {
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[5], value);
+
+ /* NOTE: parameters reordered! */
+ /* ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2) */
+- retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value);
++ int retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value);
+ if (retval != ERROR_OK)
+- return JIM_ERR;
++ return retval;
+ } else {
++ value = 0;
+ /* NOTE: parameters reordered! */
+ /* ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2) */
+- retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value);
++ int retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value);
+ if (retval != ERROR_OK)
+- return JIM_ERR;
++ return retval;
+
+- Jim_SetResult(interp, Jim_NewIntObj(interp, value));
++ command_print(CMD, "0x%" PRIx32, value);
+ }
+
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ static const struct command_registration aarch64_exec_command_handlers[] = {
+@@ -3122,14 +3085,14 @@ static const struct command_registration aarch64_exec_command_handlers[] = {
+ {
+ .name = "mcr",
+ .mode = COMMAND_EXEC,
+- .jim_handler = jim_mcrmrc,
++ .handler = aarch64_mcrmrc_command,
+ .help = "write coprocessor register",
+ .usage = "cpnum op1 CRn CRm op2 value",
+ },
+ {
+ .name = "mrc",
+ .mode = COMMAND_EXEC,
+- .jim_handler = jim_mcrmrc,
++ .handler = aarch64_mcrmrc_command,
+ .help = "read coprocessor register",
+ .usage = "cpnum op1 CRn CRm op2",
+ },
new file mode 100644
@@ -0,0 +1,222 @@
+From c4f2337d02d3c0d452a9958e44e82a8e6454dead Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 13:02:59 +0100
+Subject: [PATCH] target: armv4_5: rewrite commands 'arm mcr/mrc' as
+ COMMAND_HANDLER
+
+While there, add a check for target halted and check the number of
+parameters accordingly to the command name.
+
+Change-Id: I9e8bb109c35039561997d14782fac682267aee65
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7491
+Tested-by: jenkins
+---
+ src/target/armv4_5.c | 132 +++++++++++++++++--------------------------
+ 1 file changed, 53 insertions(+), 79 deletions(-)
+
+diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
+index 48af5035a..9586adc97 100644
+--- a/src/target/armv4_5.c
++++ b/src/target/armv4_5.c
+@@ -989,36 +989,37 @@ COMMAND_HANDLER(handle_arm_disassemble_command)
+ #endif
+ }
+
+-static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(handle_armv4_5_mcrmrc)
+ {
+- struct command_context *context;
+- struct target *target;
+- struct arm *arm;
+- int retval;
++ bool is_mcr = false;
++ unsigned int arg_cnt = 5;
++
++ if (!strcmp(CMD_NAME, "mcr")) {
++ is_mcr = true;
++ arg_cnt = 6;
++ }
+
+- context = current_command_context(interp);
+- assert(context);
++ if (arg_cnt != CMD_ARGC)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- target = get_current_target(context);
++ struct target *target = get_current_target(CMD_CTX);
+ if (!target) {
+- LOG_ERROR("%s: no current target", __func__);
+- return JIM_ERR;
++ command_print(CMD, "no current target");
++ return ERROR_FAIL;
+ }
+ if (!target_was_examined(target)) {
+- LOG_ERROR("%s: not yet examined", target_name(target));
+- return JIM_ERR;
++ command_print(CMD, "%s: not yet examined", target_name(target));
++ return ERROR_TARGET_NOT_EXAMINED;
+ }
+- arm = target_to_arm(target);
++
++ struct arm *arm = target_to_arm(target);
+ if (!is_arm(arm)) {
+- LOG_ERROR("%s: not an ARM", target_name(target));
+- return JIM_ERR;
++ command_print(CMD, "%s: not an ARM", target_name(target));
++ return ERROR_FAIL;
+ }
+
+- if ((argc < 6) || (argc > 7)) {
+- /* FIXME use the command name to verify # params... */
+- LOG_ERROR("%s: wrong number of arguments", __func__);
+- return JIM_ERR;
+- }
++ if (target->state != TARGET_HALTED)
++ return ERROR_TARGET_NOT_HALTED;
+
+ int cpnum;
+ uint32_t op1;
+@@ -1026,95 +1027,68 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+ uint32_t crn;
+ uint32_t crm;
+ uint32_t value;
+- long l;
+
+ /* NOTE: parameter sequence matches ARM instruction set usage:
+ * MCR pNUM, op1, rX, CRn, CRm, op2 ; write CP from rX
+ * MRC pNUM, op1, rX, CRn, CRm, op2 ; read CP into rX
+ * The "rX" is necessarily omitted; it uses Tcl mechanisms.
+ */
+- retval = Jim_GetLong(interp, argv[1], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0xf) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "coprocessor", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cpnum);
++ if (cpnum & ~0xf) {
++ command_print(CMD, "coprocessor %d out of range", cpnum);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- cpnum = l;
+
+- retval = Jim_GetLong(interp, argv[2], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0x7) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "op1", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], op1);
++ if (op1 & ~0x7) {
++ command_print(CMD, "op1 %d out of range", op1);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- op1 = l;
+
+- retval = Jim_GetLong(interp, argv[3], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0xf) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "CRn", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], crn);
++ if (crn & ~0xf) {
++ command_print(CMD, "CRn %d out of range", crn);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- crn = l;
+
+- retval = Jim_GetLong(interp, argv[4], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0xf) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "CRm", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], crm);
++ if (crm & ~0xf) {
++ command_print(CMD, "CRm %d out of range", crm);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- crm = l;
+
+- retval = Jim_GetLong(interp, argv[5], &l);
+- if (retval != JIM_OK)
+- return retval;
+- if (l & ~0x7) {
+- LOG_ERROR("%s: %s %d out of range", __func__,
+- "op2", (int) l);
+- return JIM_ERR;
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], op2);
++ if (op2 & ~0x7) {
++ command_print(CMD, "op2 %d out of range", op2);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+- op2 = l;
+-
+- value = 0;
+
+- /* FIXME don't assume "mrc" vs "mcr" from the number of params;
+- * that could easily be a typo! Check both...
+- *
++ /*
+ * FIXME change the call syntax here ... simplest to just pass
+ * the MRC() or MCR() instruction to be executed. That will also
+ * let us support the "mrc2" and "mcr2" opcodes (toggling one bit)
+ * if that's ever needed.
+ */
+- if (argc == 7) {
+- retval = Jim_GetLong(interp, argv[6], &l);
+- if (retval != JIM_OK)
+- return retval;
+- value = l;
++ if (is_mcr) {
++ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[5], value);
+
+ /* NOTE: parameters reordered! */
+ /* ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2) */
+- retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value);
++ int retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value);
+ if (retval != ERROR_OK)
+- return JIM_ERR;
++ return retval;
+ } else {
++ value = 0;
+ /* NOTE: parameters reordered! */
+ /* ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2) */
+- retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value);
++ int retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value);
+ if (retval != ERROR_OK)
+- return JIM_ERR;
++ return retval;
+
+- Jim_SetResult(interp, Jim_NewIntObj(interp, value));
++ command_print(CMD, "0x%" PRIx32, value);
+ }
+
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ static const struct command_registration arm_exec_command_handlers[] = {
+@@ -1128,14 +1102,14 @@ static const struct command_registration arm_exec_command_handlers[] = {
+ {
+ .name = "mcr",
+ .mode = COMMAND_EXEC,
+- .jim_handler = &jim_mcrmrc,
++ .handler = handle_armv4_5_mcrmrc,
+ .help = "write coprocessor register",
+ .usage = "cpnum op1 CRn CRm op2 value",
+ },
+ {
+ .name = "mrc",
+ .mode = COMMAND_EXEC,
+- .jim_handler = &jim_mcrmrc,
++ .handler = handle_armv4_5_mcrmrc,
+ .help = "read coprocessor register",
+ .usage = "cpnum op1 CRn CRm op2",
+ },
new file mode 100644
@@ -0,0 +1,58 @@
+From 5da4ef25c8a2e57325bc1706c07f54cc99ce0ce1 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 17:55:13 +0100
+Subject: [PATCH] target: cti: rewrite command 'cti names' as COMMAND_HANDLER
+
+While there, format in a human readable way the output list by
+using one line per cti name.
+
+Change-Id: I6d4870ee512fe7e6935d73355c2377ad805ccc3b
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7492
+Tested-by: jenkins
+---
+ src/target/arm_cti.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c
+index 3612874e2..7637ad015 100644
+--- a/src/target/arm_cti.c
++++ b/src/target/arm_cti.c
+@@ -525,20 +525,17 @@ static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+ return cti_create(&goi);
+ }
+
+-static int jim_cti_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(cti_handle_names)
+ {
+ struct arm_cti *obj;
+
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+- return JIM_ERR;
+- }
+- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
+- list_for_each_entry(obj, &all_cti, lh) {
+- Jim_ListAppendElement(interp, Jim_GetResult(interp),
+- Jim_NewStringObj(interp, obj->name, -1));
+- }
+- return JIM_OK;
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ list_for_each_entry(obj, &all_cti, lh)
++ command_print(CMD, "%s", obj->name);
++
++ return ERROR_OK;
+ }
+
+
+@@ -553,7 +550,7 @@ static const struct command_registration cti_subcommand_handlers[] = {
+ {
+ .name = "names",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_cti_names,
++ .handler = cti_handle_names,
+ .usage = "",
+ .help = "Lists all registered CTI objects by name",
+ },
new file mode 100644
@@ -0,0 +1,62 @@
+From 19e2a0d6af3783e572a80e4cbf0f471f6dbf66e7 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 18 Dec 2022 22:11:14 +0100
+Subject: [PATCH] jtag: rewrite command 'adapter name' as COMMAND_HANDLER
+
+Trivial change.
+Add the mandatory 'usage' field.
+
+Change-Id: Id92af5cd873fb86f5de79f785f156d1ef734b005
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7493
+Tested-by: jenkins
+---
+ src/jtag/adapter.c | 22 ++++++++++------------
+ 1 file changed, 10 insertions(+), 12 deletions(-)
+
+diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
+index eb73fcb9a..76a6620be 100644
+--- a/src/jtag/adapter.c
++++ b/src/jtag/adapter.c
+@@ -378,21 +378,18 @@ done:
+ return equal;
+ }
+
+-static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(handle_adapter_name)
+ {
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc-1, argv + 1);
+-
+ /* return the name of the interface */
+ /* TCL code might need to know the exact type... */
+ /* FUTURE: we allow this as a means to "set" the interface. */
+- if (goi.argc != 0) {
+- Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
+- return JIM_ERR;
+- }
+- const char *name = adapter_driver ? adapter_driver->name : NULL;
+- Jim_SetResultString(goi.interp, name ? name : "undefined", -1);
+- return JIM_OK;
++
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ command_print(CMD, "%s", adapter_driver ? adapter_driver->name : "undefined");
++
++ return ERROR_OK;
+ }
+
+ COMMAND_HANDLER(adapter_transports_command)
+@@ -1127,9 +1124,10 @@ static const struct command_registration adapter_command_handlers[] = {
+ {
+ .name = "name",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_adapter_name,
++ .handler = handle_adapter_name,
+ .help = "Returns the name of the currently "
+ "selected adapter (driver)",
++ .usage = "",
+ },
+ {
+ .name = "srst",
new file mode 100644
@@ -0,0 +1,65 @@
+From 27741252571d7c34b9049275d02cf6c34b1ae7d2 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 18:08:03 +0100
+Subject: [PATCH] jtag: rewrite command 'jtag names' as COMMAND_HANDLER
+
+While there:
+- format in a human readable way the output list by using one line
+ per tap name;
+- add the mandatory 'usage' field.
+
+Change-Id: I295449220c78fac8973478b265413342ea832f61
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7494
+Tested-by: jenkins
+---
+ src/jtag/tcl.c | 26 +++++++++-----------------
+ 1 file changed, 9 insertions(+), 17 deletions(-)
+
+diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
+index fc0d562e2..83cb0a18b 100644
+--- a/src/jtag/tcl.c
++++ b/src/jtag/tcl.c
+@@ -805,24 +805,15 @@ int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+ return jtag_tap_configure_cmd(&goi, t);
+ }
+
+-static int jim_jtag_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_jtag_names)
+ {
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc-1, argv + 1);
+- if (goi.argc != 0) {
+- Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
+- return JIM_ERR;
+- }
+- Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
+- struct jtag_tap *tap;
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- for (tap = jtag_all_taps(); tap; tap = tap->next_tap) {
+- Jim_ListAppendElement(goi.interp,
+- Jim_GetResult(goi.interp),
+- Jim_NewStringObj(goi.interp,
+- tap->dotted_name, -1));
+- }
+- return JIM_OK;
++ for (struct jtag_tap *tap = jtag_all_taps(); tap; tap = tap->next_tap)
++ command_print(CMD, "%s", tap->dotted_name);
++
++ return ERROR_OK;
+ }
+
+ COMMAND_HANDLER(handle_jtag_init_command)
+@@ -921,8 +912,9 @@ static const struct command_registration jtag_subcommand_handlers[] = {
+ {
+ .name = "names",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_jtag_names,
++ .handler = handle_jtag_names,
+ .help = "Returns list of all JTAG tap names.",
++ .usage = "",
+ },
+ {
+ .chain = jtag_command_handlers_to_move,
new file mode 100644
@@ -0,0 +1,60 @@
+From ff0fdcf61427b76f1cfc9c3ecd551f058c0957d0 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 18:18:48 +0100
+Subject: [PATCH] jtag: rewrite command 'jtag arp_init' as COMMAND_HANDLER
+
+While there add the mandatory 'usage' field.
+
+Change-Id: I3491ed79d11c5a3e81cc9afd2423da14b8df72ff
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7495
+Tested-by: jenkins
+---
+ src/jtag/tcl.c | 23 +++++++----------------
+ 1 file changed, 7 insertions(+), 16 deletions(-)
+
+diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
+index 83cb0a18b..f154295dd 100644
+--- a/src/jtag/tcl.c
++++ b/src/jtag/tcl.c
+@@ -664,22 +664,12 @@ static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e)
+ }
+ }
+
+-static int jim_jtag_arp_init(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_jtag_arp_init)
+ {
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc-1, argv + 1);
+- if (goi.argc != 0) {
+- Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
+- return JIM_ERR;
+- }
+- struct command_context *context = current_command_context(interp);
+- int e = jtag_init_inner(context);
+- if (e != ERROR_OK) {
+- Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
+- Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
+- return JIM_ERR;
+- }
+- return JIM_OK;
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ return jtag_init_inner(CMD_CTX);
+ }
+
+ static int jim_jtag_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+@@ -843,10 +833,11 @@ static const struct command_registration jtag_subcommand_handlers[] = {
+ {
+ .name = "arp_init",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_jtag_arp_init,
++ .handler = handle_jtag_arp_init,
+ .help = "Validates JTAG scan chain against the list of "
+ "declared TAPs using just the four standard JTAG "
+ "signals.",
++ .usage = "",
+ },
+ {
+ .name = "arp_init-reset",
new file mode 100644
@@ -0,0 +1,70 @@
+From 254598ba25265b79bac4a5e32fa2abb5d252d2cb Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 18:23:11 +0100
+Subject: [PATCH] jtag: rewrite command 'jtag arp_init-reset' as
+ COMMAND_HANDLER
+
+While there add the mandatory 'usage' field.
+
+Change-Id: I316fb31e24e94985dcc724e428b0384be7ef5bdd
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7496
+Tested-by: jenkins
+---
+ src/jtag/tcl.c | 32 ++++++++++++--------------------
+ 1 file changed, 12 insertions(+), 20 deletions(-)
+
+diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
+index f154295dd..c6ca04810 100644
+--- a/src/jtag/tcl.c
++++ b/src/jtag/tcl.c
+@@ -672,27 +672,18 @@ COMMAND_HANDLER(handle_jtag_arp_init)
+ return jtag_init_inner(CMD_CTX);
+ }
+
+-static int jim_jtag_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_jtag_arp_init_reset)
+ {
+- int e = ERROR_OK;
+- struct jim_getopt_info goi;
+- jim_getopt_setup(&goi, interp, argc-1, argv + 1);
+- if (goi.argc != 0) {
+- Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
+- return JIM_ERR;
+- }
+- struct command_context *context = current_command_context(interp);
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
+ if (transport_is_jtag())
+- e = jtag_init_reset(context);
+- else if (transport_is_swd())
+- e = swd_init_reset(context);
++ return jtag_init_reset(CMD_CTX);
+
+- if (e != ERROR_OK) {
+- Jim_Obj *obj = Jim_NewIntObj(goi.interp, e);
+- Jim_SetResultFormatted(goi.interp, "error: %#s", obj);
+- return JIM_ERR;
+- }
+- return JIM_OK;
++ if (transport_is_swd())
++ return swd_init_reset(CMD_CTX);
++
++ return ERROR_OK;
+ }
+
+ int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+@@ -842,9 +833,10 @@ static const struct command_registration jtag_subcommand_handlers[] = {
+ {
+ .name = "arp_init-reset",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_jtag_arp_init_reset,
++ .handler = handle_jtag_arp_init_reset,
+ .help = "Uses TRST and SRST to try resetting everything on "
+- "the JTAG scan chain, then performs 'jtag arp_init'."
++ "the JTAG scan chain, then performs 'jtag arp_init'.",
++ .usage = "",
+ },
+ {
+ .name = "newtap",
new file mode 100644
@@ -0,0 +1,53 @@
+From fbb7a50cbd5b9cda29698b3192e2a4596b3a6371 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 18:29:08 +0100
+Subject: [PATCH] jtag: rewrite command 'flush_count' as COMMAND_HANDLER
+
+While there:
+- check the number of command parameters;
+- add the mandatory 'usage' field.
+
+Change-Id: I7cd16f049753caedf19f313f7dc84be98efdba42
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7497
+Tested-by: jenkins
+---
+ src/jtag/tcl.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c
+index c6ca04810..b3cbc48b4 100644
+--- a/src/jtag/tcl.c
++++ b/src/jtag/tcl.c
+@@ -249,12 +249,15 @@ static int jim_command_pathmove(Jim_Interp *interp, int argc, Jim_Obj * const *a
+ return JIM_OK;
+ }
+
+-
+-static int jim_command_flush_count(Jim_Interp *interp, int argc, Jim_Obj * const *args)
++COMMAND_HANDLER(handle_jtag_flush_count)
+ {
+- Jim_SetResult(interp, Jim_NewIntObj(interp, jtag_get_flush_queue_count()));
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- return JIM_OK;
++ int count = jtag_get_flush_queue_count();
++ command_print_sameline(CMD, "%d", count);
++
++ return ERROR_OK;
+ }
+
+ /* REVISIT Just what about these should "move" ... ?
+@@ -279,9 +282,10 @@ static const struct command_registration jtag_command_handlers_to_move[] = {
+ {
+ .name = "flush_count",
+ .mode = COMMAND_EXEC,
+- .jim_handler = jim_command_flush_count,
++ .handler = handle_jtag_flush_count,
+ .help = "Returns the number of times the JTAG queue "
+ "has been flushed.",
++ .usage = "",
+ },
+ {
+ .name = "pathmove",
new file mode 100644
@@ -0,0 +1,58 @@
+From f76e67a440bb1761b90ea0cab89e0422a4224779 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 18:35:23 +0100
+Subject: [PATCH] target: arm_dap: rewrite command 'dap names' as
+ COMMAND_HANDLER
+
+While there, format in a human readable way the output list by
+using one line per dap name.
+
+Change-Id: I24a47350105b90db15808c61790f05d807120739
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7498
+Tested-by: jenkins
+---
+ src/target/arm_dap.c | 20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c
+index e21136dd6..bc9d96236 100644
+--- a/src/target/arm_dap.c
++++ b/src/target/arm_dap.c
+@@ -421,20 +421,16 @@ static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+ return dap_create(&goi);
+ }
+
+-static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_dap_names)
+ {
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
+ struct arm_dap_object *obj;
++ list_for_each_entry(obj, &all_dap, lh)
++ command_print(CMD, "%s", obj->name);
+
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+- return JIM_ERR;
+- }
+- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
+- list_for_each_entry(obj, &all_dap, lh) {
+- Jim_ListAppendElement(interp, Jim_GetResult(interp),
+- Jim_NewStringObj(interp, obj->name, -1));
+- }
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ COMMAND_HANDLER(handle_dap_init)
+@@ -500,7 +496,7 @@ static const struct command_registration dap_subcommand_handlers[] = {
+ {
+ .name = "names",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_dap_names,
++ .handler = handle_dap_names,
+ .usage = "",
+ .help = "Lists all registered DAP instances by name",
+ },
new file mode 100644
@@ -0,0 +1,76 @@
+From 8fa6db6e8e992793f5dcc23a7182e2b0cb70257e Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 20:28:56 +0100
+Subject: [PATCH] target: arm_tpiu_swo: rewrite command 'tpiu disable' as
+ COMMAND_HANDLER
+
+Change-Id: I689482f898bde2afa2881b2f311676a6b98abb9a
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7499
+Tested-by: jenkins
+---
+ src/target/arm_tpiu_swo.c | 24 ++++++++++--------------
+ 1 file changed, 10 insertions(+), 14 deletions(-)
+
+diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c
+index 7096db305..897a9316c 100644
+--- a/src/target/arm_tpiu_swo.c
++++ b/src/target/arm_tpiu_swo.c
+@@ -820,18 +820,15 @@ error_exit:
+ return JIM_ERR;
+ }
+
+-static int jim_arm_tpiu_swo_disable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_arm_tpiu_swo_disable)
+ {
+- struct command *c = jim_to_command(interp);
+- struct arm_tpiu_swo_object *obj = c->jim_handler_data;
++ struct arm_tpiu_swo_object *obj = CMD_DATA;
+
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+- return JIM_ERR;
+- }
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ if (!obj->enabled)
+- return JIM_OK;
++ return ERROR_OK;
+ obj->enabled = false;
+
+ arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_PRE_DISABLE);
+@@ -845,20 +842,19 @@ static int jim_arm_tpiu_swo_disable(Jim_Interp *interp, int argc, Jim_Obj *const
+
+ int retval = adapter_config_trace(false, 0, 0, NULL, 0, NULL);
+ if (retval != ERROR_OK) {
+- LOG_ERROR("Failed to stop adapter's trace");
+- return JIM_ERR;
++ command_print(CMD, "Failed to stop adapter's trace");
++ return retval;
+ }
+ }
+
+ arm_tpiu_swo_handle_event(obj, TPIU_SWO_EVENT_POST_DISABLE);
+
+ /* START_DEPRECATED_TPIU */
+- struct command_context *cmd_ctx = current_command_context(interp);
+- struct target *target = get_current_target(cmd_ctx);
++ struct target *target = get_current_target(CMD_CTX);
+ target_handle_event(target, TARGET_EVENT_TRACE_CONFIG);
+ /* END_DEPRECATED_TPIU */
+
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ static const struct command_registration arm_tpiu_swo_instance_command_handlers[] = {
+@@ -893,7 +889,7 @@ static const struct command_registration arm_tpiu_swo_instance_command_handlers[
+ {
+ .name = "disable",
+ .mode = COMMAND_EXEC,
+- .jim_handler = jim_arm_tpiu_swo_disable,
++ .handler = handle_arm_tpiu_swo_disable,
+ .usage = "",
+ .help = "Disables the TPIU/SWO output",
+ },
new file mode 100644
@@ -0,0 +1,233 @@
+From 5d39a8852ab604bed29d9e0d28da2cb5f7a87958 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 20:52:51 +0100
+Subject: [PATCH] target: arm_tpiu_swo: rewrite command 'tpiu enable' as
+ COMMAND_HANDLER
+
+Change-Id: Ia600948b99a229ef0490b7f576df62f880db8546
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7500
+Tested-by: jenkins
+---
+ src/target/arm_tpiu_swo.c | 94 +++++++++++++++++++--------------------
+ 1 file changed, 45 insertions(+), 49 deletions(-)
+
+diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c
+index 897a9316c..3cf306377 100644
+--- a/src/target/arm_tpiu_swo.c
++++ b/src/target/arm_tpiu_swo.c
+@@ -595,54 +595,52 @@ static const struct service_driver arm_tpiu_swo_service_driver = {
+ .keep_client_alive_handler = NULL,
+ };
+
+-static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_arm_tpiu_swo_enable)
+ {
+- struct command *c = jim_to_command(interp);
+- struct arm_tpiu_swo_object *obj = c->jim_handler_data;
+- struct command_context *cmd_ctx = current_command_context(interp);
++ struct arm_tpiu_swo_object *obj = CMD_DATA;
+ uint32_t value;
+ int retval;
+
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+- return JIM_ERR;
+- }
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- if (cmd_ctx->mode == COMMAND_CONFIG) {
++ if (CMD_CTX->mode == COMMAND_CONFIG) {
+ LOG_DEBUG("%s: enable deferred", obj->name);
+ obj->deferred_enable = true;
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ if (obj->enabled)
+- return JIM_OK;
++ return ERROR_OK;
+
+ if (transport_is_hla() && obj->spot.ap_num != 0) {
+- LOG_ERROR("Invalid access port 0x%" PRIx64 ". Only AP#0 allowed with hla transport", obj->spot.ap_num);
+- return JIM_ERR;
++ command_print(CMD,
++ "Invalid access port 0x%" PRIx64 ". Only AP#0 allowed with hla transport",
++ obj->spot.ap_num);
++ return ERROR_FAIL;
+ }
+
+ if (!obj->traceclkin_freq) {
+- LOG_ERROR("Trace clock-in frequency not set");
+- return JIM_ERR;
++ command_print(CMD, "Trace clock-in frequency not set");
++ return ERROR_FAIL;
+ }
+
+ if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART)
+ if (!obj->swo_pin_freq)
+ LOG_DEBUG("SWO pin frequency not set, will be autodetected by the adapter");
+
+- struct target *target = get_current_target(cmd_ctx);
++ struct target *target = get_current_target(CMD_CTX);
+
+ /* START_DEPRECATED_TPIU */
+ if (obj->recheck_ap_cur_target) {
+ if (strcmp(target->type->name, "cortex_m") &&
+ strcmp(target->type->name, "hla_target")) {
+ LOG_ERROR(MSG "Current target is not a Cortex-M nor a HLA");
+- return JIM_ERR;
++ return ERROR_FAIL;
+ }
+ if (!target_was_examined(target)) {
+ LOG_ERROR(MSG "Current target not examined yet");
+- return JIM_ERR;
++ return ERROR_FAIL;
+ }
+ struct cortex_m_common *cm = target_to_cm(target);
+ obj->recheck_ap_cur_target = false;
+@@ -660,8 +658,8 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const
+ if (!obj->ap) {
+ obj->ap = dap_get_ap(obj->spot.dap, obj->spot.ap_num);
+ if (!obj->ap) {
+- LOG_ERROR("Cannot get AP");
+- return JIM_ERR;
++ command_print(CMD, "Cannot get AP");
++ return ERROR_FAIL;
+ }
+ }
+
+@@ -670,8 +668,8 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const
+
+ retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_DEVID_OFFSET, &value);
+ if (retval != ERROR_OK) {
+- LOG_ERROR("Unable to read %s", obj->name);
+- return JIM_ERR;
++ command_print(CMD, "Unable to read %s", obj->name);
++ return retval;
+ }
+ switch (obj->pin_protocol) {
+ case TPIU_SPPR_PROTOCOL_SYNC:
+@@ -687,21 +685,20 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const
+ value = 0;
+ }
+ if (!value) {
+- struct jim_nvp *p;
+- jim_nvp_value2name(interp, nvp_arm_tpiu_swo_protocol_opts, obj->pin_protocol, &p);
+- LOG_ERROR("%s does not support protocol %s", obj->name, p->name);
+- return JIM_ERR;
++ struct jim_nvp *p = jim_nvp_value2name_simple(nvp_arm_tpiu_swo_protocol_opts, obj->pin_protocol);
++ command_print(CMD, "%s does not support protocol %s", obj->name, p->name);
++ return ERROR_FAIL;
+ }
+
+ if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_SYNC) {
+ retval = wrap_read_u32(target, obj->ap, obj->spot.base + TPIU_SSPSR_OFFSET, &value);
+ if (retval != ERROR_OK) {
+- LOG_ERROR("Cannot read TPIU register SSPSR");
+- return JIM_ERR;
++ command_print(CMD, "Cannot read TPIU register SSPSR");
++ return retval;
+ }
+ if (!(value & BIT(obj->port_width - 1))) {
+- LOG_ERROR("TPIU does not support port-width of %d bits", obj->port_width);
+- return JIM_ERR;
++ command_print(CMD, "TPIU does not support port-width of %d bits", obj->port_width);
++ return ERROR_FAIL;
+ }
+ }
+
+@@ -713,41 +710,42 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const
+ struct arm_tpiu_swo_priv_connection *priv = malloc(sizeof(*priv));
+ if (!priv) {
+ LOG_ERROR("Out of memory");
+- return JIM_ERR;
++ return ERROR_FAIL;
+ }
+ priv->obj = obj;
+ LOG_INFO("starting trace server for %s on %s", obj->name, &obj->out_filename[1]);
+ retval = add_service(&arm_tpiu_swo_service_driver, &obj->out_filename[1],
+ CONNECTION_LIMIT_UNLIMITED, priv);
+ if (retval != ERROR_OK) {
+- LOG_ERROR("Can't configure trace TCP port %s", &obj->out_filename[1]);
+- return JIM_ERR;
++ command_print(CMD, "Can't configure trace TCP port %s", &obj->out_filename[1]);
++ return retval;
+ }
+ } else if (strcmp(obj->out_filename, "-")) {
+ obj->file = fopen(obj->out_filename, "ab");
+ if (!obj->file) {
+- LOG_ERROR("Can't open trace destination file \"%s\"", obj->out_filename);
+- return JIM_ERR;
++ command_print(CMD, "Can't open trace destination file \"%s\"", obj->out_filename);
++ return ERROR_FAIL;
+ }
+ }
+
+ retval = adapter_config_trace(true, obj->pin_protocol, obj->port_width,
+ &swo_pin_freq, obj->traceclkin_freq, &prescaler);
+ if (retval != ERROR_OK) {
+- LOG_ERROR("Failed to start adapter's trace");
++ command_print(CMD, "Failed to start adapter's trace");
+ arm_tpiu_swo_close_output(obj);
+- return JIM_ERR;
++ return retval;
+ }
+
+ if (obj->pin_protocol == TPIU_SPPR_PROTOCOL_MANCHESTER || obj->pin_protocol == TPIU_SPPR_PROTOCOL_UART)
+ if (!swo_pin_freq) {
+ if (obj->swo_pin_freq)
+- LOG_ERROR("Adapter rejected SWO pin frequency %d Hz", obj->swo_pin_freq);
++ command_print(CMD, "Adapter rejected SWO pin frequency %d Hz", obj->swo_pin_freq);
+ else
+- LOG_ERROR("Adapter does not support auto-detection of SWO pin frequency nor a default value");
++ command_print(CMD,
++ "Adapter does not support auto-detection of SWO pin frequency nor a default value");
+
+ arm_tpiu_swo_close_output(obj);
+- return JIM_ERR;
++ return ERROR_FAIL;
+ }
+
+ if (obj->swo_pin_freq != swo_pin_freq)
+@@ -799,10 +797,10 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const
+ /* END_DEPRECATED_TPIU */
+
+ obj->enabled = true;
+- return JIM_OK;
++ return ERROR_OK;
+
+ error_exit:
+- LOG_ERROR("Error!");
++ command_print(CMD, "Error!");
+
+ if (obj->en_capture) {
+ obj->en_capture = false;
+@@ -811,13 +809,11 @@ error_exit:
+
+ target_unregister_timer_callback(arm_tpiu_swo_poll_trace, obj);
+
+- retval = adapter_config_trace(false, 0, 0, NULL, 0, NULL);
+- if (retval != ERROR_OK) {
+- LOG_ERROR("Failed to stop adapter's trace");
+- return JIM_ERR;
+- }
++ int retval1 = adapter_config_trace(false, 0, 0, NULL, 0, NULL);
++ if (retval1 != ERROR_OK)
++ command_print(CMD, "Failed to stop adapter's trace");
+ }
+- return JIM_ERR;
++ return retval;
+ }
+
+ COMMAND_HANDLER(handle_arm_tpiu_swo_disable)
+@@ -882,7 +878,7 @@ static const struct command_registration arm_tpiu_swo_instance_command_handlers[
+ {
+ .name = "enable",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_arm_tpiu_swo_enable,
++ .handler = handle_arm_tpiu_swo_enable,
+ .usage = "",
+ .help = "Enables the TPIU/SWO output",
+ },
new file mode 100644
@@ -0,0 +1,59 @@
+From 90ddac12e38ab21b1d3934235e0d1242e0f13616 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 20:56:40 +0100
+Subject: [PATCH] target: arm_tpiu_swo: rewrite command 'tpiu names' as
+ COMMAND_HANDLER
+
+While there, format in a human readable way the output list by
+using one line per tpiu name.
+
+Change-Id: I937c92b6c1e92509cf8aa96be1517a51bc363600
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7501
+Tested-by: jenkins
+---
+ src/target/arm_tpiu_swo.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c
+index 3cf306377..55201e6fe 100644
+--- a/src/target/arm_tpiu_swo.c
++++ b/src/target/arm_tpiu_swo.c
+@@ -981,20 +981,17 @@ err_exit:
+ return JIM_ERR;
+ }
+
+-static int jim_arm_tpiu_swo_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_arm_tpiu_swo_names)
+ {
+ struct arm_tpiu_swo_object *obj;
+
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+- return JIM_ERR;
+- }
+- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
+- list_for_each_entry(obj, &all_tpiu_swo, lh) {
+- Jim_ListAppendElement(interp, Jim_GetResult(interp),
+- Jim_NewStringObj(interp, obj->name, -1));
+- }
+- return JIM_OK;
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ list_for_each_entry(obj, &all_tpiu_swo, lh)
++ command_print(CMD, "%s", obj->name);
++
++ return ERROR_OK;
+ }
+
+ static int jim_arm_tpiu_swo_init(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+@@ -1185,7 +1182,7 @@ static const struct command_registration arm_tpiu_swo_subcommand_handlers[] = {
+ {
+ .name = "names",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_arm_tpiu_swo_names,
++ .handler = handle_arm_tpiu_swo_names,
+ .usage = "",
+ .help = "Lists all registered TPIU and SWO objects by name",
+ },
new file mode 100644
@@ -0,0 +1,58 @@
+From 6f8c27dcfc51c3775f11785711d44563adb6eb17 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 21:00:42 +0100
+Subject: [PATCH] target: arm_tpiu_swo: rewrite command 'tpiu init' as
+ COMMAND_HANDLER
+
+Change-Id: Iaaccfc62dd85267066a152c434f254d1b9a0c4f1
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7502
+Tested-by: jenkins
+---
+ src/target/arm_tpiu_swo.c | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+diff --git a/src/target/arm_tpiu_swo.c b/src/target/arm_tpiu_swo.c
+index 55201e6fe..5cea682ec 100644
+--- a/src/target/arm_tpiu_swo.c
++++ b/src/target/arm_tpiu_swo.c
+@@ -994,23 +994,21 @@ COMMAND_HANDLER(handle_arm_tpiu_swo_names)
+ return ERROR_OK;
+ }
+
+-static int jim_arm_tpiu_swo_init(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_arm_tpiu_swo_init)
+ {
+- struct command_context *cmd_ctx = current_command_context(interp);
+ struct arm_tpiu_swo_object *obj;
+- int retval = JIM_OK;
++ int retval = ERROR_OK;
++
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+- return JIM_ERR;
+- }
+ list_for_each_entry(obj, &all_tpiu_swo, lh) {
+ if (!obj->deferred_enable)
+ continue;
+ LOG_DEBUG("%s: running enable during init", obj->name);
+- int retval2 = command_run_linef(cmd_ctx, "%s enable", obj->name);
++ int retval2 = command_run_linef(CMD_CTX, "%s enable", obj->name);
+ if (retval2 != ERROR_OK)
+- retval = JIM_ERR;
++ retval = retval2;
+ }
+ return retval;
+ }
+@@ -1189,7 +1187,7 @@ static const struct command_registration arm_tpiu_swo_subcommand_handlers[] = {
+ {
+ .name = "init",
+ .mode = COMMAND_EXEC,
+- .jim_handler = jim_arm_tpiu_swo_init,
++ .handler = handle_arm_tpiu_swo_init,
+ .usage = "",
+ .help = "Initialize TPIU and SWO",
+ },
new file mode 100644
@@ -0,0 +1,212 @@
+From 584986ab1c9902fb58d928c1cb4ae885989fecbf Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 23:15:54 +0100
+Subject: [PATCH] target: rewrite command 'read_memory' as COMMAND_HANDLER
+
+While there, fix typo on 'exceeds'.
+In a following patch, the output could be formatted and split in N
+values per line to make it easier to read by humans.
+
+Change-Id: I295111a80934393011e46311f6cf6c13f2bdc0a3
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7503
+Tested-by: jenkins
+---
+ src/target/target.c | 110 ++++++++++++++++----------------------------
+ 1 file changed, 39 insertions(+), 71 deletions(-)
+
+diff --git a/src/target/target.c b/src/target/target.c
+index ae419ac8b..07c3c29a4 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -4592,57 +4592,36 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
+ return e;
+ }
+
+-static int target_jim_read_memory(Jim_Interp *interp, int argc,
+- Jim_Obj * const *argv)
++COMMAND_HANDLER(handle_target_read_memory)
+ {
+ /*
+- * argv[1] = memory address
+- * argv[2] = desired element width in bits
+- * argv[3] = number of elements to read
+- * argv[4] = optional "phys"
++ * CMD_ARGV[0] = memory address
++ * CMD_ARGV[1] = desired element width in bits
++ * CMD_ARGV[2] = number of elements to read
++ * CMD_ARGV[3] = optional "phys"
+ */
+
+- if (argc < 4 || argc > 5) {
+- Jim_WrongNumArgs(interp, 1, argv, "address width count ['phys']");
+- return JIM_ERR;
+- }
++ if (CMD_ARGC < 3 || CMD_ARGC > 4)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ /* Arg 1: Memory address. */
+- jim_wide wide_addr;
+- int e;
+- e = Jim_GetWide(interp, argv[1], &wide_addr);
+-
+- if (e != JIM_OK)
+- return e;
+-
+- target_addr_t addr = (target_addr_t)wide_addr;
++ target_addr_t addr;
++ COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], addr);
+
+ /* Arg 2: Bit width of one element. */
+- long l;
+- e = Jim_GetLong(interp, argv[2], &l);
+-
+- if (e != JIM_OK)
+- return e;
+-
+- const unsigned int width_bits = l;
++ unsigned int width_bits;
++ COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], width_bits);
+
+ /* Arg 3: Number of elements to read. */
+- e = Jim_GetLong(interp, argv[3], &l);
+-
+- if (e != JIM_OK)
+- return e;
+-
+- size_t count = l;
++ unsigned int count;
++ COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count);
+
+ /* Arg 4: Optional 'phys'. */
+ bool is_phys = false;
+-
+- if (argc > 4) {
+- const char *phys = Jim_GetString(argv[4], NULL);
+-
+- if (strcmp(phys, "phys")) {
+- Jim_SetResultFormatted(interp, "invalid argument '%s', must be 'phys'", phys);
+- return JIM_ERR;
++ if (CMD_ARGC == 4) {
++ if (strcmp(CMD_ARGV[3], "phys")) {
++ command_print(CMD, "invalid argument '%s', must be 'phys'", CMD_ARGV[3]);
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ is_phys = true;
+@@ -4655,37 +4634,33 @@ static int target_jim_read_memory(Jim_Interp *interp, int argc,
+ case 64:
+ break;
+ default:
+- Jim_SetResultString(interp, "invalid width, must be 8, 16, 32 or 64", -1);
+- return JIM_ERR;
++ command_print(CMD, "invalid width, must be 8, 16, 32 or 64");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ const unsigned int width = width_bits / 8;
+
+ if ((addr + (count * width)) < addr) {
+- Jim_SetResultString(interp, "read_memory: addr + count wraps to zero", -1);
+- return JIM_ERR;
++ command_print(CMD, "read_memory: addr + count wraps to zero");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ if (count > 65536) {
+- Jim_SetResultString(interp, "read_memory: too large read request, exeeds 64K elements", -1);
+- return JIM_ERR;
++ command_print(CMD, "read_memory: too large read request, exceeds 64K elements");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx != NULL);
+- struct target *target = get_current_target(cmd_ctx);
++ struct target *target = get_current_target(CMD_CTX);
+
+ const size_t buffersize = 4096;
+ uint8_t *buffer = malloc(buffersize);
+
+ if (!buffer) {
+ LOG_ERROR("Failed to allocate memory");
+- return JIM_ERR;
++ return ERROR_FAIL;
+ }
+
+- Jim_Obj *result_list = Jim_NewListObj(interp, NULL, 0);
+- Jim_IncrRefCount(result_list);
+-
++ char *separator = "";
+ while (count > 0) {
+ const unsigned int max_chunk_len = buffersize / width;
+ const size_t chunk_len = MIN(count, max_chunk_len);
+@@ -4698,11 +4673,15 @@ static int target_jim_read_memory(Jim_Interp *interp, int argc,
+ retval = target_read_memory(target, addr, width, chunk_len, buffer);
+
+ if (retval != ERROR_OK) {
+- LOG_ERROR("read_memory: read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed",
++ LOG_DEBUG("read_memory: read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed",
+ addr, width_bits, chunk_len);
+- Jim_SetResultString(interp, "read_memory: failed to read memory", -1);
+- e = JIM_ERR;
+- break;
++ /*
++ * FIXME: we append the errmsg to the list of value already read.
++ * Add a way to flush and replace old output, but LOG_DEBUG() it
++ */
++ command_print(CMD, "read_memory: failed to read memory");
++ free(buffer);
++ return retval;
+ }
+
+ for (size_t i = 0; i < chunk_len ; i++) {
+@@ -4723,11 +4702,8 @@ static int target_jim_read_memory(Jim_Interp *interp, int argc,
+ break;
+ }
+
+- char value_buf[19];
+- snprintf(value_buf, sizeof(value_buf), "0x%" PRIx64, v);
+-
+- Jim_ListAppendElement(interp, result_list,
+- Jim_NewStringObj(interp, value_buf, -1));
++ command_print_sameline(CMD, "%s0x%" PRIx64, separator, v);
++ separator = " ";
+ }
+
+ count -= chunk_len;
+@@ -4736,15 +4712,7 @@ static int target_jim_read_memory(Jim_Interp *interp, int argc,
+
+ free(buffer);
+
+- if (e != JIM_OK) {
+- Jim_DecrRefCount(interp, result_list);
+- return e;
+- }
+-
+- Jim_SetResult(interp, result_list);
+- Jim_DecrRefCount(interp, result_list);
+-
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+ static int get_u64_array_element(Jim_Interp *interp, const char *varname, size_t idx, uint64_t *val)
+@@ -6074,7 +6042,7 @@ static const struct command_registration target_instance_command_handlers[] = {
+ {
+ .name = "read_memory",
+ .mode = COMMAND_EXEC,
+- .jim_handler = target_jim_read_memory,
++ .handler = handle_target_read_memory,
+ .help = "Read Tcl list of 8/16/32/64 bit numbers from target memory",
+ .usage = "address width count ['phys']",
+ },
+@@ -7203,7 +7171,7 @@ static const struct command_registration target_exec_command_handlers[] = {
+ {
+ .name = "read_memory",
+ .mode = COMMAND_EXEC,
+- .jim_handler = target_jim_read_memory,
++ .handler = handle_target_read_memory,
+ .help = "Read Tcl list of 8/16/32/64 bit numbers from target memory",
+ .usage = "address width count ['phys']",
+ },
new file mode 100644
@@ -0,0 +1,60 @@
+From 113ba58231683e8cba329bf83b96d2192c39ad93 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 23:25:21 +0100
+Subject: [PATCH] target: rewrite command 'target curstate' as COMMAND_HANDLER
+
+While there, add the mandatory 'usage' field.
+
+Change-Id: Ibfda6f56a1450e2eb9ad3092d756de0778f4a092
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7504
+Tested-by: jenkins
+---
+ src/target/target.c | 24 +++++++++++++-----------
+ 1 file changed, 13 insertions(+), 11 deletions(-)
+
+diff --git a/src/target/target.c b/src/target/target.c
+index 07c3c29a4..da9cab904 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -5904,18 +5904,19 @@ COMMAND_HANDLER(handle_target_event_list)
+ command_print(CMD, "***END***");
+ return ERROR_OK;
+ }
+-static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++
++COMMAND_HANDLER(handle_target_current_state)
+ {
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
+- return JIM_ERR;
+- }
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
+- struct target *target = get_current_target(cmd_ctx);
+- Jim_SetResultString(interp, target_state_name(target), -1);
+- return JIM_OK;
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ struct target *target = get_current_target(CMD_CTX);
++
++ command_print(CMD, "%s", target_state_name(target));
++
++ return ERROR_OK;
+ }
++
+ static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+ {
+ struct jim_getopt_info goi;
+@@ -6063,8 +6064,9 @@ static const struct command_registration target_instance_command_handlers[] = {
+ {
+ .name = "curstate",
+ .mode = COMMAND_EXEC,
+- .jim_handler = jim_target_current_state,
++ .handler = handle_target_current_state,
+ .help = "displays the current state of this target",
++ .usage = "",
+ },
+ {
+ .name = "arp_examine",
new file mode 100644
@@ -0,0 +1,53 @@
+From cca64798f8f01f2f06dbc020113cf9497b56f68b Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 23:37:07 +0100
+Subject: [PATCH] target: rewrite command 'was_examined' as COMMAND_HANDLER
+
+Check for empty command line, add the mandatory 'usage' field.
+
+Change-Id: I3f59448458fe01268bf5f4293aea5adcbd6d8279
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7505
+Tested-by: jenkins
+---
+ src/target/target.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/src/target/target.c b/src/target/target.c
+index da9cab904..264b85f21 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -5716,14 +5716,16 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv
+ return JIM_OK;
+ }
+
+-static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(handle_target_was_examined)
+ {
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
+- struct target *target = get_current_target(cmd_ctx);
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- Jim_SetResultBool(interp, target_was_examined(target));
+- return JIM_OK;
++ struct target *target = get_current_target(CMD_CTX);
++
++ command_print(CMD, "%d", target_was_examined(target) ? 1 : 0);
++
++ return ERROR_OK;
+ }
+
+ static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+@@ -6078,8 +6080,9 @@ static const struct command_registration target_instance_command_handlers[] = {
+ {
+ .name = "was_examined",
+ .mode = COMMAND_EXEC,
+- .jim_handler = jim_target_was_examined,
++ .handler = handle_target_was_examined,
+ .help = "used internally for reset processing",
++ .usage = "",
+ },
+ {
+ .name = "examine_deferred",
new file mode 100644
@@ -0,0 +1,53 @@
+From 2dda0e37d91f3ba9345dc20253ac162ff449504d Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 23:41:22 +0100
+Subject: [PATCH] target: rewrite command 'examine_deferred' as COMMAND_HANDLER
+
+Check for empty command line, add the mandatory 'usage' field.
+
+Change-Id: I9c3606242ec3dda9026fe19222162a110e618bff
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7506
+Tested-by: jenkins
+---
+ src/target/target.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/src/target/target.c b/src/target/target.c
+index 264b85f21..a2c857a95 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -5728,14 +5728,16 @@ COMMAND_HANDLER(handle_target_was_examined)
+ return ERROR_OK;
+ }
+
+-static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
++COMMAND_HANDLER(handle_target_examine_deferred)
+ {
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
+- struct target *target = get_current_target(cmd_ctx);
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- Jim_SetResultBool(interp, target->defer_examine);
+- return JIM_OK;
++ struct target *target = get_current_target(CMD_CTX);
++
++ command_print(CMD, "%d", target->defer_examine ? 1 : 0);
++
++ return ERROR_OK;
+ }
+
+ static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+@@ -6087,8 +6089,9 @@ static const struct command_registration target_instance_command_handlers[] = {
+ {
+ .name = "examine_deferred",
+ .mode = COMMAND_EXEC,
+- .jim_handler = jim_target_examine_deferred,
++ .handler = handle_target_examine_deferred,
+ .help = "used internally for reset processing",
++ .usage = "",
+ },
+ {
+ .name = "arp_halt_gdb",
new file mode 100644
@@ -0,0 +1,56 @@
+From 583efa68f71b9ad8e06b8e1246af25fc6c70e052 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 23:44:04 +0100
+Subject: [PATCH] target: rewrite command 'arp_halt_gdb' as COMMAND_HANDLER
+
+While there add the mandatory 'usage' field.
+
+Change-Id: I5389881dac25877dc32930ec36ee546e48ecc14d
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7507
+Tested-by: jenkins
+---
+ src/target/target.c | 19 +++++++------------
+ 1 file changed, 7 insertions(+), 12 deletions(-)
+
+diff --git a/src/target/target.c b/src/target/target.c
+index a2c857a95..4e2914648 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -5740,20 +5740,14 @@ COMMAND_HANDLER(handle_target_examine_deferred)
+ return ERROR_OK;
+ }
+
+-static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_target_halt_gdb)
+ {
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
+- return JIM_ERR;
+- }
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
+- struct target *target = get_current_target(cmd_ctx);
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK)
+- return JIM_ERR;
++ struct target *target = get_current_target(CMD_CTX);
+
+- return JIM_OK;
++ return target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
+ }
+
+ static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+@@ -6096,8 +6090,9 @@ static const struct command_registration target_instance_command_handlers[] = {
+ {
+ .name = "arp_halt_gdb",
+ .mode = COMMAND_EXEC,
+- .jim_handler = jim_target_halt_gdb,
++ .handler = handle_target_halt_gdb,
+ .help = "used internally for reset processing to halt GDB",
++ .usage = "",
+ },
+ {
+ .name = "arp_poll",
new file mode 100644
@@ -0,0 +1,57 @@
+From 26f457896c456c57a57719e484d055d444ba67ee Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 23:50:23 +0100
+Subject: [PATCH] target: rewrite command 'target current' as COMMAND_HANDLER
+
+While there add the mandatory 'usage' field.
+
+Change-Id: I3e5b826ca58f7ade30a443ada0cb4a9cd9ea35c2
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7508
+Tested-by: jenkins
+---
+ src/target/target.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/src/target/target.c b/src/target/target.c
+index 4e2914648..ae5f74cbf 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -6365,19 +6365,16 @@ static int target_create(struct jim_getopt_info *goi)
+ return JIM_OK;
+ }
+
+-static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_target_current)
+ {
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+- return JIM_ERR;
+- }
+- struct command_context *cmd_ctx = current_command_context(interp);
+- assert(cmd_ctx);
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- struct target *target = get_current_target_or_null(cmd_ctx);
++ struct target *target = get_current_target_or_null(CMD_CTX);
+ if (target)
+- Jim_SetResultString(interp, target_name(target), -1);
+- return JIM_OK;
++ command_print(CMD, "%s", target_name(target));
++
++ return ERROR_OK;
+ }
+
+ static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+@@ -6522,8 +6519,9 @@ static const struct command_registration target_subcommand_handlers[] = {
+ {
+ .name = "current",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_target_current,
++ .handler = handle_target_current,
+ .help = "Returns the currently selected target",
++ .usage = "",
+ },
+ {
+ .name = "types",
new file mode 100644
@@ -0,0 +1,59 @@
+From d9d698103e974b2a94c611864cccb92359509b7d Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 23:54:10 +0100
+Subject: [PATCH] target: rewrite command 'target types' as COMMAND_HANDLER
+
+Print one entry per line.
+While there add the mandatory 'usage' field.
+
+Change-Id: I135556e12154e33fdbd0f71d89f6fe37c69813b7
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7509
+Tested-by: jenkins
+---
+ src/target/target.c | 22 ++++++++++------------
+ 1 file changed, 10 insertions(+), 12 deletions(-)
+
+diff --git a/src/target/target.c b/src/target/target.c
+index ae5f74cbf..b77a25a2a 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -6377,18 +6377,15 @@ COMMAND_HANDLER(handle_target_current)
+ return ERROR_OK;
+ }
+
+-static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_target_types)
+ {
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+- return JIM_ERR;
+- }
+- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
+- for (unsigned x = 0; target_types[x]; x++) {
+- Jim_ListAppendElement(interp, Jim_GetResult(interp),
+- Jim_NewStringObj(interp, target_types[x]->name, -1));
+- }
+- return JIM_OK;
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ for (unsigned int x = 0; target_types[x]; x++)
++ command_print(CMD, "%s", target_types[x]->name);
++
++ return ERROR_OK;
+ }
+
+ static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+@@ -6526,9 +6523,10 @@ static const struct command_registration target_subcommand_handlers[] = {
+ {
+ .name = "types",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_target_types,
++ .handler = handle_target_types,
+ .help = "Returns the available target types as "
+ "a list of strings",
++ .usage = "",
+ },
+ {
+ .name = "names",
new file mode 100644
@@ -0,0 +1,59 @@
+From 12b405a4ac3dddd18e2fd822e135bb783cae0236 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Mon, 19 Dec 2022 23:58:01 +0100
+Subject: [PATCH] target: rewrite command 'target names' as COMMAND_HANDLER
+
+Print one entry per line.
+While there add the mandatory 'usage' field.
+
+Change-Id: Ia832684817f3bdbfa4cb943cd97e3f9fb2605902
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7510
+Tested-by: jenkins
+---
+ src/target/target.c | 19 +++++++++----------
+ 1 file changed, 9 insertions(+), 10 deletions(-)
+
+diff --git a/src/target/target.c b/src/target/target.c
+index b77a25a2a..3fdb34ec6 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -6388,20 +6388,18 @@ COMMAND_HANDLER(handle_target_types)
+ return ERROR_OK;
+ }
+
+-static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_target_names)
+ {
+- if (argc != 1) {
+- Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+- return JIM_ERR;
+- }
+- Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
++ if (CMD_ARGC != 0)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
+ struct target *target = all_targets;
+ while (target) {
+- Jim_ListAppendElement(interp, Jim_GetResult(interp),
+- Jim_NewStringObj(interp, target_name(target), -1));
++ command_print(CMD, "%s", target_name(target));
+ target = target->next;
+ }
+- return JIM_OK;
++
++ return ERROR_OK;
+ }
+
+ static struct target_list *
+@@ -6531,8 +6529,9 @@ static const struct command_registration target_subcommand_handlers[] = {
+ {
+ .name = "names",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_target_names,
++ .handler = handle_target_names,
+ .help = "Returns the names of all targets as a list of strings",
++ .usage = "",
+ },
+ {
+ .name = "smp",
new file mode 100644
@@ -0,0 +1,121 @@
+From e9a7221b68d0775d9c96c8a12a7a26e2729caf37 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Tue, 20 Dec 2022 00:11:41 +0100
+Subject: [PATCH] target: rewrite command 'target smp' as COMMAND_HANDLER
+
+This also fixes an incorrect return ERROR_xx from a jim command,
+propagated from return value of rtos_smp_init().
+
+Change-Id: Icf4893c00aabd8fadd60077c5e8a2e926f687518
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7511
+Tested-by: jenkins
+---
+ src/target/target.c | 41 ++++++++++++++++++++---------------------
+ 1 file changed, 20 insertions(+), 21 deletions(-)
+
+diff --git a/src/target/target.c b/src/target/target.c
+index 3fdb34ec6..47abd2823 100644
+--- a/src/target/target.c
++++ b/src/target/target.c
+@@ -6404,9 +6404,8 @@ COMMAND_HANDLER(handle_target_names)
+
+ static struct target_list *
+ __attribute__((warn_unused_result))
+-create_target_list_node(Jim_Obj *const name) {
+- int len;
+- const char *targetname = Jim_GetString(name, &len);
++create_target_list_node(const char *targetname)
++{
+ struct target *target = get_target(targetname);
+ LOG_DEBUG("%s ", targetname);
+ if (!target)
+@@ -6422,7 +6421,8 @@ create_target_list_node(Jim_Obj *const name) {
+ return new;
+ }
+
+-static int get_target_with_common_rtos_type(struct list_head *lh, struct target **result)
++static int get_target_with_common_rtos_type(struct command_invocation *cmd,
++ struct list_head *lh, struct target **result)
+ {
+ struct target *target = NULL;
+ struct target_list *curr;
+@@ -6430,39 +6430,39 @@ static int get_target_with_common_rtos_type(struct list_head *lh, struct target
+ struct rtos *curr_rtos = curr->target->rtos;
+ if (curr_rtos) {
+ if (target && target->rtos && target->rtos->type != curr_rtos->type) {
+- LOG_ERROR("Different rtos types in members of one smp target!");
+- return JIM_ERR;
++ command_print(cmd, "Different rtos types in members of one smp target!");
++ return ERROR_FAIL;
+ }
+ target = curr->target;
+ }
+ }
+ *result = target;
+- return JIM_OK;
++ return ERROR_OK;
+ }
+
+-static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
++COMMAND_HANDLER(handle_target_smp)
+ {
+ static int smp_group = 1;
+
+- if (argc == 1) {
++ if (CMD_ARGC == 0) {
+ LOG_DEBUG("Empty SMP target");
+- return JIM_OK;
++ return ERROR_OK;
+ }
+- LOG_DEBUG("%d", argc);
+- /* argv[1] = target to associate in smp
+- * argv[2] = target to associate in smp
+- * argv[3] ...
++ LOG_DEBUG("%d", CMD_ARGC);
++ /* CMD_ARGC[0] = target to associate in smp
++ * CMD_ARGC[1] = target to associate in smp
++ * CMD_ARGC[2] ...
+ */
+
+ struct list_head *lh = malloc(sizeof(*lh));
+ if (!lh) {
+ LOG_ERROR("Out of memory");
+- return JIM_ERR;
++ return ERROR_FAIL;
+ }
+ INIT_LIST_HEAD(lh);
+
+- for (int i = 1; i < argc; i++) {
+- struct target_list *new = create_target_list_node(argv[i]);
++ for (unsigned int i = 0; i < CMD_ARGC; i++) {
++ struct target_list *new = create_target_list_node(CMD_ARGV[i]);
+ if (new)
+ list_add_tail(&new->lh, lh);
+ }
+@@ -6476,14 +6476,13 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+ smp_group++;
+
+ struct target *rtos_target;
+- int retval = get_target_with_common_rtos_type(lh, &rtos_target);
+- if (retval == JIM_OK && rtos_target)
++ int retval = get_target_with_common_rtos_type(CMD, lh, &rtos_target);
++ if (retval == ERROR_OK && rtos_target)
+ retval = rtos_smp_init(rtos_target);
+
+ return retval;
+ }
+
+-
+ static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+ {
+ struct jim_getopt_info goi;
+@@ -6536,7 +6535,7 @@ static const struct command_registration target_subcommand_handlers[] = {
+ {
+ .name = "smp",
+ .mode = COMMAND_ANY,
+- .jim_handler = jim_target_smp,
++ .handler = handle_target_smp,
+ .usage = "targetname1 targetname2 ...",
+ .help = "gather several target in a smp list"
+ },
new file mode 100644
@@ -0,0 +1,126 @@
+From f0e8f7b790f6d945c35b4bb868cafee5fcea3a22 Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa@kernel.org>
+Date: Fri, 3 Mar 2023 12:26:46 +0100
+Subject: [PATCH] tcl/board/calao-usb-a9260: fix and refactor broken support
+
+The old configuration files did not work because of a missing
+'at91sam9260minimal.cfg' file. Also, the config files were placed
+wrongly. Update them, put them to the proper location, merge the two
+supported boards into one, remove now superfluous include, remove
+defunct web page, etc.. Tested with a Calao USB-A9G20 and a hacked
+'device_desc' to match. Native support for it will come next.
+
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Change-Id: Iec578c8777c5a6134e132dbac17c2988c7634742
+Reviewed-on: https://review.openocd.org/c/openocd/+/7522
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ tcl/board/calao-usb-a9260.cfg | 14 +++++++++++++
+ tcl/interface/calao-usb-a9260.cfg | 12 -----------
+ tcl/interface/ftdi/calao-usb-a9260-c01.cfg | 24 ----------------------
+ tcl/interface/ftdi/calao-usb-a9260-c02.cfg | 24 ----------------------
+ 4 files changed, 14 insertions(+), 60 deletions(-)
+ create mode 100644 tcl/board/calao-usb-a9260.cfg
+ delete mode 100644 tcl/interface/calao-usb-a9260.cfg
+ delete mode 100644 tcl/interface/ftdi/calao-usb-a9260-c01.cfg
+ delete mode 100644 tcl/interface/ftdi/calao-usb-a9260-c02.cfg
+
+diff --git a/tcl/board/calao-usb-a9260.cfg b/tcl/board/calao-usb-a9260.cfg
+new file mode 100644
+index 000000000..52fede0fa
+--- /dev/null
++++ b/tcl/board/calao-usb-a9260.cfg
+@@ -0,0 +1,14 @@
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++# CALAO Systems USB-A9260 (C01 and C02)
++
++adapter driver ftdi
++ftdi device_desc "USB-A9260"
++ftdi vid_pid 0x0403 0x6001 0x0403 0x6010
++ftdi layout_init 0x0c08 0x0f1b
++ftdi layout_signal nTRST -data 0x0100 -noe 0x0400
++ftdi layout_signal nSRST -data 0x0200 -noe 0x0800
++
++transport select jtag
++
++source [find target/at91sam9260.cfg]
+diff --git a/tcl/interface/calao-usb-a9260.cfg b/tcl/interface/calao-usb-a9260.cfg
+deleted file mode 100644
+index ff652ef8f..000000000
+--- a/tcl/interface/calao-usb-a9260.cfg
++++ /dev/null
+@@ -1,12 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-#
+-# CALAO Systems USB-A9260 common -C01 -C02 setup
+-#
+-# http://www.calao-systems.com/
+-#
+-# See calao-usb-a9260-c01.cfg and calao-usb-a9260-c02.cfg.
+-#
+-
+-adapter srst delay 200
+-jtag_ntrst_delay 200
+diff --git a/tcl/interface/ftdi/calao-usb-a9260-c01.cfg b/tcl/interface/ftdi/calao-usb-a9260-c01.cfg
+deleted file mode 100644
+index c84e77874..000000000
+--- a/tcl/interface/ftdi/calao-usb-a9260-c01.cfg
++++ /dev/null
+@@ -1,24 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-#
+-# CALAO Systems USB-A9260-C01
+-#
+-# http://www.calao-systems.com/
+-#
+-
+-echo "WARNING!"
+-echo "This file was not tested with real interface, but is assumed to work as this"
+-echo "interface uses the same layout as configs that were verified. Please report your"
+-echo "experience with this file to openocd-devel mailing list, so it could be marked"
+-echo "as working or fixed."
+-
+-adapter driver ftdi
+-ftdi device_desc "USB-A9260"
+-ftdi vid_pid 0x0403 0x6010
+-
+-ftdi layout_init 0x0c08 0x0f1b
+-ftdi layout_signal nTRST -data 0x0100 -noe 0x0400
+-ftdi layout_signal nSRST -data 0x0200 -noe 0x0800
+-
+-script interface/calao-usb-a9260.cfg
+-script target/at91sam9260minimal.cfg
+diff --git a/tcl/interface/ftdi/calao-usb-a9260-c02.cfg b/tcl/interface/ftdi/calao-usb-a9260-c02.cfg
+deleted file mode 100644
+index 9d79b2600..000000000
+--- a/tcl/interface/ftdi/calao-usb-a9260-c02.cfg
++++ /dev/null
+@@ -1,24 +0,0 @@
+-# SPDX-License-Identifier: GPL-2.0-or-later
+-
+-#
+-# CALAO Systems USB-A9260-C02
+-#
+-# http://www.calao-systems.com/
+-#
+-
+-echo "WARNING!"
+-echo "This file was not tested with real interface, but is assumed to work as this"
+-echo "interface uses the same layout as configs that were verified. Please report your"
+-echo "experience with this file to openocd-devel mailing list, so it could be marked"
+-echo "as working or fixed."
+-
+-adapter driver ftdi
+-ftdi device_desc "USB-A9260"
+-ftdi vid_pid 0x0403 0x6001
+-
+-ftdi layout_init 0x0c08 0x0f1b
+-ftdi layout_signal nTRST -data 0x0100 -noe 0x0400
+-ftdi layout_signal nSRST -data 0x0200 -noe 0x0800
+-
+-script interface/calao-usb-a9260.cfg
+-script target/at91sam9260minimal.cfg
new file mode 100644
@@ -0,0 +1,37 @@
+From b939224ab6e6e28e5211aac0303951ae4fabaf1f Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa@kernel.org>
+Date: Sun, 5 Mar 2023 08:38:14 +0100
+Subject: [PATCH] tcl/board: add Calao USB-A9G20
+
+Add a basic config.
+
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Change-Id: Ie68e5fbb26b1c2f3028e561af0255fa71ec61828
+Reviewed-on: https://review.openocd.org/c/openocd/+/7524
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ tcl/board/calao-usb-a9g20-c01.cfg | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+ create mode 100644 tcl/board/calao-usb-a9g20-c01.cfg
+
+diff --git a/tcl/board/calao-usb-a9g20-c01.cfg b/tcl/board/calao-usb-a9g20-c01.cfg
+new file mode 100644
+index 000000000..6c4bd40fe
+--- /dev/null
++++ b/tcl/board/calao-usb-a9g20-c01.cfg
+@@ -0,0 +1,14 @@
++# SPDX-License-Identifier: GPL-2.0-or-later
++
++# CALAO Systems USB-A9G20-C01
++
++adapter driver ftdi
++ftdi device_desc "USB-A9G20"
++ftdi vid_pid 0x0403 0x6010
++ftdi layout_init 0x0c08 0x0f1b
++ftdi layout_signal nTRST -data 0x0100 -noe 0x0400
++ftdi layout_signal nSRST -data 0x0200 -noe 0x0800
++
++transport select jtag
++
++source [find target/at91sam9g20.cfg]
new file mode 100644
@@ -0,0 +1,28 @@
+From c1b14d678fd77095ef5c076c0e927aeed6a753c7 Mon Sep 17 00:00:00 2001
+From: panciyan <panciyan@eswincomputing.com>
+Date: Mon, 20 Mar 2023 02:26:58 +0000
+Subject: [PATCH] flash/nor: missing fileio_close.
+
+If the file read abnormally, need to close it which was opened before.
+
+Signed-off-by: panciyan <panciyan@eswincomputing.com>
+Change-Id: I6142f154741dcd38088b7add2793219ee4dd2ae9
+Reviewed-on: https://review.openocd.org/c/openocd/+/7546
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/flash/nor/tcl.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
+index ecbcf00aa..22c1710ad 100644
+--- a/src/flash/nor/tcl.c
++++ b/src/flash/nor/tcl.c
+@@ -814,6 +814,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
+ if (buf_cnt != length) {
+ LOG_ERROR("Short read");
+ free(buffer);
++ fileio_close(fileio);
+ return ERROR_FAIL;
+ }
+
new file mode 100644
@@ -0,0 +1,67 @@
+From 4b9b55a832e43815a1dd1b219107a01a1beadc1e Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Sat, 25 Mar 2023 02:56:19 +0300
+Subject: [PATCH] github/workflow: increase delete-tag-and-release version
+
+During setup job in the GH actions, GH tries to resolve
+all actions before starting to run the scripts.
+It can not find 0.2.0 version inside
+'dev-drprasad/delete-tag-and-release 'repo and action fails.
+
+This patch fixes that error.
+Also, switched to the latest ubuntu image
+Hidapi version updated to 0.13.1
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: I02af41f6189d5a28f874c9b008073d74de46b4ca
+Reviewed-on: https://review.openocd.org/c/openocd/+/7551
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ .github/workflows/snapshot.yml | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml
+index e5997a055..b48388ef7 100644
+--- a/.github/workflows/snapshot.yml
++++ b/.github/workflows/snapshot.yml
+@@ -8,7 +8,7 @@ name: OpenOCD Snapshot
+
+ jobs:
+ package:
+- runs-on: [ubuntu-18.04]
++ runs-on: [ubuntu-20.04]
+ env:
+ DL_DIR: ../downloads
+ BUILD_DIR: ../build
+@@ -30,7 +30,7 @@ jobs:
+ echo "LIBUSB1_SRC=$PWD/libusb-${LIBUSB1_VER}" >> $GITHUB_ENV
+ - name: Prepare hidapi
+ env:
+- HIDAPI_VER: 0.11.2
++ HIDAPI_VER: 0.13.1
+ run: |
+ mkdir -p $DL_DIR && cd $DL_DIR
+ wget "https://github.com/libusb/hidapi/archive/hidapi-${HIDAPI_VER}.tar.gz"
+@@ -82,6 +82,7 @@ jobs:
+ # add missing dlls
+ cd $HOST-root/usr
+ cp `$HOST-gcc --print-file-name=libwinpthread-1.dll` ./bin/
++ # required by libftdi1.dll. For the gcc-mingw-10.3.x or later "libgcc_s_dw2-1.dll" will need to be copied.
+ cp `$HOST-gcc --print-file-name=libgcc_s_sjlj-1.dll` ./bin/
+ # prepare the artifact
+ ARTIFACT="openocd-${OPENOCD_TAG}-${HOST}.tar.gz"
+@@ -90,11 +91,11 @@ jobs:
+ echo "IS_PRE_RELEASE=$IS_PRE_RELEASE" >> $GITHUB_ENV
+ echo "ARTIFACT_PATH=$PWD/$ARTIFACT" >> $GITHUB_ENV
+ - name: Publish OpenOCD packaged for windows
+- uses: actions/upload-artifact@v2
++ uses: actions/upload-artifact@v3
+ with:
+ path: ${{ env.ARTIFACT_PATH }}
+ - name: Delete 'latest' Release
+- uses: dev-drprasad/delete-tag-and-release@v0.2.0
++ uses: dev-drprasad/delete-tag-and-release@v0.2.1
+ with:
+ delete_release: true
+ tag_name: ${{ env.RELEASE_NAME }}
new file mode 100644
@@ -0,0 +1,96 @@
+From 99ec5760961d264599a9c9fb1a4d5d6042bc3ba8 Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Sat, 25 Mar 2023 03:00:51 +0300
+Subject: [PATCH] github/workflow: build libjaylink from source
+
+Libjaylink submodule disabled by default at
+https://review.openocd.org/c/openocd/+/7129
+
+--enable-internal-libjaylink config option will be deprecated soon.
+
+So, building the source is a permanent solution.
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: Id06654d806a3a49f35e3ba41e9e4cc58c1a0d388
+Reviewed-on: https://review.openocd.org/c/openocd/+/7552
+Tested-by: jenkins
+Reviewed-by: zapb <dev@zapb.de>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ .github/workflows/snapshot.yml | 11 +++++++++++
+ contrib/cross-build.sh | 13 +++++++++++++
+ 2 files changed, 24 insertions(+)
+
+diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml
+index b48388ef7..f5cf56459 100644
+--- a/.github/workflows/snapshot.yml
++++ b/.github/workflows/snapshot.yml
+@@ -56,6 +56,16 @@ jobs:
+ wget "https://github.com/aquynh/capstone/archive/${CAPSTONE_VER}.tar.gz"
+ tar -xzf ${CAPSTONE_VER}.tar.gz
+ echo "CAPSTONE_SRC=$PWD/capstone-${CAPSTONE_VER}" >> $GITHUB_ENV
++ - name: Prepare libjaylink
++ env:
++ LIBJAYLINK_VER: 0.3.1
++ run: |
++ mkdir -p $DL_DIR && cd $DL_DIR
++ wget https://gitlab.zapb.de/libjaylink/libjaylink/-/archive/${LIBJAYLINK_VER}/libjaylink-${LIBJAYLINK_VER}.tar.gz
++ tar -xzf libjaylink-${LIBJAYLINK_VER}.tar.gz
++ cd libjaylink-${LIBJAYLINK_VER}
++ ./autogen.sh
++ echo "LIBJAYLINK_SRC=$PWD" >> $GITHUB_ENV
+ - name: Package OpenOCD for windows
+ env:
+ MAKE_JOBS: 2
+@@ -64,6 +74,7 @@ jobs:
+ HIDAPI_CONFIG: --enable-shared --disable-static --disable-testgui
+ LIBFTDI_CONFIG: -DSTATICLIBS=OFF -DEXAMPLES=OFF -DFTDI_EEPROM=OFF
+ CAPSTONE_CONFIG: "CAPSTONE_BUILD_CORE_ONLY=yes CAPSTONE_STATIC=yes CAPSTONE_SHARED=no"
++ LIBJAYLINK_CONFIG: --enable-shared --disable-static
+ run: |
+ # check if there is tag pointing at HEAD, otherwise take the HEAD SHA-1 as OPENOCD_TAG
+ OPENOCD_TAG="`git tag --points-at HEAD`"
+diff --git a/contrib/cross-build.sh b/contrib/cross-build.sh
+index b199bf715..bb8c8c47d 100755
+--- a/contrib/cross-build.sh
++++ b/contrib/cross-build.sh
+@@ -41,12 +41,14 @@ WORK_DIR=$PWD
+ : ${HIDAPI_SRC:=/path/to/hidapi}
+ : ${LIBFTDI_SRC:=/path/to/libftdi}
+ : ${CAPSTONE_SRC:=/path/to/capstone}
++: ${LIBJAYLINK_SRC:=/path/to/libjaylink}
+
+ OPENOCD_SRC=`readlink -m $OPENOCD_SRC`
+ LIBUSB1_SRC=`readlink -m $LIBUSB1_SRC`
+ HIDAPI_SRC=`readlink -m $HIDAPI_SRC`
+ LIBFTDI_SRC=`readlink -m $LIBFTDI_SRC`
+ CAPSTONE_SRC=`readlink -m $CAPSTONE_SRC`
++LIBJAYLINK_SRC=`readlink -m $LIBJAYLINK_SRC`
+
+ HOST_TRIPLET=$1
+ BUILD_DIR=$WORK_DIR/$HOST_TRIPLET-build
+@@ -54,6 +56,7 @@ LIBUSB1_BUILD_DIR=$BUILD_DIR/libusb1
+ HIDAPI_BUILD_DIR=$BUILD_DIR/hidapi
+ LIBFTDI_BUILD_DIR=$BUILD_DIR/libftdi
+ CAPSTONE_BUILD_DIR=$BUILD_DIR/capstone
++LIBJAYLINK_BUILD_DIR=$BUILD_DIR/libjaylink
+ OPENOCD_BUILD_DIR=$BUILD_DIR/openocd
+
+ ## Root of host file tree
+@@ -158,6 +161,16 @@ libdir=${exec_prefix}/lib \
+ includedir=${prefix}/include/capstone\n\n;' $CAPSTONE_PC_FILE
+ fi
+
++# libjaylink build & install into sysroot
++if [ -d $LIBJAYLINK_SRC ] ; then
++ mkdir -p $LIBJAYLINK_BUILD_DIR
++ cd $LIBJAYLINK_BUILD_DIR
++ $LIBJAYLINK_SRC/configure --build=`$LIBJAYLINK_SRC/config.guess` --host=$HOST_TRIPLET \
++ --with-sysroot=$SYSROOT --prefix=$PREFIX \
++ $LIBJAYLINK_CONFIG
++ make -j $MAKE_JOBS
++ make install DESTDIR=$SYSROOT
++fi
+
+ # OpenOCD build & install into sysroot
+ mkdir -p $OPENOCD_BUILD_DIR
new file mode 100644
@@ -0,0 +1,51 @@
+From 41037eb26585114209c3c8f1d63f7788a421df07 Mon Sep 17 00:00:00 2001
+From: Chao Du <duchao@eswincomputing.com>
+Date: Wed, 22 Mar 2023 06:51:51 +0000
+Subject: [PATCH] rtos/FreeRTOS: some optimization of freertos_update_threads()
+
+1.
+update the rtos->thread_count in time, to make sure the allocated
+thread_name_str and extra_info_str could be freed by
+rtos_free_threadlist(). Otherwise the abnormal return may cause a
+memory leak.
+2.
+remove a redundant assignment to threadid.
+
+Signed-off-by: Chao Du <duchao@eswincomputing.com>
+Change-Id: Ifabc59d501c925b3d6aec8b04b2856d2c31cc4e2
+Reviewed-on: https://review.openocd.org/c/openocd/+/7549
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/rtos/FreeRTOS.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c
+index 070275f2c..e8df030aa 100644
+--- a/src/rtos/FreeRTOS.c
++++ b/src/rtos/FreeRTOS.c
+@@ -312,7 +312,6 @@ static int freertos_update_threads(struct rtos *rtos)
+ (list_elem_ptr != prev_list_elem_ptr) &&
+ (tasks_found < thread_list_size)) {
+ /* Get the location of the thread structure. */
+- rtos->thread_details[tasks_found].threadid = 0;
+ retval = target_read_u32(rtos->target,
+ list_elem_ptr + param->list_elem_content_offset,
+ &pointer_casts_are_bad);
+@@ -365,6 +364,7 @@ static int freertos_update_threads(struct rtos *rtos)
+
+ tasks_found++;
+ list_thread_count--;
++ rtos->thread_count = tasks_found;
+
+ prev_list_elem_ptr = list_elem_ptr;
+ list_elem_ptr = 0;
+@@ -383,7 +383,6 @@ static int freertos_update_threads(struct rtos *rtos)
+ }
+
+ free(list_of_lists);
+- rtos->thread_count = tasks_found;
+ return 0;
+ }
+
new file mode 100644
@@ -0,0 +1,38 @@
+From 18aacc8bf3ff7c7481673cbbfe82f0104e4dccf9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20LEGAL?= <devel@thom.fr.eu.org>
+Date: Wed, 29 Mar 2023 14:19:48 +0200
+Subject: [PATCH] src/target/mips_m4k : fix condition on overlapping workspace
+ data area
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The condition to check if the workspace area (used by actual MIPS code
+executed on target) and data area (sandbox to put data to be read/written
+to/from flash) is wrong, thus preventing the use of FAST_* commands to
+program/verify FLASH.
+
+Signed-off-by: François LEGAL <devel@thom.fr.eu.org>
+Change-Id: Ic68424b7f42d44e550433a120093db5e7980fd56
+Reviewed-on: https://review.openocd.org/c/openocd/+/7563
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/target/mips_m4k.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c
+index 491b247b1..d3b07585d 100644
+--- a/src/target/mips_m4k.c
++++ b/src/target/mips_m4k.c
+@@ -1218,8 +1218,8 @@ static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t addre
+
+ fast_data_area = mips32->fast_data_area;
+
+- if (address <= fast_data_area->address + fast_data_area->size &&
+- fast_data_area->address <= address + count) {
++ if (address < (fast_data_area->address + fast_data_area->size) &&
++ fast_data_area->address < (address + count)) {
+ LOG_ERROR("fast_data (" TARGET_ADDR_FMT ") is within write area "
+ "(" TARGET_ADDR_FMT "-" TARGET_ADDR_FMT ").",
+ fast_data_area->address, address, address + count);
new file mode 100644
@@ -0,0 +1,119 @@
+From 55e04e3157cd4d817cfd39c6f1384f96d61a0951 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20LEGAL?= <devel@thom.fr.eu.org>
+Date: Wed, 29 Mar 2023 17:46:38 +0200
+Subject: [PATCH] src/target/mips_m4k : add fast read method
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add the fast read method to speed up flash verification
+after programming. Works the same as fast write already
+implemented.
+
+Signed-off-by: François LEGAL <devel@thom.fr.eu.org>
+Change-Id: I74611a3542a88212f0483ec8ee368aba3d1f03c7
+Reviewed-on: https://review.openocd.org/c/openocd/+/7564
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/target/mips_m4k.c | 73 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 73 insertions(+)
+
+diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c
+index d3b07585d..14e3f3b27 100644
+--- a/src/target/mips_m4k.c
++++ b/src/target/mips_m4k.c
+@@ -36,6 +36,8 @@ static int mips_m4k_internal_restore(struct target *target, int current,
+ static int mips_m4k_halt(struct target *target);
+ static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address,
+ uint32_t count, const uint8_t *buffer);
++static int mips_m4k_bulk_read_memory(struct target *target, target_addr_t address,
++ uint32_t count, uint8_t *buffer);
+
+ static int mips_m4k_examine_debug_reason(struct target *target)
+ {
+@@ -1021,6 +1023,12 @@ static int mips_m4k_read_memory(struct target *target, target_addr_t address,
+ if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+ return ERROR_TARGET_UNALIGNED_ACCESS;
+
++ if (size == 4 && count > 32) {
++ int retval = mips_m4k_bulk_read_memory(target, address, count, buffer);
++ if (retval == ERROR_OK)
++ return ERROR_OK;
++ LOG_WARNING("Falling back to non-bulk read");
++ }
+ /* since we don't know if buffer is aligned, we allocate new mem that is always aligned */
+ void *t = NULL;
+
+@@ -1249,6 +1257,71 @@ static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t addre
+ return retval;
+ }
+
++static int mips_m4k_bulk_read_memory(struct target *target, target_addr_t address,
++ uint32_t count, uint8_t *buffer)
++{
++ struct mips32_common *mips32 = target_to_mips32(target);
++ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
++ struct working_area *fast_data_area;
++ int retval;
++ int write_t = 0;
++
++ LOG_DEBUG("address: " TARGET_ADDR_FMT ", count: 0x%8.8" PRIx32 "",
++ address, count);
++
++ /* check alignment */
++ if (address & 0x3u)
++ return ERROR_TARGET_UNALIGNED_ACCESS;
++
++ if (!mips32->fast_data_area) {
++ /* Get memory for block read handler
++ * we preserve this area between calls and gain a speed increase
++ * of about 3kb/sec when reading flash
++ * this will be released/nulled by the system when the target is resumed or reset */
++ retval = target_alloc_working_area(target,
++ MIPS32_FASTDATA_HANDLER_SIZE,
++ &mips32->fast_data_area);
++ if (retval != ERROR_OK) {
++ LOG_ERROR("No working area available");
++ return retval;
++ }
++
++ /* reset fastadata state so the algo get reloaded */
++ ejtag_info->fast_access_save = -1;
++ }
++
++ fast_data_area = mips32->fast_data_area;
++
++ if (address < (fast_data_area->address + fast_data_area->size) &&
++ fast_data_area->address < (address + count)) {
++ LOG_ERROR("fast_data (" TARGET_ADDR_FMT ") is within read area "
++ "(" TARGET_ADDR_FMT "-" TARGET_ADDR_FMT ").",
++ fast_data_area->address, address, address + count);
++ LOG_ERROR("Change work-area-phys or load_image address!");
++ return ERROR_FAIL;
++ }
++
++ /* mips32_pracc_fastdata_xfer requires uint32_t in host endianness, */
++ /* but byte array represents target endianness */
++ uint32_t *t = malloc(count * sizeof(uint32_t));
++ if (!t) {
++ LOG_ERROR("Out of memory");
++ return ERROR_FAIL;
++ }
++
++ retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address,
++ count, t);
++
++ target_buffer_set_u32_array(target, buffer, count, t);
++
++ free(t);
++
++ if (retval != ERROR_OK)
++ LOG_ERROR("Fastdata access Failed");
++
++ return retval;
++}
++
+ static int mips_m4k_verify_pointer(struct command_invocation *cmd,
+ struct mips_m4k_common *mips_m4k)
+ {
new file mode 100644
@@ -0,0 +1,285 @@
+From 90ce9da644d751466d8dc451d7d2a043cdbf7d72 Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Tue, 14 Mar 2023 15:01:18 +0100
+Subject: [PATCH] helper/list: remove unused hlist_*
+
+The file list.h is taken from Linux and includes two similar
+implementation of double linked lists:
+- with single linked list's head (hlist_*), and
+- with double linked list's head (list_*).
+While the former offers a minor memory footprint improvement,
+keeping two implementations makes harder for newbie developers
+to approach them.
+
+So far only the latter implementation has been used and no new
+patches in gerrit is going to change that.
+
+Drop the support for lists with single linked head.
+It can be easily taken back from git history, if needed.
+
+Change-Id: I420e5de38ab755fdfbeb2115538c61818308ec2b
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7567
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/helper/list.h | 239 +---------------------------------------------
+ 1 file changed, 1 insertion(+), 238 deletions(-)
+
+diff --git a/src/helper/list.h b/src/helper/list.h
+index 552a3202a..396ff06c9 100644
+--- a/src/helper/list.h
++++ b/src/helper/list.h
+@@ -27,13 +27,6 @@ struct list_head {
+ struct list_head *next, *prev;
+ };
+
+-struct hlist_head {
+- struct hlist_node *first;
+-};
+-
+-struct hlist_node {
+- struct hlist_node *next, **pprev;
+-};
+ /* end local changes */
+
+ /*
+@@ -811,237 +804,7 @@ static inline void list_splice_tail_init(struct list_head *list,
+
+ /*
+ * Double linked lists with a single pointer list head.
+- * Mostly useful for hash tables where the two pointer list head is
+- * too wasteful.
+- * You lose the ability to access the tail in O(1).
+- */
+-
+-#define HLIST_HEAD_INIT { .first = NULL }
+-#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
+-#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+-static inline void INIT_HLIST_NODE(struct hlist_node *h)
+-{
+- h->next = NULL;
+- h->pprev = NULL;
+-}
+-
+-/**
+- * hlist_unhashed - Has node been removed from list and reinitialized?
+- * @param h Node to be checked
+- *
+- * Not that not all removal functions will leave a node in unhashed
+- * state. For example, hlist_nulls_del_init_rcu() does leave the
+- * node in unhashed state, but hlist_nulls_del() does not.
+- */
+-static inline int hlist_unhashed(const struct hlist_node *h)
+-{
+- return !h->pprev;
+-}
+-
+-/* Ignore kernel hlist_unhashed_lockless() */
+-
+-/**
+- * hlist_empty - Is the specified hlist_head structure an empty hlist?
+- * @param h Structure to check.
+- */
+-static inline int hlist_empty(const struct hlist_head *h)
+-{
+- return !h->first;
+-}
+-
+-static inline void __hlist_del(struct hlist_node *n)
+-{
+- struct hlist_node *next = n->next;
+- struct hlist_node **pprev = n->pprev;
+-
+- *pprev = next;
+- if (next)
+- next->pprev = pprev;
+-}
+-
+-/**
+- * hlist_del - Delete the specified hlist_node from its list
+- * @param n Node to delete.
+- *
+- * Note that this function leaves the node in hashed state. Use
+- * hlist_del_init() or similar instead to unhash @a n.
+- */
+-static inline void hlist_del(struct hlist_node *n)
+-{
+- __hlist_del(n);
+- n->next = LIST_POISON1;
+- n->pprev = LIST_POISON2;
+-}
+-
+-/**
+- * hlist_del_init - Delete the specified hlist_node from its list and initialize
+- * @param n Node to delete.
+- *
+- * Note that this function leaves the node in unhashed state.
+- */
+-static inline void hlist_del_init(struct hlist_node *n)
+-{
+- if (!hlist_unhashed(n)) {
+- __hlist_del(n);
+- INIT_HLIST_NODE(n);
+- }
+-}
+-
+-/**
+- * hlist_add_head - add a new entry at the beginning of the hlist
+- * @param n new entry to be added
+- * @param h hlist head to add it after
+- *
+- * Insert a new entry after the specified head.
+- * This is good for implementing stacks.
+- */
+-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+-{
+- struct hlist_node *first = h->first;
+- n->next = first;
+- if (first)
+- first->pprev = &n->next;
+- h->first = n;
+- n->pprev = &h->first;
+-}
+-
+-/**
+- * hlist_add_before - add a new entry before the one specified
+- * @param n new entry to be added
+- * @param next hlist node to add it before, which must be non-NULL
+- */
+-static inline void hlist_add_before(struct hlist_node *n,
+- struct hlist_node *next)
+-{
+- n->pprev = next->pprev;
+- n->next = next;
+- next->pprev = &n->next;
+- *(n->pprev) = n;
+-}
+-
+-/**
+- * hlist_add_behind - add a new entry after the one specified
+- * @param n new entry to be added
+- * @param prev hlist node to add it after, which must be non-NULL
+- */
+-static inline void hlist_add_behind(struct hlist_node *n,
+- struct hlist_node *prev)
+-{
+- n->next = prev->next;
+- prev->next = n;
+- n->pprev = &prev->next;
+-
+- if (n->next)
+- n->next->pprev = &n->next;
+-}
+-
+-/**
+- * hlist_add_fake - create a fake hlist consisting of a single headless node
+- * @param n Node to make a fake list out of
+- *
+- * This makes @a n appear to be its own predecessor on a headless hlist.
+- * The point of this is to allow things like hlist_del() to work correctly
+- * in cases where there is no list.
+- */
+-static inline void hlist_add_fake(struct hlist_node *n)
+-{
+- n->pprev = &n->next;
+-}
+-
+-/**
+- * hlist_fake: Is this node a fake hlist?
+- * @param h Node to check for being a self-referential fake hlist.
+- */
+-static inline bool hlist_fake(struct hlist_node *h)
+-{
+- return h->pprev == &h->next;
+-}
+-
+-/**
+- * hlist_is_singular_node - is node the only element of the specified hlist?
+- * @param n Node to check for singularity.
+- * @param h Header for potentially singular list.
+- *
+- * Check whether the node is the only node of the head without
+- * accessing head, thus avoiding unnecessary cache misses.
+- */
+-static inline bool
+-hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h)
+-{
+- return !n->next && n->pprev == &h->first;
+-}
+-
+-/**
+- * hlist_move_list - Move an hlist
+- * @param old hlist_head for old list.
+- * @param new hlist_head for new list.
+- *
+- * Move a list from one list head to another. Fixup the pprev
+- * reference of the first entry if it exists.
+- */
+-static inline void hlist_move_list(struct hlist_head *old,
+- struct hlist_head *new)
+-{
+- new->first = old->first;
+- if (new->first)
+- new->first->pprev = &new->first;
+- old->first = NULL;
+-}
+-
+-#define hlist_entry(ptr, type, member) container_of(ptr, type, member)
+-
+-#define hlist_for_each(pos, head) \
+- for (pos = (head)->first; pos ; pos = pos->next)
+-
+-#define hlist_for_each_safe(pos, n, head) \
+- for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+- pos = n)
+-
+-#define hlist_entry_safe(ptr, type, member) \
+- ({ typeof(ptr) ____ptr = (ptr); \
+- ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
+- })
+-
+-/**
+- * hlist_for_each_entry - iterate over list of given type
+- * @param pos the type * to use as a loop cursor.
+- * @param head the head for your list.
+- * @param member the name of the hlist_node within the struct.
+- */
+-#define hlist_for_each_entry(pos, head, member) \
+- for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
+- pos; \
+- pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+-
+-/**
+- * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
+- * @param pos the type * to use as a loop cursor.
+- * @param member the name of the hlist_node within the struct.
+- */
+-#define hlist_for_each_entry_continue(pos, member) \
+- for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\
+- pos; \
+- pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+-
+-/**
+- * hlist_for_each_entry_from - iterate over a hlist continuing from current point
+- * @param pos the type * to use as a loop cursor.
+- * @param member the name of the hlist_node within the struct.
+- */
+-#define hlist_for_each_entry_from(pos, member) \
+- for (; pos; \
+- pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+-
+-/**
+- * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+- * @param pos the type * to use as a loop cursor.
+- * @param n a &struct hlist_node to use as temporary storage
+- * @param head the head for your list.
+- * @param member the name of the hlist_node within the struct.
++ * IGNORED
+ */
+-#define hlist_for_each_entry_safe(pos, n, head, member) \
+- for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\
+- pos && ({ n = pos->member.next; 1; }); \
+- pos = hlist_entry_safe(n, typeof(*pos), member))
+
+ #endif /* OPENOCD_HELPER_LIST_H */
new file mode 100644
@@ -0,0 +1,145 @@
+From c8de1b82ec7f74c0717bfa0094f5fb6b79fbbfaf Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Tue, 14 Mar 2023 15:20:14 +0100
+Subject: [PATCH] helper/list: re-align with Linux kernel 6.3-rc1
+
+Minor changes due to kernel switch to 100 char/line.
+Added four new functions.
+
+Silent checkpatch; we don't want to diverge from Linux reference
+code.
+Checkpatch-ignore: MACRO_ARG_REUSE, UNNECESSARY_PARENTHESES
+Checkpatch-ignore: MACRO_ARG_PRECEDENCE
+
+Change-Id: I1d2ff25bf3bab8cd0f5c9be55c7501795490ea75
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7568
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ src/helper/list.h | 66 +++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 58 insertions(+), 8 deletions(-)
+
+diff --git a/src/helper/list.h b/src/helper/list.h
+index 396ff06c9..c9de0569b 100644
+--- a/src/helper/list.h
++++ b/src/helper/list.h
+@@ -265,8 +265,7 @@ static inline void list_bulk_move_tail(struct list_head *head,
+ * @param list the entry to test
+ * @param head the head of the list
+ */
+-static inline int list_is_first(const struct list_head *list,
+- const struct list_head *head)
++static inline int list_is_first(const struct list_head *list, const struct list_head *head)
+ {
+ return list->prev == head;
+ }
+@@ -276,12 +275,21 @@ static inline int list_is_first(const struct list_head *list,
+ * @param list the entry to test
+ * @param head the head of the list
+ */
+-static inline int list_is_last(const struct list_head *list,
+- const struct list_head *head)
++static inline int list_is_last(const struct list_head *list, const struct list_head *head)
+ {
+ return list->next == head;
+ }
+
++/**
++ * list_is_head - tests whether @a list is the list @a head
++ * @param list the entry to test
++ * @param head the head of the list
++ */
++static inline int list_is_head(const struct list_head *list, const struct list_head *head)
++{
++ return list == head;
++}
++
+ /**
+ * list_empty - tests whether a list is empty
+ * @param head the list to test.
+@@ -400,10 +408,9 @@ static inline void list_cut_position(struct list_head *list,
+ {
+ if (list_empty(head))
+ return;
+- if (list_is_singular(head) &&
+- (head->next != entry && head != entry))
++ if (list_is_singular(head) && !list_is_head(entry, head) && (entry != head->next))
+ return;
+- if (entry == head)
++ if (list_is_head(entry, head))
+ INIT_LIST_HEAD(list);
+ else
+ __list_cut_position(list, head, entry);
+@@ -563,6 +570,19 @@ static inline void list_splice_tail_init(struct list_head *list,
+ #define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
++/**
++ * list_next_entry_circular - get the next element in list
++ * @param pos the type * to cursor.
++ * @param head the list head to take the element from.
++ * @param member the name of the list_head within the struct.
++ *
++ * Wraparound if pos is the last element (return the first element).
++ * Note, that list is expected to be not empty.
++ */
++#define list_next_entry_circular(pos, head, member) \
++ (list_is_last(&(pos)->member, head) ? \
++ list_first_entry(head, typeof(*(pos)), member) : list_next_entry(pos, member))
++
+ /**
+ * list_prev_entry - get the prev element in list
+ * @param pos the type * to cursor
+@@ -571,13 +591,28 @@ static inline void list_splice_tail_init(struct list_head *list,
+ #define list_prev_entry(pos, member) \
+ list_entry((pos)->member.prev, typeof(*(pos)), member)
+
++/**
++ * list_prev_entry_circular - get the prev element in list
++ * @param pos the type * to cursor.
++ * @param head the list head to take the element from.
++ * @param member the name of the list_head within the struct.
++ *
++ * Wraparound if pos is the first element (return the last element).
++ * Note, that list is expected to be not empty.
++ */
++#define list_prev_entry_circular(pos, head, member) \
++ (list_is_first(&(pos)->member, head) ? \
++ list_last_entry(head, typeof(*(pos)), member) : list_prev_entry(pos, member))
++
+ /**
+ * list_for_each - iterate over a list
+ * @param pos the &struct list_head to use as a loop cursor.
+ * @param head the head for your list.
+ */
+ #define list_for_each(pos, head) \
+- for (pos = (head)->next; pos != (head); pos = pos->next)
++ for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next)
++
++/* Ignore kernel list_for_each_rcu() */
+
+ /**
+ * list_for_each_continue - continue iteration over a list
+@@ -618,6 +653,21 @@ static inline void list_splice_tail_init(struct list_head *list,
+ pos != (head); \
+ pos = n, n = pos->prev)
+
++/**
++ * list_count_nodes - count nodes in the list
++ * @param head the head for your list.
++ */
++static inline size_t list_count_nodes(struct list_head *head)
++{
++ struct list_head *pos;
++ size_t count = 0;
++
++ list_for_each(pos, head)
++ count++;
++
++ return count;
++}
++
+ /**
+ * list_entry_is_head - test if the entry points to the head of the list
+ * @param pos the type * to cursor
new file mode 100644
@@ -0,0 +1,100 @@
+From 7e0797d19ac1837e3001df9d45030b5eb97ca36d Mon Sep 17 00:00:00 2001
+From: Daniel Anselmi <danselmi@gmx.ch>
+Date: Wed, 14 Dec 2022 12:51:48 +0100
+Subject: [PATCH] ipdbg: whitespaces
+
+Change-Id: I9294c551cf2e795ad5e3e92dc3926c564424e067
+Signed-off-by: Daniel Anselmi <danselmi@gmx.ch>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7399
+Tested-by: jenkins
+Reviewed-by: Jonathan McDowell <noodles-openocd@earth.li>
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/server/ipdbg.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c
+index f4a6f6cdc..755d0510e 100644
+--- a/src/server/ipdbg.c
++++ b/src/server/ipdbg.c
+@@ -90,7 +90,7 @@ static void ipdbg_zero_rd_idx(struct ipdbg_fifo *fifo)
+ return;
+
+ size_t ri = fifo->rd_idx;
+- for (size_t idx = 0 ; idx < fifo->count ; ++idx)
++ for (size_t idx = 0; idx < fifo->count; ++idx)
+ fifo->buffer[idx] = fifo->buffer[ri++];
+ fifo->rd_idx = 0;
+ }
+@@ -149,7 +149,7 @@ static int ipdbg_max_tools_from_data_register_length(uint8_t data_register_lengt
+ static struct ipdbg_service *ipdbg_find_service(struct ipdbg_hub *hub, uint8_t tool)
+ {
+ struct ipdbg_service *service;
+- for (service = ipdbg_first_service ; service ; service = service->next) {
++ for (service = ipdbg_first_service; service; service = service->next) {
+ if (service->hub == hub && service->tool == tool)
+ break;
+ }
+@@ -160,7 +160,7 @@ static void ipdbg_add_service(struct ipdbg_service *service)
+ {
+ struct ipdbg_service *iservice;
+ if (ipdbg_first_service) {
+- for (iservice = ipdbg_first_service ; iservice->next; iservice = iservice->next)
++ for (iservice = ipdbg_first_service; iservice->next; iservice = iservice->next)
+ ;
+ iservice->next = service;
+ } else
+@@ -192,7 +192,7 @@ static int ipdbg_remove_service(struct ipdbg_service *service)
+ return ERROR_OK;
+ }
+
+- for (struct ipdbg_service *iservice = ipdbg_first_service ; iservice->next ; iservice = iservice->next) {
++ for (struct ipdbg_service *iservice = ipdbg_first_service; iservice->next; iservice = iservice->next) {
+ if (service == iservice->next) {
+ iservice->next = service->next;
+ return ERROR_OK;
+@@ -205,7 +205,7 @@ static struct ipdbg_hub *ipdbg_find_hub(struct jtag_tap *tap,
+ uint32_t user_instruction, struct ipdbg_virtual_ir_info *virtual_ir)
+ {
+ struct ipdbg_hub *hub = NULL;
+- for (hub = ipdbg_first_hub ; hub ; hub = hub->next) {
++ for (hub = ipdbg_first_hub; hub; hub = hub->next) {
+ if (hub->tap == tap && hub->user_instruction == user_instruction) {
+ if ((!virtual_ir && !hub->virtual_ir) ||
+ (virtual_ir && hub->virtual_ir &&
+@@ -223,7 +223,7 @@ static void ipdbg_add_hub(struct ipdbg_hub *hub)
+ {
+ struct ipdbg_hub *ihub;
+ if (ipdbg_first_hub) {
+- for (ihub = ipdbg_first_hub ; ihub->next; ihub = ihub->next)
++ for (ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next)
+ ;
+ ihub->next = hub;
+ } else
+@@ -281,7 +281,7 @@ static int ipdbg_remove_hub(struct ipdbg_hub *hub)
+ return ERROR_OK;
+ }
+
+- for (struct ipdbg_hub *ihub = ipdbg_first_hub ; ihub->next ; ihub = ihub->next) {
++ for (struct ipdbg_hub *ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) {
+ if (hub == ihub->next) {
+ ihub->next = hub->next;
+ return ERROR_OK;
+@@ -447,7 +447,7 @@ static int ipdbg_polling_callback(void *priv)
+
+ /* transfer dn buffers to jtag-hub */
+ unsigned int num_transfers = 0;
+- for (size_t tool = 0 ; tool < hub->max_tools ; ++tool) {
++ for (size_t tool = 0; tool < hub->max_tools; ++tool) {
+ struct connection *conn = hub->connections[tool];
+ if (conn && conn->priv) {
+ struct ipdbg_connection *connection = conn->priv;
+@@ -475,7 +475,7 @@ static int ipdbg_polling_callback(void *priv)
+ }
+
+ /* write from up fifos to sockets */
+- for (size_t tool = 0 ; tool < hub->max_tools ; ++tool) {
++ for (size_t tool = 0; tool < hub->max_tools; ++tool) {
+ struct connection *conn = hub->connections[tool];
+ if (conn && conn->priv) {
+ struct ipdbg_connection *connection = conn->priv;
new file mode 100644
@@ -0,0 +1,40 @@
+From 561f27fde9dc51f014b672c227dc7c8ca2530fcf Mon Sep 17 00:00:00 2001
+From: Antonio Borneo <borneo.antonio@gmail.com>
+Date: Sun, 2 Apr 2023 14:24:23 +0200
+Subject: [PATCH] helper/compiler fix build with gcc on MacOS
+
+On MacOS libc includes files from MacOSX.sdk that define the macro
+ #define __nonnull
+without arguments, causing compile error.
+
+Extend the existing check for clang on MacOS and undefine the
+macro for gcc too.
+
+Change-Id: Ic99de78348c6aa86561212a3aded9342e5d32e02
+Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
+Reported-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7571
+Reviewed-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Tested-by: jenkins
+---
+ src/helper/compiler.h | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/helper/compiler.h b/src/helper/compiler.h
+index 33a075d64..312d261fc 100644
+--- a/src/helper/compiler.h
++++ b/src/helper/compiler.h
+@@ -36,9 +36,11 @@
+ * clang for Apple defines
+ * #define __nonnull _Nonnull
+ * that is a per argument attribute, incompatible with the gcc per function attribute __nonnull__.
+- * Undefine it to keep compatibility among compilers.
++ * gcc for Apple includes sys/cdefs.h from MacOSX.sdk that defines
++ * #define __nonnull
++ * In both cases, undefine __nonnull to keep compatibility among compilers and platforms.
+ */
+-#if defined(__clang__) && defined(__APPLE__)
++#if defined(__APPLE__)
+ # undef __nonnull
+ #endif
+ #ifndef __nonnull
new file mode 100644
@@ -0,0 +1,59 @@
+From e87fa5e3ab424d3ccd66eeddccfbe1e0181e20d0 Mon Sep 17 00:00:00 2001
+From: Daniel Anselmi <danselmi@gmx.ch>
+Date: Wed, 30 Nov 2022 03:42:18 +0100
+Subject: [PATCH] tcl: zynq_7000: add missing id codes
+
+Add missing ID codes and ignore the version in the ID.
+
+Change-Id: Idd2d3a5eddb6995f3af1c45afd2adf76ce3442bf
+Signed-off-by: Daniel Anselmi <danselmi@gmx.ch>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7386
+Tested-by: jenkins
+Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
+---
+ tcl/target/zynq_7000.cfg | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/tcl/target/zynq_7000.cfg b/tcl/target/zynq_7000.cfg
+index 0272587c1..a6f899541 100644
+--- a/tcl/target/zynq_7000.cfg
++++ b/tcl/target/zynq_7000.cfg
+@@ -1,18 +1,34 @@
+ # SPDX-License-Identifier: GPL-2.0-or-later
+
+-#
+ # Xilinx Zynq-7000 All Programmable SoC
+ #
+ # http://www.xilinx.com/products/silicon-devices/soc/zynq-7000/index.htm
++# https://www.xilinx.com/member/forms/download/sim-model-eval-license-xef.html?filename=bsdl_zynq_2.zip
+ #
++# 0x03736093 XQ7Z100 XC7Z100I XC7Z100
++# 0x03731093 XQ7Z045 XC7Z045I XC7Z045
++# 0x0372c093 XQ7Z030 XC7Z030I XC7Z030 XA7Z030
++# 0x03727093 XQ7Z020 XC7Z020I XC7Z020 XA7Z020
++# 0x03732093 XC7Z035I XC7Z035
++# 0x0373b093 XC7Z015I XC7Z015
++# 0x03728093 XC7Z014S
++# 0x0373c093 XC7Z012S
++# 0x03722093 XC7Z010I XC7Z010 XA7Z010
++# 0x03723093 XC7Z007S
+
+ set _CHIPNAME zynq
+ set _TARGETNAME $_CHIPNAME.cpu
+
+-jtag newtap zynq_pl bs -irlen 6 -ircapture 0x1 -irmask 0x03 \
+- -expected-id 0x23727093 \
+- -expected-id 0x13722093 \
++jtag newtap zynq_pl bs -irlen 6 -ignore-version -ircapture 0x1 -irmask 0x03 \
++ -expected-id 0x03723093 \
++ -expected-id 0x03722093 \
++ -expected-id 0x0373c093 \
++ -expected-id 0x03728093 \
++ -expected-id 0x0373B093 \
++ -expected-id 0x03732093 \
+ -expected-id 0x03727093 \
++ -expected-id 0x0372C093 \
++ -expected-id 0x03731093 \
+ -expected-id 0x03736093
+
+ jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 0x4ba00477
new file mode 100644
@@ -0,0 +1,51 @@
+From ffd9638bdb04fb3021a20f78330c4692a2ebab6a Mon Sep 17 00:00:00 2001
+From: Daniel Anselmi <danselmi@gmx.ch>
+Date: Wed, 30 Nov 2022 04:05:44 +0100
+Subject: [PATCH] tcl: cpld/xilinx-xc7: remove virtex-7 devices with ir-length
+ > 6
+
+They have an ir length of 22, 24 or 38 bit and different command codes.
+
+Change-Id: I488e8613f1c4d017e1590111f60b2725ec62964b
+Signed-off-by: Daniel Anselmi <danselmi@gmx.ch>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7387
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ tcl/cpld/xilinx-xc7.cfg | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/tcl/cpld/xilinx-xc7.cfg b/tcl/cpld/xilinx-xc7.cfg
+index 22e0aea7f..91a07f9eb 100644
+--- a/tcl/cpld/xilinx-xc7.cfg
++++ b/tcl/cpld/xilinx-xc7.cfg
+@@ -33,19 +33,21 @@ jtag newtap $_CHIPNAME tap -irlen 6 -ignore-version \
+ -expected-id 0x03752093 \
+ -expected-id 0x03751093 \
+ -expected-id 0x03671093 \
+- -expected-id 0x036B3093 \
+- -expected-id 0x036B7093 \
+- -expected-id 0x036BB093 \
+- -expected-id 0x036BF093 \
+ -expected-id 0x03667093 \
+ -expected-id 0x03682093 \
+ -expected-id 0x03687093 \
+ -expected-id 0x03692093 \
+ -expected-id 0x03691093 \
+- -expected-id 0x03696093 \
+- -expected-id 0x036D5093 \
+- -expected-id 0x036D9093 \
+- -expected-id 0x036DB093
++ -expected-id 0x03696093
++
++#jtag newtap $_CHIPNAME tap -irlen 24 -ignore-version \
++# -expected-id 0x036B3093 -expected-id 0x036B7093 \
++# -expected-id 0x036BB093 -expected-id 0x036BF093 \
++# -expected-id 0x036D5093
++
++#jtag newtap $_CHIPNAME tap -irlen 22 -ignore-version -expected-id 0x036D9093
++
++#jtag newtap $_CHIPNAME tap -irlen 38 -ignore-version -expected-id 0x036DB093
+
+ pld device virtex2 $_CHIPNAME.tap 1
+
new file mode 100644
@@ -0,0 +1,36 @@
+From 0384fe5d596f42388f8b84d42959d899f29388ab Mon Sep 17 00:00:00 2001
+From: Tomas Vanek <vanekt@fbl.cz>
+Date: Tue, 4 Apr 2023 13:03:59 +0200
+Subject: [PATCH] doc: drop "resume will wait 5 seconds"
+
+Checkpatch-ignore: GIT_COMMIT_ID
+
+Waiting for running state was removed from handle_resume_command()
+in commit a92d27afb073 ("very long and bad structured commit msg
+without anything relevant to resume") around year 2008.
+Update the doc accordingly.
+
+Silent checkpatch or we have to copy 10 or more lines
+of the old commit msg.
+
+Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
+Change-Id: I3296cb2c29cf80aeed63eddd8fbf352edec778c1
+Reviewed-on: https://review.openocd.org/c/openocd/+/7579
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ doc/openocd.texi | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index 67661845d..fe72cf5fa 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -8780,7 +8780,6 @@ power consumption (because the CPU is needlessly clocked).
+ @deffn {Command} {resume} [address]
+ Resume the target at its current code position,
+ or the optional @var{address} if it is provided.
+-OpenOCD will wait 5 seconds for the target to resume.
+ @end deffn
+
+ @deffn {Command} {step} [address]
new file mode 100644
@@ -0,0 +1,2250 @@
+From 8d1dcf293a0cee71b264787c65749de3f6c4d8bc Mon Sep 17 00:00:00 2001
+From: Erhan Kurubas <erhan.kurubas@espressif.com>
+Date: Thu, 25 Aug 2022 15:38:34 +0300
+Subject: [PATCH] target/espressif: add application tracing functionality over
+ JTAG
+
+This feature allows to transfer arbitrary data between host and
+ESP32 via JTAG.
+
+The main use cases:
+
+1- Collecting application specific data
+2- Lightweight logging to the host
+3- System behaviour analysis with SEGGER SystemView
+4- Source code coverage
+
+Signed-off-by: Erhan Kurubas <erhan.kurubas@espressif.com>
+Change-Id: I95dee00ac22891fa326915a3fcac3c088cbb2afc
+Reviewed-on: https://review.openocd.org/c/openocd/+/7163
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ doc/openocd.texi | 40 +
+ src/target/espressif/Makefile.am | 4 +
+ src/target/espressif/esp32.c | 5 +
+ src/target/espressif/esp32_apptrace.c | 1376 ++++++++++++++++++++
+ src/target/espressif/esp32_apptrace.h | 126 ++
+ src/target/espressif/esp32s2.c | 5 +
+ src/target/espressif/esp32s3.c | 5 +
+ src/target/espressif/esp_xtensa.c | 2 +
+ src/target/espressif/esp_xtensa.h | 2 +
+ src/target/espressif/esp_xtensa_apptrace.c | 497 +++++++
+ src/target/espressif/esp_xtensa_apptrace.h | 37 +
+ 11 files changed, 2099 insertions(+)
+ create mode 100644 src/target/espressif/esp32_apptrace.c
+ create mode 100644 src/target/espressif/esp32_apptrace.h
+ create mode 100644 src/target/espressif/esp_xtensa_apptrace.c
+ create mode 100644 src/target/espressif/esp_xtensa_apptrace.h
+
+diff --git a/doc/openocd.texi b/doc/openocd.texi
+index fe72cf5fa..4154e56b5 100644
+--- a/doc/openocd.texi
++++ b/doc/openocd.texi
+@@ -11137,6 +11137,46 @@ Stop current trace as started by the tracestart command.
+ Dump trace memory to a file.
+ @end deffn
+
++@section Espressif Specific Commands
++
++@deffn {Command} {esp apptrace} (start <destination> [<poll_period> [<trace_size> [<stop_tmo> [<wait4halt> [<skip_size>]]]]])
++Starts
++@uref{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#application-level-tracing-library, application level tracing}.
++Data will be stored to specified destination. Available destinations are:
++@itemize @bullet
++@item @code{file://<outfile>} - Save trace logs into file.
++@item @code{tcp://<host>:<port>} - Send trace logs to tcp port on specified host. OpenOCD will act as a tcp client.
++@item @code{con:} - Print trace logs to the stdout.
++@end itemize
++Other parameters will be same for each destination.
++@itemize @bullet
++@item @code{poll_period} - trace data polling period in ms.
++@item @code{trace_size} - maximum trace data size.
++Tracing will be stopped automatically when that amount is reached.
++Use "-1" to disable the limitation.
++@item @code{stop_tmo} - Data reception timeout in ms.
++Tracing will be stopped automatically when no data is received within that period.
++@item @code{wait4halt} - if non-zero then wait for target to be halted before tracing start.
++@item @code{skip_size} - amount of tracing data to be skipped before writing it to destination.
++@end itemize
++@end deffn
++
++@deffn {Command} {esp apptrace} (stop)
++Stops tracing started with above command.
++@end deffn
++
++@deffn {Command} {esp apptrace} (status)
++Requests ongoing tracing status.
++@end deffn
++
++@deffn {Command} {esp apptrace} (dump file://<outfile>)
++Dumps tracing data from target buffer. It can be useful to dump the latest data
++buffered on target for post-mortem analysis. For example when target starts tracing automatically
++w/o OpenOCD command and keeps only the latest data window which fit into the buffer.
++@uref{https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/app_trace.html#application-level-tracing-library, application level tracing}.
++Data will be stored to specified destination.
++@end deffn
++
+ @anchor{softwaredebugmessagesandtracing}
+ @section Software Debug Messages and Tracing
+ @cindex Linux-ARM DCC support
+diff --git a/src/target/espressif/Makefile.am b/src/target/espressif/Makefile.am
+index 8367a3881..c1759ed77 100644
+--- a/src/target/espressif/Makefile.am
++++ b/src/target/espressif/Makefile.am
+@@ -8,6 +8,10 @@ noinst_LTLIBRARIES += %D%/libespressif.la
+ %D%/esp_xtensa_smp.h \
+ %D%/esp_xtensa_semihosting.c \
+ %D%/esp_xtensa_semihosting.h \
++ %D%/esp_xtensa_apptrace.c \
++ %D%/esp_xtensa_apptrace.h \
++ %D%/esp32_apptrace.c \
++ %D%/esp32_apptrace.h \
+ %D%/esp32.c \
+ %D%/esp32s2.c \
+ %D%/esp32s3.c \
+diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c
+index 63055cf18..74bbe50bd 100644
+--- a/src/target/espressif/esp32.c
++++ b/src/target/espressif/esp32.c
+@@ -440,6 +440,11 @@ static const struct command_registration esp32_command_handlers[] = {
+ {
+ .chain = esp_xtensa_smp_command_handlers,
+ },
++ {
++ .name = "esp",
++ .usage = "",
++ .chain = esp32_apptrace_command_handlers,
++ },
+ {
+ .name = "esp32",
+ .usage = "",
+diff --git a/src/target/espressif/esp32_apptrace.c b/src/target/espressif/esp32_apptrace.c
+new file mode 100644
+index 000000000..dfeb79401
+--- /dev/null
++++ b/src/target/espressif/esp32_apptrace.c
+@@ -0,0 +1,1376 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++/***************************************************************************
++ * ESP32xx application tracing module for OpenOCD *
++ * Copyright (C) 2017 Espressif Systems Ltd. *
++ ***************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#ifdef HAVE_ARPA_INET_H
++#include <arpa/inet.h>
++#endif
++
++#ifdef HAVE_NETDB_H
++#include <netdb.h>
++#endif
++
++#ifndef _WIN32
++#include <netinet/tcp.h>
++#include <sys/ioctl.h>
++#endif
++
++#include <helper/list.h>
++#include <helper/time_support.h>
++#include <target/target.h>
++#include <target/target_type.h>
++#include <target/smp.h>
++#include <server/server.h>
++#include "esp_xtensa.h"
++#include "esp_xtensa_smp.h"
++#include "esp_xtensa_apptrace.h"
++#include "esp32_apptrace.h"
++
++#define ESP32_APPTRACE_USER_BLOCK_CORE(_v_) ((_v_) >> 15)
++#define ESP32_APPTRACE_USER_BLOCK_LEN(_v_) ((_v_) & ~BIT(15))
++
++#define ESP32_APPTRACE_USER_BLOCK_HDR_SZ 4
++
++#define ESP_APPTRACE_CMD_MODE_GEN 0
++#define ESP_APPTRACE_CMD_MODE_SYSVIEW 1
++#define ESP_APPTRACE_CMD_MODE_SYSVIEW_MCORE 2
++#define ESP_APPTRACE_CMD_MODE_SYNC 3
++
++#define ESP32_APPTRACE_TGT_STATE_TMO 5000
++#define ESP_APPTRACE_BLOCKS_POOL_SZ 10
++
++struct esp32_apptrace_dest_file_data {
++ int fout;
++};
++
++struct esp32_apptrace_dest_tcp_data {
++ int sockfd;
++};
++
++struct esp32_apptrace_target_state {
++ int running;
++ uint32_t block_id;
++ uint32_t data_len;
++};
++
++struct esp_apptrace_target2host_hdr {
++ uint16_t block_sz;
++ uint16_t wr_sz;
++};
++#define APPTRACE_BLOCK_SIZE_OFFSET 0
++#define APPTRACE_WR_SIZE_OFFSET 2
++
++struct esp32_apptrace_block {
++ struct list_head node;
++ uint8_t *data;
++ uint32_t data_len;
++};
++
++static int esp32_apptrace_data_processor(void *priv);
++static int esp32_apptrace_get_data_info(struct esp32_apptrace_cmd_ctx *ctx,
++ struct esp32_apptrace_target_state *target_state,
++ uint32_t *fired_target_num);
++static int esp32_apptrace_safe_halt_targets(struct esp32_apptrace_cmd_ctx *ctx,
++ struct esp32_apptrace_target_state *targets);
++static struct esp32_apptrace_block *esp32_apptrace_free_block_get(struct esp32_apptrace_cmd_ctx *ctx);
++static int esp32_apptrace_handle_trace_block(struct esp32_apptrace_cmd_ctx *ctx,
++ struct esp32_apptrace_block *block);
++
++static const bool s_time_stats_enable = true;
++
++/*********************************************************************
++* Trace destination API
++**********************************************************************/
++
++static int esp32_apptrace_file_dest_write(void *priv, uint8_t *data, int size)
++{
++ struct esp32_apptrace_dest_file_data *dest_data = (struct esp32_apptrace_dest_file_data *)priv;
++
++ int wr_sz = write(dest_data->fout, data, size);
++ if (wr_sz != size) {
++ LOG_ERROR("Failed to write %d bytes to out file (%d)! Written %d.", size, errno, wr_sz);
++ return ERROR_FAIL;
++ }
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_file_dest_cleanup(void *priv)
++{
++ struct esp32_apptrace_dest_file_data *dest_data = (struct esp32_apptrace_dest_file_data *)priv;
++
++ if (dest_data->fout > 0)
++ close(dest_data->fout);
++ free(dest_data);
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_file_dest_init(struct esp32_apptrace_dest *dest, const char *dest_name)
++{
++ struct esp32_apptrace_dest_file_data *dest_data = calloc(1, sizeof(*dest_data));
++ if (!dest_data) {
++ LOG_ERROR("Failed to alloc mem for file dest!");
++ return ERROR_FAIL;
++ }
++
++ LOG_INFO("Open file %s", dest_name);
++ dest_data->fout = open(dest_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
++ if (dest_data->fout <= 0) {
++ LOG_ERROR("Failed to open file %s", dest_name);
++ free(dest_data);
++ return ERROR_FAIL;
++ }
++
++ dest->priv = dest_data;
++ dest->write = esp32_apptrace_file_dest_write;
++ dest->clean = esp32_apptrace_file_dest_cleanup;
++ dest->log_progress = true;
++
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_console_dest_write(void *priv, uint8_t *data, int size)
++{
++ LOG_USER_N("%.*s", size, data);
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_console_dest_cleanup(void *priv)
++{
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_console_dest_init(struct esp32_apptrace_dest *dest, const char *dest_name)
++{
++ dest->priv = NULL;
++ dest->write = esp32_apptrace_console_dest_write;
++ dest->clean = esp32_apptrace_console_dest_cleanup;
++ dest->log_progress = false;
++
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_tcp_dest_write(void *priv, uint8_t *data, int size)
++{
++ struct esp32_apptrace_dest_tcp_data *dest_data = (struct esp32_apptrace_dest_tcp_data *)priv;
++ int wr_sz = write_socket(dest_data->sockfd, data, size);
++ if (wr_sz != size) {
++ LOG_ERROR("Failed to write %u bytes to out socket (%d)! Written %d.", size, errno, wr_sz);
++ return ERROR_FAIL;
++ }
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_tcp_dest_cleanup(void *priv)
++{
++ struct esp32_apptrace_dest_tcp_data *dest_data = (struct esp32_apptrace_dest_tcp_data *)priv;
++
++ if (dest_data->sockfd > 0)
++ close_socket(dest_data->sockfd);
++ free(dest_data);
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_tcp_dest_init(struct esp32_apptrace_dest *dest, const char *dest_name)
++{
++ const char *port_sep = strchr(dest_name, ':');
++ /* separator not found, or was the first or the last character */
++ if (!port_sep || port_sep == dest_name || port_sep == dest_name + strlen(dest_name) - 1) {
++ LOG_ERROR("apptrace: Invalid connection URI, format should be tcp://host:port");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
++ size_t hostname_len = port_sep - dest_name;
++
++ char hostname[64] = { 0 };
++ if (hostname_len >= sizeof(hostname)) {
++ LOG_ERROR("apptrace: Hostname too long");
++ return ERROR_COMMAND_ARGUMENT_INVALID;
++ }
++ memcpy(hostname, dest_name, hostname_len);
++
++ const char *port_str = port_sep + 1;
++ struct addrinfo *ai;
++ int flags = 0;
++#ifdef AI_NUMERICSERV
++ flags |= AI_NUMERICSERV;
++#endif /* AI_NUMERICSERV */
++ struct addrinfo hint = {
++ .ai_family = AF_UNSPEC,
++ .ai_socktype = SOCK_STREAM,
++ .ai_protocol = 0,
++ .ai_flags = flags
++ };
++ int res = getaddrinfo(hostname, port_str, &hint, &ai);
++ if (res != 0) {
++ LOG_ERROR("apptrace: Failed to resolve host name: %s", hostname);
++ return ERROR_FAIL;
++ }
++ int sockfd = -1;
++ for (struct addrinfo *ai_it = ai; ai_it; ai_it = ai_it->ai_next) {
++ sockfd = socket(ai_it->ai_family, ai_it->ai_socktype, ai_it->ai_protocol);
++ if (sockfd < 0) {
++ LOG_DEBUG("apptrace: Failed to create socket (%d, %d, %d) (%s)",
++ ai_it->ai_family,
++ ai_it->ai_socktype,
++ ai_it->ai_protocol,
++ strerror(errno));
++ continue;
++ }
++
++ char cur_hostname[NI_MAXHOST];
++ char cur_portname[NI_MAXSERV];
++ res =
++ getnameinfo(ai_it->ai_addr, ai_it->ai_addrlen, cur_hostname,
++ sizeof(cur_hostname),
++ cur_portname, sizeof(cur_portname),
++ NI_NUMERICHOST | NI_NUMERICSERV);
++ if (res != 0)
++ continue;
++
++ LOG_INFO("apptrace: Trying to connect to %s:%s", cur_hostname, cur_portname);
++ if (connect(sockfd, ai_it->ai_addr, ai_it->ai_addrlen) < 0) {
++ close_socket(sockfd);
++ sockfd = -1;
++ LOG_WARNING("apptrace: Connection failed (%s)", strerror(errno));
++ continue;
++ }
++ break;
++ }
++ freeaddrinfo(ai);
++ if (sockfd < 0) {
++ LOG_ERROR("apptrace: Could not connect to %s:%s", hostname, port_str);
++ return ERROR_FAIL;
++ }
++ LOG_INFO("apptrace: Connected!");
++
++ struct esp32_apptrace_dest_tcp_data *dest_data = calloc(1, sizeof(struct esp32_apptrace_dest_tcp_data));
++ if (!dest_data) {
++ LOG_ERROR("apptrace: Failed to alloc mem for tcp dest!");
++ close_socket(sockfd);
++ return ERROR_FAIL;
++ }
++
++ dest_data->sockfd = sockfd;
++ dest->priv = dest_data;
++ dest->write = esp32_apptrace_tcp_dest_write;
++ dest->clean = esp32_apptrace_tcp_dest_cleanup;
++ dest->log_progress = true;
++
++ return ERROR_OK;
++}
++
++int esp32_apptrace_dest_init(struct esp32_apptrace_dest dest[], const char *dest_paths[], unsigned int max_dests)
++{
++ int res;
++ unsigned int i;
++
++ for (i = 0; i < max_dests; i++) {
++ if (strncmp(dest_paths[i], "file://", 7) == 0)
++ res = esp32_apptrace_file_dest_init(&dest[i], &dest_paths[i][7]);
++ else if (strncmp(dest_paths[i], "con:", 4) == 0)
++ res = esp32_apptrace_console_dest_init(&dest[i], NULL);
++ else if (strncmp(dest_paths[i], "tcp://", 6) == 0)
++ res = esp32_apptrace_tcp_dest_init(&dest[i], &dest_paths[i][6]);
++ else
++ break;
++
++ if (res != ERROR_OK) {
++ LOG_ERROR("apptrace: Failed to init trace data destination '%s'!", dest_paths[i]);
++ return 0;
++ }
++ }
++
++ return i;
++}
++
++int esp32_apptrace_dest_cleanup(struct esp32_apptrace_dest dest[], unsigned int max_dests)
++{
++ for (unsigned int i = 0; i < max_dests; i++) {
++ if (dest[i].clean && dest[i].priv) {
++ int res = dest[i].clean(dest[i].priv);
++ dest[i].priv = NULL;
++ return res;
++ }
++ }
++ return ERROR_OK;
++}
++
++/*********************************************************************
++* Trace data blocks management API
++**********************************************************************/
++static void esp32_apptrace_blocks_pool_cleanup(struct esp32_apptrace_cmd_ctx *ctx)
++{
++ struct esp32_apptrace_block *cur;
++ struct list_head *head = &ctx->free_trace_blocks;
++ struct list_head *tmp, *pos;
++
++ list_for_each_safe(pos, tmp, head) {
++ cur = list_entry(pos, struct esp32_apptrace_block, node);
++ if (cur) {
++ list_del(&cur->node);
++ free(cur->data);
++ free(cur);
++ }
++ }
++
++ head = &ctx->ready_trace_blocks;
++
++ list_for_each_safe(pos, tmp, head) {
++ cur = list_entry(pos, struct esp32_apptrace_block, node);
++ if (cur) {
++ list_del(&cur->node);
++ free(cur->data);
++ free(cur);
++ }
++ }
++}
++
++struct esp32_apptrace_block *esp32_apptrace_free_block_get(struct esp32_apptrace_cmd_ctx *ctx)
++{
++ struct esp32_apptrace_block *block = NULL;
++
++ if (!list_empty(&ctx->free_trace_blocks)) {
++ /*get first */
++ block = list_first_entry(&ctx->free_trace_blocks, struct esp32_apptrace_block, node);
++ list_del(&block->node);
++ }
++
++ return block;
++}
++
++static int esp32_apptrace_ready_block_put(struct esp32_apptrace_cmd_ctx *ctx, struct esp32_apptrace_block *block)
++{
++ LOG_DEBUG("esp32_apptrace_ready_block_put");
++ /* add to ready blocks list */
++ INIT_LIST_HEAD(&block->node);
++ list_add(&block->node, &ctx->ready_trace_blocks);
++
++ return ERROR_OK;
++}
++
++static struct esp32_apptrace_block *esp32_apptrace_ready_block_get(struct esp32_apptrace_cmd_ctx *ctx)
++{
++ struct esp32_apptrace_block *block = NULL;
++
++ if (!list_empty(&ctx->ready_trace_blocks)) {
++ struct list_head *head = &ctx->ready_trace_blocks;
++ struct list_head *tmp, *pos;
++
++ list_for_each_safe(pos, tmp, head) {
++ block = list_entry(pos, struct esp32_apptrace_block, node);
++ }
++ /* remove it from ready list */
++ list_del(&block->node);
++ }
++
++ return block;
++}
++
++static int esp32_apptrace_block_free(struct esp32_apptrace_cmd_ctx *ctx, struct esp32_apptrace_block *block)
++{
++ /* add to free blocks list */
++ INIT_LIST_HEAD(&block->node);
++ list_add(&block->node, &ctx->free_trace_blocks);
++
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_wait_tracing_finished(struct esp32_apptrace_cmd_ctx *ctx)
++{
++ int64_t timeout = timeval_ms() + (LOG_LEVEL_IS(LOG_LVL_DEBUG) ? 70000 : 5000);
++ while (!list_empty(&ctx->ready_trace_blocks)) {
++ alive_sleep(100);
++ if (timeval_ms() >= timeout) {
++ LOG_ERROR("Failed to wait for pended trace blocks!");
++ return ERROR_FAIL;
++ }
++ }
++ /* signal timer callback to stop */
++ ctx->running = 0;
++ target_unregister_timer_callback(esp32_apptrace_data_processor, ctx);
++ return ERROR_OK;
++}
++
++/*********************************************************************
++* Trace commands
++**********************************************************************/
++
++int esp32_apptrace_cmd_ctx_init(struct esp32_apptrace_cmd_ctx *cmd_ctx, struct command_invocation *cmd, int mode)
++{
++ struct target *target = get_current_target(CMD_CTX);
++
++ memset(cmd_ctx, 0, sizeof(struct esp32_apptrace_cmd_ctx));
++ cmd_ctx->target = target;
++ cmd_ctx->mode = mode;
++ cmd_ctx->target_state = target->state;
++ cmd_ctx->cmd = cmd;
++
++ if (target->smp) {
++ struct target_list *head;
++ struct target *curr;
++ unsigned int i = 0;
++ cmd_ctx->cores_num = 0;
++ foreach_smp_target(head, target->smp_targets) {
++ curr = head->target;
++ if (i == ESP32_APPTRACE_MAX_CORES_NUM) {
++ command_print(cmd, "Too many cores configured! Max %d cores are supported.",
++ ESP32_APPTRACE_MAX_CORES_NUM);
++ return ERROR_FAIL;
++ }
++ if (!target_was_examined(curr))
++ continue;
++ cmd_ctx->cores_num++;
++ cmd_ctx->cpus[i++] = curr;
++ }
++ } else {
++ cmd_ctx->cores_num = 1;
++ cmd_ctx->cpus[0] = target;
++ }
++ /* some relies on ESP32_APPTRACE_MAX_CORES_NUM
++ * TODO: remove that dependency */
++ assert(cmd_ctx->cores_num <= ESP32_APPTRACE_MAX_CORES_NUM && "Too many cores number!");
++
++ struct xtensa *xtensa = target->arch_info;
++ if (xtensa->common_magic == XTENSA_COMMON_MAGIC) {
++ cmd_ctx->hw = target_to_esp_xtensa(target)->apptrace.hw;
++ } else { /* TODO: riscv is not supported yet */
++ command_print(cmd, "Unsupported target arch 0x%X", xtensa->common_magic);
++ return ERROR_FAIL;
++ }
++
++ cmd_ctx->max_trace_block_sz = cmd_ctx->hw->max_block_size_get(cmd_ctx->cpus[0]);
++ if (cmd_ctx->max_trace_block_sz == 0) {
++ command_print(cmd, "Failed to get max trace block size!");
++ return ERROR_FAIL;
++ }
++ LOG_INFO("Total trace memory: %" PRIu32 " bytes", cmd_ctx->max_trace_block_sz);
++
++ INIT_LIST_HEAD(&cmd_ctx->ready_trace_blocks);
++ INIT_LIST_HEAD(&cmd_ctx->free_trace_blocks);
++ for (unsigned int i = 0; i < ESP_APPTRACE_BLOCKS_POOL_SZ; i++) {
++ struct esp32_apptrace_block *block = calloc(1, sizeof(struct esp32_apptrace_block));
++ if (!block) {
++ command_print(cmd, "Failed to alloc trace buffer entry!");
++ esp32_apptrace_blocks_pool_cleanup(cmd_ctx);
++ return ERROR_FAIL;
++ }
++ block->data = malloc(cmd_ctx->max_trace_block_sz);
++ if (!block->data) {
++ free(block);
++ command_print(cmd, "Failed to alloc trace buffer %" PRIu32 " bytes!", cmd_ctx->max_trace_block_sz);
++ esp32_apptrace_blocks_pool_cleanup(cmd_ctx);
++ return ERROR_FAIL;
++ }
++ INIT_LIST_HEAD(&block->node);
++ list_add(&block->node, &cmd_ctx->free_trace_blocks);
++ }
++
++ cmd_ctx->running = 1;
++ if (cmd_ctx->mode != ESP_APPTRACE_CMD_MODE_SYNC) {
++ int res = target_register_timer_callback(esp32_apptrace_data_processor,
++ 0,
++ TARGET_TIMER_TYPE_PERIODIC,
++ cmd_ctx);
++ if (res != ERROR_OK) {
++ command_print(cmd, "Failed to start trace data timer callback (%d)!", res);
++ esp32_apptrace_blocks_pool_cleanup(cmd_ctx);
++ return ERROR_FAIL;
++ }
++ }
++
++ if (s_time_stats_enable) {
++ cmd_ctx->stats.min_blk_read_time = 1000000.0;
++ cmd_ctx->stats.min_blk_proc_time = 1000000.0;
++ }
++ if (duration_start(&cmd_ctx->idle_time) != 0) {
++ command_print(cmd, "Failed to start idle time measurement!");
++ esp32_apptrace_cmd_ctx_cleanup(cmd_ctx);
++ return ERROR_FAIL;
++ }
++
++ return ERROR_OK;
++}
++
++int esp32_apptrace_cmd_ctx_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx)
++{
++ esp32_apptrace_blocks_pool_cleanup(cmd_ctx);
++ return ERROR_OK;
++}
++
++#define ESP32_APPTRACE_CMD_NUM_ARG_CHECK(_cmd_, _arg_, _start_, _end_) \
++ do { \
++ if ((_arg_) == 0 && (_start_) == (_end_)) { \
++ command_print(_cmd_, "Invalid '" # _arg_ "' arg!"); \
++ return; \
++ } \
++ } while (0)
++
++void esp32_apptrace_cmd_args_parse(struct esp32_apptrace_cmd_ctx *cmd_ctx,
++ struct esp32_apptrace_cmd_data *cmd_data,
++ const char **argv,
++ int argc)
++{
++ char *end;
++
++ cmd_data->poll_period = strtoul(argv[0], &end, 10);
++ ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx->cmd, cmd_data->poll_period, argv[0], end);
++ if (argc > 1) {
++ cmd_data->max_len = strtoul(argv[1], &end, 10);
++ ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx->cmd, cmd_data->max_len, argv[1], end);
++ if (argc > 2) {
++ int32_t tmo = strtol(argv[2], &end, 10);
++ ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx->cmd, tmo, argv[2], end);
++ cmd_ctx->stop_tmo = 1.0 * tmo;
++ if (argc > 3) {
++ cmd_data->wait4halt = strtoul(argv[3], &end, 10);
++ ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx->cmd, cmd_data->wait4halt, argv[3], end);
++ if (argc > 4) {
++ cmd_data->skip_len = strtoul(argv[4], &end, 10);
++ ESP32_APPTRACE_CMD_NUM_ARG_CHECK(cmd_ctx->cmd, cmd_data->skip_len, argv[4], end);
++ }
++ }
++ }
++ }
++}
++
++static int esp32_apptrace_core_id_get(struct target *target, uint8_t *hdr_buf)
++{
++ return ESP32_APPTRACE_USER_BLOCK_CORE(target_buffer_get_u16(target, hdr_buf + APPTRACE_BLOCK_SIZE_OFFSET));
++}
++
++static uint32_t esp32_apptrace_usr_block_len_get(struct target *target, uint8_t *hdr_buf, uint32_t *wr_len)
++{
++ *wr_len = ESP32_APPTRACE_USER_BLOCK_LEN(target_buffer_get_u16(target, hdr_buf + APPTRACE_WR_SIZE_OFFSET));
++ return ESP32_APPTRACE_USER_BLOCK_LEN(target_buffer_get_u16(target, hdr_buf + APPTRACE_BLOCK_SIZE_OFFSET));
++}
++
++static int esp32_apptrace_cmd_init(struct esp32_apptrace_cmd_ctx *cmd_ctx,
++ struct command_invocation *cmd,
++ int mode,
++ const char **argv,
++ int argc)
++{
++ struct esp32_apptrace_cmd_data *cmd_data;
++
++ if (argc < 1) {
++ command_print(cmd, "Not enough args! Need trace data destination!");
++ return ERROR_FAIL;
++ }
++
++ int res = esp32_apptrace_cmd_ctx_init(cmd_ctx, cmd, mode);
++ if (res != ERROR_OK)
++ return res;
++
++ cmd_data = calloc(1, sizeof(*cmd_data));
++ assert(cmd_data && "No memory for command data!");
++ cmd_ctx->cmd_priv = cmd_data;
++
++ /*outfile1 [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]] */
++ res = esp32_apptrace_dest_init(&cmd_data->data_dest, argv, 1);
++ if (res != 1) { /* only one destination needs to be initialized */
++ command_print(cmd, "Wrong args! Needs a trace data destination!");
++ free(cmd_data);
++ goto on_error;
++ }
++ cmd_ctx->stop_tmo = -1.0; /* infinite */
++ cmd_data->max_len = UINT32_MAX;
++ cmd_data->poll_period = 0 /*ms*/;
++ if (argc > 1)
++ /* parse remaining args */
++ esp32_apptrace_cmd_args_parse(cmd_ctx, cmd_data, &argv[1], argc - 1);
++
++ LOG_USER("App trace params: from %d cores, size %" PRId32 " bytes, stop_tmo %g s, poll period %" PRId32
++ " ms, wait_rst %d, skip %" PRId32 " bytes", cmd_ctx->cores_num,
++ cmd_data->max_len,
++ cmd_ctx->stop_tmo,
++ cmd_data->poll_period,
++ cmd_data->wait4halt,
++ cmd_data->skip_len);
++
++ cmd_ctx->trace_format.hdr_sz = ESP32_APPTRACE_USER_BLOCK_HDR_SZ;
++ cmd_ctx->trace_format.core_id_get = esp32_apptrace_core_id_get;
++ cmd_ctx->trace_format.usr_block_len_get = esp32_apptrace_usr_block_len_get;
++ return ERROR_OK;
++on_error:
++ command_print(cmd, "Not enough args! Need %d trace data destinations!", cmd_ctx->cores_num);
++ cmd_ctx->running = 0;
++ esp32_apptrace_cmd_ctx_cleanup(cmd_ctx);
++ return res;
++}
++
++static int esp32_apptrace_cmd_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx)
++{
++ struct esp32_apptrace_cmd_data *cmd_data = cmd_ctx->cmd_priv;
++
++ esp32_apptrace_dest_cleanup(&cmd_data->data_dest, 1);
++ free(cmd_data);
++ cmd_ctx->cmd_priv = NULL;
++ esp32_apptrace_cmd_ctx_cleanup(cmd_ctx);
++ return ERROR_OK;
++}
++
++static void esp32_apptrace_print_stats(struct esp32_apptrace_cmd_ctx *ctx)
++{
++ struct esp32_apptrace_cmd_data *cmd_data = ctx->cmd_priv;
++ uint32_t trace_sz = 0;
++
++ if (cmd_data)
++ trace_sz = ctx->tot_len > cmd_data->skip_len ? ctx->tot_len - cmd_data->skip_len : 0;
++ LOG_USER("Tracing is %s. Size is %" PRId32 " of %" PRId32 " @ %f (%f) KiB/s",
++ !ctx->running ? "STOPPED" : "RUNNING",
++ trace_sz,
++ cmd_data ? cmd_data->max_len : 0,
++ duration_kbps(&ctx->read_time, ctx->tot_len),
++ duration_kbps(&ctx->read_time, ctx->raw_tot_len));
++ LOG_USER("Data: blocks incomplete %" PRId32 ", lost bytes: %" PRId32,
++ ctx->stats.incompl_blocks,
++ ctx->stats.lost_bytes);
++ if (s_time_stats_enable) {
++ LOG_USER("Block read time [%f..%f] ms",
++ 1000 * ctx->stats.min_blk_read_time,
++ 1000 * ctx->stats.max_blk_read_time);
++ LOG_USER("Block proc time [%f..%f] ms",
++ 1000 * ctx->stats.min_blk_proc_time,
++ 1000 * ctx->stats.max_blk_proc_time);
++ }
++}
++
++static int esp32_apptrace_wait4halt(struct esp32_apptrace_cmd_ctx *ctx, struct target *target)
++{
++ LOG_USER("Wait for halt...");
++ while (!openocd_is_shutdown_pending()) {
++ int res = target_poll(target);
++ if (res != ERROR_OK)
++ return res;
++ if (target->state == TARGET_HALTED) {
++ LOG_USER("%s: HALTED", target->cmd_name);
++ break;
++ }
++ alive_sleep(500);
++ }
++ return ERROR_OK;
++}
++
++int esp32_apptrace_safe_halt_targets(struct esp32_apptrace_cmd_ctx *ctx,
++ struct esp32_apptrace_target_state *targets)
++{
++ int res = ERROR_OK;
++
++ memset(targets, 0, ctx->cores_num * sizeof(struct esp32_apptrace_target_state));
++ /* halt all CPUs */
++ LOG_DEBUG("Halt all targets!");
++ for (unsigned int k = 0; k < ctx->cores_num; k++) {
++ if (!target_was_examined(ctx->cpus[k]))
++ continue;
++ if (ctx->cpus[k]->state == TARGET_HALTED)
++ continue;
++ res = target_halt(ctx->cpus[k]);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to halt target (%d)!", res);
++ return res;
++ }
++ res = target_wait_state(ctx->cpus[k], TARGET_HALTED, ESP32_APPTRACE_TGT_STATE_TMO);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to wait halt target %s / %d (%d)!",
++ target_name(ctx->cpus[k]),
++ ctx->cpus[k]->state,
++ res);
++ return res;
++ }
++ }
++ /* read current block statuses from CPUs */
++ LOG_DEBUG("Read current block statuses");
++ for (unsigned int k = 0; k < ctx->cores_num; k++) {
++ uint32_t stat;
++ res = ctx->hw->status_reg_read(ctx->cpus[k], &stat);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to read trace status (%d)!", res);
++ return res;
++ }
++ /* check if some CPU stopped inside tracing regs update critical section */
++ if (stat) {
++ if (ctx->hw->leave_trace_crit_section_start) {
++ res = ctx->hw->leave_trace_crit_section_start(ctx->cpus[k]);
++ if (res != ERROR_OK)
++ return res;
++ }
++ uint32_t bp_addr = stat;
++ res = breakpoint_add(ctx->cpus[k], bp_addr, 1, BKPT_HARD);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to set breakpoint (%d)!", res);
++ return res;
++ }
++ while (stat) {
++ /* allow this CPU to leave ERI write critical section */
++ res = target_resume(ctx->cpus[k], 1, 0, 1, 0);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to resume target (%d)!", res);
++ breakpoint_remove(ctx->cpus[k], bp_addr);
++ return res;
++ }
++ /* wait for CPU to be halted on BP */
++ enum target_debug_reason debug_reason = DBG_REASON_UNDEFINED;
++ while (debug_reason != DBG_REASON_BREAKPOINT) {
++ res = target_wait_state(ctx->cpus[k], TARGET_HALTED,
++ ESP32_APPTRACE_TGT_STATE_TMO);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to wait halt on bp (%d)!", res);
++ breakpoint_remove(ctx->cpus[k], bp_addr);
++ return res;
++ }
++ debug_reason = ctx->cpus[k]->debug_reason;
++ }
++ res = ctx->hw->status_reg_read(ctx->cpus[k], &stat);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to read trace status (%d)!", res);
++ breakpoint_remove(ctx->cpus[k], bp_addr);
++ return res;
++ }
++ }
++ breakpoint_remove(ctx->cpus[k], bp_addr);
++ if (ctx->hw->leave_trace_crit_section_stop) {
++ res = ctx->hw->leave_trace_crit_section_stop(ctx->cpus[k]);
++ if (res != ERROR_OK)
++ return res;
++ }
++ }
++ res = ctx->hw->data_len_read(ctx->cpus[k], &targets[k].block_id, &targets[k].data_len);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to read trace status (%d)!", res);
++ return res;
++ }
++ }
++
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_connect_targets(struct esp32_apptrace_cmd_ctx *ctx,
++ bool conn,
++ bool resume_target)
++{
++ struct esp32_apptrace_target_state target_to_connect[ESP32_APPTRACE_MAX_CORES_NUM];
++
++ if (conn)
++ LOG_USER("Connect targets...");
++ else
++ LOG_USER("Disconnect targets...");
++
++ int res = esp32_apptrace_safe_halt_targets(ctx, target_to_connect);
++ if (res != ERROR_OK) {
++ command_print(ctx->cmd, "Failed to halt targets (%d)!", res);
++ return res;
++ }
++ if (ctx->cores_num > 1) {
++ /* set block ids to the highest value */
++ uint32_t max_id = 0;
++ for (unsigned int k = 0; k < ctx->cores_num; k++) {
++ if (target_to_connect[k].block_id > max_id)
++ max_id = target_to_connect[k].block_id;
++ }
++ for (unsigned int k = 0; k < ctx->cores_num; k++)
++ target_to_connect[k].block_id = max_id;
++ }
++ for (unsigned int k = 0; k < ctx->cores_num; k++) {
++ /* update host connected status */
++ res = ctx->hw->ctrl_reg_write(ctx->cpus[k],
++ target_to_connect[k].block_id,
++ 0 /*ack target data*/,
++ conn,
++ false /*no host data*/);
++ if (res != ERROR_OK) {
++ command_print(ctx->cmd, "Failed to read trace status (%d)!", res);
++ return res;
++ }
++ }
++ if (resume_target) {
++ LOG_DEBUG("Resume targets");
++ bool smp_resumed = false;
++ for (unsigned int k = 0; k < ctx->cores_num; k++) {
++ if (smp_resumed && ctx->cpus[k]->smp) {
++ /* in SMP mode we need to call target_resume for one core only */
++ continue;
++ }
++ res = target_resume(ctx->cpus[k], 1, 0, 1, 0);
++ if (res != ERROR_OK) {
++ command_print(ctx->cmd, "Failed to resume target (%d)!", res);
++ return res;
++ }
++ if (ctx->cpus[k]->smp)
++ smp_resumed = true;
++ }
++ }
++ if (conn)
++ LOG_INFO("Targets connected.");
++ else
++ LOG_INFO("Targets disconnected.");
++ return ERROR_OK;
++}
++
++int esp_apptrace_usr_block_write(const struct esp32_apptrace_hw *hw, struct target *target,
++ uint32_t block_id,
++ const uint8_t *data,
++ uint32_t size)
++{
++ struct esp_apptrace_host2target_hdr hdr = { .block_sz = size };
++ uint32_t buf_sz[2] = { sizeof(hdr), size };
++ const uint8_t *bufs[2] = { (const uint8_t *)&hdr, data };
++
++ if (size > hw->usr_block_max_size_get(target)) {
++ LOG_ERROR("Too large user block %" PRId32, size);
++ return ERROR_FAIL;
++ }
++
++ return hw->buffs_write(target,
++ ARRAY_SIZE(buf_sz),
++ buf_sz,
++ bufs,
++ block_id,
++ true /*ack target data*/,
++ true /*host data*/);
++}
++
++static uint32_t esp32_apptrace_usr_block_check(struct esp32_apptrace_cmd_ctx *ctx, uint8_t *hdr_buf)
++{
++ uint32_t wr_len = 0;
++ uint32_t usr_len = ctx->trace_format.usr_block_len_get(ctx->target, hdr_buf, &wr_len);
++ if (usr_len != wr_len) {
++ LOG_ERROR("Incomplete block sz %" PRId32 ", wr %" PRId32, usr_len, wr_len);
++ ctx->stats.incompl_blocks++;
++ ctx->stats.lost_bytes += usr_len - wr_len;
++ }
++ return usr_len;
++}
++
++int esp32_apptrace_get_data_info(struct esp32_apptrace_cmd_ctx *ctx,
++ struct esp32_apptrace_target_state *target_state,
++ uint32_t *fired_target_num)
++{
++ if (fired_target_num)
++ *fired_target_num = UINT32_MAX;
++
++ for (unsigned int i = 0; i < ctx->cores_num; i++) {
++ int res = ctx->hw->data_len_read(ctx->cpus[i], &target_state[i].block_id, &target_state[i].data_len);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to read data len on (%s)!", target_name(ctx->cpus[i]));
++ return res;
++ }
++ if (target_state[i].data_len) {
++ LOG_TARGET_DEBUG(ctx->cpus[i], "Block %" PRId32 ", len %" PRId32 " bytes on fired",
++ target_state[i].block_id, target_state[i].data_len);
++ if (fired_target_num)
++ *fired_target_num = i;
++ break;
++ }
++ }
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_process_data(struct esp32_apptrace_cmd_ctx *ctx,
++ unsigned int core_id,
++ uint8_t *data,
++ uint32_t data_len)
++{
++ struct esp32_apptrace_cmd_data *cmd_data = ctx->cmd_priv;
++
++ LOG_DEBUG("Got block %" PRId32 " bytes [%x %x...%x %x]", data_len, data[12], data[13],
++ data[data_len - 2], data[data_len - 1]);
++ if (ctx->tot_len + data_len > cmd_data->skip_len) {
++ uint32_t wr_idx = 0, wr_chunk_len = data_len;
++ if (ctx->tot_len < cmd_data->skip_len) {
++ wr_chunk_len = (ctx->tot_len + wr_chunk_len) - cmd_data->skip_len;
++ wr_idx = cmd_data->skip_len - ctx->tot_len;
++ }
++ if (ctx->tot_len + wr_chunk_len > cmd_data->max_len)
++ wr_chunk_len -= (ctx->tot_len + wr_chunk_len - cmd_data->skip_len) - cmd_data->max_len;
++ if (wr_chunk_len > 0) {
++ int res = cmd_data->data_dest.write(cmd_data->data_dest.priv, data + wr_idx, wr_chunk_len);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to write %" PRId32 " bytes to dest 0!", data_len);
++ return res;
++ }
++ }
++ ctx->tot_len += wr_chunk_len;
++ } else {
++ ctx->tot_len += data_len;
++ }
++
++ if (cmd_data->data_dest.log_progress)
++ LOG_USER("%" PRId32 " ", ctx->tot_len);
++ /* check for stop condition */
++ if (ctx->tot_len > cmd_data->skip_len && (ctx->tot_len - cmd_data->skip_len >= cmd_data->max_len)) {
++ ctx->running = 0;
++ if (duration_measure(&ctx->read_time) != 0) {
++ LOG_ERROR("Failed to stop trace read time measure!");
++ return ERROR_FAIL;
++ }
++ }
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_handle_trace_block(struct esp32_apptrace_cmd_ctx *ctx,
++ struct esp32_apptrace_block *block)
++{
++ uint32_t processed = 0;
++ uint32_t hdr_sz = ctx->trace_format.hdr_sz;
++
++ LOG_DEBUG("Got block %" PRId32 " bytes", block->data_len);
++ /* process user blocks one by one */
++ while (processed < block->data_len) {
++ LOG_DEBUG("Process usr block %" PRId32 "/%" PRId32, processed, block->data_len);
++ /* process user block */
++ uint32_t usr_len = esp32_apptrace_usr_block_check(ctx, block->data + processed);
++ int core_id = ctx->trace_format.core_id_get(ctx->target, block->data + processed);
++ /* process user data */
++ int res = ctx->process_data(ctx, core_id, block->data + processed + hdr_sz, usr_len);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to process %" PRId32 " bytes!", usr_len);
++ return res;
++ }
++ processed += usr_len + hdr_sz;
++ }
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_data_processor(void *priv)
++{
++ struct esp32_apptrace_cmd_ctx *ctx = (struct esp32_apptrace_cmd_ctx *)priv;
++
++ if (!ctx->running)
++ return ERROR_OK;
++
++ struct esp32_apptrace_block *block = esp32_apptrace_ready_block_get(ctx);
++ if (!block)
++ return ERROR_OK;
++
++ int res = esp32_apptrace_handle_trace_block(ctx, block);
++ if (res != ERROR_OK) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to process trace block %" PRId32 " bytes!", block->data_len);
++ return res;
++ }
++ res = esp32_apptrace_block_free(ctx, block);
++ if (res != ERROR_OK) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to free ready block!");
++ return res;
++ }
++
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_check_connection(struct esp32_apptrace_cmd_ctx *ctx)
++{
++ if (!ctx)
++ return ERROR_FAIL;
++
++ unsigned int busy_target_num = 0;
++
++ for (unsigned int i = 0; i < ctx->cores_num; i++) {
++ bool conn = true;
++ int res = ctx->hw->ctrl_reg_read(ctx->cpus[i], NULL, NULL, &conn);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to read apptrace control reg for cpu(%d) res(%d)!", i, res);
++ return res;
++ }
++ if (!conn) {
++ uint32_t stat = 0;
++ LOG_TARGET_WARNING(ctx->cpus[i], "apptrace connection is lost. Re-connect.");
++ res = ctx->hw->status_reg_read(ctx->cpus[i], &stat);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to read trace status (%d)!", res);
++ return res;
++ }
++ if (stat) {
++ LOG_TARGET_WARNING(ctx->cpus[i], "in critical state. Retry in next poll");
++ if (++busy_target_num == ctx->cores_num) {
++ LOG_WARNING("No available core");
++ return ERROR_WAIT;
++ }
++ continue;
++ }
++ res = ctx->hw->ctrl_reg_write(ctx->cpus[i],
++ 0,
++ 0,
++ true /*host connected*/,
++ false /*no host data*/);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to write apptrace control reg for cpu(%d) res(%d)!", i, res);
++ return res;
++ }
++ if (ctx->stop_tmo != -1.0) {
++ /* re-start idle time measurement */
++ if (duration_start(&ctx->idle_time) != 0) {
++ LOG_ERROR("Failed to re-start idle time measure!");
++ return ERROR_FAIL;
++ }
++ }
++ }
++ }
++
++ return ERROR_OK;
++}
++
++static int esp32_apptrace_poll(void *priv)
++{
++ struct esp32_apptrace_cmd_ctx *ctx = (struct esp32_apptrace_cmd_ctx *)priv;
++ int res;
++ uint32_t fired_target_num = 0;
++ struct esp32_apptrace_target_state target_state[ESP32_APPTRACE_MAX_CORES_NUM];
++ struct duration blk_proc_time;
++
++ if (!ctx->running) {
++ if (ctx->auto_clean)
++ ctx->auto_clean(ctx);
++ return ERROR_FAIL;
++ }
++
++ /* Check for connection is alive.For some reason target and therefore host_connected flag
++ * might have been reset */
++ res = esp32_apptrace_check_connection(ctx);
++ if (res != ERROR_OK) {
++ if (res != ERROR_WAIT)
++ ctx->running = 0;
++ return res;
++ }
++
++ /* check for data from target */
++ res = esp32_apptrace_get_data_info(ctx, target_state, &fired_target_num);
++ if (res != ERROR_OK) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to read data len!");
++ return res;
++ }
++ /* LOG_DEBUG("Block %d (%d bytes) on target (%s)!", target_state[0].block_id,
++ * target_state[0].data_len, target_name(ctx->cpus[0])); */
++ if (fired_target_num == UINT32_MAX) {
++ /* no data has been received, but block could be switched due to the data transferred
++ * from host to target */
++ if (ctx->cores_num > 1) {
++ uint32_t max_block_id = 0, min_block_id = ctx->hw->max_block_id;
++ /* find maximum block ID and set the same ID in control reg for both cores
++ * */
++ for (unsigned int i = 0; i < ctx->cores_num; i++) {
++ if (max_block_id < target_state[i].block_id)
++ max_block_id = target_state[i].block_id;
++ if (min_block_id > target_state[i].block_id)
++ min_block_id = target_state[i].block_id;
++ }
++ /* handle block ID overflow */
++ if (max_block_id == ctx->hw->max_block_id && min_block_id == 0)
++ max_block_id = 0;
++ for (unsigned int i = 0; i < ctx->cores_num; i++) {
++ if (max_block_id != target_state[i].block_id) {
++ LOG_TARGET_DEBUG(ctx->cpus[i], "Ack empty block %" PRId32 "!", max_block_id);
++ res = ctx->hw->ctrl_reg_write(ctx->cpus[i],
++ max_block_id,
++ 0 /*all read*/,
++ true /*host connected*/,
++ false /*no host data*/);
++ if (res != ERROR_OK) {
++ ctx->running = 0;
++ LOG_TARGET_ERROR(ctx->cpus[i], "Failed to ack empty data block!");
++ return res;
++ }
++ }
++ }
++ ctx->last_blk_id = max_block_id;
++ }
++ if (ctx->stop_tmo != -1.0) {
++ if (duration_measure(&ctx->idle_time) != 0) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to measure idle time!");
++ return ERROR_FAIL;
++ }
++ if (duration_elapsed(&ctx->idle_time) >= ctx->stop_tmo) {
++ ctx->running = 0;
++ LOG_ERROR("Data timeout!");
++ return ERROR_FAIL;
++ }
++ }
++ return ERROR_OK;/* no data */
++ }
++ /* sanity check */
++ if (target_state[fired_target_num].data_len > ctx->max_trace_block_sz) {
++ ctx->running = 0;
++ LOG_ERROR("Too large block size %" PRId32 "!", target_state[fired_target_num].data_len);
++ return ERROR_FAIL;
++ }
++ if (ctx->tot_len == 0) {
++ if (duration_start(&ctx->read_time) != 0) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to start trace read time measurement!");
++ return ERROR_FAIL;
++ }
++ }
++ struct esp32_apptrace_block *block = esp32_apptrace_free_block_get(ctx);
++ if (!block) {
++ ctx->running = 0;
++ LOG_TARGET_ERROR(ctx->cpus[fired_target_num], "Failed to get free block for data!");
++ return ERROR_FAIL;
++ }
++ if (s_time_stats_enable) {
++ /* read block */
++ if (duration_start(&blk_proc_time) != 0) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to start block read time measurement!");
++ return ERROR_FAIL;
++ }
++ }
++ res =
++ ctx->hw->data_read(ctx->cpus[fired_target_num],
++ target_state[fired_target_num].data_len,
++ block->data,
++ target_state[fired_target_num].block_id,
++ /* do not ack target data in sync mode,
++ esp32_apptrace_handle_trace_block() can write response data and will do ack thereafter */
++ ctx->mode != ESP_APPTRACE_CMD_MODE_SYNC);
++ if (res != ERROR_OK) {
++ ctx->running = 0;
++ LOG_TARGET_ERROR(ctx->cpus[fired_target_num], "Failed to read data!");
++ return res;
++ }
++ ctx->last_blk_id = target_state[fired_target_num].block_id;
++ block->data_len = target_state[fired_target_num].data_len;
++ ctx->raw_tot_len += block->data_len;
++ if (s_time_stats_enable) {
++ if (duration_measure(&blk_proc_time) != 0) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to measure block read time!");
++ return ERROR_FAIL;
++ }
++ /* update stats */
++ float brt = duration_elapsed(&blk_proc_time);
++ if (brt > ctx->stats.max_blk_read_time)
++ ctx->stats.max_blk_read_time = brt;
++ if (brt < ctx->stats.min_blk_read_time)
++ ctx->stats.min_blk_read_time = brt;
++
++ if (duration_start(&blk_proc_time) != 0) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to start block proc time measurement!");
++ return ERROR_FAIL;
++ }
++ }
++ /* in sync mode do not ack target data on other cores, esp32_apptrace_handle_trace_block() can write response
++ * data and will do ack thereafter */
++ if (ctx->mode != ESP_APPTRACE_CMD_MODE_SYNC) {
++ for (unsigned int i = 0; i < ctx->cores_num; i++) {
++ if (i == fired_target_num)
++ continue;
++ res = ctx->hw->ctrl_reg_write(ctx->cpus[i],
++ ctx->last_blk_id,
++ 0 /*all read*/,
++ true /*host connected*/,
++ false /*no host data*/);
++ if (res != ERROR_OK) {
++ ctx->running = 0;
++ LOG_TARGET_ERROR(ctx->cpus[i], "Failed to ack data!");
++ return res;
++ }
++ LOG_TARGET_DEBUG(ctx->cpus[i], "Ack block %" PRId32, ctx->last_blk_id);
++ }
++ res = esp32_apptrace_ready_block_put(ctx, block);
++ if (res != ERROR_OK) {
++ ctx->running = 0;
++ LOG_TARGET_ERROR(ctx->cpus[fired_target_num], "Failed to put ready block of data!");
++ return res;
++ }
++ } else {
++ res = esp32_apptrace_handle_trace_block(ctx, block);
++ if (res != ERROR_OK) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to process trace block %" PRId32 " bytes!", block->data_len);
++ return res;
++ }
++ res = esp32_apptrace_block_free(ctx, block);
++ if (res != ERROR_OK) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to free ready block!");
++ return res;
++ }
++ }
++ if (ctx->stop_tmo != -1.0) {
++ /* start idle time measurement */
++ if (duration_start(&ctx->idle_time) != 0) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to start idle time measure!");
++ return ERROR_FAIL;
++ }
++ }
++ if (s_time_stats_enable) {
++ if (duration_measure(&blk_proc_time) != 0) {
++ ctx->running = 0;
++ LOG_ERROR("Failed to stop block proc time measure!");
++ return ERROR_FAIL;
++ }
++ /* update stats */
++ float bt = duration_elapsed(&blk_proc_time);
++ if (bt > ctx->stats.max_blk_proc_time)
++ ctx->stats.max_blk_proc_time = bt;
++ if (bt < ctx->stats.min_blk_proc_time)
++ ctx->stats.min_blk_proc_time = bt;
++ }
++ return ERROR_OK;
++}
++
++static void esp32_apptrace_cmd_stop(struct esp32_apptrace_cmd_ctx *ctx)
++{
++ if (duration_measure(&ctx->read_time) != 0)
++ LOG_ERROR("Failed to stop trace read time measurement!");
++ int res = target_unregister_timer_callback(esp32_apptrace_poll, ctx);
++ if (res != ERROR_OK)
++ LOG_ERROR("Failed to unregister target timer handler (%d)!", res);
++
++ /* data processor is alive, so wait for all received blocks to be processed */
++ res = esp32_apptrace_wait_tracing_finished(ctx);
++ if (res != ERROR_OK)
++ LOG_ERROR("Failed to wait for pended blocks (%d)!", res);
++ res = esp32_apptrace_connect_targets(ctx, false, ctx->target_state == TARGET_RUNNING);
++ if (res != ERROR_OK)
++ LOG_ERROR("Failed to disconnect targets (%d)!", res);
++ esp32_apptrace_print_stats(ctx);
++ res = esp32_apptrace_cmd_cleanup(ctx);
++ if (res != ERROR_OK)
++ LOG_ERROR("Failed to cleanup cmd ctx (%d)!", res);
++}
++
++int esp32_cmd_apptrace_generic(struct command_invocation *cmd, int mode, const char **argv, int argc)
++{
++ static struct esp32_apptrace_cmd_ctx s_at_cmd_ctx;
++ struct esp32_apptrace_cmd_data *cmd_data;
++ int res = ERROR_FAIL;
++ enum target_state old_state;
++ struct target *target = get_current_target(CMD_CTX);
++
++ if (argc < 1)
++ return ERROR_COMMAND_SYNTAX_ERROR;
++
++ /* command can be invoked on unexamined core, if so find examined one */
++ if (target->smp && !target_was_examined(target)) {
++ struct target_list *head;
++ struct target *curr;
++ LOG_WARNING("Current target '%s' was not examined!", target_name(target));
++ foreach_smp_target(head, target->smp_targets) {
++ curr = head->target;
++ if (target_was_examined(curr)) {
++ target = curr;
++ LOG_WARNING("Run command on target '%s'", target_name(target));
++ break;
++ }
++ }
++ }
++ old_state = target->state;
++
++ if (strcmp(argv[0], "start") == 0) {
++ res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
++ cmd,
++ mode,
++ &argv[1],
++ argc - 1);
++ if (res != ERROR_OK) {
++ command_print(cmd, "Failed to init cmd ctx (%d)!", res);
++ return res;
++ }
++ cmd_data = s_at_cmd_ctx.cmd_priv;
++ s_at_cmd_ctx.process_data = esp32_apptrace_process_data;
++ s_at_cmd_ctx.auto_clean = esp32_apptrace_cmd_stop;
++ if (cmd_data->wait4halt) {
++ res = esp32_apptrace_wait4halt(&s_at_cmd_ctx, target);
++ if (res != ERROR_OK) {
++ command_print(cmd, "Failed to wait for halt target (%d)!", res);
++ goto _on_start_error;
++ }
++ }
++ res = esp32_apptrace_connect_targets(&s_at_cmd_ctx, true, old_state == TARGET_RUNNING);
++ if (res != ERROR_OK) {
++ command_print(cmd, "Failed to connect to targets (%d)!", res);
++ goto _on_start_error;
++ }
++ res = target_register_timer_callback(esp32_apptrace_poll,
++ cmd_data->poll_period,
++ TARGET_TIMER_TYPE_PERIODIC,
++ &s_at_cmd_ctx);
++ if (res != ERROR_OK) {
++ command_print(cmd, "Failed to register target timer handler (%d)!", res);
++ goto _on_start_error;
++ }
++ } else if (strcmp(argv[0], "stop") == 0) {
++ if (!s_at_cmd_ctx.running) {
++ command_print(cmd, "Tracing is not running!");
++ return ERROR_FAIL;
++ }
++ esp32_apptrace_cmd_stop(&s_at_cmd_ctx);
++ return ERROR_OK;
++ } else if (strcmp(argv[0], "status") == 0) {
++ if (s_at_cmd_ctx.running && duration_measure(&s_at_cmd_ctx.read_time) != 0)
++ LOG_ERROR("Failed to measure trace read time!");
++ esp32_apptrace_print_stats(&s_at_cmd_ctx);
++ return ERROR_OK;
++ } else if (strcmp(argv[0], "dump") == 0) {
++ /* [dump outfile] - post-mortem dump without connection to targets */
++ res = esp32_apptrace_cmd_init(&s_at_cmd_ctx,
++ cmd,
++ mode,
++ &argv[1],
++ argc - 1);
++ if (res != ERROR_OK) {
++ command_print(cmd, "Failed to init cmd ctx (%d)!", res);
++ return res;
++ }
++ s_at_cmd_ctx.stop_tmo = 0.01; /* use small stop tmo */
++ s_at_cmd_ctx.process_data = esp32_apptrace_process_data;
++ /* check for exit signal and command completion */
++ while (!openocd_is_shutdown_pending() && s_at_cmd_ctx.running) {
++ res = esp32_apptrace_poll(&s_at_cmd_ctx);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to poll target for trace data (%d)!", res);
++ break;
++ }
++ /* let registered timer callbacks to run */
++ target_call_timer_callbacks();
++ }
++ if (s_at_cmd_ctx.running) {
++ /* data processor is alive, so wait for all received blocks to be processed */
++ res = esp32_apptrace_wait_tracing_finished(&s_at_cmd_ctx);
++ if (res != ERROR_OK)
++ LOG_ERROR("Failed to wait for pended blocks (%d)!", res);
++ }
++ esp32_apptrace_print_stats(&s_at_cmd_ctx);
++ res = esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx);
++ if (res != ERROR_OK)
++ command_print(cmd, "Failed to cleanup cmd ctx (%d)!", res);
++ } else {
++ command_print(cmd, "Invalid action '%s'!", argv[0]);
++ }
++
++ return res;
++
++_on_start_error:
++ s_at_cmd_ctx.running = 0;
++ esp32_apptrace_cmd_cleanup(&s_at_cmd_ctx);
++ return res;
++}
++
++COMMAND_HANDLER(esp32_cmd_apptrace)
++{
++ return esp32_cmd_apptrace_generic(CMD, ESP_APPTRACE_CMD_MODE_GEN, CMD_ARGV, CMD_ARGC);
++}
++
++const struct command_registration esp32_apptrace_command_handlers[] = {
++ {
++ .name = "apptrace",
++ .handler = esp32_cmd_apptrace,
++ .mode = COMMAND_EXEC,
++ .help =
++ "App Tracing: application level trace control. Starts, stops or queries tracing process status.",
++ .usage =
++ "[start <destination> [poll_period [trace_size [stop_tmo [wait4halt [skip_size]]]]] | [stop] | [status] | [dump <destination>]",
++ },
++ COMMAND_REGISTRATION_DONE
++};
+diff --git a/src/target/espressif/esp32_apptrace.h b/src/target/espressif/esp32_apptrace.h
+new file mode 100644
+index 000000000..387334222
+--- /dev/null
++++ b/src/target/espressif/esp32_apptrace.h
+@@ -0,0 +1,126 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++/***************************************************************************
++ * ESP32 application trace module *
++ * Copyright (C) 2017-2019 Espressif Systems Ltd. *
++ ***************************************************************************/
++
++#ifndef OPENOCD_TARGET_ESP32_APPTRACE_H
++#define OPENOCD_TARGET_ESP32_APPTRACE_H
++
++#include <helper/command.h>
++#include <helper/time_support.h>
++#include <target/target.h>
++
++#define ESP32_APPTRACE_MAX_CORES_NUM 2
++
++struct esp32_apptrace_hw {
++ uint32_t max_block_id;
++ uint32_t (*max_block_size_get)(struct target *target);
++ int (*status_reg_read)(struct target *target, uint32_t *stat);
++ int (*ctrl_reg_write)(struct target *target,
++ uint32_t block_id,
++ uint32_t len,
++ bool conn,
++ bool data);
++ int (*ctrl_reg_read)(struct target *target,
++ uint32_t *block_id,
++ uint32_t *len,
++ bool *conn);
++ int (*data_len_read)(struct target *target,
++ uint32_t *block_id,
++ uint32_t *len);
++ int (*data_read)(struct target *target,
++ uint32_t size,
++ uint8_t *buffer,
++ uint32_t block_id,
++ bool ack);
++ uint32_t (*usr_block_max_size_get)(struct target *target);
++ int (*buffs_write)(struct target *target,
++ uint32_t bufs_num,
++ uint32_t buf_sz[],
++ const uint8_t *bufs[],
++ uint32_t block_id,
++ bool ack,
++ bool data);
++ int (*leave_trace_crit_section_start)(struct target *target);
++ int (*leave_trace_crit_section_stop)(struct target *target);
++};
++
++struct esp_apptrace_host2target_hdr {
++ uint16_t block_sz;
++};
++
++struct esp32_apptrace_dest {
++ void *priv;
++ int (*write)(void *priv, uint8_t *data, int size);
++ int (*clean)(void *priv);
++ bool log_progress;
++};
++
++struct esp32_apptrace_format {
++ uint32_t hdr_sz;
++ int (*core_id_get)(struct target *target, uint8_t *hdr_buf);
++ uint32_t (*usr_block_len_get)(struct target *target, uint8_t *hdr_buf, uint32_t *wr_len);
++};
++
++struct esp32_apptrace_cmd_stats {
++ uint32_t incompl_blocks;
++ uint32_t lost_bytes;
++ float min_blk_read_time;
++ float max_blk_read_time;
++ float min_blk_proc_time;
++ float max_blk_proc_time;
++};
++
++struct esp32_apptrace_cmd_ctx {
++ volatile int running;
++ int mode;
++ /* TODO: use subtargets from target arch info */
++ struct target *cpus[ESP32_APPTRACE_MAX_CORES_NUM];
++ /* TODO: use cores num from target */
++ unsigned int cores_num;
++ const struct esp32_apptrace_hw *hw;
++ enum target_state target_state;
++ uint32_t last_blk_id;
++ struct list_head free_trace_blocks;
++ struct list_head ready_trace_blocks;
++ uint32_t max_trace_block_sz;
++ struct esp32_apptrace_format trace_format;
++ int (*process_data)(struct esp32_apptrace_cmd_ctx *ctx, unsigned int core_id, uint8_t *data, uint32_t data_len);
++ void (*auto_clean)(struct esp32_apptrace_cmd_ctx *ctx);
++ uint32_t tot_len;
++ uint32_t raw_tot_len;
++ float stop_tmo;
++ struct esp32_apptrace_cmd_stats stats;
++ struct duration read_time;
++ struct duration idle_time;
++ void *cmd_priv;
++ struct target *target;
++ struct command_invocation *cmd;
++};
++
++struct esp32_apptrace_cmd_data {
++ struct esp32_apptrace_dest data_dest;
++ uint32_t poll_period;
++ uint32_t max_len;
++ uint32_t skip_len;
++ bool wait4halt;
++};
++
++int esp32_apptrace_cmd_ctx_init(struct esp32_apptrace_cmd_ctx *cmd_ctx, struct command_invocation *cmd, int mode);
++int esp32_apptrace_cmd_ctx_cleanup(struct esp32_apptrace_cmd_ctx *cmd_ctx);
++void esp32_apptrace_cmd_args_parse(struct esp32_apptrace_cmd_ctx *cmd_ctx,
++ struct esp32_apptrace_cmd_data *cmd_data,
++ const char **argv,
++ int argc);
++int esp32_apptrace_dest_init(struct esp32_apptrace_dest dest[], const char *dest_paths[], unsigned int max_dests);
++int esp32_apptrace_dest_cleanup(struct esp32_apptrace_dest dest[], unsigned int max_dests);
++int esp_apptrace_usr_block_write(const struct esp32_apptrace_hw *hw, struct target *target,
++ uint32_t block_id,
++ const uint8_t *data,
++ uint32_t size);
++
++extern const struct command_registration esp32_apptrace_command_handlers[];
++
++#endif /* OPENOCD_TARGET_ESP32_APPTRACE_H */
+diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c
+index 64fa69057..a11d05f0f 100644
+--- a/src/target/espressif/esp32s2.c
++++ b/src/target/espressif/esp32s2.c
+@@ -496,6 +496,11 @@ static const struct command_registration esp32s2_command_handlers[] = {
+ {
+ .chain = xtensa_command_handlers,
+ },
++ {
++ .name = "esp",
++ .usage = "",
++ .chain = esp32_apptrace_command_handlers,
++ },
+ {
+ .name = "arm",
+ .mode = COMMAND_ANY,
+diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c
+index 62b22b135..485567836 100644
+--- a/src/target/espressif/esp32s3.c
++++ b/src/target/espressif/esp32s3.c
+@@ -364,6 +364,11 @@ static const struct command_registration esp32s3_command_handlers[] = {
+ .usage = "",
+ .chain = esp_xtensa_smp_command_handlers,
+ },
++ {
++ .name = "esp",
++ .usage = "",
++ .chain = esp32_apptrace_command_handlers,
++ },
+ {
+ .name = "esp32",
+ .usage = "",
+diff --git a/src/target/espressif/esp_xtensa.c b/src/target/espressif/esp_xtensa.c
+index fcc340c82..44764aeca 100644
+--- a/src/target/espressif/esp_xtensa.c
++++ b/src/target/espressif/esp_xtensa.c
+@@ -12,6 +12,7 @@
+ #include <stdbool.h>
+ #include <stdint.h>
+ #include <target/smp.h>
++#include "esp_xtensa_apptrace.h"
+ #include <target/register.h>
+ #include "esp_xtensa.h"
+ #include "esp_semihosting.h"
+@@ -25,6 +26,7 @@ int esp_xtensa_init_arch_info(struct target *target,
+ if (ret != ERROR_OK)
+ return ret;
+ esp_xtensa->semihost.ops = (struct esp_semihost_ops *)semihost_ops;
++ esp_xtensa->apptrace.hw = &esp_xtensa_apptrace_hw;
+ return ERROR_OK;
+ }
+
+diff --git a/src/target/espressif/esp_xtensa.h b/src/target/espressif/esp_xtensa.h
+index 1ad6c377f..8807f0c32 100644
+--- a/src/target/espressif/esp_xtensa.h
++++ b/src/target/espressif/esp_xtensa.h
+@@ -12,10 +12,12 @@
+ #include <target/xtensa/xtensa.h>
+ #include "esp_xtensa.h"
+ #include "esp_semihosting.h"
++#include "esp_xtensa_apptrace.h"
+
+ struct esp_xtensa_common {
+ struct xtensa xtensa; /* must be the first element */
+ struct esp_semihost_data semihost;
++ struct esp_xtensa_apptrace_info apptrace;
+ };
+
+ static inline struct esp_xtensa_common *target_to_esp_xtensa(struct target *target)
+diff --git a/src/target/espressif/esp_xtensa_apptrace.c b/src/target/espressif/esp_xtensa_apptrace.c
+new file mode 100644
+index 000000000..dfb846da0
+--- /dev/null
++++ b/src/target/espressif/esp_xtensa_apptrace.c
+@@ -0,0 +1,497 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++
++/***************************************************************************
++ * Xtensa application tracing module for OpenOCD *
++ * Copyright (C) 2017 Espressif Systems Ltd. *
++ ***************************************************************************/
++
++/*
++ How it works?
++ https://github.com/espressif/esp-idf/blob/master/components/app_trace/port/xtensa/port.c#L8
++*/
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <helper/align.h>
++#include <target/xtensa/xtensa.h>
++#include <target/xtensa/xtensa_debug_module.h>
++#include "esp_xtensa_apptrace.h"
++
++/* TRAX is disabled, so we use its registers for our own purposes
++ * | 31..XXXXXX..24 | 23 .(host_connect). 23 | 22 .(host_data). 22| 21..(block_id)..15 | 14..(block_len)..0 |
++ */
++#define XTENSA_APPTRACE_CTRL_REG XDMREG_DELAYCNT
++#define XTENSA_APPTRACE_BLOCK_ID_MSK 0x7FUL
++#define XTENSA_APPTRACE_BLOCK_ID_MAX XTENSA_APPTRACE_BLOCK_ID_MSK
++/* if non-zero then apptrace code entered the critical section and the value is an address of the
++ * critical section's exit point */
++#define XTENSA_APPTRACE_STAT_REG XDMREG_TRIGGERPC
++
++#define XTENSA_APPTRACE_BLOCK_LEN_MSK 0x7FFFUL
++#define XTENSA_APPTRACE_BLOCK_LEN(_l_) ((_l_) & XTENSA_APPTRACE_BLOCK_LEN_MSK)
++#define XTENSA_APPTRACE_BLOCK_LEN_GET(_v_) ((_v_) & XTENSA_APPTRACE_BLOCK_LEN_MSK)
++#define XTENSA_APPTRACE_BLOCK_ID(_id_) (((_id_) & XTENSA_APPTRACE_BLOCK_ID_MSK) << 15)
++#define XTENSA_APPTRACE_BLOCK_ID_GET(_v_) (((_v_) >> 15) & XTENSA_APPTRACE_BLOCK_ID_MSK)
++#define XTENSA_APPTRACE_HOST_DATA BIT(22)
++#define XTENSA_APPTRACE_HOST_CONNECT BIT(23)
++
++static int esp_xtensa_apptrace_leave_crit_section_start(struct target *target);
++static int esp_xtensa_apptrace_leave_crit_section_stop(struct target *target);
++static int esp_xtensa_apptrace_buffs_write(struct target *target,
++ uint32_t bufs_num,
++ uint32_t buf_sz[],
++ const uint8_t *bufs[],
++ uint32_t block_id,
++ bool ack,
++ bool data);
++
++struct esp32_apptrace_hw esp_xtensa_apptrace_hw = {
++ .max_block_id = XTENSA_APPTRACE_BLOCK_ID_MAX,
++ .max_block_size_get = esp_xtensa_apptrace_block_max_size_get,
++ .status_reg_read = esp_xtensa_apptrace_status_reg_read,
++ .ctrl_reg_write = esp_xtensa_apptrace_ctrl_reg_write,
++ .ctrl_reg_read = esp_xtensa_apptrace_ctrl_reg_read,
++ .data_len_read = esp_xtensa_apptrace_data_len_read,
++ .data_read = esp_xtensa_apptrace_data_read,
++ .usr_block_max_size_get = esp_xtensa_apptrace_usr_block_max_size_get,
++ .buffs_write = esp_xtensa_apptrace_buffs_write,
++ .leave_trace_crit_section_start = esp_xtensa_apptrace_leave_crit_section_start,
++ .leave_trace_crit_section_stop = esp_xtensa_apptrace_leave_crit_section_stop,
++};
++
++uint32_t esp_xtensa_apptrace_block_max_size_get(struct target *target)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++ struct xtensa_trace_status trace_status;
++ struct xtensa_trace_config trace_config;
++ uint32_t max_trace_block_sz;
++
++ int res = xtensa_dm_trace_status_read(&xtensa->dbg_mod, &trace_status);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to read TRAX status (%d)!", res);
++ return 0;
++ }
++
++ max_trace_block_sz = BIT(((trace_status.stat >> 8) & 0x1f) - 2) * 4;
++ res = xtensa_dm_trace_config_read(&xtensa->dbg_mod, &trace_config);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to read TRAX config (%d)!", res);
++ return 0;
++ }
++ LOG_DEBUG("ctrl=0x%" PRIx32 " memadrstart=0x%" PRIx32 " memadrend=0x%" PRIx32 " traxadr=0x%" PRIx32,
++ trace_config.ctrl,
++ trace_config.memaddr_start,
++ trace_config.memaddr_end,
++ trace_config.addr);
++
++ return max_trace_block_sz;
++}
++
++uint32_t esp_xtensa_apptrace_usr_block_max_size_get(struct target *target)
++{
++ return esp_xtensa_apptrace_block_max_size_get(target) - sizeof(struct esp_apptrace_host2target_hdr);
++}
++
++int esp_xtensa_apptrace_data_len_read(struct target *target,
++ uint32_t *block_id,
++ uint32_t *len)
++{
++ return esp_xtensa_apptrace_ctrl_reg_read(target, block_id, len, NULL);
++}
++
++int esp_xtensa_apptrace_usr_block_write(struct target *target,
++ uint32_t block_id,
++ const uint8_t *data,
++ uint32_t size)
++{
++ return esp_apptrace_usr_block_write(&esp_xtensa_apptrace_hw, target, block_id, data, size);
++}
++
++static int esp_xtensa_apptrace_data_reverse_read(struct xtensa *xtensa,
++ uint32_t size,
++ uint8_t *buffer,
++ uint8_t *unal_bytes)
++{
++ int res = 0;
++ uint32_t rd_sz = ALIGN_UP(size, 4);
++
++ res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXADDR, (xtensa->core_config->trace.mem_sz - rd_sz) / 4);
++ if (res != ERROR_OK)
++ return res;
++ if (!IS_ALIGNED(size, 4)) {
++ res = xtensa_queue_dbg_reg_read(xtensa, XDMREG_TRAXDATA, unal_bytes);
++ if (res != ERROR_OK)
++ return res;
++ }
++ for (unsigned int i = size / 4; i != 0; i--) {
++ res = xtensa_queue_dbg_reg_read(xtensa, XDMREG_TRAXDATA, &buffer[(i - 1) * 4]);
++ if (res != ERROR_OK)
++ return res;
++ }
++ return ERROR_OK;
++}
++
++static int esp_xtensa_apptrace_data_normal_read(struct xtensa *xtensa,
++ uint32_t size,
++ uint8_t *buffer,
++ uint8_t *unal_bytes)
++{
++ int res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXADDR, 0);
++ if (res != ERROR_OK)
++ return res;
++ for (unsigned int i = 0; i < size / 4; i++) {
++ res = xtensa_queue_dbg_reg_read(xtensa, XDMREG_TRAXDATA, &buffer[i * 4]);
++ if (res != ERROR_OK)
++ return res;
++ }
++ if (!IS_ALIGNED(size, 4)) {
++ res = xtensa_queue_dbg_reg_read(xtensa, XDMREG_TRAXDATA, unal_bytes);
++ if (res != ERROR_OK)
++ return res;
++ }
++ return ERROR_OK;
++}
++
++int esp_xtensa_apptrace_data_read(struct target *target,
++ uint32_t size,
++ uint8_t *buffer,
++ uint32_t block_id,
++ bool ack)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++ int res;
++ uint32_t tmp = XTENSA_APPTRACE_HOST_CONNECT | XTENSA_APPTRACE_BLOCK_ID(block_id) |
++ XTENSA_APPTRACE_BLOCK_LEN(0);
++ uint8_t unal_bytes[4];
++
++ LOG_DEBUG("Read data on target (%s)", target_name(target));
++ if (xtensa->core_config->trace.reversed_mem_access)
++ res = esp_xtensa_apptrace_data_reverse_read(xtensa, size, buffer, unal_bytes);
++ else
++ res = esp_xtensa_apptrace_data_normal_read(xtensa, size, buffer, unal_bytes);
++ if (res != ERROR_OK)
++ return res;
++ if (ack) {
++ LOG_DEBUG("Ack block %" PRIu32 " target (%s)!", block_id, target_name(target));
++ res = xtensa_queue_dbg_reg_write(xtensa, XTENSA_APPTRACE_CTRL_REG, tmp);
++ if (res != ERROR_OK)
++ return res;
++ }
++ xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
++ res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to exec JTAG queue!");
++ return res;
++ }
++ if (!IS_ALIGNED(size, 4)) {
++ /* copy the last unaligned bytes */
++ memcpy(buffer + ALIGN_DOWN(size, 4), unal_bytes, size & 0x3UL);
++ }
++ return ERROR_OK;
++}
++
++int esp_xtensa_apptrace_ctrl_reg_write(struct target *target,
++ uint32_t block_id,
++ uint32_t len,
++ bool conn,
++ bool data)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++ uint32_t tmp = (conn ? XTENSA_APPTRACE_HOST_CONNECT : 0) |
++ (data ? XTENSA_APPTRACE_HOST_DATA : 0) | XTENSA_APPTRACE_BLOCK_ID(block_id) |
++ XTENSA_APPTRACE_BLOCK_LEN(len);
++
++ xtensa_queue_dbg_reg_write(xtensa, XTENSA_APPTRACE_CTRL_REG, tmp);
++ xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
++ int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to exec JTAG queue!");
++ return res;
++ }
++
++ return ERROR_OK;
++}
++
++int esp_xtensa_apptrace_ctrl_reg_read(struct target *target,
++ uint32_t *block_id,
++ uint32_t *len,
++ bool *conn)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++ uint8_t tmp[4];
++
++ xtensa_queue_dbg_reg_read(xtensa, XTENSA_APPTRACE_CTRL_REG, tmp);
++ xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
++ int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
++ if (res != ERROR_OK)
++ return res;
++ uint32_t val = target_buffer_get_u32(target, tmp);
++ if (block_id)
++ *block_id = XTENSA_APPTRACE_BLOCK_ID_GET(val);
++ if (len)
++ *len = XTENSA_APPTRACE_BLOCK_LEN_GET(val);
++ if (conn)
++ *conn = val & XTENSA_APPTRACE_HOST_CONNECT;
++ return ERROR_OK;
++}
++
++int esp_xtensa_apptrace_status_reg_read(struct target *target, uint32_t *stat)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++ uint8_t tmp[4];
++
++ xtensa_queue_dbg_reg_read(xtensa, XTENSA_APPTRACE_STAT_REG, tmp);
++ xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
++ int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to exec JTAG queue!");
++ return res;
++ }
++ *stat = buf_get_u32(tmp, 0, 32);
++ return ERROR_OK;
++}
++
++int esp_xtensa_apptrace_status_reg_write(struct target *target, uint32_t stat)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++
++ xtensa_queue_dbg_reg_write(xtensa, XTENSA_APPTRACE_STAT_REG, stat);
++ xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
++ int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to exec JTAG queue!");
++ return res;
++ }
++ return ERROR_OK;
++}
++
++static int esp_xtensa_swdbg_activate(struct target *target, int enab)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++
++ xtensa_queue_dbg_reg_write(xtensa, enab ? XDMREG_DCRSET : XDMREG_DCRCLR, OCDDCR_DEBUGSWACTIVE);
++ xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
++ int res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
++ if (res != ERROR_OK) {
++ LOG_ERROR("%s: writing DCR failed!", target->cmd_name);
++ return res;
++ }
++
++ return ERROR_OK;
++}
++
++static int esp_xtensa_apptrace_leave_crit_section_start(struct target *target)
++{
++ /* TODO: not sure that we need this, but it seems that we fail to leave tracing critical
++ *section w/o this */
++ int res = esp_xtensa_swdbg_activate(target, 1 /*enable*/);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to activate SW debug (%d)!", res);
++ return res;
++ }
++ return ERROR_OK;
++}
++
++static int esp_xtensa_apptrace_leave_crit_section_stop(struct target *target)
++{
++ int res = esp_xtensa_swdbg_activate(target, 0 /*disable*/);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to activate SW debug (%d)!", res);
++ return res;
++ }
++ return ERROR_OK;
++}
++
++static int esp_xtensa_apptrace_queue_reverse_write(struct target *target, uint32_t bufs_num,
++ uint32_t buf_sz[], const uint8_t *bufs[])
++{
++ int res = ERROR_OK;
++ uint32_t cached_bytes = 0, total_sz = 0;
++ uint8_t cached_data8[sizeof(uint32_t)] = { 0 };
++ uint32_t cached_data32 = 0;
++
++ struct xtensa *xtensa = target_to_xtensa(target);
++
++ for (uint32_t i = 0; i < bufs_num; i++)
++ total_sz += buf_sz[i];
++ if (!IS_ALIGNED(total_sz, 4)) {
++ cached_bytes = sizeof(uint32_t) - (total_sz & 0x3UL);
++ total_sz = ALIGN_UP(total_sz, 4);
++ }
++ xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXADDR, (xtensa->core_config->trace.mem_sz - total_sz) / 4);
++ for (uint32_t i = bufs_num; i > 0; i--) {
++ uint32_t bsz = buf_sz[i - 1];
++ const uint8_t *cur_buf = &bufs[i - 1][bsz];
++ uint32_t bytes_to_cache;
++ /* if there are cached bytes from the previous buffer, combine them with the last
++ * from the current buffer */
++ if (cached_bytes) {
++ if ((cached_bytes + bsz) < sizeof(uint32_t))
++ bytes_to_cache = bsz;
++ else
++ bytes_to_cache = sizeof(uint32_t) - cached_bytes;
++ memcpy(&cached_data8[sizeof(uint32_t) - cached_bytes - bytes_to_cache],
++ cur_buf - bytes_to_cache,
++ bytes_to_cache);
++ cached_data32 = target_buffer_get_u32(target, cached_data8);
++ cached_bytes += bytes_to_cache;
++ if (cached_bytes < sizeof(uint32_t))
++ continue;
++ res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
++ if (res != ERROR_OK)
++ return res;
++ bsz -= bytes_to_cache;
++ cur_buf -= bytes_to_cache;
++ memset(cached_data8, 0x00, sizeof(cached_data8));
++ cached_bytes = 0;
++ }
++ /* write full dwords */
++ for (unsigned int k = bsz; k >= sizeof(uint32_t); k -= sizeof(uint32_t)) {
++ uint32_t temp = target_buffer_get_u32(target, cur_buf - sizeof(uint32_t));
++ res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, temp);
++ if (res != ERROR_OK)
++ return res;
++ cur_buf -= sizeof(uint32_t);
++ }
++ /* if there are bytes to be cached (1..3) */
++ bytes_to_cache = bsz & 0x3UL;
++ if (bytes_to_cache > 0) {
++ if (bytes_to_cache + cached_bytes >= sizeof(uint32_t)) {
++ /* filling the cache buffer from the end to beginning */
++ uint32_t to_copy = sizeof(uint32_t) - cached_bytes;
++ memcpy(&cached_data8[0], cur_buf - to_copy, to_copy);
++ cached_data32 = target_buffer_get_u32(target, cached_data8);
++ /* write full word of cached bytes */
++ res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
++ if (res != ERROR_OK)
++ return res;
++ /* cache remaining bytes */
++ memset(cached_data8, 0x00, sizeof(cached_data8));
++ cur_buf -= to_copy;
++ to_copy = bytes_to_cache + cached_bytes - sizeof(uint32_t);
++ memcpy(&cached_data8[sizeof(uint32_t) - to_copy], cur_buf - to_copy, to_copy);
++ cached_bytes = to_copy;
++ } else {
++ /* filling the cache buffer from the end to beginning */
++ memcpy(&cached_data8[sizeof(uint32_t) - cached_bytes - bytes_to_cache],
++ cur_buf - bytes_to_cache,
++ bytes_to_cache);
++ cached_bytes += bytes_to_cache;
++ }
++ }
++ }
++ return ERROR_OK;
++}
++
++static int esp_xtensa_apptrace_queue_normal_write(struct target *target, uint32_t bufs_num,
++ uint32_t buf_sz[], const uint8_t *bufs[])
++{
++ int res = ERROR_OK;
++ uint32_t cached_bytes = 0;
++ uint8_t cached_data8[4] = { 0 };
++ uint32_t cached_data32 = 0;
++
++ struct xtensa *xtensa = target_to_xtensa(target);
++
++ /* | 1 | 2 | 1 | 2 | 4 |.......|
++ * | 4 | 4 | 4 | */
++ xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXADDR, 0);
++ for (unsigned int i = 0; i < bufs_num; i++) {
++ uint32_t bsz = buf_sz[i];
++ const uint8_t *cur_buf = bufs[i];
++ uint32_t bytes_to_cache;
++ /* if there are cached bytes from the previous buffer, combine them with the last
++ * from the current buffer */
++ if (cached_bytes) {
++ if ((cached_bytes + bsz) < sizeof(uint32_t))
++ bytes_to_cache = bsz;
++ else
++ bytes_to_cache = sizeof(uint32_t) - cached_bytes;
++ memcpy(&cached_data8[cached_bytes], cur_buf, bytes_to_cache);
++ cached_bytes += bytes_to_cache;
++ if (cached_bytes < sizeof(uint32_t))
++ continue;
++ cached_data32 = target_buffer_get_u32(target, cached_data8);
++ res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
++ if (res != ERROR_OK)
++ return res;
++ bsz -= bytes_to_cache;
++ cur_buf += bytes_to_cache;
++ memset(cached_data8, 0x00, sizeof(cached_data8));
++ cached_bytes = 0;
++ }
++ /* write full dwords */
++ for (unsigned int k = 0; (k + sizeof(uint32_t)) <= bsz; k += sizeof(uint32_t)) {
++ uint32_t temp = target_buffer_get_u32(target, cur_buf);
++ res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, temp);
++ if (res != ERROR_OK)
++ return res;
++ cur_buf += sizeof(uint32_t);
++ }
++ /* if there are bytes to be cached (1..3) */
++ bytes_to_cache = bsz & 0x3UL;
++ if (bytes_to_cache > 0) {
++ if (bytes_to_cache + cached_bytes >= sizeof(uint32_t)) {
++ memcpy(&cached_data8[0], cur_buf, sizeof(uint32_t) - cached_bytes);
++ cached_data32 = target_buffer_get_u32(target, cached_data8);
++ /* write full word of cached bytes */
++ res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
++ if (res != ERROR_OK)
++ return res;
++ /* cache remaining bytes */
++ memset(cached_data8, 0x00, sizeof(cached_data8));
++ cur_buf += sizeof(uint32_t) - cached_bytes;
++ cached_bytes = bytes_to_cache + cached_bytes - sizeof(uint32_t);
++ memcpy(&cached_data8[0], cur_buf, cached_bytes);
++ } else {
++ memcpy(&cached_data8[cached_bytes], cur_buf, bytes_to_cache);
++ cached_bytes += bytes_to_cache;
++ }
++ }
++ }
++ if (cached_bytes) {
++ /* write remaining cached bytes */
++ cached_data32 = target_buffer_get_u32(target, cached_data8);
++ res = xtensa_queue_dbg_reg_write(xtensa, XDMREG_TRAXDATA, cached_data32);
++ if (res != ERROR_OK)
++ return res;
++ }
++ return ERROR_OK;
++}
++
++static int esp_xtensa_apptrace_buffs_write(struct target *target,
++ uint32_t bufs_num,
++ uint32_t buf_sz[],
++ const uint8_t *bufs[],
++ uint32_t block_id,
++ bool ack,
++ bool data)
++{
++ struct xtensa *xtensa = target_to_xtensa(target);
++ int res = ERROR_OK;
++ uint32_t tmp = XTENSA_APPTRACE_HOST_CONNECT |
++ (data ? XTENSA_APPTRACE_HOST_DATA : 0) | XTENSA_APPTRACE_BLOCK_ID(block_id) |
++ XTENSA_APPTRACE_BLOCK_LEN(0);
++
++ if (xtensa->core_config->trace.reversed_mem_access)
++ res = esp_xtensa_apptrace_queue_reverse_write(target, bufs_num, buf_sz, bufs);
++ else
++ res = esp_xtensa_apptrace_queue_normal_write(target, bufs_num, buf_sz, bufs);
++ if (res != ERROR_OK)
++ return res;
++ if (ack) {
++ LOG_DEBUG("Ack block %" PRId32 " on target (%s)!", block_id, target_name(target));
++ res = xtensa_queue_dbg_reg_write(xtensa, XTENSA_APPTRACE_CTRL_REG, tmp);
++ if (res != ERROR_OK)
++ return res;
++ }
++ xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
++ res = xtensa_dm_queue_execute(&xtensa->dbg_mod);
++ if (res != ERROR_OK) {
++ LOG_ERROR("Failed to exec JTAG queue!");
++ return res;
++ }
++ return ERROR_OK;
++}
+diff --git a/src/target/espressif/esp_xtensa_apptrace.h b/src/target/espressif/esp_xtensa_apptrace.h
+new file mode 100644
+index 000000000..0a9be731f
+--- /dev/null
++++ b/src/target/espressif/esp_xtensa_apptrace.h
+@@ -0,0 +1,37 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++
++/***************************************************************************
++ * Xtensa application tracing module for OpenOCD *
++ * Copyright (C) 2017 Espressif Systems Ltd. *
++ ***************************************************************************/
++
++#ifndef OPENOCD_TARGET_ESP_XTENSA_APPTRACE_H
++#define OPENOCD_TARGET_ESP_XTENSA_APPTRACE_H
++
++#include "esp32_apptrace.h"
++
++struct esp_xtensa_apptrace_info {
++ const struct esp32_apptrace_hw *hw;
++};
++
++extern struct esp32_apptrace_hw esp_xtensa_apptrace_hw;
++
++int esp_xtensa_apptrace_data_len_read(struct target *target, uint32_t *block_id, uint32_t *len);
++int esp_xtensa_apptrace_data_read(struct target *target,
++ uint32_t size,
++ uint8_t *buffer,
++ uint32_t block_id,
++ bool ack);
++int esp_xtensa_apptrace_ctrl_reg_read(struct target *target, uint32_t *block_id, uint32_t *len, bool *conn);
++int esp_xtensa_apptrace_ctrl_reg_write(struct target *target,
++ uint32_t block_id,
++ uint32_t len,
++ bool conn,
++ bool data);
++int esp_xtensa_apptrace_status_reg_write(struct target *target, uint32_t stat);
++int esp_xtensa_apptrace_status_reg_read(struct target *target, uint32_t *stat);
++uint32_t esp_xtensa_apptrace_block_max_size_get(struct target *target);
++uint32_t esp_xtensa_apptrace_usr_block_max_size_get(struct target *target);
++int esp_xtensa_apptrace_usr_block_write(struct target *target, uint32_t block_id, const uint8_t *data, uint32_t size);
++
++#endif /* OPENOCD_TARGET_ESP_XTENSA_APPTRACE_H */
new file mode 100644
@@ -0,0 +1,28 @@
+From 1c31f6225f41dd2bd371571e829fbf6855788d24 Mon Sep 17 00:00:00 2001
+From: panciyan <panciyan@eswincomputing.com>
+Date: Fri, 31 Mar 2023 15:12:08 +0000
+Subject: [PATCH] src/server: Fix memory leak of reg_list
+
+memory leak of reg_list when local_list realloc fail.
+
+Signed-off-by: panciyan <panciyan@eswincomputing.com>
+Change-Id: I6b09137ecd132ab326205f5a575a38bcc82e8469
+Reviewed-on: https://review.openocd.org/c/openocd/+/7566
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/server/gdb_server.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c
+index d8dbc2c8b..b15a6c1c3 100644
+--- a/src/server/gdb_server.c
++++ b/src/server/gdb_server.c
+@@ -2348,6 +2348,7 @@ static int smp_reg_list_noread(struct target *target,
+ local_list = realloc(local_list, combined_allocated * sizeof(struct reg *));
+ if (!local_list) {
+ LOG_ERROR("realloc(%zu) failed", combined_allocated * sizeof(struct reg *));
++ free(reg_list);
+ return ERROR_FAIL;
+ }
+ }
new file mode 100644
@@ -0,0 +1,29 @@
+From 1e6df1675ccea95d99d767e6d2b9a735c8ee2a36 Mon Sep 17 00:00:00 2001
+From: panciyan <panciyan@eswincomputing.com>
+Date: Sun, 2 Apr 2023 05:17:17 +0000
+Subject: [PATCH] rtos/linux.c: Fix Linux user space border check
+
+Linux kernel and user space border is 0xc0000000 not 0xc000000
+
+Signed-off-by: panciyan <panciyan@eswincomputing.com>
+Change-Id: I6b487cce62ac31737deca97d5f5f7bbc081280f4
+Reviewed-on: https://review.openocd.org/c/openocd/+/7570
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/rtos/linux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/rtos/linux.c b/src/rtos/linux.c
+index f9edabc2b..7517ec7a9 100644
+--- a/src/rtos/linux.c
++++ b/src/rtos/linux.c
+@@ -123,7 +123,7 @@ static int linux_read_memory(struct target *target,
+ target->rtos->rtos_specific_params;
+ uint32_t pa = (address & linux_os->phys_mask) + linux_os->phys_base;
+ #endif
+- if (address < 0xc000000) {
++ if (address < 0xc0000000) {
+ LOG_ERROR("linux awareness : address in user space");
+ return ERROR_FAIL;
+ }
new file mode 100644
@@ -0,0 +1,27 @@
+From 95c27731d4f76c0554147030075ab476d68f9f83 Mon Sep 17 00:00:00 2001
+From: Mark Zhuang <mark.zhuang@spacemit.com>
+Date: Mon, 10 Apr 2023 10:57:55 +0800
+Subject: [PATCH] flash/rsl10: fix typo
+
+Change-Id: I11af37309fe4684fcb340a00fcc7b2096b8dad76
+Signed-off-by: Mark Zhuang <mark.zhuang@spacemit.com>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7584
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ contrib/loaders/flash/rsl10/rom_launcher.S | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/contrib/loaders/flash/rsl10/rom_launcher.S b/contrib/loaders/flash/rsl10/rom_launcher.S
+index 70f000e72..aafedfb46 100644
+--- a/contrib/loaders/flash/rsl10/rom_launcher.S
++++ b/contrib/loaders/flash/rsl10/rom_launcher.S
+@@ -21,7 +21,7 @@
+ .global _start
+ _start:
+ launch_program_in_rom:
+- // variables are already set, addres to jump is in r3
++ // variables are already set, address to jump is in r3
+ blx r3
+ exit:
+ // Wait for OpenOCD
new file mode 100644
@@ -0,0 +1,90 @@
+From 91bd4313444c5a949ce49d88ab487608df7d6c37 Mon Sep 17 00:00:00 2001
+From: Daniel Anselmi <danselmi@gmx.ch>
+Date: Wed, 14 Dec 2022 09:27:38 +0100
+Subject: [PATCH] pld: move file sanity checks to pld.c
+
+Change-Id: Id64b1165b25a03634949ac22b8af16eb0e24c1fa
+Signed-off-by: Daniel Anselmi <danselmi@gmx.ch>
+Reviewed-on: https://review.openocd.org/c/openocd/+/7388
+Tested-by: jenkins
+Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
+---
+ src/pld/pld.c | 17 +++++++++++++++++
+ src/pld/xilinx_bit.c | 17 -----------------
+ 2 files changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/src/pld/pld.c b/src/pld/pld.c
+index e2e0ef413..af1836907 100644
+--- a/src/pld/pld.c
++++ b/src/pld/pld.c
+@@ -10,6 +10,7 @@
+ #endif
+
+ #include "pld.h"
++#include <sys/stat.h>
+ #include <helper/log.h>
+ #include <helper/replacements.h>
+ #include <helper/time_support.h>
+@@ -134,6 +135,22 @@ COMMAND_HANDLER(handle_pld_load_command)
+ return ERROR_OK;
+ }
+
++ struct stat input_stat;
++ if (stat(CMD_ARGV[1], &input_stat) == -1) {
++ LOG_ERROR("couldn't stat() %s: %s", CMD_ARGV[1], strerror(errno));
++ return ERROR_PLD_FILE_LOAD_FAILED;
++ }
++
++ if (S_ISDIR(input_stat.st_mode)) {
++ LOG_ERROR("%s is a directory", CMD_ARGV[1]);
++ return ERROR_PLD_FILE_LOAD_FAILED;
++ }
++
++ if (input_stat.st_size == 0) {
++ LOG_ERROR("Empty file %s", CMD_ARGV[1]);
++ return ERROR_PLD_FILE_LOAD_FAILED;
++ }
++
+ retval = p->driver->load(p, CMD_ARGV[1]);
+ if (retval != ERROR_OK) {
+ command_print(CMD, "failed loading file %s to pld device %u",
+diff --git a/src/pld/xilinx_bit.c b/src/pld/xilinx_bit.c
+index 792b3375b..e4cc52ef9 100644
+--- a/src/pld/xilinx_bit.c
++++ b/src/pld/xilinx_bit.c
+@@ -13,7 +13,6 @@
+ #include "pld.h"
+ #include <helper/log.h>
+
+-#include <sys/stat.h>
+ #include <helper/system.h>
+
+ static int read_section(FILE *input_file, int length_size, char section,
+@@ -60,27 +59,11 @@ static int read_section(FILE *input_file, int length_size, char section,
+ int xilinx_read_bit_file(struct xilinx_bit_file *bit_file, const char *filename)
+ {
+ FILE *input_file;
+- struct stat input_stat;
+ int read_count;
+
+ if (!filename || !bit_file)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+- if (stat(filename, &input_stat) == -1) {
+- LOG_ERROR("couldn't stat() %s: %s", filename, strerror(errno));
+- return ERROR_PLD_FILE_LOAD_FAILED;
+- }
+-
+- if (S_ISDIR(input_stat.st_mode)) {
+- LOG_ERROR("%s is a directory", filename);
+- return ERROR_PLD_FILE_LOAD_FAILED;
+- }
+-
+- if (input_stat.st_size == 0) {
+- LOG_ERROR("Empty file %s", filename);
+- return ERROR_PLD_FILE_LOAD_FAILED;
+- }
+-
+ input_file = fopen(filename, "rb");
+ if (!input_file) {
+ LOG_ERROR("couldn't open %s: %s", filename, strerror(errno));
new file mode 100644
@@ -0,0 +1,24 @@
+From 16801a7c4cfd5abe8f7a55e9ddd5c9251c422de0 Mon Sep 17 00:00:00 2001
+From: OpenEmbedded <oe.patch@oe>
+Date: Fri, 3 Nov 2023 17:29:27 +0000
+Subject: [PATCH] Committing changes from do_patch
+
+---
+ jimtcl | 2 +-
+ src/jtag/drivers/libjaylink | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/jimtcl b/jimtcl
+index 1933e5457..fcbb4499a 160000
+--- a/jimtcl
++++ b/jimtcl
+@@ -1 +1 @@
+-Subproject commit 1933e5457b9512d39ebbe11ed32578aada149f49
++Subproject commit fcbb4499a6b46ef69e7a95da53e30796e20817f0
+diff --git a/src/jtag/drivers/libjaylink b/src/jtag/drivers/libjaylink
+index 0d23921a0..9aa7a5957 160000
+--- a/src/jtag/drivers/libjaylink
++++ b/src/jtag/drivers/libjaylink
+@@ -1 +1 @@
+-Subproject commit 0d23921a05d5d427332a142d154c213d0c306eb1
++Subproject commit 9aa7a5957c07bb6e862fc1a6d3153d109c7407e4
@@ -4,12 +4,163 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=599d2d1ee7fc84c0467b3d19801db870"
DEPENDS = "libusb-compat libftdi"
RDEPENDS:${PN} = "libusb1"
-SRC_URI = " \
- git://repo.or.cz/openocd.git;protocol=http;name=openocd;branch=master \
- git://repo.or.cz/r/git2cl.git;protocol=http;destsuffix=tools/git2cl;name=git2cl;branch=master \
- git://github.com/msteveb/jimtcl.git;protocol=http;destsuffix=git/jimtcl;name=jimtcl;branch=master \
- git://repo.or.cz/r/libjaylink.git;protocol=http;destsuffix=git/src/jtag/drivers/libjaylink;name=libjaylink;branch=master \
-"
+SRCREV = "9ea7f3d647c8ecf6b0f1424002dfc3f4504a162c"
+SRC_URI = "git://repo.or.cz/openocd.git;protocol=http;name=openocd;branch=master \
+ git://repo.or.cz/r/git2cl.git;protocol=http;destsuffix=tools/git2cl;name=git2cl;branch=master \
+ git://github.com/msteveb/jimtcl.git;protocol=http;destsuffix=git/jimtcl;name=jimtcl;branch=master \
+ git://repo.or.cz/r/libjaylink.git;protocol=http;destsuffix=git/src/jtag/drivers/libjaylink;name=libjaylink;branch=master \
+ file://0001-Restore-normal-development-cycle.patch \
+ file://0002-Deprecate-libjaylink-Git-submodule.patch \
+ file://0003-nds32-drop-it-together-with-aice-adapter-driver.patch \
+ file://0004-openocd-revert-workarounds-for-expr-syntax-change.patch \
+ file://0005-flash-nor-avrf-add-ATmega32U4-support.patch \
+ file://0006-target-xtensa-remove-needless-target_was_examined-ch.patch \
+ file://0007-flash-nor-spi-Add-issi-is25lq040b-to-device-list.patch \
+ file://0008-src-rtos-eCos-Support-per-build-configuration-specif.patch \
+ file://0009-armv8-Add-support-of-pointer-authentication.patch \
+ file://0010-target-armv7m-check-error-in-armv7m_restore_context.patch \
+ file://0011-target-cortex_m-add-SMP-support-for-Cortex-M.patch \
+ file://0012-flash-nor-rp2040-make-SPI-flash-ID-detection-optiona.patch \
+ file://0013-tcl-target-add-SMP-mode-to-rp2040.cfg.patch \
+ file://0014-tcl-target-remove-rp2040-core0.cfg.patch \
+ file://0015-riscv-drop-deprecated-command-riscv-set_prefer_sba.patch \
+ file://0016-riscv-drop-deprecated-command-riscv-test_sba_config_.patch \
+ file://0017-adapter-Improve-three-adapter-related-prints.patch \
+ file://0018-flash-stm32l4x-avoid-multiple-assignments.patch \
+ file://0019-target-armv7m-Rename-xPSR-to-xpsr.patch \
+ file://0020-flash-nor-numicro-reorder-the-parts-list.patch \
+ file://0021-flash-support-Nuvoton-M541-NUC442-472-series.patch \
+ file://0022-tcl-add-a-configuration-file-for-Nuvoton-M541-NUC442.patch \
+ file://0023-flash-nor-contrib-loaders-move-numicro-M4-write-asse.patch \
+ file://0024-flash-nor-contrib-loaders-move-numicro-M0-write-asse.patch \
+ file://0025-doc-usb_adapters-add-container-for-lsusb-dump-of-ada.patch \
+ file://0026-doc-usb_adapters-add-lsusb-dump-of-few-adapters.patch \
+ file://0027-doc-usb_adapters-add-other-adapters.patch \
+ file://0028-tools-add-disassembler-helper-for-files-.inc.patch \
+ file://0029-jtag-drivers-cmsis_dap-move-pending-request-FIFO.patch \
+ file://0030-jtag-drivers-cmsis_dap-use-dap-parameter-instead-of-.patch \
+ file://0031-jtag-drivers-cmsis_dap-use-unsigned-types.patch \
+ file://0032-jtag-drivers-cmsis_dap-introduce-packet_usable_size.patch \
+ file://0033-jtag-drivers-cmsis_dap-improve-USB-packets-filling.patch \
+ file://0034-jtag-drivers-cmsis_dap-speed-up-long-transfers-using.patch \
+ file://0035-jtag-drivers-cmsis_dap-prevent-conn-discon-workaroun.patch \
+ file://0036-tcl-target-enable-rtos-hwthread.patch \
+ file://0037-flash-nor-stm32l4x-Add-revision-X-and-C-for-STM32U57.patch \
+ file://0038-.gitignore-Add-.cache-and-compile_commands.json.patch \
+ file://0039-jtag-parse-command-options-in-swd-newdap.patch \
+ file://0040-jtag-hla-use-generic-helper-for-commands-jtag-newtap.patch \
+ file://0041-flash-nor-psoc4-drop-jtag_poll_mask-from-flash-write.patch \
+ file://0042-helper-Add-generic-little-endian-CRC32-function.patch \
+ file://0043-stm32f3x-Allow-overriding-the-flash-bank-size.patch \
+ file://0044-doc-fix-broken-link-to-IgnoreHardwareSerialNumber-in.patch \
+ file://0045-doc-usb_adapters-add-lsusb-dump-of-esp_usb_jtag.patch \
+ file://0046-rtos-nuttx-move-stacking-info-to-the-new-nuttx-stack.patch \
+ file://0047-rtos-nuttx-add-riscv-stacking-info.patch \
+ file://0048-rtos-add-custom-stack-read-function.patch \
+ file://0049-rtos-nuttx-add-stacking-info-for-Espressif-Xtensa-ch.patch \
+ file://0050-rtos-Support-rt-kernel.patch \
+ file://0051-rtos-Fix-constness-of-struct-rtos_type.patch \
+ file://0052-jtag-drivers-openjtag-fix-annoying-num_cycles-16-war.patch \
+ file://0053-jtag-drivers-bitbang-avoid-mostly-harmless-glitch-on.patch \
+ file://0054-jtag-drivers-bcm2835gpio-use-rounding-in-delay-math.patch \
+ file://0055-jtag-drivers-bcm2835gpio-refactor-delays-to-inline-f.patch \
+ file://0056-tcl-interface-universal-config-for-all-Raspberry-Pi-.patch \
+ file://0057-rtos-remove-config.h-includes-from-stackings-headers.patch \
+ file://0058-jtag-drivers-jlink-allow-SWD-multidrop.patch \
+ file://0059-tcl-target-add-rescue-mode-to-RP2040-config.patch \
+ file://0060-flash-nor-spi-Add-some-zbit-flash-chips.patch \
+ file://0061-target-arc-rewrite-command-arc-jtag-get-aux-reg-as-C.patch \
+ file://0062-target-arc-rewrite-command-arc-jtag-set-aux-reg-as-C.patch \
+ file://0063-target-arc-rewrite-command-arc-jtag-get-core-reg-as-.patch \
+ file://0064-target-arc-rewrite-command-arc-jtag-set-core-reg-as-.patch \
+ file://0065-target-arc-rewrite-command-arc-get-reg-field-as-COMM.patch \
+ file://0066-target-arc-rewrite-command-arc-num-actionpoints-as-C.patch \
+ file://0067-target-arc-fix-error-handling-in-command-arc-set-reg.patch \
+ file://0068-helper-nvp-add-openocd-nvp-files.patch \
+ file://0069-target-arc-rewrite-command-arc-add-reg-type-flags-as.patch \
+ file://0070-target-arc-rewrite-command-arc-add-reg-type-struct-a.patch \
+ file://0071-target-arc-rewrite-command-arc-add-reg-as-COMMAND_HA.patch \
+ file://0072-flash-nor-stm32l4x-Add-revision-Z-for-STM32L552-562-.patch \
+ file://0073-README-Remove-statement-about-libjaylink-Git-submodu.patch \
+ file://0074-new-SPI-memory-devices-continuation-code-for-manufac.patch \
+ file://0075-flash-nor-spi-add-25pe-10-20-40-80-16.patch \
+ file://0076-helper-command-drop-last-LF-n-from-sequence-of-comma.patch \
+ file://0077-jtag-drivers-cmsis_dap-run-queue-on-reaching-transac.patch \
+ file://0078-tlc-interface-does-fix-source-of-raspberrypi-gpio-co.patch \
+ file://0079-tcl-board-at91sam9g20-ek-remove-outdated-FIXME.patch \
+ file://0080-TODO-remove-outdated-AT91SAM92xx-entry.patch \
+ file://0081-drivers-libusb_helper-allow-external-use-of-jtag_lib.patch \
+ file://0082-drivers-ftdi-prevent-misleading-error-msg-when-more-.patch \
+ file://0083-flash-nor-at91samd-fix-RAM-size-for-SAMR34-35.patch \
+ file://0084-flash-nor-at91samd-add-missing-SAMR34-35-part-number.patch \
+ file://0085-doc-add-missing-FreeRTOS-symbol.patch \
+ file://0086-target-image-zero-initialize-ELF-segments-up-to-p_me.patch \
+ file://0087-target-xtensa-add-NX-support.patch \
+ file://0088-helper-add-compiler.h-to-handle-compiler-specific-wo.patch \
+ file://0089-openocd-drop-JIM_EMBEDDED-macro.patch \
+ file://0090-build-fix-distcheck-for-jimtcl.patch \
+ file://0091-jimtcl-update-to-version-0.82.patch \
+ file://0092-tcl-tools-test_cpu_speed-Fix-register-name.patch \
+ file://0093-tcl-remove-exec-permission-to-tcl-config-files.patch \
+ file://0094-svf-new-command-line-options-noreset-and-addcycles.patch \
+ file://0095-helper-compiler-fix-build-on-MacOS.patch \
+ file://0096-rtos-nuttx-add-Espressif-target-support-and-refactor.patch \
+ file://0097-target-espressif-check-common_magic-instead-of-gdb_a.patch \
+ file://0098-target-adi_v5_swd-update-comment-about-SWD-capabilit.patch \
+ file://0099-target-adi_v5_jtag-fix-endianness-error-in-transacti.patch \
+ file://0100-svf-fix-leaking-file-descriptor.patch \
+ file://0101-svf-fix-memory-leak-on-error-during-command-executio.patch \
+ file://0102-svf-make-command-svf-syntax-consistent.patch \
+ file://0103-helper-command-rewrite-command-ocd_find-as-COMMAND_H.patch \
+ file://0104-transport-rewrite-command-transport-select-as-COMMAN.patch \
+ file://0105-flash-nor-rewrite-command-flash-list-as-COMMAND_HAND.patch \
+ file://0106-helper-util-rewrite-command-ms-as-COMMAND_HANDLER.patch \
+ file://0107-openocd-rewrite-command-version-as-COMMAND_HANDLER.patch \
+ file://0108-rtt-rewrite-command-rtt-channellist-as-COMMAND_HANDL.patch \
+ file://0109-target-aarch64-rewrite-commands-aarch64-mcr-mrc-as-C.patch \
+ file://0110-target-armv4_5-rewrite-commands-arm-mcr-mrc-as-COMMA.patch \
+ file://0111-target-cti-rewrite-command-cti-names-as-COMMAND_HAND.patch \
+ file://0112-jtag-rewrite-command-adapter-name-as-COMMAND_HANDLER.patch \
+ file://0113-jtag-rewrite-command-jtag-names-as-COMMAND_HANDLER.patch \
+ file://0114-jtag-rewrite-command-jtag-arp_init-as-COMMAND_HANDLE.patch \
+ file://0115-jtag-rewrite-command-jtag-arp_init-reset-as-COMMAND_.patch \
+ file://0116-jtag-rewrite-command-flush_count-as-COMMAND_HANDLER.patch \
+ file://0117-target-arm_dap-rewrite-command-dap-names-as-COMMAND_.patch \
+ file://0118-target-arm_tpiu_swo-rewrite-command-tpiu-disable-as-.patch \
+ file://0119-target-arm_tpiu_swo-rewrite-command-tpiu-enable-as-C.patch \
+ file://0120-target-arm_tpiu_swo-rewrite-command-tpiu-names-as-CO.patch \
+ file://0121-target-arm_tpiu_swo-rewrite-command-tpiu-init-as-COM.patch \
+ file://0122-target-rewrite-command-read_memory-as-COMMAND_HANDLE.patch \
+ file://0123-target-rewrite-command-target-curstate-as-COMMAND_HA.patch \
+ file://0124-target-rewrite-command-was_examined-as-COMMAND_HANDL.patch \
+ file://0125-target-rewrite-command-examine_deferred-as-COMMAND_H.patch \
+ file://0126-target-rewrite-command-arp_halt_gdb-as-COMMAND_HANDL.patch \
+ file://0127-target-rewrite-command-target-current-as-COMMAND_HAN.patch \
+ file://0128-target-rewrite-command-target-types-as-COMMAND_HANDL.patch \
+ file://0129-target-rewrite-command-target-names-as-COMMAND_HANDL.patch \
+ file://0130-target-rewrite-command-target-smp-as-COMMAND_HANDLER.patch \
+ file://0131-tcl-board-calao-usb-a9260-fix-and-refactor-broken-su.patch \
+ file://0132-tcl-board-add-Calao-USB-A9G20.patch \
+ file://0133-flash-nor-missing-fileio_close.patch \
+ file://0134-github-workflow-increase-delete-tag-and-release-vers.patch \
+ file://0135-github-workflow-build-libjaylink-from-source.patch \
+ file://0136-rtos-FreeRTOS-some-optimization-of-freertos_update_t.patch \
+ file://0137-src-target-mips_m4k-fix-condition-on-overlapping-wor.patch \
+ file://0138-src-target-mips_m4k-add-fast-read-method.patch \
+ file://0139-helper-list-remove-unused-hlist_.patch \
+ file://0140-helper-list-re-align-with-Linux-kernel-6.3-rc1.patch \
+ file://0141-ipdbg-whitespaces.patch \
+ file://0142-helper-compiler-fix-build-with-gcc-on-MacOS.patch \
+ file://0143-tcl-zynq_7000-add-missing-id-codes.patch \
+ file://0144-tcl-cpld-xilinx-xc7-remove-virtex-7-devices-with-ir-.patch \
+ file://0145-doc-drop-resume-will-wait-5-seconds.patch \
+ file://0146-target-espressif-add-application-tracing-functionali.patch \
+ file://0147-src-server-Fix-memory-leak-of-reg_list.patch \
+ file://0148-rtos-linux.c-Fix-Linux-user-space-border-check.patch \
+ file://0149-flash-rsl10-fix-typo.patch \
+ file://0150-pld-move-file-sanity-checks-to-pld.c.patch \
+ file://0151-Committing-changes-from-do_patch.patch \
+ "
SRCREV_FORMAT = "openocd"
SRCREV_openocd = "91bd4313444c5a949ce49d88ab487608df7d6c37"
@@ -17,7 +168,7 @@ SRCREV_git2cl = "8373c9f74993e218a08819cbcdbab3f3564bbeba"
SRCREV_jimtcl = "fcbb4499a6b46ef69e7a95da53e30796e20817f0"
SRCREV_libjaylink = "9aa7a5957c07bb6e862fc1a6d3153d109c7407e4"
-PV = "0.12+gitr${SRCPV}"
+PV = "0.12.0"
S = "${WORKDIR}/git"
inherit pkgconfig autotools-brokensep gettext
Hello, this email is a notification from the Auto Upgrade Helper that the automatic attempt to upgrade the recipe *openocd* to *0.12.0* has Failed(do_compile). Detailed error information: do_compile failed Next steps: - apply the patch: git am 0001-openocd-upgrade-0.12-0.12.0.patch - check the changes to upstream patches and summarize them in the commit message, - compile an image that contains the package - perform some basic sanity tests - amend the patch and sign it off: git commit -s --reset-author --amend - send it to the appropriate mailing list Alternatively, if you believe the recipe should not be upgraded at this time, you can fill RECIPE_NO_UPDATE_REASON in respective recipe file so that automatic upgrades would no longer be attempted. Please review the attached files for further information and build/update failures. Any problem please file a bug at https://bugzilla.yoctoproject.org/enter_bug.cgi?product=Automated%20Update%20Handler Regards, The Upgrade Helper -- >8 -- From 5701927d6fe08949ba5f9d78a4788065e9cda4b0 Mon Sep 17 00:00:00 2001 From: Upgrade Helper <auh@yoctoproject.org> Date: Fri, 3 Nov 2023 17:30:30 +0000 Subject: [PATCH] openocd: upgrade 0.12 -> 0.12.0 --- ...001-Restore-normal-development-cycle.patch | 296 + ...2-Deprecate-libjaylink-Git-submodule.patch | 67 + ...it-together-with-aice-adapter-driver.patch | 19095 ++++++++++++++++ ...t-workarounds-for-expr-syntax-change.patch | 127 + ...lash-nor-avrf-add-ATmega32U4-support.patch | 66 + ...move-needless-target_was_examined-ch.patch | 31 + ...i-Add-issi-is25lq040b-to-device-list.patch | 30 + ...pport-per-build-configuration-specif.patch | 1295 ++ ...dd-support-of-pointer-authentication.patch | 460 + ...heck-error-in-armv7m_restore_context.patch | 34 + ...ortex_m-add-SMP-support-for-Cortex-M.patch | 400 + ...-make-SPI-flash-ID-detection-optiona.patch | 103 + ...cl-target-add-SMP-mode-to-rp2040.cfg.patch | 51 + ...4-tcl-target-remove-rp2040-core0.cfg.patch | 83 + ...recated-command-riscv-set_prefer_sba.patch | 71 + ...cated-command-riscv-test_sba_config_.patch | 480 + ...Improve-three-adapter-related-prints.patch | 66 + ...-stm32l4x-avoid-multiple-assignments.patch | 29 + ...19-target-armv7m-Rename-xPSR-to-xpsr.patch | 34 + ...h-nor-numicro-reorder-the-parts-list.patch | 1395 ++ ...pport-Nuvoton-M541-NUC442-472-series.patch | 649 + ...uration-file-for-Nuvoton-M541-NUC442.patch | 101 + ...b-loaders-move-numicro-M4-write-asse.patch | 216 + ...b-loaders-move-numicro-M0-write-asse.patch | 222 + ...-add-container-for-lsusb-dump-of-ada.patch | 103 + ...pters-add-lsusb-dump-of-few-adapters.patch | 2773 +++ ...-doc-usb_adapters-add-other-adapters.patch | 1326 ++ ...d-disassembler-helper-for-files-.inc.patch | 80 + ...-cmsis_dap-move-pending-request-FIFO.patch | 269 + ...is_dap-use-dap-parameter-instead-of-.patch | 68 + ...drivers-cmsis_dap-use-unsigned-types.patch | 179 + ...sis_dap-introduce-packet_usable_size.patch | 104 + ...msis_dap-improve-USB-packets-filling.patch | 180 + ...is_dap-speed-up-long-transfers-using.patch | 239 + ...is_dap-prevent-conn-discon-workaroun.patch | 34 + ...0036-tcl-target-enable-rtos-hwthread.patch | 84 + ...4x-Add-revision-X-and-C-for-STM32U57.patch | 27 + ...Add-.cache-and-compile_commands.json.patch | 43 + ...-parse-command-options-in-swd-newdap.patch | 49 + ...eric-helper-for-commands-jtag-newtap.patch | 270 + ...drop-jtag_poll_mask-from-flash-write.patch | 40 + ...generic-little-endian-CRC32-function.patch | 216 + ...Allow-overriding-the-flash-bank-size.patch | 44 + ...ink-to-IgnoreHardwareSerialNumber-in.patch | 30 + ...pters-add-lsusb-dump-of-esp_usb_jtag.patch | 185 + ...stacking-info-to-the-new-nuttx-stack.patch | 204 + ...7-rtos-nuttx-add-riscv-stacking-info.patch | 89 + ...-rtos-add-custom-stack-read-function.patch | 52 + ...tacking-info-for-Espressif-Xtensa-ch.patch | 382 + .../openocd/0050-rtos-Support-rt-kernel.patch | 473 + ...os-Fix-constness-of-struct-rtos_type.patch | 168 + ...njtag-fix-annoying-num_cycles-16-war.patch | 51 + ...bang-avoid-mostly-harmless-glitch-on.patch | 68 + ...m2835gpio-use-rounding-in-delay-math.patch | 50 + ...2835gpio-refactor-delays-to-inline-f.patch | 63 + ...iversal-config-for-all-Raspberry-Pi-.patch | 242 + ...ig.h-includes-from-stackings-headers.patch | 237 + ...ag-drivers-jlink-allow-SWD-multidrop.patch | 60 + ...get-add-rescue-mode-to-RP2040-config.patch | 71 + ...sh-nor-spi-Add-some-zbit-flash-chips.patch | 50 + ...te-command-arc-jtag-get-aux-reg-as-C.patch | 81 + ...te-command-arc-jtag-set-aux-reg-as-C.patch | 78 + ...te-command-arc-jtag-get-core-reg-as-.patch | 89 + ...te-command-arc-jtag-set-core-reg-as-.patch | 84 + ...te-command-arc-get-reg-field-as-COMM.patch | 116 + ...te-command-arc-num-actionpoints-as-C.patch | 105 + ...rror-handling-in-command-arc-set-reg.patch | 40 + ...068-helper-nvp-add-openocd-nvp-files.patch | 205 + ...te-command-arc-add-reg-type-flags-as.patch | 293 + ...te-command-arc-add-reg-type-struct-a.patch | 345 + ...te-command-arc-add-reg-as-COMMAND_HA.patch | 334 + ...4x-Add-revision-Z-for-STM32L552-562-.patch | 28 + ...atement-about-libjaylink-Git-submodu.patch | 28 + ...evices-continuation-code-for-manufac.patch | 156 + ...lash-nor-spi-add-25pe-10-20-40-80-16.patch | 31 + ...rop-last-LF-n-from-sequence-of-comma.patch | 83 + ...is_dap-run-queue-on-reaching-transac.patch | 47 + ...es-fix-source-of-raspberrypi-gpio-co.patch | 27 + ...at91sam9g20-ek-remove-outdated-FIXME.patch | 31 + ...DO-remove-outdated-AT91SAM92xx-entry.patch | 31 + ...elper-allow-external-use-of-jtag_lib.patch | 45 + ...vent-misleading-error-msg-when-more-.patch | 111 + ...-at91samd-fix-RAM-size-for-SAMR34-35.patch | 31 + ...md-add-missing-SAMR34-35-part-number.patch | 32 + ...0085-doc-add-missing-FreeRTOS-symbol.patch | 31 + ...o-initialize-ELF-segments-up-to-p_me.patch | 166 + .../0087-target-xtensa-add-NX-support.patch | 806 + ...ler.h-to-handle-compiler-specific-wo.patch | 111 + ...0089-openocd-drop-JIM_EMBEDDED-macro.patch | 35 + .../0090-build-fix-distcheck-for-jimtcl.patch | 81 + .../0091-jimtcl-update-to-version-0.82.patch | 53 + ...ols-test_cpu_speed-Fix-register-name.patch | 30 + ...-exec-permission-to-tcl-config-files.patch | 28 + ...d-line-options-noreset-and-addcycles.patch | 145 + ...5-helper-compiler-fix-build-on-MacOS.patch | 41 + ...spressif-target-support-and-refactor.patch | 758 + ...-check-common_magic-instead-of-gdb_a.patch | 42 + ...d-update-comment-about-SWD-capabilit.patch | 29 + ...ag-fix-endianness-error-in-transacti.patch | 46 + ...0100-svf-fix-leaking-file-descriptor.patch | 54 + ...eak-on-error-during-command-executio.patch | 68 + ...f-make-command-svf-syntax-consistent.patch | 218 + ...ewrite-command-ocd_find-as-COMMAND_H.patch | 62 + ...e-command-transport-select-as-COMMAN.patch | 149 + ...e-command-flash-list-as-COMMAND_HAND.patch | 95 + ...ewrite-command-ms-as-COMMAND_HANDLER.patch | 55 + ...e-command-version-as-COMMAND_HANDLER.patch | 89 + ...and-rtt-channellist-as-COMMAND_HANDL.patch | 158 + ...ewrite-commands-aarch64-mcr-mrc-as-C.patch | 224 + ...ewrite-commands-arm-mcr-mrc-as-COMMA.patch | 222 + ...te-command-cti-names-as-COMMAND_HAND.patch | 58 + ...mand-adapter-name-as-COMMAND_HANDLER.patch | 62 + ...ommand-jtag-names-as-COMMAND_HANDLER.patch | 65 + ...mand-jtag-arp_init-as-COMMAND_HANDLE.patch | 60 + ...mand-jtag-arp_init-reset-as-COMMAND_.patch | 70 + ...mmand-flush_count-as-COMMAND_HANDLER.patch | 53 + ...ewrite-command-dap-names-as-COMMAND_.patch | 58 + ...swo-rewrite-command-tpiu-disable-as-.patch | 76 + ...swo-rewrite-command-tpiu-enable-as-C.patch | 233 + ...swo-rewrite-command-tpiu-names-as-CO.patch | 59 + ...swo-rewrite-command-tpiu-init-as-COM.patch | 58 + ...ommand-read_memory-as-COMMAND_HANDLE.patch | 212 + ...ommand-target-curstate-as-COMMAND_HA.patch | 60 + ...ommand-was_examined-as-COMMAND_HANDL.patch | 53 + ...ommand-examine_deferred-as-COMMAND_H.patch | 53 + ...ommand-arp_halt_gdb-as-COMMAND_HANDL.patch | 56 + ...ommand-target-current-as-COMMAND_HAN.patch | 57 + ...ommand-target-types-as-COMMAND_HANDL.patch | 59 + ...ommand-target-names-as-COMMAND_HANDL.patch | 59 + ...ommand-target-smp-as-COMMAND_HANDLER.patch | 121 + ...usb-a9260-fix-and-refactor-broken-su.patch | 126 + .../0132-tcl-board-add-Calao-USB-A9G20.patch | 37 + .../0133-flash-nor-missing-fileio_close.patch | 28 + ...increase-delete-tag-and-release-vers.patch | 67 + ...orkflow-build-libjaylink-from-source.patch | 96 + ...me-optimization-of-freertos_update_t.patch | 51 + ...m4k-fix-condition-on-overlapping-wor.patch | 38 + ...target-mips_m4k-add-fast-read-method.patch | 119 + ...139-helper-list-remove-unused-hlist_.patch | 285 + ...t-re-align-with-Linux-kernel-6.3-rc1.patch | 145 + .../openocd/0141-ipdbg-whitespaces.patch | 100 + ...compiler-fix-build-with-gcc-on-MacOS.patch | 40 + ...3-tcl-zynq_7000-add-missing-id-codes.patch | 59 + ...xc7-remove-virtex-7-devices-with-ir-.patch | 51 + ...-doc-drop-resume-will-wait-5-seconds.patch | 36 + ...-add-application-tracing-functionali.patch | 2250 ++ ...c-server-Fix-memory-leak-of-reg_list.patch | 28 + ....c-Fix-Linux-user-space-border-check.patch | 29 + .../openocd/0149-flash-rsl10-fix-typo.patch | 27 + ...pld-move-file-sanity-checks-to-pld.c.patch | 90 + ...151-Committing-changes-from-do_patch.patch | 24 + .../recipes-devtools/openocd/openocd_git.bb | 165 +- 152 files changed, 45717 insertions(+), 7 deletions(-) create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0001-Restore-normal-development-cycle.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0002-Deprecate-libjaylink-Git-submodule.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0003-nds32-drop-it-together-with-aice-adapter-driver.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0004-openocd-revert-workarounds-for-expr-syntax-change.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0005-flash-nor-avrf-add-ATmega32U4-support.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0006-target-xtensa-remove-needless-target_was_examined-ch.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0007-flash-nor-spi-Add-issi-is25lq040b-to-device-list.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0008-src-rtos-eCos-Support-per-build-configuration-specif.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0009-armv8-Add-support-of-pointer-authentication.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0010-target-armv7m-check-error-in-armv7m_restore_context.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0011-target-cortex_m-add-SMP-support-for-Cortex-M.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0012-flash-nor-rp2040-make-SPI-flash-ID-detection-optiona.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0013-tcl-target-add-SMP-mode-to-rp2040.cfg.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0014-tcl-target-remove-rp2040-core0.cfg.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0015-riscv-drop-deprecated-command-riscv-set_prefer_sba.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0016-riscv-drop-deprecated-command-riscv-test_sba_config_.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0017-adapter-Improve-three-adapter-related-prints.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0018-flash-stm32l4x-avoid-multiple-assignments.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0019-target-armv7m-Rename-xPSR-to-xpsr.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0020-flash-nor-numicro-reorder-the-parts-list.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0021-flash-support-Nuvoton-M541-NUC442-472-series.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0022-tcl-add-a-configuration-file-for-Nuvoton-M541-NUC442.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0023-flash-nor-contrib-loaders-move-numicro-M4-write-asse.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0024-flash-nor-contrib-loaders-move-numicro-M0-write-asse.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0025-doc-usb_adapters-add-container-for-lsusb-dump-of-ada.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0026-doc-usb_adapters-add-lsusb-dump-of-few-adapters.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0027-doc-usb_adapters-add-other-adapters.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0028-tools-add-disassembler-helper-for-files-.inc.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0029-jtag-drivers-cmsis_dap-move-pending-request-FIFO.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0030-jtag-drivers-cmsis_dap-use-dap-parameter-instead-of-.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0031-jtag-drivers-cmsis_dap-use-unsigned-types.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0032-jtag-drivers-cmsis_dap-introduce-packet_usable_size.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0033-jtag-drivers-cmsis_dap-improve-USB-packets-filling.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0034-jtag-drivers-cmsis_dap-speed-up-long-transfers-using.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0035-jtag-drivers-cmsis_dap-prevent-conn-discon-workaroun.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0036-tcl-target-enable-rtos-hwthread.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0037-flash-nor-stm32l4x-Add-revision-X-and-C-for-STM32U57.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0038-.gitignore-Add-.cache-and-compile_commands.json.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0039-jtag-parse-command-options-in-swd-newdap.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0040-jtag-hla-use-generic-helper-for-commands-jtag-newtap.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0041-flash-nor-psoc4-drop-jtag_poll_mask-from-flash-write.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0042-helper-Add-generic-little-endian-CRC32-function.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0043-stm32f3x-Allow-overriding-the-flash-bank-size.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0044-doc-fix-broken-link-to-IgnoreHardwareSerialNumber-in.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0045-doc-usb_adapters-add-lsusb-dump-of-esp_usb_jtag.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0046-rtos-nuttx-move-stacking-info-to-the-new-nuttx-stack.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0047-rtos-nuttx-add-riscv-stacking-info.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0048-rtos-add-custom-stack-read-function.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0049-rtos-nuttx-add-stacking-info-for-Espressif-Xtensa-ch.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0050-rtos-Support-rt-kernel.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0051-rtos-Fix-constness-of-struct-rtos_type.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0052-jtag-drivers-openjtag-fix-annoying-num_cycles-16-war.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0053-jtag-drivers-bitbang-avoid-mostly-harmless-glitch-on.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0054-jtag-drivers-bcm2835gpio-use-rounding-in-delay-math.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0055-jtag-drivers-bcm2835gpio-refactor-delays-to-inline-f.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0056-tcl-interface-universal-config-for-all-Raspberry-Pi-.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0057-rtos-remove-config.h-includes-from-stackings-headers.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0058-jtag-drivers-jlink-allow-SWD-multidrop.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0059-tcl-target-add-rescue-mode-to-RP2040-config.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0060-flash-nor-spi-Add-some-zbit-flash-chips.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0061-target-arc-rewrite-command-arc-jtag-get-aux-reg-as-C.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0062-target-arc-rewrite-command-arc-jtag-set-aux-reg-as-C.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0063-target-arc-rewrite-command-arc-jtag-get-core-reg-as-.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0064-target-arc-rewrite-command-arc-jtag-set-core-reg-as-.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0065-target-arc-rewrite-command-arc-get-reg-field-as-COMM.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0066-target-arc-rewrite-command-arc-num-actionpoints-as-C.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0067-target-arc-fix-error-handling-in-command-arc-set-reg.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0068-helper-nvp-add-openocd-nvp-files.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0069-target-arc-rewrite-command-arc-add-reg-type-flags-as.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0070-target-arc-rewrite-command-arc-add-reg-type-struct-a.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0071-target-arc-rewrite-command-arc-add-reg-as-COMMAND_HA.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0072-flash-nor-stm32l4x-Add-revision-Z-for-STM32L552-562-.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0073-README-Remove-statement-about-libjaylink-Git-submodu.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0074-new-SPI-memory-devices-continuation-code-for-manufac.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0075-flash-nor-spi-add-25pe-10-20-40-80-16.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0076-helper-command-drop-last-LF-n-from-sequence-of-comma.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0077-jtag-drivers-cmsis_dap-run-queue-on-reaching-transac.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0078-tlc-interface-does-fix-source-of-raspberrypi-gpio-co.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0079-tcl-board-at91sam9g20-ek-remove-outdated-FIXME.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0080-TODO-remove-outdated-AT91SAM92xx-entry.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0081-drivers-libusb_helper-allow-external-use-of-jtag_lib.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0082-drivers-ftdi-prevent-misleading-error-msg-when-more-.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0083-flash-nor-at91samd-fix-RAM-size-for-SAMR34-35.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0084-flash-nor-at91samd-add-missing-SAMR34-35-part-number.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0085-doc-add-missing-FreeRTOS-symbol.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0086-target-image-zero-initialize-ELF-segments-up-to-p_me.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0087-target-xtensa-add-NX-support.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0088-helper-add-compiler.h-to-handle-compiler-specific-wo.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0089-openocd-drop-JIM_EMBEDDED-macro.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0090-build-fix-distcheck-for-jimtcl.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0091-jimtcl-update-to-version-0.82.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0092-tcl-tools-test_cpu_speed-Fix-register-name.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0093-tcl-remove-exec-permission-to-tcl-config-files.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0094-svf-new-command-line-options-noreset-and-addcycles.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0095-helper-compiler-fix-build-on-MacOS.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0096-rtos-nuttx-add-Espressif-target-support-and-refactor.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0097-target-espressif-check-common_magic-instead-of-gdb_a.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0098-target-adi_v5_swd-update-comment-about-SWD-capabilit.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0099-target-adi_v5_jtag-fix-endianness-error-in-transacti.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0100-svf-fix-leaking-file-descriptor.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0101-svf-fix-memory-leak-on-error-during-command-executio.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0102-svf-make-command-svf-syntax-consistent.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0103-helper-command-rewrite-command-ocd_find-as-COMMAND_H.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0104-transport-rewrite-command-transport-select-as-COMMAN.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0105-flash-nor-rewrite-command-flash-list-as-COMMAND_HAND.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0106-helper-util-rewrite-command-ms-as-COMMAND_HANDLER.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0107-openocd-rewrite-command-version-as-COMMAND_HANDLER.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0108-rtt-rewrite-command-rtt-channellist-as-COMMAND_HANDL.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0109-target-aarch64-rewrite-commands-aarch64-mcr-mrc-as-C.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0110-target-armv4_5-rewrite-commands-arm-mcr-mrc-as-COMMA.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0111-target-cti-rewrite-command-cti-names-as-COMMAND_HAND.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0112-jtag-rewrite-command-adapter-name-as-COMMAND_HANDLER.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0113-jtag-rewrite-command-jtag-names-as-COMMAND_HANDLER.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0114-jtag-rewrite-command-jtag-arp_init-as-COMMAND_HANDLE.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0115-jtag-rewrite-command-jtag-arp_init-reset-as-COMMAND_.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0116-jtag-rewrite-command-flush_count-as-COMMAND_HANDLER.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0117-target-arm_dap-rewrite-command-dap-names-as-COMMAND_.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0118-target-arm_tpiu_swo-rewrite-command-tpiu-disable-as-.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0119-target-arm_tpiu_swo-rewrite-command-tpiu-enable-as-C.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0120-target-arm_tpiu_swo-rewrite-command-tpiu-names-as-CO.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0121-target-arm_tpiu_swo-rewrite-command-tpiu-init-as-COM.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0122-target-rewrite-command-read_memory-as-COMMAND_HANDLE.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0123-target-rewrite-command-target-curstate-as-COMMAND_HA.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0124-target-rewrite-command-was_examined-as-COMMAND_HANDL.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0125-target-rewrite-command-examine_deferred-as-COMMAND_H.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0126-target-rewrite-command-arp_halt_gdb-as-COMMAND_HANDL.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0127-target-rewrite-command-target-current-as-COMMAND_HAN.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0128-target-rewrite-command-target-types-as-COMMAND_HANDL.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0129-target-rewrite-command-target-names-as-COMMAND_HANDL.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0130-target-rewrite-command-target-smp-as-COMMAND_HANDLER.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0131-tcl-board-calao-usb-a9260-fix-and-refactor-broken-su.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0132-tcl-board-add-Calao-USB-A9G20.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0133-flash-nor-missing-fileio_close.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0134-github-workflow-increase-delete-tag-and-release-vers.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0135-github-workflow-build-libjaylink-from-source.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0136-rtos-FreeRTOS-some-optimization-of-freertos_update_t.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0137-src-target-mips_m4k-fix-condition-on-overlapping-wor.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0138-src-target-mips_m4k-add-fast-read-method.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0139-helper-list-remove-unused-hlist_.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0140-helper-list-re-align-with-Linux-kernel-6.3-rc1.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0141-ipdbg-whitespaces.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0142-helper-compiler-fix-build-with-gcc-on-MacOS.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0143-tcl-zynq_7000-add-missing-id-codes.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0144-tcl-cpld-xilinx-xc7-remove-virtex-7-devices-with-ir-.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0145-doc-drop-resume-will-wait-5-seconds.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0146-target-espressif-add-application-tracing-functionali.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0147-src-server-Fix-memory-leak-of-reg_list.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0148-rtos-linux.c-Fix-Linux-user-space-border-check.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0149-flash-rsl10-fix-typo.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0150-pld-move-file-sanity-checks-to-pld.c.patch create mode 100644 meta-oe/recipes-devtools/openocd/openocd/0151-Committing-changes-from-do_patch.patch