diff mbox series

[AUH] openocd: upgrading to 0.12.0 FAILED

Message ID 0101018b96bee806-c64e7174-8dbd-41c6-848e-43e3abb36c98-000000@us-west-2.amazonses.com
State New
Headers show
Series [AUH] openocd: upgrading to 0.12.0 FAILED | expand

Commit Message

auh@yoctoproject.org Nov. 3, 2023, 7:52 p.m. UTC
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
diff mbox series

Patch

diff --git a/meta-oe/recipes-devtools/openocd/openocd/0001-Restore-normal-development-cycle.patch b/meta-oe/recipes-devtools/openocd/openocd/0001-Restore-normal-development-cycle.patch
new file mode 100644
index 000000000..91a724b11
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0001-Restore-normal-development-cycle.patch
@@ -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])
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0002-Deprecate-libjaylink-Git-submodule.patch b/meta-oe/recipes-devtools/openocd/openocd/0002-Deprecate-libjaylink-Git-submodule.patch
new file mode 100644
index 000000000..539007fef
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0002-Deprecate-libjaylink-Git-submodule.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0003-nds32-drop-it-together-with-aice-adapter-driver.patch b/meta-oe/recipes-devtools/openocd/openocd/0003-nds32-drop-it-together-with-aice-adapter-driver.patch
new file mode 100644
index 000000000..01c9c1660
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0003-nds32-drop-it-together-with-aice-adapter-driver.patch
@@ -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(&param) != 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 = &reg_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, &reg_r0);
+-	nds32_get_mapped_reg(nds32, R1, &reg_r1);
+-	nds32_get_mapped_reg(nds32, R2, &reg_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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0004-openocd-revert-workarounds-for-expr-syntax-change.patch b/meta-oe/recipes-devtools/openocd/openocd/0004-openocd-revert-workarounds-for-expr-syntax-change.patch
new file mode 100644
index 000000000..766790bf1
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0004-openocd-revert-workarounds-for-expr-syntax-change.patch
@@ -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,
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0005-flash-nor-avrf-add-ATmega32U4-support.patch b/meta-oe/recipes-devtools/openocd/openocd/0005-flash-nor-avrf-add-ATmega32U4-support.patch
new file mode 100644
index 000000000..0473d29bc
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0005-flash-nor-avrf-add-ATmega32U4-support.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0006-target-xtensa-remove-needless-target_was_examined-ch.patch b/meta-oe/recipes-devtools/openocd/openocd/0006-target-xtensa-remove-needless-target_was_examined-ch.patch
new file mode 100644
index 000000000..1fcbd580a
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0006-target-xtensa-remove-needless-target_was_examined-ch.patch
@@ -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;
+ }
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0007-flash-nor-spi-Add-issi-is25lq040b-to-device-list.patch b/meta-oe/recipes-devtools/openocd/openocd/0007-flash-nor-spi-Add-issi-is25lq040b-to-device-list.patch
new file mode 100644
index 000000000..587a66a86
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0007-flash-nor-spi-Add-issi-is25lq040b-to-device-list.patch
@@ -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),
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0008-src-rtos-eCos-Support-per-build-configuration-specif.patch b/meta-oe/recipes-devtools/openocd/openocd/0008-src-rtos-eCos-Support-per-build-configuration-specif.patch
new file mode 100644
index 000000000..f64a45b97
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0008-src-rtos-eCos-Support-per-build-configuration-specif.patch
@@ -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('<', "&lt;"),
++	XMLENTRY('&', "&amp;"),
++	XMLENTRY('>', "&gt;"),
++	XMLENTRY('\'', "&apos;"),
++	XMLENTRY('"', "&quot;")
++};
++
++/** 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 *)&current_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, &current_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   */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0009-armv8-Add-support-of-pointer-authentication.patch b/meta-oe/recipes-devtools/openocd/openocd/0009-armv8-Add-support-of-pointer-authentication.patch
new file mode 100644
index 000000000..c9081a3f9
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0009-armv8-Add-support-of-pointer-authentication.patch
@@ -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;
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0010-target-armv7m-check-error-in-armv7m_restore_context.patch b/meta-oe/recipes-devtools/openocd/openocd/0010-target-armv7m-check-error-in-armv7m_restore_context.patch
new file mode 100644
index 000000000..b694f5565
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0010-target-armv7m-check-error-in-armv7m_restore_context.patch
@@ -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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0011-target-cortex_m-add-SMP-support-for-Cortex-M.patch b/meta-oe/recipes-devtools/openocd/openocd/0011-target-cortex_m-add-SMP-support-for-Cortex-M.patch
new file mode 100644
index 000000000..bffd6269c
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0011-target-cortex_m-add-SMP-support-for-Cortex-M.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0012-flash-nor-rp2040-make-SPI-flash-ID-detection-optiona.patch b/meta-oe/recipes-devtools/openocd/openocd/0012-flash-nor-rp2040-make-SPI-flash-ID-detection-optiona.patch
new file mode 100644
index 000000000..7358bfc9a
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0012-flash-nor-rp2040-make-SPI-flash-ID-detection-optiona.patch
@@ -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)
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0013-tcl-target-add-SMP-mode-to-rp2040.cfg.patch b/meta-oe/recipes-devtools/openocd/openocd/0013-tcl-target-add-SMP-mode-to-rp2040.cfg.patch
new file mode 100644
index 000000000..0fff6b8b6
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0013-tcl-target-add-SMP-mode-to-rp2040.cfg.patch
@@ -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 {
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0014-tcl-target-remove-rp2040-core0.cfg.patch b/meta-oe/recipes-devtools/openocd/openocd/0014-tcl-target-remove-rp2040-core0.cfg.patch
new file mode 100644
index 000000000..e82b5860d
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0014-tcl-target-remove-rp2040-core0.cfg.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0015-riscv-drop-deprecated-command-riscv-set_prefer_sba.patch b/meta-oe/recipes-devtools/openocd/openocd/0015-riscv-drop-deprecated-command-riscv-set_prefer_sba.patch
new file mode 100644
index 000000000..282940944
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0015-riscv-drop-deprecated-command-riscv-set_prefer_sba.patch
@@ -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,
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0016-riscv-drop-deprecated-command-riscv-test_sba_config_.patch b/meta-oe/recipes-devtools/openocd/openocd/0016-riscv-drop-deprecated-command-riscv-test_sba_config_.patch
new file mode 100644
index 000000000..ca4e83581
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0016-riscv-drop-deprecated-command-riscv-test_sba_config_.patch
@@ -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,
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0017-adapter-Improve-three-adapter-related-prints.patch b/meta-oe/recipes-devtools/openocd/openocd/0017-adapter-Improve-three-adapter-related-prints.patch
new file mode 100644
index 000000000..216adcda1
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0017-adapter-Improve-three-adapter-related-prints.patch
@@ -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]);
+ 	}
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0018-flash-stm32l4x-avoid-multiple-assignments.patch b/meta-oe/recipes-devtools/openocd/openocd/0018-flash-stm32l4x-avoid-multiple-assignments.patch
new file mode 100644
index 000000000..380c86714
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0018-flash-stm32l4x-avoid-multiple-assignments.patch
@@ -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)
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0019-target-armv7m-Rename-xPSR-to-xpsr.patch b/meta-oe/recipes-devtools/openocd/openocd/0019-target-armv7m-Rename-xPSR-to-xpsr.patch
new file mode 100644
index 000000000..1b0343442
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0019-target-armv7m-Rename-xPSR-to-xpsr.patch
@@ -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" },
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0020-flash-nor-numicro-reorder-the-parts-list.patch b/meta-oe/recipes-devtools/openocd/openocd/0020-flash-nor-numicro-reorder-the-parts-list.patch
new file mode 100644
index 000000000..47bec1988
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0020-flash-nor-numicro-reorder-the-parts-list.patch
@@ -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. */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0021-flash-support-Nuvoton-M541-NUC442-472-series.patch b/meta-oe/recipes-devtools/openocd/openocd/0021-flash-support-Nuvoton-M541-NUC442-472-series.patch
new file mode 100644
index 000000000..42bf2cd95
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0021-flash-support-Nuvoton-M541-NUC442-472-series.patch
@@ -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, &reg_stat);
++	retval = target_read_u32(target, NUMICRO_SYSCLK_AHBCLK - m_address_bias_offset, &reg_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, &reg_stat);
++	retval = target_read_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, &reg_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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0022-tcl-add-a-configuration-file-for-Nuvoton-M541-NUC442.patch b/meta-oe/recipes-devtools/openocd/openocd/0022-tcl-add-a-configuration-file-for-Nuvoton-M541-NUC442.patch
new file mode 100644
index 000000000..27bd959ad
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0022-tcl-add-a-configuration-file-for-Nuvoton-M541-NUC442.patch
@@ -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
++}
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0023-flash-nor-contrib-loaders-move-numicro-M4-write-asse.patch b/meta-oe/recipes-devtools/openocd/openocd/0023-flash-nor-contrib-loaders-move-numicro-M4-write-asse.patch
new file mode 100644
index 000000000..e36244f62
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0023-flash-nor-contrib-loaders-move-numicro-M4-write-asse.patch
@@ -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 */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0024-flash-nor-contrib-loaders-move-numicro-M0-write-asse.patch b/meta-oe/recipes-devtools/openocd/openocd/0024-flash-nor-contrib-loaders-move-numicro-M0-write-asse.patch
new file mode 100644
index 000000000..da6f75c46
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0024-flash-nor-contrib-loaders-move-numicro-M0-write-asse.patch
@@ -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 */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0025-doc-usb_adapters-add-container-for-lsusb-dump-of-ada.patch b/meta-oe/recipes-devtools/openocd/openocd/0025-doc-usb_adapters-add-container-for-lsusb-dump-of-ada.patch
new file mode 100644
index 000000000..209dae10b
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0025-doc-usb_adapters-add-container-for-lsusb-dump-of-ada.patch
@@ -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.
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0026-doc-usb_adapters-add-lsusb-dump-of-few-adapters.patch b/meta-oe/recipes-devtools/openocd/openocd/0026-doc-usb_adapters-add-lsusb-dump-of-few-adapters.patch
new file mode 100644
index 000000000..5c99855a7
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0026-doc-usb_adapters-add-lsusb-dump-of-few-adapters.patch
@@ -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)
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0027-doc-usb_adapters-add-other-adapters.patch b/meta-oe/recipes-devtools/openocd/openocd/0027-doc-usb_adapters-add-other-adapters.patch
new file mode 100644
index 000000000..97f25245c
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0027-doc-usb_adapters-add-other-adapters.patch
@@ -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)
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0028-tools-add-disassembler-helper-for-files-.inc.patch b/meta-oe/recipes-devtools/openocd/openocd/0028-tools-add-disassembler-helper-for-files-.inc.patch
new file mode 100644
index 000000000..1984e59c0
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0028-tools-add-disassembler-helper-for-files-.inc.patch
@@ -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}
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0029-jtag-drivers-cmsis_dap-move-pending-request-FIFO.patch b/meta-oe/recipes-devtools/openocd/openocd/0029-jtag-drivers-cmsis_dap-move-pending-request-FIFO.patch
new file mode 100644
index 000000000..81d0828ca
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0029-jtag-drivers-cmsis_dap-move-pending-request-FIFO.patch
@@ -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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0030-jtag-drivers-cmsis_dap-use-dap-parameter-instead-of-.patch b/meta-oe/recipes-devtools/openocd/openocd/0030-jtag-drivers-cmsis_dap-use-dap-parameter-instead-of-.patch
new file mode 100644
index 000000000..8c5f74621
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0030-jtag-drivers-cmsis_dap-use-dap-parameter-instead-of-.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0031-jtag-drivers-cmsis_dap-use-unsigned-types.patch b/meta-oe/recipes-devtools/openocd/openocd/0031-jtag-drivers-cmsis_dap-use-unsigned-types.patch
new file mode 100644
index 000000000..71d660cf9
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0031-jtag-drivers-cmsis_dap-use-unsigned-types.patch
@@ -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;
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0032-jtag-drivers-cmsis_dap-introduce-packet_usable_size.patch b/meta-oe/recipes-devtools/openocd/openocd/0032-jtag-drivers-cmsis_dap-introduce-packet_usable_size.patch
new file mode 100644
index 000000000..f848b75d8
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0032-jtag-drivers-cmsis_dap-introduce-packet_usable_size.patch
@@ -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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0033-jtag-drivers-cmsis_dap-improve-USB-packets-filling.patch b/meta-oe/recipes-devtools/openocd/openocd/0033-jtag-drivers-cmsis_dap-improve-USB-packets-filling.patch
new file mode 100644
index 000000000..6fa1aee1a
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0033-jtag-drivers-cmsis_dap-improve-USB-packets-filling.patch
@@ -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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0034-jtag-drivers-cmsis_dap-speed-up-long-transfers-using.patch b/meta-oe/recipes-devtools/openocd/openocd/0034-jtag-drivers-cmsis_dap-speed-up-long-transfers-using.patch
new file mode 100644
index 000000000..f1bba4651
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0034-jtag-drivers-cmsis_dap-speed-up-long-transfers-using.patch
@@ -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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0035-jtag-drivers-cmsis_dap-prevent-conn-discon-workaroun.patch b/meta-oe/recipes-devtools/openocd/openocd/0035-jtag-drivers-cmsis_dap-prevent-conn-discon-workaroun.patch
new file mode 100644
index 000000000..b2ce3b27b
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0035-jtag-drivers-cmsis_dap-prevent-conn-discon-workaroun.patch
@@ -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. */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0036-tcl-target-enable-rtos-hwthread.patch b/meta-oe/recipes-devtools/openocd/openocd/0036-tcl-target-enable-rtos-hwthread.patch
new file mode 100644
index 000000000..4537346c3
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0036-tcl-target-enable-rtos-hwthread.patch
@@ -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"
+     }
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0037-flash-nor-stm32l4x-Add-revision-X-and-C-for-STM32U57.patch b/meta-oe/recipes-devtools/openocd/openocd/0037-flash-nor-stm32l4x-Add-revision-X-and-C-for-STM32U57.patch
new file mode 100644
index 000000000..251c39da3
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0037-flash-nor-stm32l4x-Add-revision-X-and-C-for-STM32U57.patch
@@ -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[] = {
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0038-.gitignore-Add-.cache-and-compile_commands.json.patch b/meta-oe/recipes-devtools/openocd/openocd/0038-.gitignore-Add-.cache-and-compile_commands.json.patch
new file mode 100644
index 000000000..a912e5b04
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0038-.gitignore-Add-.cache-and-compile_commands.json.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0039-jtag-parse-command-options-in-swd-newdap.patch b/meta-oe/recipes-devtools/openocd/openocd/0039-jtag-parse-command-options-in-swd-newdap.patch
new file mode 100644
index 000000000..bc449bd7c
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0039-jtag-parse-command-options-in-swd-newdap.patch
@@ -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;
+ 	}
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0040-jtag-hla-use-generic-helper-for-commands-jtag-newtap.patch b/meta-oe/recipes-devtools/openocd/openocd/0040-jtag-hla-use-generic-helper-for-commands-jtag-newtap.patch
new file mode 100644
index 000000000..a9f75aeeb
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0040-jtag-hla-use-generic-helper-for-commands-jtag-newtap.patch
@@ -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 "
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0041-flash-nor-psoc4-drop-jtag_poll_mask-from-flash-write.patch b/meta-oe/recipes-devtools/openocd/openocd/0041-flash-nor-psoc4-drop-jtag_poll_mask-from-flash-write.patch
new file mode 100644
index 000000000..64f1b07c1
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0041-flash-nor-psoc4-drop-jtag_poll_mask-from-flash-write.patch
@@ -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;
+ }
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0042-helper-Add-generic-little-endian-CRC32-function.patch b/meta-oe/recipes-devtools/openocd/openocd/0042-helper-Add-generic-little-endian-CRC32-function.patch
new file mode 100644
index 000000000..6a234984e
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0042-helper-Add-generic-little-endian-CRC32-function.patch
@@ -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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0043-stm32f3x-Allow-overriding-the-flash-bank-size.patch b/meta-oe/recipes-devtools/openocd/openocd/0043-stm32f3x-Allow-overriding-the-flash-bank-size.patch
new file mode 100644
index 000000000..d6a4bcbf1
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0043-stm32f3x-Allow-overriding-the-flash-bank-size.patch
@@ -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
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0044-doc-fix-broken-link-to-IgnoreHardwareSerialNumber-in.patch b/meta-oe/recipes-devtools/openocd/openocd/0044-doc-fix-broken-link-to-IgnoreHardwareSerialNumber-in.patch
new file mode 100644
index 000000000..92a20916a
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0044-doc-fix-broken-link-to-IgnoreHardwareSerialNumber-in.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0045-doc-usb_adapters-add-lsusb-dump-of-esp_usb_jtag.patch b/meta-oe/recipes-devtools/openocd/openocd/0045-doc-usb_adapters-add-lsusb-dump-of-esp_usb_jtag.patch
new file mode 100644
index 000000000..f81687d89
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0045-doc-usb_adapters-add-lsusb-dump-of-esp_usb_jtag.patch
@@ -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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0046-rtos-nuttx-move-stacking-info-to-the-new-nuttx-stack.patch b/meta-oe/recipes-devtools/openocd/openocd/0046-rtos-nuttx-move-stacking-info-to-the-new-nuttx-stack.patch
new file mode 100644
index 000000000..53c7c77fd
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0046-rtos-nuttx-move-stacking-info-to-the-new-nuttx-stack.patch
@@ -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 */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0047-rtos-nuttx-add-riscv-stacking-info.patch b/meta-oe/recipes-devtools/openocd/openocd/0047-rtos-nuttx-add-riscv-stacking-info.patch
new file mode 100644
index 000000000..3a3c1a733
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0047-rtos-nuttx-add-riscv-stacking-info.patch
@@ -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 */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0048-rtos-add-custom-stack-read-function.patch b/meta-oe/recipes-devtools/openocd/openocd/0048-rtos-add-custom-stack-read-function.patch
new file mode 100644
index 000000000..626b3b674
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0048-rtos-add-custom-stack-read-function.patch
@@ -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)
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0049-rtos-nuttx-add-stacking-info-for-Espressif-Xtensa-ch.patch b/meta-oe/recipes-devtools/openocd/openocd/0049-rtos-nuttx-add-stacking-info-for-Espressif-Xtensa-ch.patch
new file mode 100644
index 000000000..a4cdebd65
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0049-rtos-nuttx-add-stacking-info-for-Espressif-Xtensa-ch.patch
@@ -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,
++};
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0050-rtos-Support-rt-kernel.patch b/meta-oe/recipes-devtools/openocd/openocd/0050-rtos-Support-rt-kernel.patch
new file mode 100644
index 000000000..d8428dc6b
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0050-rtos-Support-rt-kernel.patch
@@ -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,
++			&current_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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0051-rtos-Fix-constness-of-struct-rtos_type.patch b/meta-oe/recipes-devtools/openocd/openocd/0051-rtos-Fix-constness-of-struct-rtos_type.patch
new file mode 100644
index 000000000..7d6ea6709
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0051-rtos-Fix-constness-of-struct-rtos_type.patch
@@ -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,
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0052-jtag-drivers-openjtag-fix-annoying-num_cycles-16-war.patch b/meta-oe/recipes-devtools/openocd/openocd/0052-jtag-drivers-openjtag-fix-annoying-num_cycles-16-war.patch
new file mode 100644
index 000000000..c6619e88b
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0052-jtag-drivers-openjtag-fix-annoying-num_cycles-16-war.patch
@@ -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);
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0053-jtag-drivers-bitbang-avoid-mostly-harmless-glitch-on.patch b/meta-oe/recipes-devtools/openocd/openocd/0053-jtag-drivers-bitbang-avoid-mostly-harmless-glitch-on.patch
new file mode 100644
index 000000000..f92c29133
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0053-jtag-drivers-bitbang-avoid-mostly-harmless-glitch-on.patch
@@ -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);
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0054-jtag-drivers-bcm2835gpio-use-rounding-in-delay-math.patch b/meta-oe/recipes-devtools/openocd/openocd/0054-jtag-drivers-bcm2835gpio-use-rounding-in-delay-math.patch
new file mode 100644
index 000000000..a9a9d237a
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0054-jtag-drivers-bcm2835gpio-use-rounding-in-delay-math.patch
@@ -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;
+ }
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0055-jtag-drivers-bcm2835gpio-refactor-delays-to-inline-f.patch b/meta-oe/recipes-devtools/openocd/openocd/0055-jtag-drivers-bcm2835gpio-refactor-delays-to-inline-f.patch
new file mode 100644
index 000000000..7e24aeb5d
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0055-jtag-drivers-bcm2835gpio-refactor-delays-to-inline-f.patch
@@ -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;
+ }
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0056-tcl-interface-universal-config-for-all-Raspberry-Pi-.patch b/meta-oe/recipes-devtools/openocd/openocd/0056-tcl-interface-universal-config-for-all-Raspberry-Pi-.patch
new file mode 100644
index 000000000..52a435c80
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0056-tcl-interface-universal-config-for-all-Raspberry-Pi-.patch
@@ -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]
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0057-rtos-remove-config.h-includes-from-stackings-headers.patch b/meta-oe/recipes-devtools/openocd/openocd/0057-rtos-remove-config.h-includes-from-stackings-headers.patch
new file mode 100644
index 000000000..ae529b18c
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0057-rtos-remove-config.h-includes-from-stackings-headers.patch
@@ -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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0058-jtag-drivers-jlink-allow-SWD-multidrop.patch b/meta-oe/recipes-devtools/openocd/openocd/0058-jtag-drivers-jlink-allow-SWD-multidrop.patch
new file mode 100644
index 000000000..ba75b3d35
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0058-jtag-drivers-jlink-allow-SWD-multidrop.patch
@@ -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);
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0059-tcl-target-add-rescue-mode-to-RP2040-config.patch b/meta-oe/recipes-devtools/openocd/openocd/0059-tcl-target-add-rescue-mode-to-RP2040-config.patch
new file mode 100644
index 000000000..3a4a96e00
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0059-tcl-target-add-rescue-mode-to-RP2040-config.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0060-flash-nor-spi-Add-some-zbit-flash-chips.patch b/meta-oe/recipes-devtools/openocd/openocd/0060-flash-nor-spi-Add-some-zbit-flash-chips.patch
new file mode 100644
index 000000000..9b65c75fa
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0060-flash-nor-spi-Add-some-zbit-flash-chips.patch
@@ -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),
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0061-target-arc-rewrite-command-arc-jtag-get-aux-reg-as-C.patch b/meta-oe/recipes-devtools/openocd/openocd/0061-target-arc-rewrite-command-arc-jtag-get-aux-reg-as-C.patch
new file mode 100644
index 000000000..8d92ccec3
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0061-target-arc-rewrite-command-arc-jtag-get-aux-reg-as-C.patch
@@ -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, &regnum));
++	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 "
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0062-target-arc-rewrite-command-arc-jtag-set-aux-reg-as-C.patch b/meta-oe/recipes-devtools/openocd/openocd/0062-target-arc-rewrite-command-arc-jtag-set-aux-reg-as-C.patch
new file mode 100644
index 000000000..c3aab0f52
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0062-target-arc-rewrite-command-arc-jtag-set-aux-reg-as-C.patch
@@ -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, &regnum));
++	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 "
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0063-target-arc-rewrite-command-arc-jtag-get-core-reg-as-.patch b/meta-oe/recipes-devtools/openocd/openocd/0063-target-arc-rewrite-command-arc-jtag-get-core-reg-as-.patch
new file mode 100644
index 000000000..0a5b3531d
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0063-target-arc-rewrite-command-arc-jtag-get-core-reg-as-.patch
@@ -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, &regnum));
++	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 "
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0064-target-arc-rewrite-command-arc-jtag-set-core-reg-as-.patch b/meta-oe/recipes-devtools/openocd/openocd/0064-target-arc-rewrite-command-arc-jtag-set-core-reg-as-.patch
new file mode 100644
index 000000000..87cb7ddea
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0064-target-arc-rewrite-command-arc-jtag-set-core-reg-as-.patch
@@ -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, &regnum));
++	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 "
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0065-target-arc-rewrite-command-arc-get-reg-field-as-COMM.patch b/meta-oe/recipes-devtools/openocd/openocd/0065-target-arc-rewrite-command-arc-get-reg-field-as-COMM.patch
new file mode 100644
index 000000000..31fc7f866
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0065-target-arc-rewrite-command-arc-get-reg-field-as-COMM.patch
@@ -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, &reg_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.",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0066-target-arc-rewrite-command-arc-num-actionpoints-as-C.patch b/meta-oe/recipes-devtools/openocd/openocd/0066-target-arc-rewrite-command-arc-num-actionpoints-as-C.patch
new file mode 100644
index 000000000..a6cc0fd28
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0066-target-arc-rewrite-command-arc-num-actionpoints-as-C.patch
@@ -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.",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0067-target-arc-fix-error-handling-in-command-arc-set-reg.patch b/meta-oe/recipes-devtools/openocd/openocd/0067-target-arc-fix-error-handling-in-command-arc-set-reg.patch
new file mode 100644
index 000000000..7e8a5bcd0
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0067-target-arc-fix-error-handling-in-command-arc-set-reg.patch
@@ -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)
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0068-helper-nvp-add-openocd-nvp-files.patch b/meta-oe/recipes-devtools/openocd/openocd/0068-helper-nvp-add-openocd-nvp-files.patch
new file mode 100644
index 000000000..dbfb2fcb3
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0068-helper-nvp-add-openocd-nvp-files.patch
@@ -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 */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0069-target-arc-rewrite-command-arc-add-reg-type-flags-as.patch b/meta-oe/recipes-devtools/openocd/openocd/0069-target-arc-rewrite-command-arc-add-reg-type-flags-as.patch
new file mode 100644
index 000000000..18f8f6798
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0069-target-arc-rewrite-command-arc-add-reg-type-flags-as.patch
@@ -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>]...",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0070-target-arc-rewrite-command-arc-add-reg-type-struct-a.patch b/meta-oe/recipes-devtools/openocd/openocd/0070-target-arc-rewrite-command-arc-add-reg-type-struct-a.patch
new file mode 100644
index 000000000..957567321
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0070-target-arc-rewrite-command-arc-add-reg-type-struct-a.patch
@@ -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>]...",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0071-target-arc-rewrite-command-arc-add-reg-as-COMMAND_HA.patch b/meta-oe/recipes-devtools/openocd/openocd/0071-target-arc-rewrite-command-arc-add-reg-as-COMMAND_HA.patch
new file mode 100644
index 000000000..a78e69364
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0071-target-arc-rewrite-command-arc-add-reg-as-COMMAND_HA.patch
@@ -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, &reg_name, &reg_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]",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0072-flash-nor-stm32l4x-Add-revision-Z-for-STM32L552-562-.patch b/meta-oe/recipes-devtools/openocd/openocd/0072-flash-nor-stm32l4x-Add-revision-Z-for-STM32L552-562-.patch
new file mode 100644
index 000000000..48cba6844
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0072-flash-nor-stm32l4x-Add-revision-Z-for-STM32L552-562-.patch
@@ -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[] = {
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0073-README-Remove-statement-about-libjaylink-Git-submodu.patch b/meta-oe/recipes-devtools/openocd/openocd/0073-README-Remove-statement-about-libjaylink-Git-submodu.patch
new file mode 100644
index 000000000..eeaefaf0e
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0073-README-Remove-statement-about-libjaylink-Git-submodu.patch
@@ -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.
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0074-new-SPI-memory-devices-continuation-code-for-manufac.patch b/meta-oe/recipes-devtools/openocd/openocd/0074-new-SPI-memory-devices-continuation-code-for-manufac.patch
new file mode 100644
index 000000000..b54eeecc7
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0074-new-SPI-memory-devices-continuation-code-for-manufac.patch
@@ -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)
+ };
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0075-flash-nor-spi-add-25pe-10-20-40-80-16.patch b/meta-oe/recipes-devtools/openocd/openocd/0075-flash-nor-spi-add-25pe-10-20-40-80-16.patch
new file mode 100644
index 000000000..feae06481
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0075-flash-nor-spi-add-25pe-10-20-40-80-16.patch
@@ -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),
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0076-helper-command-drop-last-LF-n-from-sequence-of-comma.patch b/meta-oe/recipes-devtools/openocd/openocd/0076-helper-command-drop-last-LF-n-from-sequence-of-comma.patch
new file mode 100644
index 000000000..a68f0c99f
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0076-helper-command-drop-last-LF-n-from-sequence-of-comma.patch
@@ -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)));
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0077-jtag-drivers-cmsis_dap-run-queue-on-reaching-transac.patch b/meta-oe/recipes-devtools/openocd/openocd/0077-jtag-drivers-cmsis_dap-run-queue-on-reaching-transac.patch
new file mode 100644
index 000000000..7bae45d01
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0077-jtag-drivers-cmsis_dap-run-queue-on-reaching-transac.patch
@@ -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);
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0078-tlc-interface-does-fix-source-of-raspberrypi-gpio-co.patch b/meta-oe/recipes-devtools/openocd/openocd/0078-tlc-interface-does-fix-source-of-raspberrypi-gpio-co.patch
new file mode 100644
index 000000000..a88e83fad
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0078-tlc-interface-does-fix-source-of-raspberrypi-gpio-co.patch
@@ -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]
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0079-tcl-board-at91sam9g20-ek-remove-outdated-FIXME.patch b/meta-oe/recipes-devtools/openocd/openocd/0079-tcl-board-at91sam9g20-ek-remove-outdated-FIXME.patch
new file mode 100644
index 000000000..4b030aa95
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0079-tcl-board-at91sam9g20-ek-remove-outdated-FIXME.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0080-TODO-remove-outdated-AT91SAM92xx-entry.patch b/meta-oe/recipes-devtools/openocd/openocd/0080-TODO-remove-outdated-AT91SAM92xx-entry.patch
new file mode 100644
index 000000000..b2a674c52
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0080-TODO-remove-outdated-AT91SAM92xx-entry.patch
@@ -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)
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0081-drivers-libusb_helper-allow-external-use-of-jtag_lib.patch b/meta-oe/recipes-devtools/openocd/openocd/0081-drivers-libusb_helper-allow-external-use-of-jtag_lib.patch
new file mode 100644
index 000000000..16d9a9794
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0081-drivers-libusb_helper-allow-external-use-of-jtag_lib.patch
@@ -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);
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0082-drivers-ftdi-prevent-misleading-error-msg-when-more-.patch b/meta-oe/recipes-devtools/openocd/openocd/0082-drivers-ftdi-prevent-misleading-error-msg-when-more-.patch
new file mode 100644
index 000000000..ef88dc83a
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0082-drivers-ftdi-prevent-misleading-error-msg-when-more-.patch
@@ -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 : "*");
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0083-flash-nor-at91samd-fix-RAM-size-for-SAMR34-35.patch b/meta-oe/recipes-devtools/openocd/openocd/0083-flash-nor-at91samd-fix-RAM-size-for-SAMR34-35.patch
new file mode 100644
index 000000000..c3c424f87
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0083-flash-nor-at91samd-fix-RAM-size-for-SAMR34-35.patch
@@ -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. */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0084-flash-nor-at91samd-add-missing-SAMR34-35-part-number.patch b/meta-oe/recipes-devtools/openocd/openocd/0084-flash-nor-at91samd-add-missing-SAMR34-35-part-number.patch
new file mode 100644
index 000000000..0248894e5
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0084-flash-nor-at91samd-add-missing-SAMR34-35-part-number.patch
@@ -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. */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0085-doc-add-missing-FreeRTOS-symbol.patch b/meta-oe/recipes-devtools/openocd/openocd/0085-doc-add-missing-FreeRTOS-symbol.patch
new file mode 100644
index 000000000..964c8746d
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0085-doc-add-missing-FreeRTOS-symbol.patch
@@ -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.
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0086-target-image-zero-initialize-ELF-segments-up-to-p_me.patch b/meta-oe/recipes-devtools/openocd/openocd/0086-target-image-zero-initialize-ELF-segments-up-to-p_me.patch
new file mode 100644
index 000000000..16778959d
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0086-target-image-zero-initialize-ELF-segments-up-to-p_me.patch
@@ -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;
+ }
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0087-target-xtensa-add-NX-support.patch b/meta-oe/recipes-devtools/openocd/openocd/0087-target-xtensa-add-NX-support.patch
new file mode 100644
index 000000000..ea280eff0
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0087-target-xtensa-add-NX-support.patch
@@ -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. */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0088-helper-add-compiler.h-to-handle-compiler-specific-wo.patch b/meta-oe/recipes-devtools/openocd/openocd/0088-helper-add-compiler.h-to-handle-compiler-specific-wo.patch
new file mode 100644
index 000000000..b6c6c6f91
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0088-helper-add-compiler.h-to-handle-compiler-specific-wo.patch
@@ -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);
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0089-openocd-drop-JIM_EMBEDDED-macro.patch b/meta-oe/recipes-devtools/openocd/openocd/0089-openocd-drop-JIM_EMBEDDED-macro.patch
new file mode 100644
index 000000000..577db87ac
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0089-openocd-drop-JIM_EMBEDDED-macro.patch
@@ -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>
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0090-build-fix-distcheck-for-jimtcl.patch b/meta-oe/recipes-devtools/openocd/openocd/0090-build-fix-distcheck-for-jimtcl.patch
new file mode 100644
index 000000000..7adfdb295
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0090-build-fix-distcheck-for-jimtcl.patch
@@ -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
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0091-jimtcl-update-to-version-0.82.patch b/meta-oe/recipes-devtools/openocd/openocd/0091-jimtcl-update-to-version-0.82.patch
new file mode 100644
index 000000000..1d729e7a0
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0091-jimtcl-update-to-version-0.82.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0092-tcl-tools-test_cpu_speed-Fix-register-name.patch b/meta-oe/recipes-devtools/openocd/openocd/0092-tcl-tools-test_cpu_speed-Fix-register-name.patch
new file mode 100644
index 000000000..5a89c3b39
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0092-tcl-tools-test_cpu_speed-Fix-register-name.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0093-tcl-remove-exec-permission-to-tcl-config-files.patch b/meta-oe/recipes-devtools/openocd/openocd/0093-tcl-remove-exec-permission-to-tcl-config-files.patch
new file mode 100644
index 000000000..10a288d37
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0093-tcl-remove-exec-permission-to-tcl-config-files.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0094-svf-new-command-line-options-noreset-and-addcycles.patch b/meta-oe/recipes-devtools/openocd/openocd/0094-svf-new-command-line-options-noreset-and-addcycles.patch
new file mode 100644
index 000000000..d71ec8630
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0094-svf-new-command-line-options-noreset-and-addcycles.patch
@@ -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
+ };
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0095-helper-compiler-fix-build-on-MacOS.patch b/meta-oe/recipes-devtools/openocd/openocd/0095-helper-compiler-fix-build-on-MacOS.patch
new file mode 100644
index 000000000..b9a30be06
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0095-helper-compiler-fix-build-on-MacOS.patch
@@ -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))
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0096-rtos-nuttx-add-Espressif-target-support-and-refactor.patch b/meta-oe/recipes-devtools/openocd/openocd/0096-rtos-nuttx-add-Espressif-target-support-and-refactor.patch
new file mode 100644
index 000000000..ea8e730ec
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0096-rtos-nuttx-add-Espressif-target-support-and-refactor.patch
@@ -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, &current_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, &regsaddr);
++	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 */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0097-target-espressif-check-common_magic-instead-of-gdb_a.patch b/meta-oe/recipes-devtools/openocd/openocd/0097-target-espressif-check-common_magic-instead-of-gdb_a.patch
new file mode 100644
index 000000000..aac158c5b
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0097-target-espressif-check-common_magic-instead-of-gdb_a.patch
@@ -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;
+ }
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0098-target-adi_v5_swd-update-comment-about-SWD-capabilit.patch b/meta-oe/recipes-devtools/openocd/openocd/0098-target-adi_v5_swd-update-comment-about-SWD-capabilit.patch
new file mode 100644
index 000000000..9c03a2aaa
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0098-target-adi_v5_swd-update-comment-about-SWD-capabilit.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0099-target-adi_v5_jtag-fix-endianness-error-in-transacti.patch b/meta-oe/recipes-devtools/openocd/openocd/0099-target-adi_v5_jtag-fix-endianness-error-in-transacti.patch
new file mode 100644
index 000000000..ad150aca4
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0099-target-adi_v5_jtag-fix-endianness-error-in-transacti.patch
@@ -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;
+ 		}
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0100-svf-fix-leaking-file-descriptor.patch b/meta-oe/recipes-devtools/openocd/openocd/0100-svf-fix-leaking-file-descriptor.patch
new file mode 100644
index 000000000..67283b70e
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0100-svf-fix-leaking-file-descriptor.patch
@@ -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);
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0101-svf-fix-memory-leak-on-error-during-command-executio.patch b/meta-oe/recipes-devtools/openocd/openocd/0101-svf-fix-memory-leak-on-error-during-command-executio.patch
new file mode 100644
index 000000000..6576c7be9
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0101-svf-fix-memory-leak-on-error-during-command-executio.patch
@@ -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;
+ 		}
+ 	}
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0102-svf-make-command-svf-syntax-consistent.patch b/meta-oe/recipes-devtools/openocd/openocd/0102-svf-make-command-svf-syntax-consistent.patch
new file mode 100644
index 000000000..43d335bc7
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0102-svf-make-command-svf-syntax-consistent.patch
@@ -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
+ };
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0103-helper-command-rewrite-command-ocd_find-as-COMMAND_H.patch b/meta-oe/recipes-devtools/openocd/openocd/0103-helper-command-rewrite-command-ocd_find-as-COMMAND_H.patch
new file mode 100644
index 000000000..13d667171
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0103-helper-command-rewrite-command-ocd_find-as-COMMAND_H.patch
@@ -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",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0104-transport-rewrite-command-transport-select-as-COMMAN.patch b/meta-oe/recipes-devtools/openocd/openocd/0104-transport-rewrite-command-transport-select-as-COMMAN.patch
new file mode 100644
index 000000000..1f3ab3283
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0104-transport-rewrite-command-transport-select-as-COMMAN.patch
@@ -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]",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0105-flash-nor-rewrite-command-flash-list-as-COMMAND_HAND.patch b/meta-oe/recipes-devtools/openocd/openocd/0105-flash-nor-rewrite-command-flash-list-as-COMMAND_HAND.patch
new file mode 100644
index 000000000..328a838f3
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0105-flash-nor-rewrite-command-flash-list-as-COMMAND_HAND.patch
@@ -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
+ };
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0106-helper-util-rewrite-command-ms-as-COMMAND_HANDLER.patch b/meta-oe/recipes-devtools/openocd/openocd/0106-helper-util-rewrite-command-ms-as-COMMAND_HANDLER.patch
new file mode 100644
index 000000000..efce23f3c
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0106-helper-util-rewrite-command-ms-as-COMMAND_HANDLER.patch
@@ -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 = "",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0107-openocd-rewrite-command-version-as-COMMAND_HANDLER.patch b/meta-oe/recipes-devtools/openocd/openocd/0107-openocd-rewrite-command-version-as-COMMAND_HANDLER.patch
new file mode 100644
index 000000000..d25471fe4
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0107-openocd-rewrite-command-version-as-COMMAND_HANDLER.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0108-rtt-rewrite-command-rtt-channellist-as-COMMAND_HANDL.patch b/meta-oe/recipes-devtools/openocd/openocd/0108-rtt-rewrite-command-rtt-channellist-as-COMMAND_HANDL.patch
new file mode 100644
index 000000000..c4bbbcc9c
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0108-rtt-rewrite-command-rtt-channellist-as-COMMAND_HANDL.patch
@@ -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 = ""
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0109-target-aarch64-rewrite-commands-aarch64-mcr-mrc-as-C.patch b/meta-oe/recipes-devtools/openocd/openocd/0109-target-aarch64-rewrite-commands-aarch64-mcr-mrc-as-C.patch
new file mode 100644
index 000000000..378b98a19
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0109-target-aarch64-rewrite-commands-aarch64-mcr-mrc-as-C.patch
@@ -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",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0110-target-armv4_5-rewrite-commands-arm-mcr-mrc-as-COMMA.patch b/meta-oe/recipes-devtools/openocd/openocd/0110-target-armv4_5-rewrite-commands-arm-mcr-mrc-as-COMMA.patch
new file mode 100644
index 000000000..d4167911e
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0110-target-armv4_5-rewrite-commands-arm-mcr-mrc-as-COMMA.patch
@@ -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",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0111-target-cti-rewrite-command-cti-names-as-COMMAND_HAND.patch b/meta-oe/recipes-devtools/openocd/openocd/0111-target-cti-rewrite-command-cti-names-as-COMMAND_HAND.patch
new file mode 100644
index 000000000..9c7961460
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0111-target-cti-rewrite-command-cti-names-as-COMMAND_HAND.patch
@@ -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",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0112-jtag-rewrite-command-adapter-name-as-COMMAND_HANDLER.patch b/meta-oe/recipes-devtools/openocd/openocd/0112-jtag-rewrite-command-adapter-name-as-COMMAND_HANDLER.patch
new file mode 100644
index 000000000..abdaba97f
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0112-jtag-rewrite-command-adapter-name-as-COMMAND_HANDLER.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0113-jtag-rewrite-command-jtag-names-as-COMMAND_HANDLER.patch b/meta-oe/recipes-devtools/openocd/openocd/0113-jtag-rewrite-command-jtag-names-as-COMMAND_HANDLER.patch
new file mode 100644
index 000000000..171a9bd48
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0113-jtag-rewrite-command-jtag-names-as-COMMAND_HANDLER.patch
@@ -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,
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0114-jtag-rewrite-command-jtag-arp_init-as-COMMAND_HANDLE.patch b/meta-oe/recipes-devtools/openocd/openocd/0114-jtag-rewrite-command-jtag-arp_init-as-COMMAND_HANDLE.patch
new file mode 100644
index 000000000..3751e9379
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0114-jtag-rewrite-command-jtag-arp_init-as-COMMAND_HANDLE.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0115-jtag-rewrite-command-jtag-arp_init-reset-as-COMMAND_.patch b/meta-oe/recipes-devtools/openocd/openocd/0115-jtag-rewrite-command-jtag-arp_init-reset-as-COMMAND_.patch
new file mode 100644
index 000000000..bb98ef3aa
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0115-jtag-rewrite-command-jtag-arp_init-reset-as-COMMAND_.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0116-jtag-rewrite-command-flush_count-as-COMMAND_HANDLER.patch b/meta-oe/recipes-devtools/openocd/openocd/0116-jtag-rewrite-command-flush_count-as-COMMAND_HANDLER.patch
new file mode 100644
index 000000000..31cdf6b07
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0116-jtag-rewrite-command-flush_count-as-COMMAND_HANDLER.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0117-target-arm_dap-rewrite-command-dap-names-as-COMMAND_.patch b/meta-oe/recipes-devtools/openocd/openocd/0117-target-arm_dap-rewrite-command-dap-names-as-COMMAND_.patch
new file mode 100644
index 000000000..ec65ba397
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0117-target-arm_dap-rewrite-command-dap-names-as-COMMAND_.patch
@@ -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",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0118-target-arm_tpiu_swo-rewrite-command-tpiu-disable-as-.patch b/meta-oe/recipes-devtools/openocd/openocd/0118-target-arm_tpiu_swo-rewrite-command-tpiu-disable-as-.patch
new file mode 100644
index 000000000..d2c8dd6d6
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0118-target-arm_tpiu_swo-rewrite-command-tpiu-disable-as-.patch
@@ -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",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0119-target-arm_tpiu_swo-rewrite-command-tpiu-enable-as-C.patch b/meta-oe/recipes-devtools/openocd/openocd/0119-target-arm_tpiu_swo-rewrite-command-tpiu-enable-as-C.patch
new file mode 100644
index 000000000..fe055d512
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0119-target-arm_tpiu_swo-rewrite-command-tpiu-enable-as-C.patch
@@ -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",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0120-target-arm_tpiu_swo-rewrite-command-tpiu-names-as-CO.patch b/meta-oe/recipes-devtools/openocd/openocd/0120-target-arm_tpiu_swo-rewrite-command-tpiu-names-as-CO.patch
new file mode 100644
index 000000000..1d52b6807
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0120-target-arm_tpiu_swo-rewrite-command-tpiu-names-as-CO.patch
@@ -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",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0121-target-arm_tpiu_swo-rewrite-command-tpiu-init-as-COM.patch b/meta-oe/recipes-devtools/openocd/openocd/0121-target-arm_tpiu_swo-rewrite-command-tpiu-init-as-COM.patch
new file mode 100644
index 000000000..567f25626
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0121-target-arm_tpiu_swo-rewrite-command-tpiu-init-as-COM.patch
@@ -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",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0122-target-rewrite-command-read_memory-as-COMMAND_HANDLE.patch b/meta-oe/recipes-devtools/openocd/openocd/0122-target-rewrite-command-read_memory-as-COMMAND_HANDLE.patch
new file mode 100644
index 000000000..f55c6692e
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0122-target-rewrite-command-read_memory-as-COMMAND_HANDLE.patch
@@ -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']",
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0123-target-rewrite-command-target-curstate-as-COMMAND_HA.patch b/meta-oe/recipes-devtools/openocd/openocd/0123-target-rewrite-command-target-curstate-as-COMMAND_HA.patch
new file mode 100644
index 000000000..abe112911
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0123-target-rewrite-command-target-curstate-as-COMMAND_HA.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0124-target-rewrite-command-was_examined-as-COMMAND_HANDL.patch b/meta-oe/recipes-devtools/openocd/openocd/0124-target-rewrite-command-was_examined-as-COMMAND_HANDL.patch
new file mode 100644
index 000000000..1ed08e529
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0124-target-rewrite-command-was_examined-as-COMMAND_HANDL.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0125-target-rewrite-command-examine_deferred-as-COMMAND_H.patch b/meta-oe/recipes-devtools/openocd/openocd/0125-target-rewrite-command-examine_deferred-as-COMMAND_H.patch
new file mode 100644
index 000000000..6a38d078f
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0125-target-rewrite-command-examine_deferred-as-COMMAND_H.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0126-target-rewrite-command-arp_halt_gdb-as-COMMAND_HANDL.patch b/meta-oe/recipes-devtools/openocd/openocd/0126-target-rewrite-command-arp_halt_gdb-as-COMMAND_HANDL.patch
new file mode 100644
index 000000000..300f784d6
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0126-target-rewrite-command-arp_halt_gdb-as-COMMAND_HANDL.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0127-target-rewrite-command-target-current-as-COMMAND_HAN.patch b/meta-oe/recipes-devtools/openocd/openocd/0127-target-rewrite-command-target-current-as-COMMAND_HAN.patch
new file mode 100644
index 000000000..8d8079145
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0127-target-rewrite-command-target-current-as-COMMAND_HAN.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0128-target-rewrite-command-target-types-as-COMMAND_HANDL.patch b/meta-oe/recipes-devtools/openocd/openocd/0128-target-rewrite-command-target-types-as-COMMAND_HANDL.patch
new file mode 100644
index 000000000..5bb740471
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0128-target-rewrite-command-target-types-as-COMMAND_HANDL.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0129-target-rewrite-command-target-names-as-COMMAND_HANDL.patch b/meta-oe/recipes-devtools/openocd/openocd/0129-target-rewrite-command-target-names-as-COMMAND_HANDL.patch
new file mode 100644
index 000000000..c1d4e79c8
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0129-target-rewrite-command-target-names-as-COMMAND_HANDL.patch
@@ -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",
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0130-target-rewrite-command-target-smp-as-COMMAND_HANDLER.patch b/meta-oe/recipes-devtools/openocd/openocd/0130-target-rewrite-command-target-smp-as-COMMAND_HANDLER.patch
new file mode 100644
index 000000000..2da792f20
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0130-target-rewrite-command-target-smp-as-COMMAND_HANDLER.patch
@@ -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"
+ 	},
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0131-tcl-board-calao-usb-a9260-fix-and-refactor-broken-su.patch b/meta-oe/recipes-devtools/openocd/openocd/0131-tcl-board-calao-usb-a9260-fix-and-refactor-broken-su.patch
new file mode 100644
index 000000000..805e2ee2f
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0131-tcl-board-calao-usb-a9260-fix-and-refactor-broken-su.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0132-tcl-board-add-Calao-USB-A9G20.patch b/meta-oe/recipes-devtools/openocd/openocd/0132-tcl-board-add-Calao-USB-A9G20.patch
new file mode 100644
index 000000000..c5a9202e2
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0132-tcl-board-add-Calao-USB-A9G20.patch
@@ -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]
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0133-flash-nor-missing-fileio_close.patch b/meta-oe/recipes-devtools/openocd/openocd/0133-flash-nor-missing-fileio_close.patch
new file mode 100644
index 000000000..a2e26f843
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0133-flash-nor-missing-fileio_close.patch
@@ -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;
+ 	}
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0134-github-workflow-increase-delete-tag-and-release-vers.patch b/meta-oe/recipes-devtools/openocd/openocd/0134-github-workflow-increase-delete-tag-and-release-vers.patch
new file mode 100644
index 000000000..3c83dff10
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0134-github-workflow-increase-delete-tag-and-release-vers.patch
@@ -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 }}
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0135-github-workflow-build-libjaylink-from-source.patch b/meta-oe/recipes-devtools/openocd/openocd/0135-github-workflow-build-libjaylink-from-source.patch
new file mode 100644
index 000000000..e708be032
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0135-github-workflow-build-libjaylink-from-source.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0136-rtos-FreeRTOS-some-optimization-of-freertos_update_t.patch b/meta-oe/recipes-devtools/openocd/openocd/0136-rtos-FreeRTOS-some-optimization-of-freertos_update_t.patch
new file mode 100644
index 000000000..db4c64b91
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0136-rtos-FreeRTOS-some-optimization-of-freertos_update_t.patch
@@ -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;
+ }
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0137-src-target-mips_m4k-fix-condition-on-overlapping-wor.patch b/meta-oe/recipes-devtools/openocd/openocd/0137-src-target-mips_m4k-fix-condition-on-overlapping-wor.patch
new file mode 100644
index 000000000..b0626e47a
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0137-src-target-mips_m4k-fix-condition-on-overlapping-wor.patch
@@ -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);
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0138-src-target-mips_m4k-add-fast-read-method.patch b/meta-oe/recipes-devtools/openocd/openocd/0138-src-target-mips_m4k-add-fast-read-method.patch
new file mode 100644
index 000000000..5f6ddaf59
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0138-src-target-mips_m4k-add-fast-read-method.patch
@@ -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)
+ {
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0139-helper-list-remove-unused-hlist_.patch b/meta-oe/recipes-devtools/openocd/openocd/0139-helper-list-remove-unused-hlist_.patch
new file mode 100644
index 000000000..cae7e0de6
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0139-helper-list-remove-unused-hlist_.patch
@@ -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 */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0140-helper-list-re-align-with-Linux-kernel-6.3-rc1.patch b/meta-oe/recipes-devtools/openocd/openocd/0140-helper-list-re-align-with-Linux-kernel-6.3-rc1.patch
new file mode 100644
index 000000000..b3cb8cf66
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0140-helper-list-re-align-with-Linux-kernel-6.3-rc1.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0141-ipdbg-whitespaces.patch b/meta-oe/recipes-devtools/openocd/openocd/0141-ipdbg-whitespaces.patch
new file mode 100644
index 000000000..35c82ba6f
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0141-ipdbg-whitespaces.patch
@@ -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;
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0142-helper-compiler-fix-build-with-gcc-on-MacOS.patch b/meta-oe/recipes-devtools/openocd/openocd/0142-helper-compiler-fix-build-with-gcc-on-MacOS.patch
new file mode 100644
index 000000000..8005111b6
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0142-helper-compiler-fix-build-with-gcc-on-MacOS.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0143-tcl-zynq_7000-add-missing-id-codes.patch b/meta-oe/recipes-devtools/openocd/openocd/0143-tcl-zynq_7000-add-missing-id-codes.patch
new file mode 100644
index 000000000..39249f4cc
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0143-tcl-zynq_7000-add-missing-id-codes.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0144-tcl-cpld-xilinx-xc7-remove-virtex-7-devices-with-ir-.patch b/meta-oe/recipes-devtools/openocd/openocd/0144-tcl-cpld-xilinx-xc7-remove-virtex-7-devices-with-ir-.patch
new file mode 100644
index 000000000..b30673f4a
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0144-tcl-cpld-xilinx-xc7-remove-virtex-7-devices-with-ir-.patch
@@ -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
+ 
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0145-doc-drop-resume-will-wait-5-seconds.patch b/meta-oe/recipes-devtools/openocd/openocd/0145-doc-drop-resume-will-wait-5-seconds.patch
new file mode 100644
index 000000000..d7691f5ee
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0145-doc-drop-resume-will-wait-5-seconds.patch
@@ -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]
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0146-target-espressif-add-application-tracing-functionali.patch b/meta-oe/recipes-devtools/openocd/openocd/0146-target-espressif-add-application-tracing-functionali.patch
new file mode 100644
index 000000000..5ea321047
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0146-target-espressif-add-application-tracing-functionali.patch
@@ -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 */
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0147-src-server-Fix-memory-leak-of-reg_list.patch b/meta-oe/recipes-devtools/openocd/openocd/0147-src-server-Fix-memory-leak-of-reg_list.patch
new file mode 100644
index 000000000..fb5757d4f
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0147-src-server-Fix-memory-leak-of-reg_list.patch
@@ -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;
+ 						}
+ 					}
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0148-rtos-linux.c-Fix-Linux-user-space-border-check.patch b/meta-oe/recipes-devtools/openocd/openocd/0148-rtos-linux.c-Fix-Linux-user-space-border-check.patch
new file mode 100644
index 000000000..8a5875c77
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0148-rtos-linux.c-Fix-Linux-user-space-border-check.patch
@@ -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;
+ 	}
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0149-flash-rsl10-fix-typo.patch b/meta-oe/recipes-devtools/openocd/openocd/0149-flash-rsl10-fix-typo.patch
new file mode 100644
index 000000000..d2f74a5ec
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0149-flash-rsl10-fix-typo.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0150-pld-move-file-sanity-checks-to-pld.c.patch b/meta-oe/recipes-devtools/openocd/openocd/0150-pld-move-file-sanity-checks-to-pld.c.patch
new file mode 100644
index 000000000..2b98c2732
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0150-pld-move-file-sanity-checks-to-pld.c.patch
@@ -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));
diff --git a/meta-oe/recipes-devtools/openocd/openocd/0151-Committing-changes-from-do_patch.patch b/meta-oe/recipes-devtools/openocd/openocd/0151-Committing-changes-from-do_patch.patch
new file mode 100644
index 000000000..074e9b788
--- /dev/null
+++ b/meta-oe/recipes-devtools/openocd/openocd/0151-Committing-changes-from-do_patch.patch
@@ -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
diff --git a/meta-oe/recipes-devtools/openocd/openocd_git.bb b/meta-oe/recipes-devtools/openocd/openocd_git.bb
index d30d9c346..98c8e5da6 100644
--- a/meta-oe/recipes-devtools/openocd/openocd_git.bb
+++ b/meta-oe/recipes-devtools/openocd/openocd_git.bb
@@ -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