server/telnet: Handle Ctrl+K 68/5868/4 master
authorBrian Brooks <brooks.brian@gmail.com>
Sun, 18 Oct 2020 13:37:09 +0000 (08:37 -0500)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 24 Oct 2020 22:25:33 +0000 (23:25 +0100)
Handle Ctrl+K shortcut which clears the line from the cursor position
to the end of line.

Change-Id: I2ecff5284473cef7c11cf9cb7e1c0c97d55f6c1c
Signed-off-by: Brian Brooks <brooks.brian@gmail.com>
Reviewed-on: http://openocd.zylin.com/5868
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
Reviewed-by: Marc Schink <dev@zapb.de>
46 files changed:
configure.ac
doc/openocd.texi
src/flash/nor/at91sam4.c
src/flash/nor/stm32h7x.c
src/flash/nor/stm32l4x.c
src/helper/log.h
src/helper/options.c
src/jtag/drivers/Makefile.am
src/jtag/drivers/jlink.c
src/jtag/drivers/jtag_dpi.c [new file with mode: 0644]
src/jtag/drivers/ti_icdi_usb.c
src/jtag/interfaces.c
src/rtos/FreeRTOS.c
src/server/telnet_server.c
src/target/Makefile.am
src/target/a64_disassembler.c [new file with mode: 0644]
src/target/a64_disassembler.h [new file with mode: 0644]
src/target/aarch64.c
src/target/arc.c
src/target/arm_disassembler.c
src/target/arm_disassembler.h
src/target/armv4_5.c
src/target/armv7m.c
src/target/cortex_m.c
src/target/cortex_m.h
src/target/hla_target.c
src/target/riscv/asm.h
src/target/riscv/batch.c
src/target/riscv/batch.h
src/target/riscv/debug_defines.h
src/target/riscv/encoding.h
src/target/riscv/gdb_regs.h
src/target/riscv/opcodes.h
src/target/riscv/program.c
src/target/riscv/program.h
src/target/riscv/riscv-011.c
src/target/riscv/riscv-013.c
src/target/riscv/riscv.c
src/target/riscv/riscv.h
src/target/riscv/riscv_semihosting.c
tcl/board/dp_busblaster_v4.cfg [new file with mode: 0644]
tcl/board/quicklogic_quickfeather.cfg [new file with mode: 0644]
tcl/interface/jtag_dpi.cfg [new file with mode: 0644]
tcl/interface/ti-icdi.cfg
tcl/target/eos_s3.cfg [new file with mode: 0644]
tcl/target/nrf52.cfg

index 90ac2a9..5698166 100644 (file)
@@ -267,6 +267,10 @@ AC_ARG_ENABLE([jtag_vpi],
   AS_HELP_STRING([--enable-jtag_vpi], [Enable building support for JTAG VPI]),
   [build_jtag_vpi=$enableval], [build_jtag_vpi=no])
 
+AC_ARG_ENABLE([jtag_dpi],
+  AS_HELP_STRING([--enable-jtag_dpi], [Enable building support for JTAG DPI]),
+  [build_jtag_dpi=$enableval], [build_jtag_dpi=no])
+
 AC_ARG_ENABLE([amtjtagaccel],
   AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]),
   [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no])
@@ -569,6 +573,13 @@ AS_IF([test "x$build_jtag_vpi" = "xyes"], [
   AC_DEFINE([BUILD_JTAG_VPI], [0], [0 if you don't want JTAG VPI.])
 ])
 
+AS_IF([test "x$build_jtag_dpi" = "xyes"], [
+  AC_DEFINE([BUILD_JTAG_DPI], [1], [1 if you want JTAG DPI.])
+], [
+  AC_DEFINE([BUILD_JTAG_DPI], [0], [0 if you don't want JTAG DPI.])
+])
+
+
 AS_IF([test "x$build_amtjtagaccel" = "xyes"], [
   AC_DEFINE([BUILD_AMTJTAGACCEL], [1], [1 if you want the Amontec JTAG-Accelerator driver.])
 ], [
@@ -639,6 +650,15 @@ PKG_CHECK_MODULES([LIBUSB1], [libusb-1.0], [
 
 PKG_CHECK_MODULES([LIBUSB0], [libusb], [use_libusb0=yes], [use_libusb0=no])
 
+PKG_CHECK_MODULES([CAPSTONE], [capstone], [have_capstone=yes],
+       [have_capstone=no])
+
+AS_IF([test "x$have_capstone" = "xyes"], [
+  AC_DEFINE([HAVE_CAPSTONE], [1], [1 if you have captone disassembly framework.])
+], [
+  AC_DEFINE([HAVE_CAPSTONE], [0], [0 if you don't have captone disassembly framework.])
+])
+
 for hidapi_lib in hidapi hidapi-hidraw hidapi-libusb; do
        PKG_CHECK_MODULES([HIDAPI],[$hidapi_lib],[
                use_hidapi=yes
@@ -737,6 +757,7 @@ AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"])
 AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"])
 AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"])
 AM_CONDITIONAL([JTAG_VPI], [test "x$build_jtag_vpi" = "xyes" -o "x$build_jtag_vpi" = "xyes"])
+AM_CONDITIONAL([JTAG_DPI], [test "x$build_jtag_dpi" = "xyes" -o "x$build_jtag_dpi" = "xyes"])
 AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"])
 AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"])
 AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"])
@@ -757,6 +778,7 @@ AM_CONDITIONAL([USE_LIBGPIOD], [test "x$use_libgpiod" = "xyes"])
 AM_CONDITIONAL([USE_HIDAPI], [test "x$use_hidapi" = "xyes"])
 AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"])
 AM_CONDITIONAL([RSHIM], [test "x$build_rshim" = "xyes"])
+AM_CONDITIONAL([HAVE_CAPSTONE], [test "x$have_capstone" = "xyes"])
 
 AM_CONDITIONAL([MINIDRIVER], [test "x$build_minidriver" = "xyes"])
 AM_CONDITIONAL([MINIDRIVER_DUMMY], [test "x$build_minidriver_dummy" = "xyes"])
index 8c99228..dba2a0a 100644 (file)
@@ -615,6 +615,12 @@ produced, PDF schematics are easily found and it is easy to make.
 @* A JTAG driver acting as a client for the JTAG VPI server interface.
 @* Link: @url{http://github.com/fjullien/jtag_vpi}
 
+@item @b{jtag_dpi}
+@* A JTAG driver acting as a client for the SystemVerilog Direct Programming
+Interface (DPI) for JTAG devices. DPI allows OpenOCD to connect to the JTAG
+interface of a hardware model written in SystemVerilog, for example, on an
+emulation model of target hardware.
+
 @item @b{xlnx_pcie_xvc}
 @* A JTAG driver exposing Xilinx Virtual Cable over PCI Express to OpenOCD as JTAG/SWD interface.
 
@@ -718,8 +724,11 @@ Configuration files and scripts are searched for in
 @item the current directory,
 @item any search dir specified on the command line using the @option{-s} option,
 @item any search dir specified using the @command{add_script_search_dir} command,
-@item @file{$HOME/.openocd} (not on Windows),
 @item a directory in the @env{OPENOCD_SCRIPTS} environment variable (if set),
+@item @file{%APPDATA%/OpenOCD} (only on Windows),
+@item @file{$HOME/Library/Preferences/org.openocd} (only on Darwin),
+@item @file{$XDG_CONFIG_HOME/openocd} (@env{$XDG_CONFIG_HOME} defaults to @file{$HOME/.config}),
+@item @file{$HOME/.openocd},
 @item the site wide script library @file{$pkgdatadir/site} and
 @item the OpenOCD-supplied script library @file{$pkgdatadir/scripts}.
 @end enumerate
@@ -3235,6 +3244,22 @@ This value is only used with the standard variant.
 @end deffn
 @end deffn
 
+
+@deffn {Interface Driver} {jtag_dpi}
+SystemVerilog Direct Programming Interface (DPI) compatible driver for
+JTAG devices in emulation. The driver acts as a client for the SystemVerilog
+DPI server interface.
+
+@deffn {Config Command} {jtag_dpi_set_port} port
+Specifies the TCP/IP port number of the SystemVerilog DPI server interface.
+@end deffn
+
+@deffn {Config Command} {jtag_dpi_set_address} address
+Specifies the TCP/IP address of the SystemVerilog DPI server interface.
+@end deffn
+@end deffn
+
+
 @section Transport Configuration
 @cindex Transport
 As noted earlier, depending on the version of OpenOCD you use,
@@ -9349,6 +9374,12 @@ target code relies on. In a configuration file, the command would typically be c
 However, normally it is not necessary to use the command at all.
 @end deffn
 
+@deffn Command {aarch64 disassemble} address [count]
+@cindex disassemble
+Disassembles @var{count} instructions starting at @var{address}.
+If @var{count} is not specified, a single instruction is disassembled.
+@end deffn
+
 @deffn Command {aarch64 smp} [on|off]
 Display, enable or disable SMP handling mode. The state of SMP handling influences the way targets in an SMP group
 are handled by the run control. With SMP handling enabled, issuing halt or resume to one core will trigger
@@ -9683,8 +9714,31 @@ This is used to access 64-bit floating point registers on 32-bit targets.
 @end deffn
 
 @deffn Command {riscv set_prefer_sba} on|off
-When on, prefer to use System Bus Access to access memory.  When off, prefer to
-use the Program Buffer to access memory.
+When on, prefer to use System Bus Access to access memory.  When off (default),
+prefer to use the Program Buffer to access memory.
+@end deffn
+
+@deffn Command {riscv set_enable_virtual} on|off
+When on, memory accesses are performed on physical or virtual memory depending
+on the current system configuration. When off (default), all memory accessses are performed
+on physical memory.
+@end deffn
+
+@deffn Command {riscv set_enable_virt2phys} on|off
+When on (default), memory accesses are performed on physical or virtual memory
+depending on the current satp configuration. When off, all memory accessses are
+performed on physical memory.
+@end deffn
+
+@deffn Command {riscv resume_order} normal|reversed
+Some software assumes all harts are executing nearly continuously. Such
+software may be sensitive to the order that harts are resumed in. On harts
+that don't support hasel, this option allows the user to choose the order the
+harts are resumed in. If you are using this option, it's probably masking a
+race condition problem in your code.
+
+Normal order is from lowest hart index to highest. This is the default
+behavior. Reversed order is from highest hart index to lowest.
 @end deffn
 
 @deffn Command {riscv set_ir} (@option{idcode}|@option{dtmcs}|@option{dmi}) [value]
@@ -9698,6 +9752,26 @@ When utilizing version 0.11 of the RISC-V Debug Specification,
 and DBUS registers, respectively.
 @end deffn
 
+@deffn Command {riscv use_bscan_tunnel} value
+Enable or disable use of a BSCAN tunnel to reach DM.  Supply the width of
+the DM transport TAP's instruction register to enable.  Supply a value of 0 to disable.
+@end deffn
+
+@deffn Command {riscv set_ebreakm} on|off
+Control dcsr.ebreakm. When on (default), M-mode ebreak instructions trap to
+OpenOCD. When off, they generate a breakpoint exception handled internally.
+@end deffn
+
+@deffn Command {riscv set_ebreaks} on|off
+Control dcsr.ebreaks. When on (default), S-mode ebreak instructions trap to
+OpenOCD. When off, they generate a breakpoint exception handled internally.
+@end deffn
+
+@deffn Command {riscv set_ebreaku} on|off
+Control dcsr.ebreaku. When on (default), U-mode ebreak instructions trap to
+OpenOCD. When off, they generate a breakpoint exception handled internally.
+@end deffn
+
 @subsection RISC-V Authentication Commands
 
 The following commands can be used to authenticate to a RISC-V system. Eg.  a
@@ -9721,7 +9795,7 @@ Write the 32-bit value to authdata.
 The following commands allow direct access to the Debug Module Interface, which
 can be used to interact with custom debug features.
 
-@deffn Command {riscv dmi_read}
+@deffn Command {riscv dmi_read} address
 Perform a 32-bit DMI read at address, returning the value.
 @end deffn
 
index 1c61064..86abf70 100644 (file)
@@ -1330,7 +1330,7 @@ static const struct sam4_chip_details all_sam4_details[] = {
                }
        },
 
-       /* atsamg55g19 */
+       /* atsamg55g19 Rev.A */
        {
                .chipid_cidr    = 0x24470ae0,
                .name           = "atsamg55g19",
@@ -1364,7 +1364,41 @@ static const struct sam4_chip_details all_sam4_details[] = {
                }
        },
 
-       /* atsamg55j19 */
+       /* atsamg55g19 Rev.B */
+       {
+               .chipid_cidr    = 0x24470ae1,
+               .name           = "atsamg55g19b",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 160 * 1024,
+               .n_gpnvms       = 2,
+               .n_banks        = 1,
+
+               {
+/*                     .bank[0] = */
+                       {
+                               .probed = false,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_S,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 5,
+                               .present = true,
+                               .size_bytes =  512 * 1024,
+                               .nsectors   =  64,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+/*                     .bank[1] = */
+                       {
+                               .present = false,
+                               .probed = false,
+                               .bank_number = 1,
+                       },
+               }
+       },
+
+       /* atsamg55j19 Rev.A */
        {
                .chipid_cidr    = 0x24570ae0,
                .name           = "atsamg55j19",
@@ -1398,6 +1432,40 @@ static const struct sam4_chip_details all_sam4_details[] = {
                }
        },
 
+       /* atsamg55j19 Rev.B */
+       {
+               .chipid_cidr    = 0x24570ae1,
+               .name           = "atsamg55j19b",
+               .total_flash_size     = 512 * 1024,
+               .total_sram_size      = 160 * 1024,
+               .n_gpnvms       = 2,
+               .n_banks        = 1,
+
+               {
+/*                     .bank[0] = */
+                       {
+                               .probed = false,
+                               .pChip  = NULL,
+                               .pBank  = NULL,
+                               .bank_number = 0,
+                               .base_address = FLASH_BANK_BASE_S,
+                               .controller_address = 0x400e0a00,
+                               .flash_wait_states = 5,
+                               .present = true,
+                               .size_bytes =  512 * 1024,
+                               .nsectors   =  64,
+                               .sector_size = 8192,
+                               .page_size   = 512,
+                       },
+/*                     .bank[1] = */
+                       {
+                               .present = false,
+                               .probed = false,
+                               .bank_number = 1,
+                       },
+               }
+       },
+
        /* terminate */
        {
                .chipid_cidr    = 0,
index ac7d759..52e3e0e 100644 (file)
@@ -147,7 +147,11 @@ static const struct stm32h7x_rev stm32_480_revs[] = {
        { 0x1000, "A"},
 };
 
-static uint32_t stm32x_compute_flash_cr_450(uint32_t cmd, int snb)
+static const struct stm32h7x_rev stm32_483_revs[] = {
+       { 0x1000, "A" }, { 0x1001, "Z" },
+};
+
+static uint32_t stm32x_compute_flash_cr_450_483(uint32_t cmd, int snb)
 {
        return cmd | (snb << 8);
 }
@@ -177,7 +181,7 @@ static const struct stm32h7x_part_info stm32h7x_parts[] = {
        .fsize_addr                     = 0x1FF1E880,
        .wps_group_size         = 1,
        .wps_mask                       = 0xFF,
-       .compute_flash_cr       = stm32x_compute_flash_cr_450,
+       .compute_flash_cr       = stm32x_compute_flash_cr_450_483,
        },
        {
        .id                                     = 0x480,
@@ -194,6 +198,21 @@ static const struct stm32h7x_part_info stm32h7x_parts[] = {
        .wps_mask                       = 0xFFFFFFFF,
        .compute_flash_cr       = stm32x_compute_flash_cr_480,
        },
+       {
+       .id                                     = 0x483,
+       .revs                           = stm32_483_revs,
+       .num_revs                       = ARRAY_SIZE(stm32_483_revs),
+       .device_str                     = "STM32H72x/73x",
+       .page_size_kb           = 128,
+       .block_size                     = 32,
+       .max_flash_size_kb      = 1024,
+       .max_bank_size_kb       = 1024,
+       .has_dual_bank          = false,
+       .fsize_addr                     = 0x1FF1E880,
+       .wps_group_size         = 1,
+       .wps_mask                       = 0xFF,
+       .compute_flash_cr   = stm32x_compute_flash_cr_450_483,
+       },
 };
 
 /* flash bank stm32x <base> <size> 0 0 <target#> */
@@ -804,6 +823,8 @@ static int stm32x_probe(struct flash_bank *bank)
                        /* flash size is 2M or 1M */
                        flash_size_in_kb /= 2;
                break;
+       case 0x483:
+               break;
        default:
                LOG_ERROR("unsupported device");
                return ERROR_FAIL;
index 379f1b4..9bdc2db 100644 (file)
@@ -94,7 +94,7 @@
 /*
  * STM32G4xxx series for reference.
  *
- * RM0440 (STM32G43x/44x/47x/48x)
+ * RM0440 (STM32G43x/44x/47x/48x/49x/4Ax)
  * http://www.st.com/resource/en/reference_manual/dm00355726.pdf
  *
  * Cat. 2 devices have single bank only, page size is 2kByte.
  *
  * Bank mode is controlled by bit 22 (DBANK) in option bytes register.
  * Both banks are treated as a single OpenOCD bank.
+ *
+ * Cat. 4 devices have single bank only, page size is 2kByte.
  */
 
 /* Erase time can be as high as 25ms, 10x this and assume it's toast... */
@@ -184,6 +186,10 @@ static const struct stm32l4_rev stm32_471_revs[] = {
        { 0x1001, "Z" },
 };
 
+static const struct stm32l4_rev stm32_479_revs[] = {
+       { 0x1000, "A" },
+};
+
 static const struct stm32l4_rev stm32_495_revs[] = {
        { 0x2001, "2.1" },
 };
@@ -308,6 +314,16 @@ static const struct stm32l4_part_info stm32l4_parts[] = {
          .fsize_addr            = 0x1FFF75E0,
        },
        {
+         .id                    = 0x479,
+         .revs                  = stm32_479_revs,
+         .num_revs              = ARRAY_SIZE(stm32_479_revs),
+         .device_str            = "STM32G49/G4Axx",
+         .max_flash_size_kb     = 512,
+         .has_dual_bank         = false,
+         .flash_regs_base       = 0x40022000,
+         .fsize_addr            = 0x1FFF75E0,
+       },
+       {
          .id                    = 0x495,
          .revs                  = stm32_495_revs,
          .num_revs              = ARRAY_SIZE(stm32_495_revs),
@@ -952,6 +968,7 @@ static int stm32l4_probe(struct flash_bank *bank)
        case 0x464: /* STM32L41/L42xx */
        case 0x466: /* STM32G03/G04xx */
        case 0x468: /* STM32G43/G44xx */
+       case 0x479: /* STM32G49/G4Axx */
        case 0x497: /* STM32WLEx */
                /* single bank flash */
                page_size_kb = 2;
index 0c6623f..f2ba0da 100644 (file)
@@ -154,6 +154,7 @@ extern int debug_level;
 #define ERROR_WAIT                                             (-5)
 /* ERROR_TIMEOUT is already taken by winerror.h. */
 #define ERROR_TIMEOUT_REACHED                  (-6)
+#define ERROR_NOT_IMPLEMENTED                  (-7)
 
 
 #endif /* OPENOCD_HELPER_LOG_H */
index 6622ece..0ccbf56 100644 (file)
@@ -178,6 +178,63 @@ static char *find_relative_path(const char *from, const char *to)
        return relpath;
 }
 
+static void add_user_dirs(void)
+{
+       char *path;
+
+#if IS_WIN32
+       const char *appdata = getenv("APPDATA");
+
+       if (appdata) {
+               path = alloc_printf("%s/OpenOCD", appdata);
+               if (path) {
+                       /* Convert path separators to UNIX style, should work on Windows also. */
+                       for (char *p = path; *p; p++) {
+                               if (*p == '\\')
+                                       *p = '/';
+                       }
+                       add_script_search_dir(path);
+                       free(path);
+               }
+       }
+       /* WIN32 may also have HOME defined, particularly under Cygwin, so add those paths below too */
+#endif
+
+       const char *home = getenv("HOME");
+#if IS_DARWIN
+       if (home) {
+               path = alloc_printf("%s/Library/Preferences/org.openocd", home);
+               if (path) {
+                       add_script_search_dir(path);
+                       free(path);
+               }
+       }
+#endif
+       const char *xdg_config = getenv("XDG_CONFIG_HOME");
+
+       if (xdg_config) {
+               path = alloc_printf("%s/openocd", xdg_config);
+               if (path) {
+                       add_script_search_dir(path);
+                       free(path);
+               }
+       } else if (home) {
+               path = alloc_printf("%s/.config/openocd", home);
+               if (path) {
+                       add_script_search_dir(path);
+                       free(path);
+               }
+       }
+
+       if (home) {
+               path = alloc_printf("%s/.openocd", home);
+               if (path) {
+                       add_script_search_dir(path);
+                       free(path);
+               }
+       }
+}
+
 static void add_default_dirs(void)
 {
        char *path;
@@ -194,32 +251,11 @@ static void add_default_dirs(void)
         * listed last in the built-in search order, so the user can
         * override these scripts with site-specific customizations.
         */
-       const char *home = getenv("HOME");
-
-       if (home) {
-               path = alloc_printf("%s/.openocd", home);
-               if (path) {
-                       add_script_search_dir(path);
-                       free(path);
-               }
-       }
-
        path = getenv("OPENOCD_SCRIPTS");
-
        if (path)
                add_script_search_dir(path);
 
-#ifdef _WIN32
-       const char *appdata = getenv("APPDATA");
-
-       if (appdata) {
-               path = alloc_printf("%s/OpenOCD", appdata);
-               if (path) {
-                       add_script_search_dir(path);
-                       free(path);
-               }
-       }
-#endif
+       add_user_dirs();
 
        path = alloc_printf("%s/%s/%s", exepath, bin2data, "site");
        if (path) {
index c860833..e8d20cc 100644 (file)
@@ -82,6 +82,9 @@ endif
 if JTAG_VPI
 DRIVERFILES += %D%/jtag_vpi.c
 endif
+if JTAG_DPI
+DRIVERFILES += %D%/jtag_dpi.c
+endif
 if USB_BLASTER_DRIVER
 %C%_libocdjtagdrivers_la_LIBADD += %D%/usb_blaster/libocdusbblaster.la
 include %D%/usb_blaster/Makefile.am
index 57e357b..ae8ce49 100644 (file)
@@ -1269,17 +1269,14 @@ static uint32_t calculate_trace_buffer_size(void)
 static bool calculate_swo_prescaler(unsigned int traceclkin_freq,
                uint32_t trace_freq, uint16_t *prescaler)
 {
-       unsigned int presc;
-       double deviation;
-
-       presc = ((1.0 - SWO_MAX_FREQ_DEV) * traceclkin_freq) / trace_freq + 1;
-
+       unsigned int presc = (traceclkin_freq + trace_freq / 2) / trace_freq;
        if (presc > TPIU_ACPR_MAX_SWOSCALER)
                return false;
 
-       deviation = fabs(1.0 - ((double)trace_freq * presc / traceclkin_freq));
-
-       if (deviation > SWO_MAX_FREQ_DEV)
+       /* Probe's UART speed must be within 3% of the TPIU's SWO baud rate. */
+       unsigned int max_deviation = (traceclkin_freq * 3) / 100;
+       if (presc * trace_freq < traceclkin_freq - max_deviation ||
+           presc * trace_freq > traceclkin_freq + max_deviation)
                return false;
 
        *prescaler = presc;
diff --git a/src/jtag/drivers/jtag_dpi.c b/src/jtag/drivers/jtag_dpi.c
new file mode 100644 (file)
index 0000000..575c6bc
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * JTAG to DPI driver
+ *
+ * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
+ *
+ * Copyright (C) 2019-2020, Ampere Computing LLC
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jtag/interface.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifndef _WIN32
+#include <netinet/tcp.h>
+#endif
+
+#define SERVER_ADDRESS "127.0.0.1"
+#define SERVER_PORT    5555
+
+static uint16_t server_port = SERVER_PORT;
+static char *server_address;
+
+static int sockfd;
+static struct sockaddr_in serv_addr;
+
+static uint8_t *last_ir_buf;
+static int last_ir_num_bits;
+
+static int write_sock(char *buf, size_t len)
+{
+       if (buf == NULL) {
+               LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
+                       __func__, __FILE__, __LINE__);
+               return ERROR_FAIL;
+       }
+       if (write(sockfd, buf, len) != (ssize_t)len) {
+               LOG_ERROR("%s: %s, file %s, line %d", __func__,
+                       strerror(errno), __FILE__, __LINE__);
+               return ERROR_FAIL;
+       }
+       return ERROR_OK;
+}
+
+static int read_sock(char *buf, size_t len)
+{
+       if (buf == NULL) {
+               LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
+                       __func__, __FILE__, __LINE__);
+               return ERROR_FAIL;
+       }
+       if (read(sockfd, buf, len) != (ssize_t)len) {
+               LOG_ERROR("%s: %s, file %s, line %d", __func__,
+                       strerror(errno), __FILE__, __LINE__);
+               return ERROR_FAIL;
+       }
+       return ERROR_OK;
+}
+
+/**
+ * jtag_dpi_reset - ask to reset the JTAG device
+ * @trst: 1 if TRST is to be asserted
+ * @srst: 1 if SRST is to be asserted
+ */
+static int jtag_dpi_reset(int trst, int srst)
+{
+       char *buf = "reset\n";
+       int ret = ERROR_OK;
+
+       LOG_DEBUG_IO("JTAG DRIVER DEBUG: reset trst: %i srst %i", trst, srst);
+
+       if (trst == 1) {
+               /* reset the JTAG TAP controller */
+               ret = write_sock(buf, strlen(buf));
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("write_sock() fail, file %s, line %d",
+                               __FILE__, __LINE__);
+               }
+       }
+
+       if (srst == 1) {
+               /* System target reset not supported */
+               LOG_ERROR("DPI SRST not supported");
+               ret = ERROR_FAIL;
+       }
+
+       return ret;
+}
+
+/**
+ * jtag_dpi_scan - launches a DR-scan or IR-scan
+ * @cmd: the command to launch
+ *
+ * Launch a JTAG IR-scan or DR-scan
+ *
+ * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occured.
+ */
+static int jtag_dpi_scan(struct scan_command *cmd)
+{
+       char buf[20];
+       uint8_t *data_buf;
+       int num_bits, bytes;
+       int ret = ERROR_OK;
+
+       num_bits = jtag_build_buffer(cmd, &data_buf);
+       if (data_buf == NULL) {
+               LOG_ERROR("jtag_build_buffer call failed, data_buf == NULL, "
+                       "file %s, line %d", __FILE__, __LINE__);
+               return ERROR_FAIL;
+       }
+
+       bytes = DIV_ROUND_UP(num_bits, 8);
+       if (cmd->ir_scan) {
+               free(last_ir_buf);
+               last_ir_buf = (uint8_t *)malloc(bytes * sizeof(uint8_t));
+               if (last_ir_buf == NULL) {
+                       LOG_ERROR("%s: malloc fail, file %s, line %d",
+                               __func__, __FILE__, __LINE__);
+                       ret = ERROR_FAIL;
+                       goto out;
+               }
+               memcpy(last_ir_buf, data_buf, bytes);
+               last_ir_num_bits = num_bits;
+       }
+       snprintf(buf, sizeof(buf), "%s %d\n", cmd->ir_scan ? "ib" : "db", num_bits);
+       ret = write_sock(buf, strlen(buf));
+       if (ret != ERROR_OK) {
+               LOG_ERROR("write_sock() fail, file %s, line %d",
+                       __FILE__, __LINE__);
+               goto out;
+       }
+       ret = write_sock((char *)data_buf, bytes);
+       if (ret != ERROR_OK) {
+               LOG_ERROR("write_sock() fail, file %s, line %d",
+                       __FILE__, __LINE__);
+               goto out;
+       }
+       ret = read_sock((char *)data_buf, bytes);
+       if (ret != ERROR_OK) {
+               LOG_ERROR("read_sock() fail, file %s, line %d",
+                       __FILE__, __LINE__);
+               goto out;
+       }
+
+       ret = jtag_read_buffer(data_buf, cmd);
+       if (ret != ERROR_OK) {
+               LOG_ERROR("jtag_read_buffer() fail, file %s, line %d",
+                       __FILE__, __LINE__);
+               goto out;
+       }
+
+out:
+       free(data_buf);
+       return ret;
+}
+
+static int jtag_dpi_runtest(int cycles)
+{
+       char buf[20];
+       uint8_t *data_buf = last_ir_buf, *read_scan;
+       int num_bits = last_ir_num_bits, bytes;
+       int ret = ERROR_OK;
+
+       if (data_buf == NULL) {
+               LOG_ERROR("%s: NULL 'data_buf' argument, file %s, line %d",
+                       __func__, __FILE__, __LINE__);
+               return ERROR_FAIL;
+       }
+       if (num_bits <= 0) {
+               LOG_ERROR("%s: 'num_bits' invalid value, file %s, line %d",
+                       __func__, __FILE__, __LINE__);
+               return ERROR_FAIL;
+       }
+
+       bytes = DIV_ROUND_UP(num_bits, 8);
+       read_scan = (uint8_t *)malloc(bytes * sizeof(uint8_t));
+       if (read_scan == NULL) {
+               LOG_ERROR("%s: malloc fail, file %s, line %d",
+                       __func__, __FILE__, __LINE__);
+               return ERROR_FAIL;
+       }
+       snprintf(buf, sizeof(buf), "ib %d\n", num_bits);
+       while (cycles > 0) {
+               ret = write_sock(buf, strlen(buf));
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("write_sock() fail, file %s, line %d",
+                               __FILE__, __LINE__);
+                       goto out;
+               }
+               ret = write_sock((char *)data_buf, bytes);
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("write_sock() fail, file %s, line %d",
+                               __FILE__, __LINE__);
+                       goto out;
+               }
+               ret = read_sock((char *)read_scan, bytes);
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("read_sock() fail, file %s, line %d",
+                               __FILE__, __LINE__);
+                       goto out;
+               }
+
+               cycles -= num_bits + 6;
+       }
+
+out:
+       free(read_scan);
+       return ret;
+}
+
+static int jtag_dpi_stableclocks(int cycles)
+{
+       return jtag_dpi_runtest(cycles);
+}
+
+static int jtag_dpi_execute_queue(void)
+{
+       struct jtag_command *cmd;
+       int ret = ERROR_OK;
+
+       for (cmd = jtag_command_queue; ret == ERROR_OK && cmd != NULL;
+            cmd = cmd->next) {
+               switch (cmd->type) {
+               case JTAG_RUNTEST:
+                       ret = jtag_dpi_runtest(cmd->cmd.runtest->num_cycles);
+                       break;
+               case JTAG_STABLECLOCKS:
+                       ret = jtag_dpi_stableclocks(cmd->cmd.stableclocks->num_cycles);
+                       break;
+               case JTAG_TLR_RESET:
+                       /* Enter Test-Logic-Reset state by asserting TRST */
+                       if (cmd->cmd.statemove->end_state == TAP_RESET)
+                               jtag_dpi_reset(1, 0);
+                       break;
+               case JTAG_PATHMOVE:
+                       /* unsupported */
+                       break;
+               case JTAG_TMS:
+                       /* unsupported */
+                       break;
+               case JTAG_SLEEP:
+                       jtag_sleep(cmd->cmd.sleep->us);
+                       break;
+               case JTAG_SCAN:
+                       ret = jtag_dpi_scan(cmd->cmd.scan);
+                       break;
+               default:
+                       LOG_ERROR("BUG: unknown JTAG command type 0x%X",
+                                 cmd->type);
+                       ret = ERROR_FAIL;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+static int jtag_dpi_init(void)
+{
+       sockfd = socket(AF_INET, SOCK_STREAM, 0);
+       if (sockfd < 0) {
+               LOG_ERROR("socket: %s, function %s, file %s, line %d",
+                       strerror(errno), __func__, __FILE__, __LINE__);
+               return ERROR_FAIL;
+       }
+
+       memset(&serv_addr, 0, sizeof(serv_addr));
+
+       serv_addr.sin_family = AF_INET;
+       serv_addr.sin_port = htons(server_port);
+
+       if (server_address == NULL) {
+               server_address = strdup(SERVER_ADDRESS);
+               if (server_address == NULL) {
+                       LOG_ERROR("%s: strdup fail, file %s, line %d",
+                               __func__, __FILE__, __LINE__);
+                       return ERROR_FAIL;
+               }
+       }
+
+       serv_addr.sin_addr.s_addr = inet_addr(server_address);
+
+       if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
+               LOG_ERROR("inet_addr error occured");
+               return ERROR_FAIL;
+       }
+
+       if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+               close(sockfd);
+               LOG_ERROR("Can't connect to %s : %" PRIu16, server_address, server_port);
+               return ERROR_FAIL;
+       }
+       if (serv_addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
+               /* This increases performance dramatically for local
+               * connections, which is the most likely arrangement
+               * for a DPI connection. */
+               int flag = 1;
+               setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
+       }
+
+       LOG_INFO("Connection to %s : %" PRIu16 " succeed", server_address, server_port);
+
+       return ERROR_OK;
+}
+
+static int jtag_dpi_quit(void)
+{
+       free(server_address);
+       server_address = NULL;
+
+       return close(sockfd);
+}
+
+COMMAND_HANDLER(jtag_dpi_set_port)
+{
+       if (CMD_ARGC > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       else if (CMD_ARGC == 0)
+               LOG_INFO("Using server port %" PRIu16, server_port);
+       else {
+               COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], server_port);
+               LOG_INFO("Set server port to %" PRIu16, server_port);
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(jtag_dpi_set_address)
+{
+       if (CMD_ARGC > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       else if (CMD_ARGC == 0) {
+               if (server_address == NULL) {
+                       server_address = strdup(SERVER_ADDRESS);
+                       if (server_address == NULL) {
+                               LOG_ERROR("%s: strdup fail, file %s, line %d",
+                                       __func__, __FILE__, __LINE__);
+                               return ERROR_FAIL;
+                       }
+               }
+               LOG_INFO("Using server address %s", server_address);
+       } else {
+               free(server_address);
+               server_address = strdup(CMD_ARGV[0]);
+               if (server_address == NULL) {
+                       LOG_ERROR("%s: strdup fail, file %s, line %d",
+                               __func__, __FILE__, __LINE__);
+                       return ERROR_FAIL;
+               }
+               LOG_INFO("Set server address to %s", server_address);
+       }
+
+       return ERROR_OK;
+}
+
+static const struct command_registration jtag_dpi_command_handlers[] = {
+       {
+               .name = "jtag_dpi_set_port",
+               .handler = &jtag_dpi_set_port,
+               .mode = COMMAND_CONFIG,
+               .help = "set the port of the DPI server",
+               .usage = "[port]",
+       },
+       {
+               .name = "jtag_dpi_set_address",
+               .handler = &jtag_dpi_set_address,
+               .mode = COMMAND_CONFIG,
+               .help = "set the address of the DPI server",
+               .usage = "[address]",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static struct jtag_interface jtag_dpi_interface = {
+       .supported = DEBUG_CAP_TMS_SEQ,
+       .execute_queue = jtag_dpi_execute_queue,
+};
+
+struct adapter_driver jtag_dpi_adapter_driver = {
+       .name = "jtag_dpi",
+       .transports = jtag_only,
+       .commands = jtag_dpi_command_handlers,
+       .init = jtag_dpi_init,
+       .quit = jtag_dpi_quit,
+       .reset = jtag_dpi_reset,
+       .jtag_ops = &jtag_dpi_interface,
+};
index d276e58..920be77 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <target/cortex_m.h>
 
-#include <libusb.h>
+#include "libusb_helper.h"
 
 #define ICDI_WRITE_ENDPOINT 0x02
 #define ICDI_READ_ENDPOINT 0x83
@@ -44,8 +44,7 @@
 #define PACKET_END "#"
 
 struct icdi_usb_handle_s {
-       libusb_context *usb_ctx;
-       libusb_device_handle *usb_dev;
+       struct libusb_device_handle *usb_dev;
 
        char *read_buffer;
        char *write_buffer;
@@ -657,10 +656,7 @@ static int icdi_usb_close(void *handle)
                return ERROR_OK;
 
        if (h->usb_dev)
-               libusb_close(h->usb_dev);
-
-       if (h->usb_ctx)
-               libusb_exit(h->usb_ctx);
+               jtag_libusb_close(h->usb_dev);
 
        free(h->read_buffer);
        free(h->write_buffer);
@@ -670,6 +666,7 @@ static int icdi_usb_close(void *handle)
 
 static int icdi_usb_open(struct hl_interface_param_s *param, void **fd)
 {
+       /* TODO: Convert remaining libusb_ calls to jtag_libusb_ */
        int retval;
        struct icdi_usb_handle_s *h;
 
@@ -682,19 +679,14 @@ static int icdi_usb_open(struct hl_interface_param_s *param, void **fd)
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param->transport,
-                 param->vid[0], param->pid[0]);
-
-       /* TODO: convert libusb_ calls to jtag_libusb_ */
-       if (param->vid[1])
-               LOG_WARNING("Bad configuration: 'hla_vid_pid' command does not accept more than one VID PID pair on ti-icdi!");
+       for (uint8_t i = 0; param->vid[i] && param->pid[i]; ++i)
+               LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x serial: %s", param->transport,
+                       param->vid[i], param->pid[i], param->serial ? param->serial : "");
 
-       if (libusb_init(&h->usb_ctx) != 0) {
-               LOG_ERROR("libusb init failed");
-               goto error_open;
-       }
+       /* TI (Stellaris) ICDI provides its serial number in the USB descriptor;
+          no need to provide a callback here. */
+       jtag_libusb_open(param->vid, param->pid, param->serial, &h->usb_dev, NULL);
 
-       h->usb_dev = libusb_open_device_with_vid_pid(h->usb_ctx, param->vid[0], param->pid[0]);
        if (!h->usb_dev) {
                LOG_ERROR("open failed");
                goto error_open;
index 45e30c9..2fa53be 100644 (file)
@@ -12,6 +12,8 @@
  *   Copyright (C) 2009 Zachary T Welch                                    *
  *   zw@superlucidity.net                                                  *
  *                                                                         *
+ *   Copyright (C) 2020, Ampere Computing LLC                              *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
@@ -60,6 +62,9 @@ extern struct adapter_driver usb_blaster_adapter_driver;
 #if BUILD_JTAG_VPI == 1
 extern struct adapter_driver jtag_vpi_adapter_driver;
 #endif
+#if BUILD_JTAG_DPI == 1
+extern struct adapter_driver jtag_dpi_adapter_driver;
+#endif
 #if BUILD_FT232R == 1
 extern struct adapter_driver ft232r_adapter_driver;
 #endif
@@ -177,6 +182,9 @@ struct adapter_driver *adapter_drivers[] = {
 #if BUILD_JTAG_VPI == 1
                &jtag_vpi_adapter_driver,
 #endif
+#if BUILD_JTAG_DPI == 1
+               &jtag_dpi_adapter_driver,
+#endif
 #if BUILD_FT232R == 1
                &ft232r_adapter_driver,
 #endif
index 9a51974..ee9b48b 100644 (file)
 
 #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
 
+/* FIXME: none of the _width parameters are actually observed properly!
+ * you WILL need to edit more if you actually attempt to target a 8/16/64
+ * bit target!
+ */
+
 struct FreeRTOS_params {
        const char *target_name;
        const unsigned char thread_count_width;
@@ -158,7 +163,7 @@ static const struct symbols FreeRTOS_symbol_list[] = {
 static int FreeRTOS_update_threads(struct rtos *rtos)
 {
        int retval;
-       int tasks_found = 0;
+       unsigned int tasks_found = 0;
        const struct FreeRTOS_params *param;
 
        if (rtos->rtos_specific_params == NULL)
@@ -176,12 +181,11 @@ static int FreeRTOS_update_threads(struct rtos *rtos)
                return -2;
        }
 
-       int thread_list_size = 0;
-       retval = target_read_buffer(rtos->target,
+       uint32_t thread_list_size = 0;
+       retval = target_read_u32(rtos->target,
                        rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address,
-                       param->thread_count_width,
-                       (uint8_t *)&thread_list_size);
-       LOG_DEBUG("FreeRTOS: Read uxCurrentNumberOfTasks at 0x%" PRIx64 ", value %d\r\n",
+                       &thread_list_size);
+       LOG_DEBUG("FreeRTOS: Read uxCurrentNumberOfTasks at 0x%" PRIx64 ", value %" PRIu32,
                                                                                rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address,
                                                                                thread_list_size);
 
@@ -194,15 +198,16 @@ static int FreeRTOS_update_threads(struct rtos *rtos)
        rtos_free_threadlist(rtos);
 
        /* read the current thread */
-       retval = target_read_buffer(rtos->target,
+       uint32_t pointer_casts_are_bad;
+       retval = target_read_u32(rtos->target,
                        rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
-                       param->pointer_width,
-                       (uint8_t *)&rtos->current_thread);
+                       &pointer_casts_are_bad);
        if (retval != ERROR_OK) {
                LOG_ERROR("Error reading current thread in FreeRTOS thread list");
                return retval;
        }
-       LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
+       rtos->current_thread = pointer_casts_are_bad;
+       LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64 ", value 0x%" PRIx64,
                                                                                rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
                                                                                rtos->current_thread);
 
@@ -244,20 +249,17 @@ static int FreeRTOS_update_threads(struct rtos *rtos)
                LOG_ERROR("FreeRTOS: uxTopUsedPriority is not defined, consult the OpenOCD manual for a work-around");
                return ERROR_FAIL;
        }
-       uint64_t top_used_priority = 0;
-       /* FIXME: endianness error on almost all target_read_buffer(), see also
-        * other rtoses */
-       retval = target_read_buffer(rtos->target,
+       uint32_t top_used_priority = 0;
+       retval = target_read_u32(rtos->target,
                        rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
-                       param->pointer_width,
-                       (uint8_t *)&top_used_priority);
+                       &top_used_priority);
        if (retval != ERROR_OK)
                return retval;
-       LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64 ", value %" PRIu64 "\r\n",
+       LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64 ", value %" PRIu32,
                                                                                rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
                                                                                top_used_priority);
        if (top_used_priority > FREERTOS_MAX_PRIORITIES) {
-               LOG_ERROR("FreeRTOS top used priority is unreasonably big, not proceeding: %" PRIu64,
+               LOG_ERROR("FreeRTOS top used priority is unreasonably big, not proceeding: %" PRIu32,
                        top_used_priority);
                return ERROR_FAIL;
        }
@@ -292,35 +294,33 @@ static int FreeRTOS_update_threads(struct rtos *rtos)
                        continue;
 
                /* Read the number of threads in this list */
-               int64_t list_thread_count = 0;
-               retval = target_read_buffer(rtos->target,
+               uint32_t list_thread_count = 0;
+               retval = target_read_u32(rtos->target,
                                list_of_lists[i],
-                               param->thread_count_width,
-                               (uint8_t *)&list_thread_count);
+                               &list_thread_count);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
                        free(list_of_lists);
                        return retval;
                }
-               LOG_DEBUG("FreeRTOS: Read thread count for list %u at 0x%" PRIx64 ", value %" PRId64 "\r\n",
+               LOG_DEBUG("FreeRTOS: Read thread count for list %u at 0x%" PRIx64 ", value %" PRIu32,
                                                                                i, list_of_lists[i], list_thread_count);
 
                if (list_thread_count == 0)
                        continue;
 
                /* Read the location of first list item */
-               uint64_t prev_list_elem_ptr = -1;
-               uint64_t list_elem_ptr = 0;
-               retval = target_read_buffer(rtos->target,
+               uint32_t prev_list_elem_ptr = -1;
+               uint32_t list_elem_ptr = 0;
+               retval = target_read_u32(rtos->target,
                                list_of_lists[i] + param->list_next_offset,
-                               param->pointer_width,
-                               (uint8_t *)&list_elem_ptr);
+                               &list_elem_ptr);
                if (retval != ERROR_OK) {
                        LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
                        free(list_of_lists);
                        return retval;
                }
-               LOG_DEBUG("FreeRTOS: Read first item for list %u at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
+               LOG_DEBUG("FreeRTOS: Read first item for list %u at 0x%" PRIx64 ", value 0x%" PRIx32,
                                                                                i, list_of_lists[i] + param->list_next_offset, list_elem_ptr);
 
                while ((list_thread_count > 0) && (list_elem_ptr != 0) &&
@@ -328,16 +328,16 @@ static int FreeRTOS_update_threads(struct rtos *rtos)
                                (tasks_found < thread_list_size)) {
                        /* Get the location of the thread structure. */
                        rtos->thread_details[tasks_found].threadid = 0;
-                       retval = target_read_buffer(rtos->target,
+                       retval = target_read_u32(rtos->target,
                                        list_elem_ptr + param->list_elem_content_offset,
-                                       param->pointer_width,
-                                       (uint8_t *)&(rtos->thread_details[tasks_found].threadid));
+                                       &pointer_casts_are_bad);
                        if (retval != ERROR_OK) {
                                LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
                                free(list_of_lists);
                                return retval;
                        }
-                       LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
+                       rtos->thread_details[tasks_found].threadid = pointer_casts_are_bad;
+                       LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx32 ", value 0x%" PRIx64,
                                                                                list_elem_ptr + param->list_elem_content_offset,
                                                                                rtos->thread_details[tasks_found].threadid);
 
@@ -357,7 +357,7 @@ static int FreeRTOS_update_threads(struct rtos *rtos)
                                return retval;
                        }
                        tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
-                       LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64 ", value \"%s\"\r\n",
+                       LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64 ", value '%s'",
                                                                                rtos->thread_details[tasks_found].threadid + param->thread_name_offset,
                                                                                tmp_str);
 
@@ -383,16 +383,15 @@ static int FreeRTOS_update_threads(struct rtos *rtos)
 
                        prev_list_elem_ptr = list_elem_ptr;
                        list_elem_ptr = 0;
-                       retval = target_read_buffer(rtos->target,
+                       retval = target_read_u32(rtos->target,
                                        prev_list_elem_ptr + param->list_elem_next_offset,
-                                       param->pointer_width,
-                                       (uint8_t *)&list_elem_ptr);
+                                       &list_elem_ptr);
                        if (retval != ERROR_OK) {
                                LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
                                free(list_of_lists);
                                return retval;
                        }
-                       LOG_DEBUG("FreeRTOS: Read next thread location at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
+                       LOG_DEBUG("FreeRTOS: Read next thread location at 0x%" PRIx32 ", value 0x%" PRIx32,
                                                                                prev_list_elem_ptr + param->list_elem_next_offset,
                                                                                list_elem_ptr);
                }
@@ -422,15 +421,16 @@ static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
        param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
 
        /* Read the stack pointer */
-       retval = target_read_buffer(rtos->target,
+       uint32_t pointer_casts_are_bad;
+       retval = target_read_u32(rtos->target,
                        thread_id + param->thread_stack_offset,
-                       param->pointer_width,
-                       (uint8_t *)&stack_ptr);
+                       &pointer_casts_are_bad);
        if (retval != ERROR_OK) {
                LOG_ERROR("Error reading stack frame from FreeRTOS thread");
                return retval;
        }
-       LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
+       stack_ptr = pointer_casts_are_bad;
+       LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64 ", value 0x%" PRIx64,
                                                                                thread_id + param->thread_stack_offset,
                                                                                stack_ptr);
 
@@ -459,12 +459,11 @@ static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
        if (cm4_fpu_enabled == 1) {
                /* Read the LR to decide between stacking with or without FPU */
                uint32_t LR_svc = 0;
-               retval = target_read_buffer(rtos->target,
+               retval = target_read_u32(rtos->target,
                                stack_ptr + 0x20,
-                               param->pointer_width,
-                               (uint8_t *)&LR_svc);
+                               &LR_svc);
                if (retval != ERROR_OK) {
-                       LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
+                       LOG_OUTPUT("Error reading stack frame from FreeRTOS thread");
                        return retval;
                }
                if ((LR_svc & 0x10) == 0)
index 0243c63..407ab68 100644 (file)
@@ -538,7 +538,17 @@ static int telnet_input(struct connection *connection)
                                                        telnet_move_cursor(connection, 0);
                                                else if (*buf_p == CTRL('E'))
                                                        telnet_move_cursor(connection, t_con->line_size);
-                                               else
+                                               else if (*buf_p == CTRL('K')) {         /* kill line to end */
+                                                       if (t_con->line_cursor < t_con->line_size) {
+                                                               /* overwrite with space, until end of line, move back */
+                                                               for (size_t i = t_con->line_cursor; i < t_con->line_size; i++)
+                                                                       telnet_write(connection, " ", 1);
+                                                               for (size_t i = t_con->line_cursor; i < t_con->line_size; i++)
+                                                                       telnet_write(connection, "\b", 1);
+                                                               t_con->line[t_con->line_cursor] = '\0';
+                                                               t_con->line_size = t_con->line_cursor;
+                                                       }
+                                               } else
                                                        LOG_DEBUG("unhandled nonprintable: %2.2x", *buf_p);
                                        }
                                }
index 42d809d..19ba771 100644 (file)
@@ -7,6 +7,7 @@ endif
 %C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la \
        %D%/riscv/libriscv.la
 
+%C%_libtarget_la_CPPFLAGS = $(AM_CPPFLAGS)
 
 STARTUP_TCL_SRCS += %D%/startup.tcl
 
@@ -33,6 +34,11 @@ noinst_LTLIBRARIES += %D%/libtarget.la
        $(ARMV8_SRC) \
        $(MIPS64_SRC)
 
+if HAVE_CAPSTONE
+%C%_libtarget_la_CPPFLAGS += $(CAPSTONE_CFLAGS)
+%C%_libtarget_la_LIBADD += $(CAPSTONE_LIBS)
+endif
+
 TARGET_CORE_SRC = \
        %D%/algorithm.c \
        %D%/register.c \
@@ -83,6 +89,7 @@ ARMV8_SRC = \
        %D%/armv8_dpm.c \
        %D%/armv8_opcodes.c \
        %D%/aarch64.c \
+       %D%/a64_disassembler.c \
        %D%/armv8.c \
        %D%/armv8_cache.c
 
@@ -170,6 +177,7 @@ ARC_SRC = \
        %D%/armv7a_cache_l2x.h \
        %D%/armv7a_mmu.h \
        %D%/arm_disassembler.h \
+       %D%/a64_disassembler.h \
        %D%/arm_opcodes.h \
        %D%/arm_simulator.h \
        %D%/arm_semihosting.h \
diff --git a/src/target/a64_disassembler.c b/src/target/a64_disassembler.c
new file mode 100644 (file)
index 0000000..bd78129
--- /dev/null
@@ -0,0 +1,145 @@
+/***************************************************************************
+ *   Copyright (C) 2019 by Mete Balci                                      *
+ *   metebalci@gmail.com                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/log.h>
+#include "target.h"
+#include "a64_disassembler.h"
+
+#if HAVE_CAPSTONE
+
+#include <capstone/capstone.h>
+
+static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
+{
+       uint32_t opcode = 0;
+
+       memcpy(&opcode, insn->bytes, insn->size);
+
+       if (insn->size == 4) {
+
+               uint16_t opcode_high = opcode >> 16;
+
+               opcode = opcode & 0xffff;
+
+               command_print(cmd,
+                               "0x%08" PRIx64"  %04x %04x\t%s\t%s",
+                               insn->address,
+                               opcode,
+                               opcode_high,
+                               insn->mnemonic,
+                               insn->op_str);
+
+       } else {
+
+               command_print(
+                               cmd,
+                               "0x%08" PRIx64"  %04x\t%s\t%s",
+                               insn->address,
+                               opcode,
+                               insn->mnemonic,
+                               insn->op_str);
+
+       }
+}
+
+int a64_disassemble(struct command_invocation *cmd, struct target *target, target_addr_t address, size_t count)
+{
+       int ret;
+       int csret;
+       csh handle;
+
+       csret = cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &handle);
+
+       if (csret != CS_ERR_OK) {
+
+               LOG_ERROR("cs_open() failed: %s", cs_strerror(csret));
+               return ERROR_FAIL;
+
+       }
+
+       csret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
+
+       if (csret != CS_ERR_OK) {
+
+               LOG_ERROR("cs_option() failed: %s", cs_strerror(csret));
+               cs_close(&handle);
+               return ERROR_FAIL;
+
+       }
+
+       cs_insn *insn = cs_malloc(handle);
+
+       if (csret != CS_ERR_OK) {
+
+               LOG_ERROR("cs_malloc() failed: %s", cs_strerror(csret));
+               cs_close(&handle);
+               return ERROR_FAIL;
+
+       }
+
+       while (count > 0) {
+
+               uint8_t buffer[4];
+
+               ret = target_read_buffer(target, address, sizeof(buffer), buffer);
+
+               if (ret != ERROR_OK) {
+                       cs_free(insn, 1);
+                       cs_close(&handle);
+                       return ret;
+               }
+
+               size_t size = sizeof(buffer);
+               const uint8_t *tmp = buffer;
+
+               ret = cs_disasm_iter(handle, &tmp, &size, &address, insn);
+
+               if (!ret) {
+
+                       LOG_ERROR("cs_disasm_iter() failed: %s", cs_strerror(cs_errno(handle)));
+                       cs_free(insn, 1);
+                       cs_close(&handle);
+                       return ERROR_FAIL;
+
+               }
+
+               print_opcode(cmd, insn);
+               count--;
+
+       }
+
+       cs_free(insn, 1);
+       cs_close(&handle);
+
+       return ERROR_OK;
+}
+
+#else
+
+int a64_disassemble(struct command_invocation *cmd, struct target *target, target_addr_t address, size_t count)
+{
+       command_print(cmd, "capstone disassembly framework required");
+
+       return ERROR_FAIL;
+}
+
+#endif
diff --git a/src/target/a64_disassembler.h b/src/target/a64_disassembler.h
new file mode 100644 (file)
index 0000000..5c58bbf
--- /dev/null
@@ -0,0 +1,30 @@
+/***************************************************************************
+ *   Copyright (C) 2019 by Mete Balci                                      *
+ *   metebalci@gmail.com                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifndef OPENOCD_TARGET_AARCH64_DISASSEMBLER_H
+#define OPENOCD_TARGET_AARCH64_DISASSEMBLER_H
+
+#include "target.h"
+
+int a64_disassemble(
+               struct command_invocation *cmd,
+               struct target *target,
+               target_addr_t address,
+               size_t count);
+
+#endif /* OPENOCD_TARGET_AARCH64_DISASSEMBLER_H */
index 4febc8c..d111a05 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "breakpoints.h"
 #include "aarch64.h"
+#include "a64_disassembler.h"
 #include "register.h"
 #include "target_request.h"
 #include "target_type.h"
@@ -2247,7 +2248,7 @@ static int aarch64_examine_first(struct target *target)
        struct aarch64_common *aarch64 = target_to_aarch64(target);
        struct armv8_common *armv8 = &aarch64->armv8_common;
        struct adiv5_dap *swjdp = armv8->arm.dap;
-       struct aarch64_private_config *pc;
+       struct aarch64_private_config *pc = target->private_config;
        int i;
        int retval = ERROR_OK;
        uint64_t debug, ttypr;
@@ -2255,11 +2256,18 @@ static int aarch64_examine_first(struct target *target)
        uint32_t tmp0, tmp1, tmp2, tmp3;
        debug = ttypr = cpuid = 0;
 
-       /* Search for the APB-AB - it is needed for access to debug registers */
-       retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap);
-       if (retval != ERROR_OK) {
-               LOG_ERROR("Could not find APB-AP for debug access");
-               return retval;
+       if (pc == NULL)
+               return ERROR_FAIL;
+
+       if (pc->adiv5_config.ap_num == DP_APSEL_INVALID) {
+               /* Search for the APB-AB */
+               retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Could not find APB-AP for debug access");
+                       return retval;
+               }
+       } else {
+               armv8->debug_ap = dap_ap(swjdp, pc->adiv5_config.ap_num);
        }
 
        retval = mem_ap_init(armv8->debug_ap);
@@ -2334,10 +2342,6 @@ static int aarch64_examine_first(struct target *target)
        LOG_DEBUG("ttypr = 0x%08" PRIx64, ttypr);
        LOG_DEBUG("debug = 0x%08" PRIx64, debug);
 
-       if (target->private_config == NULL)
-               return ERROR_FAIL;
-
-       pc = (struct aarch64_private_config *)target->private_config;
        if (pc->cti == NULL)
                return ERROR_FAIL;
 
@@ -2490,6 +2494,7 @@ static int aarch64_jim_configure(struct target *target, Jim_GetOptInfo *goi)
        pc = (struct aarch64_private_config *)target->private_config;
        if (pc == NULL) {
                        pc = calloc(1, sizeof(struct aarch64_private_config));
+                       pc->adiv5_config.ap_num = DP_APSEL_INVALID;
                        target->private_config = pc;
        }
 
@@ -2499,8 +2504,13 @@ static int aarch64_jim_configure(struct target *target, Jim_GetOptInfo *goi)
         * options, JIM_OK if it correctly parsed the topmost option
         * and JIM_ERR if an error occurred during parameter evaluation.
         * For JIM_CONTINUE, we check our own params.
+        *
+        * adiv5_jim_configure() assumes 'private_config' to point to
+        * 'struct adiv5_private_config'. Override 'private_config'!
         */
+       target->private_config = &pc->adiv5_config;
        e = adiv5_jim_configure(target, goi);
+       target->private_config = pc;
        if (e != JIM_CONTINUE)
                return e;
 
@@ -2566,7 +2576,6 @@ COMMAND_HANDLER(aarch64_handle_cache_info_command)
                        &armv8->armv8_mmu.armv8_cache);
 }
 
-
 COMMAND_HANDLER(aarch64_handle_dbginit_command)
 {
        struct target *target = get_current_target(CMD_CTX);
@@ -2578,6 +2587,39 @@ COMMAND_HANDLER(aarch64_handle_dbginit_command)
        return aarch64_init_debug_access(target);
 }
 
+COMMAND_HANDLER(aarch64_handle_disassemble_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+
+       if (target == NULL) {
+               LOG_ERROR("No target selected");
+               return ERROR_FAIL;
+       }
+
+       struct aarch64_common *aarch64 = target_to_aarch64(target);
+
+       if (aarch64->common_magic != AARCH64_COMMON_MAGIC) {
+               command_print(CMD, "current target isn't an AArch64");
+               return ERROR_FAIL;
+       }
+
+       int count = 1;
+       target_addr_t address;
+
+       switch (CMD_ARGC) {
+               case 2:
+                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
+               /* FALL THROUGH */
+               case 1:
+                       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
+                       break;
+               default:
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       return a64_disassemble(CMD, target, address, count);
+}
+
 COMMAND_HANDLER(aarch64_mask_interrupts_command)
 {
        struct target *target = get_current_target(CMD_CTX);
@@ -2759,6 +2801,13 @@ static const struct command_registration aarch64_exec_command_handlers[] = {
                .usage = "",
        },
        {
+               .name = "disassemble",
+               .handler = aarch64_handle_disassemble_command,
+               .mode = COMMAND_EXEC,
+               .help = "Disassemble instructions",
+               .usage = "address [count]",
+       },
+       {
                .name = "maskisr",
                .handler = aarch64_mask_interrupts_command,
                .mode = COMMAND_ANY,
index e1b5764..cec6441 100644 (file)
@@ -48,6 +48,8 @@
  */
 
 
+static int arc_remove_watchpoint(struct target *target,
+       struct watchpoint *watchpoint);
 
 void arc_reg_data_type_add(struct target *target,
                struct arc_reg_data_type *data_type)
@@ -1696,6 +1698,7 @@ void arc_reset_actionpoints(struct target *target)
        struct arc_common *arc = target_to_arc(target);
        struct arc_actionpoint *ap_list = arc->actionpoints_list;
        struct breakpoint *next_b;
+       struct watchpoint *next_w;
 
        while (target->breakpoints) {
                next_b = target->breakpoints->next;
@@ -1704,6 +1707,12 @@ void arc_reset_actionpoints(struct target *target)
                free(target->breakpoints);
                target->breakpoints = next_b;
        }
+       while (target->watchpoints) {
+               next_w = target->watchpoints->next;
+               arc_remove_watchpoint(target, target->watchpoints);
+               free(target->watchpoints);
+               target->watchpoints = next_w;
+       }
        for (unsigned int i = 0; i < arc->actionpoints_num; i++) {
                if ((ap_list[i].used) && (ap_list[i].reg_address))
                        arc_remove_auxreg_actionpoint(target, ap_list[i].reg_address);
@@ -1800,6 +1809,159 @@ int arc_remove_auxreg_actionpoint(struct target *target, uint32_t auxreg_addr)
        return retval;
 }
 
+
+static int arc_set_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
+{
+       unsigned int wp_num;
+       struct arc_common *arc = target_to_arc(target);
+       struct arc_actionpoint *ap_list = arc->actionpoints_list;
+
+       if (watchpoint->set) {
+               LOG_WARNING("watchpoint already set");
+               return ERROR_OK;
+       }
+
+       for (wp_num = 0; wp_num < arc->actionpoints_num; wp_num++) {
+               if (!ap_list[wp_num].used)
+                       break;
+       }
+
+       if (wp_num >= arc->actionpoints_num) {
+               LOG_ERROR("No free actionpoints, maximum amount is %u",
+                               arc->actionpoints_num);
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       if (watchpoint->length != 4) {
+               LOG_ERROR("Only watchpoints of length 4 are supported");
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+       }
+
+       int enable = AP_AC_TT_DISABLE;
+       switch (watchpoint->rw) {
+               case WPT_READ:
+                       enable = AP_AC_TT_READ;
+                       break;
+               case WPT_WRITE:
+                       enable = AP_AC_TT_WRITE;
+                       break;
+               case WPT_ACCESS:
+                       enable = AP_AC_TT_READWRITE;
+                       break;
+               default:
+                       LOG_ERROR("BUG: watchpoint->rw neither read, write nor access");
+                       return ERROR_FAIL;
+       }
+
+       int retval =  arc_configure_actionpoint(target, wp_num,
+                                       watchpoint->address, enable, AP_AC_AT_MEMORY_ADDR);
+
+       if (retval == ERROR_OK) {
+               watchpoint->set = wp_num + 1;
+               ap_list[wp_num].used = 1;
+               ap_list[wp_num].bp_value = watchpoint->address;
+               ap_list[wp_num].type = ARC_AP_WATCHPOINT;
+
+               LOG_DEBUG("wpid: %" PRIu32 ", wp_num %u wp_value 0x%" PRIx32,
+                               watchpoint->unique_id, wp_num, ap_list[wp_num].bp_value);
+       }
+
+       return retval;
+}
+
+static int arc_unset_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
+{
+       /* get pointers to arch-specific information */
+       struct arc_common *arc = target_to_arc(target);
+       struct arc_actionpoint *ap_list = arc->actionpoints_list;
+
+       if (!watchpoint->set) {
+               LOG_WARNING("watchpoint not set");
+               return ERROR_OK;
+       }
+
+       unsigned int wp_num = watchpoint->set - 1;
+       if ((watchpoint->set == 0) || (wp_num >= arc->actionpoints_num)) {
+               LOG_DEBUG("Invalid actionpoint ID: %u in watchpoint: %" PRIu32,
+                               wp_num, watchpoint->unique_id);
+               return ERROR_OK;
+       }
+
+       int retval =  arc_configure_actionpoint(target, wp_num,
+                               watchpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_MEMORY_ADDR);
+
+       if (retval == ERROR_OK) {
+               watchpoint->set = 0;
+               ap_list[wp_num].used = 0;
+               ap_list[wp_num].bp_value = 0;
+
+               LOG_DEBUG("wpid: %" PRIu32 " - releasing actionpoint ID: %u",
+                               watchpoint->unique_id, wp_num);
+       }
+
+       return retval;
+}
+
+static int arc_add_watchpoint(struct target *target,
+       struct watchpoint *watchpoint)
+{
+       if (target->state != TARGET_HALTED) {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       CHECK_RETVAL(arc_set_watchpoint(target, watchpoint));
+
+       return ERROR_OK;
+}
+
+static int arc_remove_watchpoint(struct target *target,
+       struct watchpoint *watchpoint)
+{
+       if (target->state != TARGET_HALTED) {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (watchpoint->set)
+               CHECK_RETVAL(arc_unset_watchpoint(target, watchpoint));
+
+       return ERROR_OK;
+}
+
+static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint)
+{
+       assert(target);
+       assert(hit_watchpoint);
+
+       struct arc_actionpoint *actionpoint = NULL;
+       CHECK_RETVAL(get_current_actionpoint(target, &actionpoint));
+
+       if (actionpoint != NULL) {
+               if (!actionpoint->used)
+                       LOG_WARNING("Target halted by unused actionpoint.");
+
+               /* If this check fails - that is some sort of an error in OpenOCD. */
+               if (actionpoint->type != ARC_AP_WATCHPOINT)
+                       LOG_WARNING("Target halted by breakpoint, but is treated as a watchpoint.");
+
+               for (struct watchpoint *watchpoint = target->watchpoints;
+                               watchpoint != NULL;
+                               watchpoint = watchpoint->next) {
+                       if (actionpoint->bp_value == watchpoint->address) {
+                               *hit_watchpoint = watchpoint;
+                               LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %i",
+                                                       watchpoint->unique_id, watchpoint->set - 1);
+                               return ERROR_OK;
+                       }
+               }
+       }
+
+       return ERROR_FAIL;
+}
+
 /* Helper function which switches core to single_step mode by
  * doing aux r/w operations.  */
 int arc_config_step(struct target *target, int enable_step)
@@ -2106,9 +2268,9 @@ struct target_type arcv2_target = {
        .add_context_breakpoint = NULL,
        .add_hybrid_breakpoint = NULL,
        .remove_breakpoint = arc_remove_breakpoint,
-       .add_watchpoint = NULL,
-       .remove_watchpoint = NULL,
-       .hit_watchpoint = NULL,
+       .add_watchpoint = arc_add_watchpoint,
+       .remove_watchpoint = arc_remove_watchpoint,
+       .hit_watchpoint = arc_hit_watchpoint,
 
        .run_algorithm = NULL,
        .start_algorithm = NULL,
index 59c0537..9b8c09e 100644 (file)
 #include "arm_disassembler.h"
 #include <helper/log.h>
 
+#if HAVE_CAPSTONE
+#include <capstone/capstone.h>
+#endif
+
 /*
  * This disassembler supports two main functions for OpenOCD:
  *
@@ -3000,1616 +3004,126 @@ int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruct
        return -1;
 }
 
-static int t2ev_b_bl(uint32_t opcode, uint32_t address,
-                    struct arm_instruction *instruction, char *cp)
-{
-       unsigned offset;
-       unsigned b21 = 1 << 21;
-       unsigned b22 = 1 << 22;
-
-       /* instead of combining two smaller 16-bit branch instructions,
-        * Thumb2 uses only one larger 32-bit instruction.
-        */
-       offset = opcode & 0x7ff;
-       offset |= (opcode & 0x03ff0000) >> 5;
-       if (opcode & (1 << 26)) {
-               offset |= 0xff << 23;
-               if ((opcode & (1 << 11)) == 0)
-                       b21 = 0;
-               if ((opcode & (1 << 13)) == 0)
-                       b22 = 0;
-       } else {
-               if (opcode & (1 << 11))
-                       b21 = 0;
-               if (opcode & (1 << 13))
-                       b22 = 0;
-       }
-       offset |= b21;
-       offset |= b22;
-
-
-       address += 4;
-       address += offset << 1;
-
-       char *inst;
-       switch ((opcode >> 12) & 0x5) {
-       case 0x1:
-               inst = "B.W";
-               instruction->type = ARM_B;
-               break;
-       case 0x4:
-               inst = "BLX";
-               instruction->type = ARM_BLX;
-               address &= 0xfffffffc;
-               break;
-       case 0x5:
-               inst = "BL";
-               instruction->type = ARM_BL;
-               break;
-       default:
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       instruction->info.b_bl_bx_blx.reg_operand = -1;
-       instruction->info.b_bl_bx_blx.target_address = address;
-       sprintf(cp, "%s\t%#8.8" PRIx32, inst, address);
-
-       return ERROR_OK;
-}
-
-static int t2ev_cond_b(uint32_t opcode, uint32_t address,
-                      struct arm_instruction *instruction, char *cp)
-{
-       unsigned offset;
-       unsigned b17 = 1 << 17;
-       unsigned b18 = 1 << 18;
-       unsigned cond = (opcode >> 22) & 0x0f;
-
-       offset = opcode & 0x7ff;
-       offset |= (opcode & 0x003f0000) >> 5;
-       if (opcode & (1 << 26)) {
-               offset |= 0x1fff << 19;
-               if ((opcode & (1 << 11)) == 0)
-                       b17 = 0;
-               if ((opcode & (1 << 13)) == 0)
-                       b18 = 0;
-       } else {
-               if (opcode & (1 << 11))
-                       b17 = 0;
-               if (opcode & (1 << 13))
-                       b18 = 0;
-       }
-       offset |= b17;
-       offset |= b18;
-
-       address += 4;
-       address += offset << 1;
-
-       instruction->type = ARM_B;
-       instruction->info.b_bl_bx_blx.reg_operand = -1;
-       instruction->info.b_bl_bx_blx.target_address = address;
-       sprintf(cp, "B%s.W\t%#8.8" PRIx32,
-                       arm_condition_strings[cond],
-                       address);
-
-       return ERROR_OK;
-}
-
-static const char *special_name(int number)
+int arm_access_size(struct arm_instruction *instruction)
 {
-       char *special = "(RESERVED)";
-
-       switch (number) {
-               case 0:
-                       special = "apsr";
-                       break;
-               case 1:
-                       special = "iapsr";
-                       break;
-               case 2:
-                       special = "eapsr";
-                       break;
-               case 3:
-                       special = "xpsr";
-                       break;
-               case 5:
-                       special = "ipsr";
-                       break;
-               case 6:
-                       special = "epsr";
-                       break;
-               case 7:
-                       special = "iepsr";
-                       break;
-               case 8:
-                       special = "msp";
-                       break;
-               case 9:
-                       special = "psp";
-                       break;
-               case 16:
-                       special = "primask";
-                       break;
-               case 17:
-                       special = "basepri";
-                       break;
-               case 18:
-                       special = "basepri_max";
-                       break;
-               case 19:
-                       special = "faultmask";
-                       break;
-               case 20:
-                       special = "control";
-                       break;
+       if ((instruction->type == ARM_LDRB)
+           || (instruction->type == ARM_LDRBT)
+           || (instruction->type == ARM_LDRSB)
+           || (instruction->type == ARM_STRB)
+           || (instruction->type == ARM_STRBT))
+               return 1;
+       else if ((instruction->type == ARM_LDRH)
+                || (instruction->type == ARM_LDRSH)
+                || (instruction->type == ARM_STRH))
+               return 2;
+       else if ((instruction->type == ARM_LDR)
+                || (instruction->type == ARM_LDRT)
+                || (instruction->type == ARM_STR)
+                || (instruction->type == ARM_STRT))
+               return 4;
+       else if ((instruction->type == ARM_LDRD)
+                || (instruction->type == ARM_STRD))
+               return 8;
+       else {
+               LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
+                               instruction->type);
+               return 0;
        }
-       return special;
 }
 
-static int t2ev_hint(uint32_t opcode, uint32_t address,
-                    struct arm_instruction *instruction, char *cp)
+#if HAVE_CAPSTONE
+static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
 {
-       const char *mnemonic;
+       uint32_t opcode = 0;
 
-       if (opcode & 0x0700) {
-               instruction->type = ARM_UNDEFINED_INSTRUCTION;
-               strcpy(cp, "UNDEFINED");
-               return ERROR_OK;
-       }
+       memcpy(&opcode, insn->bytes, insn->size);
 
-       if (opcode & 0x00f0) {
-               sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
-               return ERROR_OK;
-       }
+       if (insn->size == 4) {
+               uint16_t opcode_high = opcode >> 16;
+               opcode = opcode & 0xffff;
 
-       switch (opcode & 0x0f) {
-               case 0:
-                       mnemonic = "NOP.W";
-                       break;
-               case 1:
-                       mnemonic = "YIELD.W";
-                       break;
-               case 2:
-                       mnemonic = "WFE.W";
-                       break;
-               case 3:
-                       mnemonic = "WFI.W";
-                       break;
-               case 4:
-                       mnemonic = "SEV.W";
-                       break;
-               default:
-                       mnemonic = "HINT.W (UNRECOGNIZED)";
-                       break;
+               command_print(cmd, "0x%08" PRIx64"  %04x %04x\t%s%s%s",
+                       insn->address, opcode, opcode_high, insn->mnemonic,
+                       insn->op_str[0] ? "\t" : "", insn->op_str);
+       } else {
+               command_print(cmd, "0x%08" PRIx64"  %04x\t%s%s%s",
+                       insn->address, opcode, insn->mnemonic,
+                       insn->op_str[0] ? "\t" : "", insn->op_str);
        }
-       strcpy(cp, mnemonic);
-       return ERROR_OK;
 }
 
-static int t2ev_misc(uint32_t opcode, uint32_t address,
-                    struct arm_instruction *instruction, char *cp)
+int arm_disassemble(struct command_invocation *cmd, struct target *target,
+               target_addr_t address, size_t count, bool thumb_mode)
 {
-       const char *mnemonic;
+       csh handle;
+       int ret;
+       cs_insn *insn;
+       cs_mode mode;
 
-       switch ((opcode >> 4) & 0x0f) {
-               case 0:
-                       mnemonic = "LEAVEX";
-                       break;
-               case 1:
-                       mnemonic = "ENTERX";
-                       break;
-               case 2:
-                       mnemonic = "CLREX";
-                       break;
-               case 4:
-                       mnemonic = "DSB";
-                       break;
-               case 5:
-                       mnemonic = "DMB";
-                       break;
-               case 6:
-                       mnemonic = "ISB";
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       strcpy(cp, mnemonic);
-       return ERROR_OK;
-}
-
-static int t2ev_b_misc(uint32_t opcode, uint32_t address,
-                      struct arm_instruction *instruction, char *cp)
-{
-       /* permanently undefined */
-       if ((opcode & 0x07f07000) == 0x07f02000) {
-               instruction->type = ARM_UNDEFINED_INSTRUCTION;
-               strcpy(cp, "UNDEFINED");
-               return ERROR_OK;
+       if (!cs_support(CS_ARCH_ARM)) {
+               LOG_ERROR("ARM architecture not supported by capstone");
+               return ERROR_FAIL;
        }
 
-       switch ((opcode >> 12) & 0x5) {
-               case 0x1:
-               case 0x4:
-               case 0x5:
-                       return t2ev_b_bl(opcode, address, instruction, cp);
-               case 0:
-                       if (((opcode >> 23) & 0x07) != 0x07)
-                               return t2ev_cond_b(opcode, address, instruction, cp);
-                       if (opcode & (1 << 26))
-                               goto undef;
-                       break;
-       }
+       mode = CS_MODE_LITTLE_ENDIAN;
 
-       switch ((opcode >> 20) & 0x7f) {
-               case 0x38:
-               case 0x39:
-                       sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
-                               (int) (opcode >> 16) & 0x0f);
-                       return ERROR_OK;
-               case 0x3a:
-                       return t2ev_hint(opcode, address, instruction, cp);
-               case 0x3b:
-                       return t2ev_misc(opcode, address, instruction, cp);
-               case 0x3c:
-                       sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
-                       return ERROR_OK;
-               case 0x3e:
-               case 0x3f:
-                       sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
-                               special_name(opcode & 0xff));
-                       return ERROR_OK;
-       }
+       if (thumb_mode)
+               mode |= CS_MODE_THUMB;
 
-undef:
-       return ERROR_COMMAND_SYNTAX_ERROR;
-}
+       ret = cs_open(CS_ARCH_ARM, mode, &handle);
 
-static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
-                              struct arm_instruction *instruction, char *cp)
-{
-       char *mnemonic = NULL;
-       int rn = (opcode >> 16) & 0xf;
-       int rd = (opcode >> 8) & 0xf;
-       unsigned immed = opcode & 0xff;
-       unsigned func;
-       bool one = false;
-       char *suffix = "";
-       char *suffix2 = "";
-
-       /* ARMv7-M: A5.3.2 Modified immediate constants */
-       func = (opcode >> 11) & 0x0e;
-       if (immed & 0x80)
-               func |= 1;
-       if (opcode & (1 << 26))
-               func |= 0x10;
-
-       /* "Modified" immediates */
-       switch (func >> 1) {
-               case 0:
-                       break;
-               case 2:
-                       immed <<= 8;
-               /* FALLTHROUGH */
-               case 1:
-                       immed += immed << 16;
-                       break;
-               case 3:
-                       immed += immed << 8;
-                       immed += immed << 16;
-                       break;
-               default:
-                       immed |= 0x80;
-                       immed = ror(immed, func);
+       if (ret != CS_ERR_OK) {
+               LOG_ERROR("cs_open() failed: %s", cs_strerror(ret));
+               return ERROR_FAIL;
        }
 
-       if (opcode & (1 << 20))
-               suffix = "S";
+       ret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
 
-       switch ((opcode >> 21) & 0xf) {
-               case 0:
-                       if (rd == 0xf) {
-                               instruction->type = ARM_TST;
-                               mnemonic = "TST";
-                               one = true;
-                               suffix = "";
-                               rd = rn;
-                       } else {
-                               instruction->type = ARM_AND;
-                               mnemonic = "AND";
-                       }
-                       break;
-               case 1:
-                       instruction->type = ARM_BIC;
-                       mnemonic = "BIC";
-                       break;
-               case 2:
-                       if (rn == 0xf) {
-                               instruction->type = ARM_MOV;
-                               mnemonic = "MOV";
-                               one = true;
-                               suffix2 = ".W";
-                       } else {
-                               instruction->type = ARM_ORR;
-                               mnemonic = "ORR";
-                       }
-                       break;
-               case 3:
-                       if (rn == 0xf) {
-                               instruction->type = ARM_MVN;
-                               mnemonic = "MVN";
-                               one = true;
-                       } else {
-                               /* instruction->type = ARM_ORN; */
-                               mnemonic = "ORN";
-                       }
-                       break;
-               case 4:
-                       if (rd == 0xf) {
-                               instruction->type = ARM_TEQ;
-                               mnemonic = "TEQ";
-                               one = true;
-                               suffix = "";
-                               rd = rn;
-                       } else {
-                               instruction->type = ARM_EOR;
-                               mnemonic = "EOR";
-                       }
-                       break;
-               case 8:
-                       if (rd == 0xf) {
-                               instruction->type = ARM_CMN;
-                               mnemonic = "CMN";
-                               one = true;
-                               suffix = "";
-                               rd = rn;
-                       } else {
-                               instruction->type = ARM_ADD;
-                               mnemonic = "ADD";
-                               suffix2 = ".W";
-                       }
-                       break;
-               case 10:
-                       instruction->type = ARM_ADC;
-                       mnemonic = "ADC";
-                       suffix2 = ".W";
-                       break;
-               case 11:
-                       instruction->type = ARM_SBC;
-                       mnemonic = "SBC";
-                       break;
-               case 13:
-                       if (rd == 0xf) {
-                               instruction->type = ARM_CMP;
-                               mnemonic = "CMP";
-                               one = true;
-                               suffix = "";
-                               rd = rn;
-                       } else {
-                               instruction->type = ARM_SUB;
-                               mnemonic = "SUB";
-                       }
-                       suffix2 = ".W";
-                       break;
-               case 14:
-                       instruction->type = ARM_RSB;
-                       mnemonic = "RSB";
-                       suffix2 = ".W";
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
+       if (ret != CS_ERR_OK) {
+               LOG_ERROR("cs_option() failed: %s", cs_strerror(ret));
+               cs_close(&handle);
+               return ERROR_FAIL;
        }
 
-       if (one)
-               sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
-                               mnemonic, suffix2, rd, immed, immed);
-       else
-               sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
-                               mnemonic, suffix, suffix2,
-                               rd, rn, immed, immed);
-
-       return ERROR_OK;
-}
-
-static int t2ev_data_immed(uint32_t opcode, uint32_t address,
-                          struct arm_instruction *instruction, char *cp)
-{
-       char *mnemonic = NULL;
-       int rn = (opcode >> 16) & 0xf;
-       int rd = (opcode >> 8) & 0xf;
-       unsigned immed;
-       bool add = false;
-       bool is_signed = false;
-
-       immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
-       if (opcode & (1 << 26))
-               immed |= (1 << 11);
+       insn = cs_malloc(handle);
 
-       switch ((opcode >> 20) & 0x1f) {
-               case 0:
-                       if (rn == 0xf) {
-                               add = true;
-                               goto do_adr;
-                       }
-                       mnemonic = "ADDW";
-                       break;
-               case 4:
-                       immed |= (opcode >> 4) & 0xf000;
-                       sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
-                       return ERROR_OK;
-               case 0x0a:
-                       if (rn == 0xf)
-                               goto do_adr;
-                       mnemonic = "SUBW";
-                       break;
-               case 0x0c:
-                       /* move constant to top 16 bits of register */
-                       immed |= (opcode >> 4) & 0xf000;
-                       sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
-                       return ERROR_OK;
-               case 0x10:
-               case 0x12:
-                       is_signed = true;
-                       /* fallthrough */
-               case 0x18:
-               case 0x1a:
-                       /* signed/unsigned saturated add */
-                       immed = (opcode >> 6) & 0x03;
-                       immed |= (opcode >> 10) & 0x1c;
-                       sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
-                               is_signed ? "S" : "U",
-                               rd, (int) (opcode & 0x1f) + is_signed, rn,
-                               (opcode & (1 << 21)) ? "ASR" : "LSL",
-                               immed ? immed : 32);
-                       return ERROR_OK;
-               case 0x14:
-                       is_signed = true;
-               /* FALLTHROUGH */
-               case 0x1c:
-                       /* signed/unsigned bitfield extract */
-                       immed = (opcode >> 6) & 0x03;
-                       immed |= (opcode >> 10) & 0x1c;
-                       sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
-                               is_signed ? "S" : "U",
-                               rd, rn, immed,
-                               (int) (opcode & 0x1f) + 1);
-                       return ERROR_OK;
-               case 0x16:
-                       immed = (opcode >> 6) & 0x03;
-                       immed |= (opcode >> 10) & 0x1c;
-                       if (rn == 0xf)  /* bitfield clear */
-                               sprintf(cp, "BFC\tr%d, #%d, #%d\t",
-                                               rd, immed,
-                                               (int) (opcode & 0x1f) + 1 - immed);
-                       else            /* bitfield insert */
-                               sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
-                                               rd, rn, immed,
-                                               (int) (opcode & 0x1f) + 1 - immed);
-                       return ERROR_OK;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
+       if (!insn) {
+               LOG_ERROR("cs_malloc() failed\n");
+               cs_close(&handle);
+               return ERROR_FAIL;
        }
 
-       sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
-                       rd, rn, immed, immed);
-       return ERROR_OK;
+       while (count > 0) {
+           uint8_t buffer[4];
 
-do_adr:
-       address = thumb_alignpc4(address);
-       if (add)
-               address += immed;
-       else
-               address -= immed;
-       /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
-        * not hiding the pc-relative stuff will sometimes be useful.
-        */
-       sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
-       return ERROR_OK;
-}
+               ret = target_read_buffer(target, address, sizeof(buffer), buffer);
 
-static int t2ev_store_single(uint32_t opcode, uint32_t address,
-                            struct arm_instruction *instruction, char *cp)
-{
-       unsigned op = (opcode >> 20) & 0xf;
-       char *size = "";
-       char *suffix = "";
-       char *p1 = "";
-       char *p2 = "]";
-       unsigned immed;
-       unsigned rn = (opcode >> 16) & 0x0f;
-       unsigned rt = (opcode >> 12) & 0x0f;
-
-       if (rn == 0xf)
-               return ERROR_COMMAND_SYNTAX_ERROR;
-
-       if (opcode & 0x0800)
-               op |= 1;
-       switch (op) {
-               /* byte */
-               case 0x8:
-               case 0x9:
-                       size = "B";
-                       goto imm12;
-               case 0x1:
-                       size = "B";
-                       goto imm8;
-               case 0x0:
-                       size = "B";
-                       break;
-               /* halfword */
-               case 0xa:
-               case 0xb:
-                       size = "H";
-                       goto imm12;
-               case 0x3:
-                       size = "H";
-                       goto imm8;
-               case 0x2:
-                       size = "H";
-                       break;
-               /* word */
-               case 0xc:
-               case 0xd:
-                       goto imm12;
-               case 0x5:
-                       goto imm8;
-               case 0x4:
-                       break;
-               /* error */
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
+               if (ret != ERROR_OK) {
+                       cs_free(insn, 1);
+                       cs_close(&handle);
+                       return ret;
+               }
 
-       sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
-                       size, rt, rn, (int) opcode & 0x0f,
-                       (int) (opcode >> 4) & 0x03);
-       return ERROR_OK;
+               size_t size = sizeof(buffer);
+               const uint8_t *tmp = buffer;
 
-imm12:
-       immed = opcode & 0x0fff;
-       sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
-                       size, rt, rn, immed, immed);
-       return ERROR_OK;
+               ret = cs_disasm_iter(handle, &tmp, &size, &address, insn);
 
-imm8:
-       immed = opcode & 0x00ff;
+               if (!ret) {
+                       LOG_ERROR("cs_disasm_iter() failed: %s",
+                               cs_strerror(cs_errno(handle)));
+                       cs_free(insn, 1);
+                       cs_close(&handle);
+                       return ERROR_FAIL;
+               }
 
-       switch (opcode & 0x700) {
-               case 0x600:
-                       suffix = "T";
-                       break;
-               case 0x000:
-               case 0x200:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
+               print_opcode(cmd, insn);
+               count--;
        }
 
-       /* two indexed modes will write back rn */
-       if (opcode & 0x100) {
-               if (opcode & 0x400)     /* pre-indexed */
-                       p2 = "]!";
-               else {                  /* post-indexed */
-                       p1 = "]";
-                       p2 = "";
-               }
-       }
+       cs_free(insn, 1);
+       cs_close(&handle);
 
-       sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
-                       size, suffix, rt, rn, p1,
-                       (opcode & 0x200) ? "" : "-",
-                       immed, p2, immed);
        return ERROR_OK;
 }
-
-static int t2ev_mul32(uint32_t opcode, uint32_t address,
-                     struct arm_instruction *instruction, char *cp)
-{
-       int ra = (opcode >> 12) & 0xf;
-
-       switch (opcode & 0x007000f0) {
-               case 0:
-                       if (ra == 0xf)
-                               sprintf(cp, "MUL\tr%d, r%d, r%d",
-                                               (int) (opcode >> 8) & 0xf,
-                                               (int) (opcode >> 16) & 0xf,
-                                               (int) (opcode >> 0) & 0xf);
-                       else
-                               sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
-                                               (int) (opcode >> 8) & 0xf,
-                                               (int) (opcode >> 16) & 0xf,
-                                               (int) (opcode >> 0) & 0xf, ra);
-                       break;
-               case 0x10:
-                       sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
-                               (int) (opcode >> 8) & 0xf,
-                               (int) (opcode >> 16) & 0xf,
-                               (int) (opcode >> 0) & 0xf, ra);
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       return ERROR_OK;
-}
-
-static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
-                         struct arm_instruction *instruction, char *cp)
-{
-       int op = (opcode >> 4) & 0xf;
-       char *infix = "MUL";
-
-       op += (opcode >> 16) & 0x70;
-       switch (op) {
-               case 0x40:
-               case 0x60:
-                       infix = "MLA";
-               /* FALLTHROUGH */
-               case 0:
-               case 0x20:
-                       sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
-                               (op & 0x20) ? 'U' : 'S',
-                               infix,
-                               (int) (opcode >> 12) & 0xf,
-                               (int) (opcode >> 8) & 0xf,
-                               (int) (opcode >> 16) & 0xf,
-                               (int) (opcode >> 0) & 0xf);
-                       break;
-               case 0x1f:
-               case 0x3f:
-                       sprintf(cp, "%cDIV\tr%d, r%d, r%d",
-                               (op & 0x20) ? 'U' : 'S',
-                               (int) (opcode >> 8) & 0xf,
-                               (int) (opcode >> 16) & 0xf,
-                               (int) (opcode >> 0) & 0xf);
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       return ERROR_OK;
-}
-
-static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
-                       struct arm_instruction *instruction, char *cp)
-{
-       int rn = (opcode >> 16) & 0xf;
-       int op = (opcode >> 22) & 0x6;
-       int t = (opcode >> 21) & 1;
-       unsigned registers = opcode & 0xffff;
-       char *mode = "";
-
-       if (opcode & (1 << 20))
-               op |= 1;
-
-       switch (op) {
-               case 0:
-                       mode = "DB";
-               /* FALL THROUGH */
-               case 6:
-                       sprintf(cp, "SRS%s\tsp%s, #%d", mode,
-                               t ? "!" : "",
-                               (unsigned) (opcode & 0x1f));
-                       return ERROR_OK;
-               case 1:
-                       mode = "DB";
-               /* FALL THROUGH */
-               case 7:
-                       sprintf(cp, "RFE%s\tr%d%s", mode,
-                               (unsigned) ((opcode >> 16) & 0xf),
-                               t ? "!" : "");
-                       return ERROR_OK;
-               case 2:
-                       sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
-                       break;
-               case 3:
-                       if (rn == 13 && t)
-                               sprintf(cp, "POP.W\t");
-                       else
-                               sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
-                       break;
-               case 4:
-                       if (rn == 13 && t)
-                               sprintf(cp, "PUSH.W\t");
-                       else
-                               sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
-                       break;
-               case 5:
-                       sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       cp = strchr(cp, 0);
-       *cp++ = '{';
-       for (t = 0; registers; t++, registers >>= 1) {
-               if ((registers & 1) == 0)
-                       continue;
-               registers &= ~1;
-               sprintf(cp, "r%d%s", t, registers ? ", " : "");
-               cp = strchr(cp, 0);
-       }
-       *cp++ = '}';
-       *cp++ = 0;
-
-       return ERROR_OK;
-}
-
-/* load/store dual or exclusive, table branch */
-static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
-                           struct arm_instruction *instruction, char *cp)
-{
-       unsigned op1op2 = (opcode >> 20) & 0x3;
-       unsigned op3 = (opcode >> 4) & 0xf;
-       char *mnemonic;
-       unsigned rn = (opcode >> 16) & 0xf;
-       unsigned rt = (opcode >> 12) & 0xf;
-       unsigned rd = (opcode >> 8) & 0xf;
-       unsigned imm = opcode & 0xff;
-       char *p1 = "";
-       char *p2 = "]";
-
-       op1op2 |= (opcode >> 21) & 0xc;
-       switch (op1op2) {
-               case 0:
-                       mnemonic = "STREX";
-                       goto strex;
-               case 1:
-                       mnemonic = "LDREX";
-                       goto ldrex;
-               case 2:
-               case 6:
-               case 8:
-               case 10:
-               case 12:
-               case 14:
-                       mnemonic = "STRD";
-                       goto immediate;
-               case 3:
-               case 7:
-               case 9:
-               case 11:
-               case 13:
-               case 15:
-                       mnemonic = "LDRD";
-                       if (rn == 15)
-                               goto literal;
-                       else
-                               goto immediate;
-               case 4:
-                       switch (op3) {
-                               case 4:
-                                       mnemonic = "STREXB";
-                                       break;
-                               case 5:
-                                       mnemonic = "STREXH";
-                                       break;
-                               default:
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                       }
-                       rd = opcode & 0xf;
-                       imm = 0;
-                       goto strex;
-               case 5:
-                       switch (op3) {
-                               case 0:
-                                       sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
-                                       return ERROR_OK;
-                               case 1:
-                                       sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
-                                       return ERROR_OK;
-                               case 4:
-                                       mnemonic = "LDREXB";
-                                       break;
-                               case 5:
-                                       mnemonic = "LDREXH";
-                                       break;
-                               default:
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                       }
-                       imm = 0;
-                       goto ldrex;
-       }
-       return ERROR_COMMAND_SYNTAX_ERROR;
-
-strex:
-       imm <<= 2;
-       if (imm)
-               sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
-                               mnemonic, rd, rt, rn, imm, imm);
-       else
-               sprintf(cp, "%s\tr%u, r%u, [r%u]",
-                               mnemonic, rd, rt, rn);
-       return ERROR_OK;
-
-ldrex:
-       imm <<= 2;
-       if (imm)
-               sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
-                               mnemonic, rt, rn, imm, imm);
-       else
-               sprintf(cp, "%s\tr%u, [r%u]",
-                               mnemonic, rt, rn);
-       return ERROR_OK;
-
-immediate:
-       /* two indexed modes will write back rn */
-       if (opcode & (1 << 21)) {
-               if (opcode & (1 << 24)) /* pre-indexed */
-                       p2 = "]!";
-               else {                  /* post-indexed */
-                       p1 = "]";
-                       p2 = "";
-               }
-       }
-
-       imm <<= 2;
-       sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
-                       mnemonic, rt, rd, rn, p1,
-                       (opcode & (1 << 23)) ? "" : "-",
-                       imm, p2, imm);
-       return ERROR_OK;
-
-literal:
-       address = thumb_alignpc4(address);
-       imm <<= 2;
-       if (opcode & (1 << 23))
-               address += imm;
-       else
-               address -= imm;
-       sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
-                       mnemonic, rt, rd, address);
-       return ERROR_OK;
-}
-
-static int t2ev_data_shift(uint32_t opcode, uint32_t address,
-                          struct arm_instruction *instruction, char *cp)
-{
-       int op = (opcode >> 21) & 0xf;
-       int rd = (opcode >> 8) & 0xf;
-       int rn = (opcode >> 16) & 0xf;
-       int type = (opcode >> 4) & 0x3;
-       int immed = (opcode >> 6) & 0x3;
-       char *mnemonic;
-       char *suffix = "";
-
-       immed |= (opcode >> 10) & 0x1c;
-       if (opcode & (1 << 20))
-               suffix = "S";
-
-       switch (op) {
-               case 0:
-                       if (rd == 0xf) {
-                               if (!(opcode & (1 << 20)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               instruction->type = ARM_TST;
-                               mnemonic = "TST";
-                               suffix = "";
-                               goto two;
-                       }
-                       instruction->type = ARM_AND;
-                       mnemonic = "AND";
-                       break;
-               case 1:
-                       instruction->type = ARM_BIC;
-                       mnemonic = "BIC";
-                       break;
-               case 2:
-                       if (rn == 0xf) {
-                               instruction->type = ARM_MOV;
-                               switch (type) {
-                                       case 0:
-                                               if (immed == 0) {
-                                                       sprintf(cp, "MOV%s.W\tr%d, r%d",
-                                                                       suffix, rd,
-                                                                       (int) (opcode & 0xf));
-                                                       return ERROR_OK;
-                                               }
-                                               mnemonic = "LSL";
-                                               break;
-                                       case 1:
-                                               mnemonic = "LSR";
-                                               break;
-                                       case 2:
-                                               mnemonic = "ASR";
-                                               break;
-                                       default:
-                                               if (immed == 0) {
-                                                       sprintf(cp, "RRX%s\tr%d, r%d",
-                                                                       suffix, rd,
-                                                                       (int) (opcode & 0xf));
-                                                       return ERROR_OK;
-                                               }
-                                               mnemonic = "ROR";
-                                               break;
-                               }
-                               goto immediate;
-                       } else {
-                               instruction->type = ARM_ORR;
-                               mnemonic = "ORR";
-                       }
-                       break;
-               case 3:
-                       if (rn == 0xf) {
-                               instruction->type = ARM_MVN;
-                               mnemonic = "MVN";
-                               rn = rd;
-                               goto two;
-                       } else {
-                               /* instruction->type = ARM_ORN; */
-                               mnemonic = "ORN";
-                       }
-                       break;
-               case 4:
-                       if (rd == 0xf) {
-                               if (!(opcode & (1 << 20)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               instruction->type = ARM_TEQ;
-                               mnemonic = "TEQ";
-                               suffix = "";
-                               goto two;
-                       }
-                       instruction->type = ARM_EOR;
-                       mnemonic = "EOR";
-                       break;
-               case 8:
-                       if (rd == 0xf) {
-                               if (!(opcode & (1 << 20)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               instruction->type = ARM_CMN;
-                               mnemonic = "CMN";
-                               suffix = "";
-                               goto two;
-                       }
-                       instruction->type = ARM_ADD;
-                       mnemonic = "ADD";
-                       break;
-               case 0xa:
-                       instruction->type = ARM_ADC;
-                       mnemonic = "ADC";
-                       break;
-               case 0xb:
-                       instruction->type = ARM_SBC;
-                       mnemonic = "SBC";
-                       break;
-               case 0xd:
-                       if (rd == 0xf) {
-                               if (!(opcode & (1 << 21)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               instruction->type = ARM_CMP;
-                               mnemonic = "CMP";
-                               suffix = "";
-                               goto two;
-                       }
-                       instruction->type = ARM_SUB;
-                       mnemonic = "SUB";
-                       break;
-               case 0xe:
-                       instruction->type = ARM_RSB;
-                       mnemonic = "RSB";
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
-                       mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
-
-shift:
-       cp = strchr(cp, 0);
-
-       switch (type) {
-               case 0:
-                       if (immed == 0)
-                               return ERROR_OK;
-                       suffix = "LSL";
-                       break;
-               case 1:
-                       suffix = "LSR";
-                       if (immed == 32)
-                               immed = 0;
-                       break;
-               case 2:
-                       suffix = "ASR";
-                       if (immed == 32)
-                               immed = 0;
-                       break;
-               case 3:
-                       if (immed == 0) {
-                               strcpy(cp, ", RRX");
-                               return ERROR_OK;
-                       }
-                       suffix = "ROR";
-                       break;
-       }
-       sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
-       return ERROR_OK;
-
-two:
-       sprintf(cp, "%s%s.W\tr%d, r%d",
-                       mnemonic, suffix, rn, (int) (opcode & 0xf));
-       goto shift;
-
-immediate:
-       sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
-                       mnemonic, suffix, rd,
-                       (int) (opcode & 0xf), immed ? immed : 32);
-       return ERROR_OK;
-}
-
-static int t2ev_data_reg(uint32_t opcode, uint32_t address,
-                        struct arm_instruction *instruction, char *cp)
-{
-       char *mnemonic;
-       char *suffix = "";
-
-       if (((opcode >> 4) & 0xf) == 0) {
-               switch ((opcode >> 21) & 0x7) {
-                       case 0:
-                               mnemonic = "LSL";
-                               break;
-                       case 1:
-                               mnemonic = "LSR";
-                               break;
-                       case 2:
-                               mnemonic = "ASR";
-                               break;
-                       case 3:
-                               mnemonic = "ROR";
-                               break;
-                       default:
-                               return ERROR_COMMAND_SYNTAX_ERROR;
-               }
-
-               instruction->type = ARM_MOV;
-               if (opcode & (1 << 20))
-                       suffix = "S";
-               sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
-                               mnemonic, suffix,
-                               (int) (opcode >> 8) & 0xf,
-                               (int) (opcode >> 16) & 0xf,
-                               (int) (opcode >> 0) & 0xf);
-
-       } else if (opcode & (1 << 7)) {
-               switch ((opcode >> 20) & 0xf) {
-                       case 0:
-                       case 1:
-                       case 4:
-                       case 5:
-                               switch ((opcode >> 4) & 0x3) {
-                                       case 1:
-                                               suffix = ", ROR #8";
-                                               break;
-                                       case 2:
-                                               suffix = ", ROR #16";
-                                               break;
-                                       case 3:
-                                               suffix = ", ROR #24";
-                                               break;
-                               }
-                               sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
-                                       (opcode & (1 << 24)) ? 'U' : 'S',
-                                       (opcode & (1 << 26)) ? 'B' : 'H',
-                                       (int) (opcode >> 8) & 0xf,
-                                       (int) (opcode >> 0) & 0xf,
-                                       suffix);
-                               break;
-                       case 8:
-                       case 9:
-                       case 0xa:
-                       case 0xb:
-                               if (opcode & (1 << 6))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               if (((opcode >> 12) & 0xf) != 0xf)
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               if (!(opcode & (1 << 20)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-
-                               switch (((opcode >> 19) & 0x04)
-                                       | ((opcode >> 4) & 0x3)) {
-                                       case 0:
-                                               mnemonic = "REV.W";
-                                               break;
-                                       case 1:
-                                               mnemonic = "REV16.W";
-                                               break;
-                                       case 2:
-                                               mnemonic = "RBIT";
-                                               break;
-                                       case 3:
-                                               mnemonic = "REVSH.W";
-                                               break;
-                                       case 4:
-                                               mnemonic = "CLZ";
-                                               break;
-                                       default:
-                                               return ERROR_COMMAND_SYNTAX_ERROR;
-                               }
-                               sprintf(cp, "%s\tr%d, r%d",
-                                       mnemonic,
-                                       (int) (opcode >> 8) & 0xf,
-                                       (int) (opcode >> 0) & 0xf);
-                               break;
-                       default:
-                               return ERROR_COMMAND_SYNTAX_ERROR;
-               }
-       }
-
-       return ERROR_OK;
-}
-
-static int t2ev_load_word(uint32_t opcode, uint32_t address,
-                         struct arm_instruction *instruction, char *cp)
-{
-       int rn = (opcode >> 16) & 0xf;
-       int immed;
-
-       instruction->type = ARM_LDR;
-
-       if (rn == 0xf) {
-               immed = opcode & 0x0fff;
-               if ((opcode & (1 << 23)) == 0)
-                       immed = -immed;
-               sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
-                               (int) (opcode >> 12) & 0xf,
-                               thumb_alignpc4(address) + immed);
-               return ERROR_OK;
-       }
-
-       if (opcode & (1 << 23)) {
-               immed = opcode & 0x0fff;
-               sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
-                               (int) (opcode >> 12) & 0xf,
-                               rn, immed, immed);
-               return ERROR_OK;
-       }
-
-       if (!(opcode & (0x3f << 6))) {
-               sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
-                               (int) (opcode >> 12) & 0xf,
-                               rn,
-                               (int) (opcode >> 0) & 0xf,
-                               (int) (opcode >> 4) & 0x3);
-               return ERROR_OK;
-       }
-
-
-       if (((opcode >> 8) & 0xf) == 0xe) {
-               immed = opcode & 0x00ff;
-
-               sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
-                               (int) (opcode >> 12) & 0xf,
-                               rn, immed, immed);
-               return ERROR_OK;
-       }
-
-       if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
-               char *p1 = "]", *p2 = "";
-
-               if (!(opcode & 0x0500))
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-
-               immed = opcode & 0x00ff;
-
-               /* two indexed modes will write back rn */
-               if (opcode & 0x100) {
-                       if (opcode & 0x400)     /* pre-indexed */
-                               p2 = "]!";
-                       else {                  /* post-indexed */
-                               p1 = "]";
-                               p2 = "";
-                       }
-               }
-
-               sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
-                               (int) (opcode >> 12) & 0xf,
-                               rn, p1,
-                               (opcode & 0x200) ? "" : "-",
-                               immed, p2, immed);
-               return ERROR_OK;
-       }
-
-       return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
-                               struct arm_instruction *instruction, char *cp)
-{
-       int rn = (opcode >> 16) & 0xf;
-       int rt = (opcode >> 12) & 0xf;
-       int op2 = (opcode >> 6) & 0x3f;
-       unsigned immed;
-       char *p1 = "", *p2 = "]";
-       char *mnemonic;
-
-       switch ((opcode >> 23) & 0x3) {
-               case 0:
-                       if ((rn & rt) == 0xf) {
-pld_literal:
-                               immed = opcode & 0xfff;
-                               address = thumb_alignpc4(address);
-                               if (opcode & (1 << 23))
-                                       address += immed;
-                               else
-                                       address -= immed;
-                               sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
-                                               rt, address);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0x0f && rt != 0x0f) {
-ldrb_literal:
-                               immed = opcode & 0xfff;
-                               address = thumb_alignpc4(address);
-                               if (opcode & (1 << 23))
-                                       address += immed;
-                               else
-                                       address -= immed;
-                               sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
-                                               rt, address);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0x0f)
-                               break;
-                       if ((op2 & 0x3c) == 0x38) {
-                               immed = opcode & 0xff;
-                               sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
-                                               rt, rn, immed, immed);
-                               return ERROR_OK;
-                       }
-                       if ((op2 & 0x3c) == 0x30) {
-                               if (rt == 0x0f) {
-                                       immed = opcode & 0xff;
-                                       immed = -immed;
-preload_immediate:
-                                       p1 = (opcode & (1 << 21)) ? "W" : "";
-                                       sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
-                                                       p1, rn, immed, immed);
-                                       return ERROR_OK;
-                               }
-                               mnemonic = "LDRB";
-ldrxb_immediate_t3:
-                               immed = opcode & 0xff;
-                               if (!(opcode & 0x200))
-                                       immed = -immed;
-
-                               /* two indexed modes will write back rn */
-                               if (opcode & 0x100) {
-                                       if (opcode & 0x400)     /* pre-indexed */
-                                               p2 = "]!";
-                                       else {          /* post-indexed */
-                                               p1 = "]";
-                                               p2 = "";
-                                       }
-                               }
-ldrxb_immediate_t2:
-                               sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
-                                               mnemonic, rt, rn, p1,
-                                               immed, p2, immed);
-                               return ERROR_OK;
-                       }
-                       if ((op2 & 0x24) == 0x24) {
-                               mnemonic = "LDRB";
-                               goto ldrxb_immediate_t3;
-                       }
-                       if (op2 == 0) {
-                               int rm = opcode & 0xf;
-
-                               if (rt == 0x0f)
-                                       sprintf(cp, "PLD\t");
-                               else
-                                       sprintf(cp, "LDRB.W\tr%d, ", rt);
-                               immed = (opcode >> 4) & 0x3;
-                               cp = strchr(cp, 0);
-                               sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
-                               return ERROR_OK;
-                       }
-                       break;
-               case 1:
-                       if ((rn & rt) == 0xf)
-                               goto pld_literal;
-                       if (rt == 0xf) {
-                               immed = opcode & 0xfff;
-                               goto preload_immediate;
-                       }
-                       if (rn == 0x0f)
-                               goto ldrb_literal;
-                       mnemonic = "LDRB.W";
-                       immed = opcode & 0xfff;
-                       goto ldrxb_immediate_t2;
-               case 2:
-                       if ((rn & rt) == 0xf) {
-                               immed = opcode & 0xfff;
-                               address = thumb_alignpc4(address);
-                               if (opcode & (1 << 23))
-                                       address += immed;
-                               else
-                                       address -= immed;
-                               sprintf(cp, "PLI\t%#8.8" PRIx32, address);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0xf && rt != 0xf) {
-ldrsb_literal:
-                               immed = opcode & 0xfff;
-                               address = thumb_alignpc4(address);
-                               if (opcode & (1 << 23))
-                                       address += immed;
-                               else
-                                       address -= immed;
-                               sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0xf)
-                               break;
-                       if ((op2 & 0x3c) == 0x38) {
-                               immed = opcode & 0xff;
-                               sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
-                                               rt, rn, immed, immed);
-                               return ERROR_OK;
-                       }
-                       if ((op2 & 0x3c) == 0x30) {
-                               if (rt == 0xf) {
-                                       immed = opcode & 0xff;
-                                       immed = -immed; /* pli */
-                                       sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
-                                                       rn, immed, -immed);
-                                       return ERROR_OK;
-                               }
-                               mnemonic = "LDRSB";
-                               goto ldrxb_immediate_t3;
-                       }
-                       if ((op2 & 0x24) == 0x24) {
-                               mnemonic = "LDRSB";
-                               goto ldrxb_immediate_t3;
-                       }
-                       if (op2 == 0) {
-                               int rm = opcode & 0xf;
-
-                               if (rt == 0x0f)
-                                       sprintf(cp, "PLI\t");
-                               else
-                                       sprintf(cp, "LDRSB.W\tr%d, ", rt);
-                               immed = (opcode >> 4) & 0x3;
-                               cp = strchr(cp, 0);
-                               sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
-                               return ERROR_OK;
-                       }
-                       break;
-               case 3:
-                       if (rt == 0xf) {
-                               immed = opcode & 0xfff;
-                               sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
-                                               rn, immed, immed);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0xf)
-                               goto ldrsb_literal;
-                       immed = opcode & 0xfff;
-                       mnemonic = "LDRSB";
-                       goto ldrxb_immediate_t2;
-       }
-
-       return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
-                             struct arm_instruction *instruction, char *cp)
-{
-       int rn = (opcode >> 16) & 0xf;
-       int rt = (opcode >> 12) & 0xf;
-       int op2 = (opcode >> 6) & 0x3f;
-       char *sign = "";
-       unsigned immed;
-
-       if (rt == 0xf) {
-               sprintf(cp, "HINT (UNALLOCATED)");
-               return ERROR_OK;
-       }
-
-       if (opcode & (1 << 24))
-               sign = "S";
-
-       if ((opcode & (1 << 23)) == 0) {
-               if (rn == 0xf) {
-ldrh_literal:
-                       immed = opcode & 0xfff;
-                       address = thumb_alignpc4(address);
-                       if (opcode & (1 << 23))
-                               address += immed;
-                       else
-                               address -= immed;
-                       sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
-                                       sign, rt, address);
-                       return ERROR_OK;
-               }
-               if (op2 == 0) {
-                       int rm = opcode & 0xf;
-
-                       immed = (opcode >> 4) & 0x3;
-                       sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
-                                       sign, rt, rn, rm, immed);
-                       return ERROR_OK;
-               }
-               if ((op2 & 0x3c) == 0x38) {
-                       immed = opcode & 0xff;
-                       sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
-                                       sign, rt, rn, immed, immed);
-                       return ERROR_OK;
-               }
-               if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
-                       char *p1 = "", *p2 = "]";
-
-                       immed = opcode & 0xff;
-                       if (!(opcode & 0x200))
-                               immed = -immed;
-
-                       /* two indexed modes will write back rn */
-                       if (opcode & 0x100) {
-                               if (opcode & 0x400)     /* pre-indexed */
-                                       p2 = "]!";
-                               else {                  /* post-indexed */
-                                       p1 = "]";
-                                       p2 = "";
-                               }
-                       }
-                       sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
-                                       sign, rt, rn, p1, immed, p2, immed);
-                       return ERROR_OK;
-               }
-       } else {
-               if (rn == 0xf)
-                       goto ldrh_literal;
-
-               immed = opcode & 0xfff;
-               sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
-                               sign, *sign ? "" : ".W",
-                               rt, rn, immed, immed);
-               return ERROR_OK;
-       }
-
-       return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-/*
- * REVISIT for Thumb2 instructions, instruction->type and friends aren't
- * always set.  That means eventual arm_simulate_step() support for Thumb2
- * will need work in this area.
- */
-int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
-{
-       int retval;
-       uint16_t op;
-       uint32_t opcode;
-       char *cp;
-
-       /* clear low bit ... it's set on function pointers */
-       address &= ~1;
-
-       /* clear fields, to avoid confusion */
-       memset(instruction, 0, sizeof(struct arm_instruction));
-
-       /* read first halfword, see if this is the only one */
-       retval = target_read_u16(target, address, &op);
-       if (retval != ERROR_OK)
-               return retval;
-
-       switch (op & 0xf800) {
-               case 0xf800:
-               case 0xf000:
-               case 0xe800:
-                       /* 32-bit instructions */
-                       instruction->instruction_size = 4;
-                       opcode = op << 16;
-                       retval = target_read_u16(target, address + 2, &op);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       opcode |= op;
-                       instruction->opcode = opcode;
-                       break;
-               default:
-                       /* 16-bit:  Thumb1 + IT + CBZ/CBNZ + ... */
-                       return thumb_evaluate_opcode(op, address, instruction);
-       }
-
-       snprintf(instruction->text, 128,
-                       "0x%8.8" PRIx32 "  0x%8.8" PRIx32 "\t",
-                       address, opcode);
-       cp = strchr(instruction->text, 0);
-       retval = ERROR_FAIL;
-
-       /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
-       if ((opcode & 0x1a008000) == 0x10000000)
-               retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
-       else if ((opcode & 0x1a008000) == 0x12000000)
-               retval = t2ev_data_immed(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
-       else if ((opcode & 0x18008000) == 0x10008000)
-               retval = t2ev_b_misc(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.5 Load/store multiple */
-       else if ((opcode & 0x1e400000) == 0x08000000)
-               retval = t2ev_ldm_stm(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
-       else if ((opcode & 0x1e400000) == 0x08400000)
-               retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.7 Load word */
-       else if ((opcode & 0x1f700000) == 0x18500000)
-               retval = t2ev_load_word(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
-       else if ((opcode & 0x1e700000) == 0x18300000)
-               retval = t2ev_load_halfword(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.9 Load byte, memory hints */
-       else if ((opcode & 0x1e700000) == 0x18100000)
-               retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.10 Store single data item */
-       else if ((opcode & 0x1f100000) == 0x18000000)
-               retval = t2ev_store_single(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.11 Data processing (shifted register) */
-       else if ((opcode & 0x1e000000) == 0x0a000000)
-               retval = t2ev_data_shift(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.12 Data processing (register)
-        * and A5.3.13 Miscellaneous operations
-        */
-       else if ((opcode & 0x1f000000) == 0x1a000000)
-               retval = t2ev_data_reg(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
-       else if ((opcode & 0x1f800000) == 0x1b000000)
-               retval = t2ev_mul32(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
-       else if ((opcode & 0x1f800000) == 0x1b800000)
-               retval = t2ev_mul64_div(opcode, address, instruction, cp);
-
-       if (retval == ERROR_OK)
-               return retval;
-
-       /*
-        * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
-        * instructions; not yet handled here.
-        */
-
-       if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
-               instruction->type = ARM_UNDEFINED_INSTRUCTION;
-               strcpy(cp, "UNDEFINED OPCODE");
-               return ERROR_OK;
-       }
-
-       LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
-                       opcode);
-
-       strcpy(cp, "(32-bit Thumb2 ...)");
-       return ERROR_OK;
-}
-
-int arm_access_size(struct arm_instruction *instruction)
-{
-       if ((instruction->type == ARM_LDRB)
-           || (instruction->type == ARM_LDRBT)
-           || (instruction->type == ARM_LDRSB)
-           || (instruction->type == ARM_STRB)
-           || (instruction->type == ARM_STRBT))
-               return 1;
-       else if ((instruction->type == ARM_LDRH)
-                || (instruction->type == ARM_LDRSH)
-                || (instruction->type == ARM_STRH))
-               return 2;
-       else if ((instruction->type == ARM_LDR)
-                || (instruction->type == ARM_LDRT)
-                || (instruction->type == ARM_STR)
-                || (instruction->type == ARM_STRT))
-               return 4;
-       else if ((instruction->type == ARM_LDRD)
-                || (instruction->type == ARM_STRD))
-               return 8;
-       else {
-               LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
-                               instruction->type);
-               return 0;
-       }
-}
+#endif /* HAVE_CAPSTONE */
index 486e903..beecb3f 100644 (file)
@@ -197,9 +197,11 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
                struct arm_instruction *instruction);
 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address,
                struct arm_instruction *instruction);
-int thumb2_opcode(struct target *target, uint32_t address,
-               struct arm_instruction *instruction);
 int arm_access_size(struct arm_instruction *instruction);
+#if HAVE_CAPSTONE
+int arm_disassemble(struct command_invocation *cmd, struct target *target,
+               target_addr_t address, size_t count, bool thumb_mode);
+#endif
 
 #define COND(opcode) (arm_condition_strings[(opcode & 0xf0000000) >> 28])
 
index 58bc339..7da28e3 100644 (file)
@@ -942,7 +942,7 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command)
 
 COMMAND_HANDLER(handle_arm_disassemble_command)
 {
-       int retval = ERROR_OK;
+#if HAVE_CAPSTONE
        struct target *target = get_current_target(CMD_CTX);
 
        if (target == NULL) {
@@ -952,8 +952,8 @@ COMMAND_HANDLER(handle_arm_disassemble_command)
 
        struct arm *arm = target_to_arm(target);
        target_addr_t address;
-       int count = 1;
-       int thumb = 0;
+       unsigned int count = 1;
+       bool thumb = false;
 
        if (!is_arm(arm)) {
                command_print(CMD, "current target isn't an ARM");
@@ -962,62 +962,37 @@ COMMAND_HANDLER(handle_arm_disassemble_command)
 
        if (arm->core_type == ARM_CORE_TYPE_M_PROFILE) {
                /* armv7m is always thumb mode */
-               thumb = 1;
+               thumb = true;
        }
 
        switch (CMD_ARGC) {
                case 3:
                        if (strcmp(CMD_ARGV[2], "thumb") != 0)
-                               goto usage;
-                       thumb = 1;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
+                       thumb = true;
                /* FALL THROUGH */
                case 2:
-                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
+                       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
                /* FALL THROUGH */
                case 1:
                        COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
                        if (address & 0x01) {
                                if (!thumb) {
                                        command_print(CMD, "Disassemble as Thumb");
-                                       thumb = 1;
+                                       thumb = true;
                                }
                                address &= ~1;
                        }
                        break;
                default:
-usage:
-                       count = 0;
-                       retval = ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       while (count-- > 0) {
-               struct arm_instruction cur_instruction;
-
-               if (thumb) {
-                       /* Always use Thumb2 disassembly for best handling
-                        * of 32-bit BL/BLX, and to work with newer cores
-                        * (some ARMv6, all ARMv7) that use Thumb2.
-                        */
-                       retval = thumb2_opcode(target, address,
-                                       &cur_instruction);
-                       if (retval != ERROR_OK)
-                               break;
-               } else {
-                       uint32_t opcode;
-
-                       retval = target_read_u32(target, address, &opcode);
-                       if (retval != ERROR_OK)
-                               break;
-                       retval = arm_evaluate_opcode(opcode, address,
-                                       &cur_instruction) != ERROR_OK;
-                       if (retval != ERROR_OK)
-                               break;
-               }
-               command_print(CMD, "%s", cur_instruction.text);
-               address += cur_instruction.instruction_size;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       return retval;
+       return arm_disassemble(CMD, target, address, count, thumb);
+#else
+       command_print(CMD, "capstone disassembly framework required");
+       return ERROR_FAIL;
+#endif
 }
 
 static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
index ea6ee61..5e0694d 100644 (file)
@@ -111,7 +111,7 @@ static const struct {
        { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
        { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
        { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
-       { ARMV7M_CONTROL, "control", 2, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
+       { ARMV7M_CONTROL, "control", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
 
        { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
        { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
index 4b0ea50..abc377f 100644 (file)
@@ -541,7 +541,7 @@ static int cortex_m_debug_entry(struct target *target)
                arm->map = armv7m_msp_reg_map;
        } else {
                unsigned control = buf_get_u32(arm->core_cache
-                               ->reg_list[ARMV7M_CONTROL].value, 0, 2);
+                               ->reg_list[ARMV7M_CONTROL].value, 0, 3);
 
                /* is this thread privileged? */
                arm->core_mode = control & 1
@@ -1678,7 +1678,7 @@ static int cortex_m_load_core_reg_u32(struct target *target,
                                        break;
 
                                case ARMV7M_CONTROL:
-                                       *value = buf_get_u32((uint8_t *)value, 24, 2);
+                                       *value = buf_get_u32((uint8_t *)value, 24, 3);
                                        break;
                        }
 
@@ -1764,7 +1764,7 @@ static int cortex_m_store_core_reg_u32(struct target *target,
                                        break;
 
                                case ARMV7M_CONTROL:
-                                       buf_set_u32((uint8_t *)&reg, 24, 2, value);
+                                       buf_set_u32((uint8_t *)&reg, 24, 3, value);
                                        break;
                        }
 
@@ -2176,11 +2176,15 @@ int cortex_m_examine(struct target *target)
                        case CORTEX_M23_PARTNO:
                                i = 23;
                                break;
-
                        case CORTEX_M33_PARTNO:
                                i = 33;
                                break;
-
+                       case CORTEX_M35P_PARTNO:
+                               i = 35;
+                               break;
+                       case CORTEX_M55_PARTNO:
+                               i = 55;
+                               break;
                        default:
                                armv7m->arm.is_armv8m = false;
                                break;
@@ -2213,7 +2217,7 @@ int cortex_m_examine(struct target *target)
                                LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i);
                                armv7m->fp_feature = FPv4_SP;
                        }
-               } else if (i == 7 || i == 33) {
+               } else if (i == 7 || i == 33 || i == 35 || i == 55) {
                        target_read_u32(target, MVFR0, &mvfr0);
                        target_read_u32(target, MVFR1, &mvfr1);
 
@@ -2498,6 +2502,11 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
        if (retval != ERROR_OK)
                return retval;
 
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
        retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DEMCR, &demcr);
        if (retval != ERROR_OK)
                return retval;
index 3545328..415a6c2 100644 (file)
@@ -44,6 +44,8 @@
 
 #define CORTEX_M23_PARTNO      0xD200
 #define CORTEX_M33_PARTNO      0xD210
+#define CORTEX_M35P_PARTNO     0xD310
+#define CORTEX_M55_PARTNO      0xD220
 
 /* Debug Control Block */
 #define DCB_DHCSR      0xE000EDF0
index f0dc572..c02cbb6 100644 (file)
@@ -123,7 +123,7 @@ static int adapter_load_core_reg_u32(struct target *target,
                        break;
 
                case ARMV7M_CONTROL:
-                       *value = buf_get_u32((uint8_t *) value, 24, 2);
+                       *value = buf_get_u32((uint8_t *) value, 24, 3);
                        break;
                }
 
@@ -215,7 +215,7 @@ static int adapter_store_core_reg_u32(struct target *target,
                        break;
 
                case ARMV7M_CONTROL:
-                       buf_set_u32((uint8_t *) &reg, 24, 2, value);
+                       buf_set_u32((uint8_t *) &reg, 24, 3, value);
                        break;
                }
 
@@ -433,7 +433,7 @@ static int adapter_debug_entry(struct target *target)
                arm->map = armv7m_msp_reg_map;
        } else {
                unsigned control = buf_get_u32(arm->core_cache
-                               ->reg_list[ARMV7M_CONTROL].value, 0, 2);
+                               ->reg_list[ARMV7M_CONTROL].value, 0, 3);
 
                /* is this thread privileged? */
                arm->core_mode = control & 1
index d81aa02..6ceb8c9 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 #ifndef TARGET__RISCV__ASM_H
 #define TARGET__RISCV__ASM_H
 
index d041ed1..43f2ffb 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 #define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
 #define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
 
+#define DTM_DMI_MAX_ADDRESS_LENGTH     ((1<<DTM_DTMCS_ABITS_LENGTH)-1)
+#define DMI_SCAN_MAX_BIT_LENGTH (DTM_DMI_MAX_ADDRESS_LENGTH + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH)
+#define DMI_SCAN_BUF_SIZE (DIV_ROUND_UP(DMI_SCAN_MAX_BIT_LENGTH, 8))
+
 static void dump_field(int idle, const struct scan_field *field);
 
 struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans, size_t idle)
 {
        scans += 4;
        struct riscv_batch *out = calloc(1, sizeof(*out));
+       if (!out)
+               goto error0;
        out->target = target;
        out->allocated_scans = scans;
        out->idle_count = idle;
-       out->data_out = malloc(sizeof(*out->data_out) * (scans) * sizeof(uint64_t));
-       out->data_in  = malloc(sizeof(*out->data_in)  * (scans) * sizeof(uint64_t));
+       out->data_out = malloc(sizeof(*out->data_out) * (scans) * DMI_SCAN_BUF_SIZE);
+       if (!out->data_out)
+               goto error1;
+       out->data_in = malloc(sizeof(*out->data_in) * (scans) * DMI_SCAN_BUF_SIZE);
+       if (!out->data_in)
+               goto error2;
        out->fields = malloc(sizeof(*out->fields) * (scans));
+       if (!out->fields)
+               goto error3;
+       if (bscan_tunnel_ir_width != 0) {
+               out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * (scans));
+               if (!out->bscan_ctxt)
+                       goto error4;
+       }
        out->last_scan = RISCV_SCAN_TYPE_INVALID;
        out->read_keys = malloc(sizeof(*out->read_keys) * (scans));
+       if (!out->read_keys)
+               goto error5;
        return out;
+
+error5:
+       free(out->bscan_ctxt);
+error4:
+       free(out->fields);
+error3:
+       free(out->data_in);
+error2:
+       free(out->data_out);
+error1:
+       free(out);
+error0:
+       return NULL;
 }
 
 void riscv_batch_free(struct riscv_batch *batch)
@@ -31,6 +65,8 @@ void riscv_batch_free(struct riscv_batch *batch)
        free(batch->data_in);
        free(batch->data_out);
        free(batch->fields);
+       free(batch->bscan_ctxt);
+       free(batch->read_keys);
        free(batch);
 }
 
@@ -51,7 +87,11 @@ int riscv_batch_run(struct riscv_batch *batch)
        riscv_batch_add_nop(batch);
 
        for (size_t i = 0; i < batch->used_scans; ++i) {
-               jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE);
+               if (bscan_tunnel_ir_width != 0)
+                       riscv_add_bscan_tunneled_scan(batch->target, batch->fields+i, batch->bscan_ctxt+i);
+               else
+                       jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE);
+
                if (batch->idle_count > 0)
                        jtag_add_runtest(batch->idle_count, TAP_IDLE);
        }
@@ -61,6 +101,12 @@ int riscv_batch_run(struct riscv_batch *batch)
                return ERROR_FAIL;
        }
 
+       if (bscan_tunnel_ir_width != 0) {
+               /* need to right-shift "in" by one bit, because of clock skew between BSCAN TAP and DM TAP */
+               for (size_t i = 0; i < batch->used_scans; ++i)
+                       buffer_shr((batch->fields + i)->in_value, DMI_SCAN_BUF_SIZE, 1);
+       }
+
        for (size_t i = 0; i < batch->used_scans; ++i)
                dump_field(batch->idle_count, batch->fields + i);
 
@@ -72,8 +118,8 @@ void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint
        assert(batch->used_scans < batch->allocated_scans);
        struct scan_field *field = batch->fields + batch->used_scans;
        field->num_bits = riscv_dmi_write_u64_bits(batch->target);
-       field->out_value = (void *)(batch->data_out + batch->used_scans * sizeof(uint64_t));
-       field->in_value  = (void *)(batch->data_in  + batch->used_scans * sizeof(uint64_t));
+       field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
+       field->in_value  = (void *)(batch->data_in  + batch->used_scans * DMI_SCAN_BUF_SIZE);
        riscv_fill_dmi_write_u64(batch->target, (char *)field->out_value, address, data);
        riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
        batch->last_scan = RISCV_SCAN_TYPE_WRITE;
@@ -85,35 +131,35 @@ size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address)
        assert(batch->used_scans < batch->allocated_scans);
        struct scan_field *field = batch->fields + batch->used_scans;
        field->num_bits = riscv_dmi_write_u64_bits(batch->target);
-       field->out_value = (void *)(batch->data_out + batch->used_scans * sizeof(uint64_t));
-       field->in_value  = (void *)(batch->data_in  + batch->used_scans * sizeof(uint64_t));
+       field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
+       field->in_value  = (void *)(batch->data_in  + batch->used_scans * DMI_SCAN_BUF_SIZE);
        riscv_fill_dmi_read_u64(batch->target, (char *)field->out_value, address);
        riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
        batch->last_scan = RISCV_SCAN_TYPE_READ;
        batch->used_scans++;
 
-       /* FIXME We get the read response back on the next scan.  For now I'm
-        * just sticking a NOP in there, but this should be coalesced away. */
-       riscv_batch_add_nop(batch);
-
-       batch->read_keys[batch->read_keys_used] = batch->used_scans - 1;
+       batch->read_keys[batch->read_keys_used] = batch->used_scans;
        return batch->read_keys_used++;
 }
 
-uint64_t riscv_batch_get_dmi_read(struct riscv_batch *batch, size_t key)
+unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key)
 {
        assert(key < batch->read_keys_used);
        size_t index = batch->read_keys[key];
        assert(index <= batch->used_scans);
-       uint8_t *base = batch->data_in + 8 * index;
-       return base[0] |
-               ((uint64_t) base[1]) << 8 |
-               ((uint64_t) base[2]) << 16 |
-               ((uint64_t) base[3]) << 24 |
-               ((uint64_t) base[4]) << 32 |
-               ((uint64_t) base[5]) << 40 |
-               ((uint64_t) base[6]) << 48 |
-               ((uint64_t) base[7]) << 56;
+       uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
+       /* extract "op" field from the DMI read result */
+       return (unsigned)buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
+}
+
+uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key)
+{
+       assert(key < batch->read_keys_used);
+       size_t index = batch->read_keys[key];
+       assert(index <= batch->used_scans);
+       uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index;
+       /* extract "data" field from the DMI read result */
+       return buf_get_u32(base, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH);
 }
 
 void riscv_batch_add_nop(struct riscv_batch *batch)
@@ -121,8 +167,8 @@ void riscv_batch_add_nop(struct riscv_batch *batch)
        assert(batch->used_scans < batch->allocated_scans);
        struct scan_field *field = batch->fields + batch->used_scans;
        field->num_bits = riscv_dmi_write_u64_bits(batch->target);
-       field->out_value = (void *)(batch->data_out + batch->used_scans * sizeof(uint64_t));
-       field->in_value  = (void *)(batch->data_in  + batch->used_scans * sizeof(uint64_t));
+       field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE);
+       field->in_value  = (void *)(batch->data_in  + batch->used_scans * DMI_SCAN_BUF_SIZE);
        riscv_fill_dmi_nop_u64(batch->target, (char *)field->out_value);
        riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value);
        batch->last_scan = RISCV_SCAN_TYPE_NOP;
@@ -151,13 +197,17 @@ void dump_field(int idle, const struct scan_field *field)
 
                log_printf_lf(LOG_LVL_DEBUG,
                                __FILE__, __LINE__, __PRETTY_FUNCTION__,
-                               "%db %di %s %08x @%02x -> %s %08x @%02x",
-                               field->num_bits, idle,
-                               op_string[out_op], out_data, out_address,
-                               status_string[in_op], in_data, in_address);
+                               "%db %s %08x @%02x -> %s %08x @%02x; %di",
+                               field->num_bits, op_string[out_op], out_data, out_address,
+                               status_string[in_op], in_data, in_address, idle);
        } else {
                log_printf_lf(LOG_LVL_DEBUG,
-                               __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %di %s %08x @%02x -> ?",
-                               field->num_bits, idle, op_string[out_op], out_data, out_address);
+                               __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?; %di",
+                               field->num_bits, op_string[out_op], out_data, out_address, idle);
        }
 }
+
+size_t riscv_batch_available_scans(struct riscv_batch *batch)
+{
+       return batch->allocated_scans - batch->used_scans - 4;
+}
index 70690a6..9c42ba8 100644 (file)
@@ -1,8 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 #ifndef TARGET__RISCV__SCANS_H
 #define TARGET__RISCV__SCANS_H
 
 #include "target/target.h"
 #include "jtag/jtag.h"
+#include "riscv.h"
 
 enum riscv_scan_type {
        RISCV_SCAN_TYPE_INVALID,
@@ -27,6 +30,11 @@ struct riscv_batch {
        uint8_t *data_in;
        struct scan_field *fields;
 
+       /* If in BSCAN mode, this field will be allocated (one per scan),
+          and utilized to tunnel all the scans in the batch.  If not in
+          BSCAN mode, this field is unallocated and stays NULL */
+       riscv_bscan_tunneled_scan_context_t *bscan_ctxt;
+
        /* In JTAG we scan out the previous value's output when performing a
         * scan.  This is a pain for users, so we just provide them the
         * illusion of not having to do this by eliding all but the last NOP.
@@ -54,11 +62,16 @@ int riscv_batch_run(struct riscv_batch *batch);
 void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data);
 
 /* DMI reads must be handled in two parts: the first one schedules a read and
- * provides a key, the second one actually obtains the value of that read .*/
+ * provides a key, the second one actually obtains the result of the read -
+ * status (op) and the actual data. */
 size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address);
-uint64_t riscv_batch_get_dmi_read(struct riscv_batch *batch, size_t key);
+unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key);
+uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key);
 
 /* Scans in a NOP. */
 void riscv_batch_add_nop(struct riscv_batch *batch);
 
+/* Returns the number of available scans. */
+size_t riscv_batch_available_scans(struct riscv_batch *batch);
+
 #endif
index d6ddd4f..cb518a8 100644 (file)
@@ -1,22 +1,27 @@
+/*
+ * This file is auto-generated by running 'make debug_defines.h' in
+ * https://github.com/riscv/riscv-debug-spec/ (30b1a97)
+ */
+
 #define DTM_IDCODE                          0x01
 /*
-* Identifies the release version of this part.
+ * Identifies the release version of this part.
  */
 #define DTM_IDCODE_VERSION_OFFSET           28
 #define DTM_IDCODE_VERSION_LENGTH           4
 #define DTM_IDCODE_VERSION                  (0xfU << DTM_IDCODE_VERSION_OFFSET)
 /*
-* Identifies the designer's part number of this part.
+ * Identifies the designer's part number of this part.
  */
 #define DTM_IDCODE_PARTNUMBER_OFFSET        12
 #define DTM_IDCODE_PARTNUMBER_LENGTH        16
 #define DTM_IDCODE_PARTNUMBER               (0xffffU << DTM_IDCODE_PARTNUMBER_OFFSET)
 /*
-* Identifies the designer/manufacturer of this part. Bits 6:0 must be
-* bits 6:0 of the designer/manufacturer's Identification Code as
-* assigned by JEDEC Standard JEP106. Bits 10:7 contain the modulo-16
-* count of the number of continuation characters (0x7f) in that same
-* Identification Code.
+ * Identifies the designer/manufacturer of this part. Bits 6:0 must be
+ * bits 6:0 of the designer/manufacturer's Identification Code as
+ * assigned by JEDEC Standard JEP106. Bits 10:7 contain the modulo-16
+ * count of the number of continuation characters (0x7f) in that same
+ * Identification Code.
  */
 #define DTM_IDCODE_MANUFID_OFFSET           1
 #define DTM_IDCODE_MANUFID_LENGTH           11
 #define DTM_IDCODE_1                        (0x1U << DTM_IDCODE_1_OFFSET)
 #define DTM_DTMCS                           0x10
 /*
-* Writing 1 to this bit does a hard reset of the DTM,
-* causing the DTM to forget about any outstanding DMI transactions.
-* In general this should only be used when the Debugger has
-* reason to expect that the outstanding DMI transaction will never
-* complete (e.g. a reset condition caused an inflight DMI transaction to
-* be cancelled).
+ * Writing 1 to this bit does a hard reset of the DTM,
+ * causing the DTM to forget about any outstanding DMI transactions, and
+ * returning all registers and internal state to their reset value.
+ * In general this should only be used when the Debugger has
+ * reason to expect that the outstanding DMI transaction will never
+ * complete (e.g. a reset condition caused an inflight DMI transaction to
+ * be cancelled).
  */
 #define DTM_DTMCS_DMIHARDRESET_OFFSET       17
 #define DTM_DTMCS_DMIHARDRESET_LENGTH       1
 #define DTM_DTMCS_DMIHARDRESET              (0x1U << DTM_DTMCS_DMIHARDRESET_OFFSET)
 /*
-* Writing 1 to this bit clears the sticky error state
-* and allows the DTM to retry or complete the previous
-* transaction.
+ * Writing 1 to this bit clears the sticky error state, but does
+ * not affect outstanding DMI transactions.
  */
 #define DTM_DTMCS_DMIRESET_OFFSET           16
 #define DTM_DTMCS_DMIRESET_LENGTH           1
 #define DTM_DTMCS_DMIRESET                  (0x1U << DTM_DTMCS_DMIRESET_OFFSET)
 /*
-* This is a hint to the debugger of the minimum number of
-* cycles a debugger should spend in
-* Run-Test/Idle after every DMI scan to avoid a `busy'
-* return code (\Fdmistat of 3). A debugger must still
-* check \Fdmistat when necessary.
-*
-* 0: It is not necessary to enter Run-Test/Idle at all.
-*
-* 1: Enter Run-Test/Idle and leave it immediately.
-*
-* 2: Enter Run-Test/Idle and stay there for 1 cycle before leaving.
-*
-* And so on.
+ * This is a hint to the debugger of the minimum number of
+ * cycles a debugger should spend in
+ * Run-Test/Idle after every DMI scan to avoid a `busy'
+ * return code (\FdtmDtmcsDmistat of 3). A debugger must still
+ * check \FdtmDtmcsDmistat when necessary.
+ *
+ * 0: It is not necessary to enter Run-Test/Idle at all.
+ *
+ * 1: Enter Run-Test/Idle and leave it immediately.
+ *
+ * 2: Enter Run-Test/Idle and stay there for 1 cycle before leaving.
+ *
+ * And so on.
  */
 #define DTM_DTMCS_IDLE_OFFSET               12
 #define DTM_DTMCS_IDLE_LENGTH               3
 #define DTM_DTMCS_IDLE                      (0x7U << DTM_DTMCS_IDLE_OFFSET)
 /*
-* 0: No error.
-*
-* 1: Reserved. Interpret the same as 2.
-*
-* 2: An operation failed (resulted in \Fop of 2).
-*
-* 3: An operation was attempted while a DMI access was still in
-* progress (resulted in \Fop of 3).
+ * 0: No error.
+ *
+ * 1: Reserved. Interpret the same as 2.
+ *
+ * 2: An operation failed (resulted in \FdtmDmiOp of 2).
+ *
+ * 3: An operation was attempted while a DMI access was still in
+ * progress (resulted in \FdtmDmiOp of 3).
  */
 #define DTM_DTMCS_DMISTAT_OFFSET            10
 #define DTM_DTMCS_DMISTAT_LENGTH            2
 #define DTM_DTMCS_DMISTAT                   (0x3U << DTM_DTMCS_DMISTAT_OFFSET)
 /*
-* The size of \Faddress in \Rdmi.
+ * The size of \FdmSbaddressZeroAddress in \RdtmDmi.
  */
 #define DTM_DTMCS_ABITS_OFFSET              4
 #define DTM_DTMCS_ABITS_LENGTH              6
 #define DTM_DTMCS_ABITS                     (0x3fU << DTM_DTMCS_ABITS_OFFSET)
 /*
-* 0: Version described in spec version 0.11.
-*
-* 1: Version described in spec version 0.13 (and later?), which
-* reduces the DMI data width to 32 bits.
-*
-* 15: Version not described in any available version of this spec.
+ * 0: Version described in spec version 0.11.
+ *
+ * 1: Version described in spec version 0.13.
+ *
+ * 15: Version not described in any available version of this spec.
  */
 #define DTM_DTMCS_VERSION_OFFSET            0
 #define DTM_DTMCS_VERSION_LENGTH            4
 #define DTM_DTMCS_VERSION                   (0xfU << DTM_DTMCS_VERSION_OFFSET)
 #define DTM_DMI                             0x11
 /*
-* Address used for DMI access. In Update-DR this value is used
-* to access the DM over the DMI.
+ * Address used for DMI access. In Update-DR this value is used
+ * to access the DM over the DMI.
  */
 #define DTM_DMI_ADDRESS_OFFSET              34
 #define DTM_DMI_ADDRESS_LENGTH              abits
-#define DTM_DMI_ADDRESS                     (((1L<<abits)-1) << DTM_DMI_ADDRESS_OFFSET)
+#define DTM_DMI_ADDRESS                     (((1L << abits) - 1) << DTM_DMI_ADDRESS_OFFSET)
 /*
-* The data to send to the DM over the DMI during Update-DR, and
-* the data returned from the DM as a result of the previous operation.
+ * The data to send to the DM over the DMI during Update-DR, and
+ * the data returned from the DM as a result of the previous operation.
  */
 #define DTM_DMI_DATA_OFFSET                 2
 #define DTM_DMI_DATA_LENGTH                 32
 #define DTM_DMI_DATA                        (0xffffffffULL << DTM_DMI_DATA_OFFSET)
 /*
-* When the debugger writes this field, it has the following meaning:
-*
-* 0: Ignore \Fdata and \Faddress. (nop)
-*
-* Don't send anything over the DMI during Update-DR.
-* This operation should never result in a busy or error response.
-* The address and data reported in the following Capture-DR
-* are undefined.
-*
-* 1: Read from \Faddress. (read)
-*
-* 2: Write \Fdata to \Faddress. (write)
-*
-* 3: Reserved.
-*
-* When the debugger reads this field, it means the following:
-*
-* 0: The previous operation completed successfully.
-*
-* 1: Reserved.
-*
-* 2: A previous operation failed.  The data scanned into \Rdmi in
-* this access will be ignored.  This status is sticky and can be
-* cleared by writing \Fdmireset in \Rdtmcs.
-*
-* This indicates that the DM itself responded with an error.
-* Note: there are no specified cases in which the DM would
-* respond with an error, and DMI is not required to support
-* returning errors.
-*
-* 3: An operation was attempted while a DMI request is still in
-* progress. The data scanned into \Rdmi in this access will be
-* ignored. This status is sticky and can be cleared by writing
-* \Fdmireset in \Rdtmcs. If a debugger sees this status, it
-* needs to give the target more TCK edges between Update-DR and
-* Capture-DR. The simplest way to do that is to add extra transitions
-* in Run-Test/Idle.
-*
-* (The DTM, DM, and/or component may be in different clock domains,
-* so synchronization may be required. Some relatively fixed number of
-* TCK ticks may be needed for the request to reach the DM, complete,
-* and for the response to be synchronized back into the TCK domain.)
+ * When the debugger writes this field, it has the following meaning:
+ *
+ * 0: Ignore \FdmSbdataZeroData and \FdmSbaddressZeroAddress. (nop)
+ *
+ * Don't send anything over the DMI during Update-DR.
+ * This operation should never result in a busy or error response.
+ * The address and data reported in the following Capture-DR
+ * are undefined.
+ *
+ * 1: Read from \FdmSbaddressZeroAddress. (read)
+ *
+ * 2: Write \FdmSbdataZeroData to \FdmSbaddressZeroAddress. (write)
+ *
+ * 3: Reserved.
+ *
+ * When the debugger reads this field, it means the following:
+ *
+ * 0: The previous operation completed successfully.
+ *
+ * 1: Reserved.
+ *
+ * 2: A previous operation failed.  The data scanned into \RdtmDmi in
+ * this access will be ignored.  This status is sticky and can be
+ * cleared by writing \FdtmDtmcsDmireset in \RdtmDtmcs.
+ *
+ * This indicates that the DM itself responded with an error.
+ * There are no specified cases in which the DM would
+ * respond with an error, and DMI is not required to support
+ * returning errors.
+ *
+ * 3: An operation was attempted while a DMI request is still in
+ * progress. The data scanned into \RdtmDmi in this access will be
+ * ignored. This status is sticky and can be cleared by writing
+ * \FdtmDtmcsDmireset in \RdtmDtmcs. If a debugger sees this status, it
+ * needs to give the target more TCK edges between Update-DR and
+ * Capture-DR. The simplest way to do that is to add extra transitions
+ * in Run-Test/Idle.
  */
 #define DTM_DMI_OP_OFFSET                   0
 #define DTM_DMI_OP_LENGTH                   2
 #define DTM_DMI_OP                          (0x3ULL << DTM_DMI_OP_OFFSET)
 #define CSR_DCSR                            0x7b0
 /*
-* 0: There is no external debug support.
-*
-* 4: External debug support exists as it is described in this document.
-*
-* 15: There is external debug support, but it does not conform to any
-* available version of this spec.
+ * 0: There is no external debug support.
+ *
+ * 4: External debug support exists as it is described in this document.
+ *
+ * 15: There is external debug support, but it does not conform to any
+ * available version of this spec.
  */
 #define CSR_DCSR_XDEBUGVER_OFFSET           28
 #define CSR_DCSR_XDEBUGVER_LENGTH           4
 #define CSR_DCSR_XDEBUGVER                  (0xfU << CSR_DCSR_XDEBUGVER_OFFSET)
 /*
-* When 1, {\tt ebreak} instructions in Machine Mode enter Debug Mode.
+ * 0: {\tt ebreak} instructions in M-mode behave as described in the
+ * Privileged Spec.
+ *
+ * 1: {\tt ebreak} instructions in M-mode enter Debug Mode.
  */
 #define CSR_DCSR_EBREAKM_OFFSET             15
 #define CSR_DCSR_EBREAKM_LENGTH             1
 #define CSR_DCSR_EBREAKM                    (0x1U << CSR_DCSR_EBREAKM_OFFSET)
 /*
-* When 1, {\tt ebreak} instructions in Supervisor Mode enter Debug Mode.
+ * 0: {\tt ebreak} instructions in S-mode behave as described in the
+ * Privileged Spec.
+ *
+ * 1: {\tt ebreak} instructions in S-mode enter Debug Mode.
+ *
+ * This bit is hardwired to 0 if the hart does not support S mode.
  */
 #define CSR_DCSR_EBREAKS_OFFSET             13
 #define CSR_DCSR_EBREAKS_LENGTH             1
 #define CSR_DCSR_EBREAKS                    (0x1U << CSR_DCSR_EBREAKS_OFFSET)
 /*
-* When 1, {\tt ebreak} instructions in User/Application Mode enter
-* Debug Mode.
+ * 0: {\tt ebreak} instructions in U-mode behave as described in the
+ * Privileged Spec.
+ *
+ * 1: {\tt ebreak} instructions in U-mode enter Debug Mode.
+ *
+ * This bit is hardwired to 0 if the hart does not support U mode.
  */
 #define CSR_DCSR_EBREAKU_OFFSET             12
 #define CSR_DCSR_EBREAKU_LENGTH             1
 #define CSR_DCSR_EBREAKU                    (0x1U << CSR_DCSR_EBREAKU_OFFSET)
 /*
-* 0: Interrupts are disabled during single stepping.
-*
-* 1: Interrupts are enabled during single stepping.
-*
-* Implementations may hard wire this bit to 0.
-* The debugger must read back the value it
-* writes to check whether the feature is supported. If not
-* supported, interrupt behavior can be emulated by the debugger.
+ * 0: Interrupts (including NMI) are disabled during single stepping.
+ *
+ * 1: Interrupts (including NMI) are enabled during single stepping.
+ *
+ * Implementations may hard wire this bit to 0.
+ * In that case interrupt behavior can be emulated by the debugger.
+ *
+ * The debugger must not change the value of this bit while the hart
+ * is running.
  */
 #define CSR_DCSR_STEPIE_OFFSET              11
 #define CSR_DCSR_STEPIE_LENGTH              1
 #define CSR_DCSR_STEPIE                     (0x1U << CSR_DCSR_STEPIE_OFFSET)
 /*
-* 0: Increment counters as usual.
-*
-* 1: Don't increment any counters while in Debug Mode or on {\tt
-* ebreak} instructions that cause entry into Debug Mode.  These
-* counters include the {\tt cycle} and {\tt instret} CSRs. This is
-* preferred for most debugging scenarios.
-*
-* An implementation may choose not to support writing to this bit.
-* The debugger must read back the value it writes to check whether
-* the feature is supported.
+ * 0: Increment counters as usual.
+ *
+ * 1: Don't increment any hart-local counters while in Debug Mode or
+ * on {\tt ebreak} instructions that cause entry into Debug Mode.
+ * These counters include the {\tt instret} CSR. On single-hart cores
+ * {\tt cycle} should be stopped, but on multi-hart cores it must keep
+ * incrementing.
+ *
+ * An implementation may hardwire this bit to 0 or 1.
  */
 #define CSR_DCSR_STOPCOUNT_OFFSET           10
 #define CSR_DCSR_STOPCOUNT_LENGTH           1
 #define CSR_DCSR_STOPCOUNT                  (0x1U << CSR_DCSR_STOPCOUNT_OFFSET)
 /*
-* 0: Increment timers as usual.
-*
-* 1: Don't increment any hart-local timers while in Debug Mode.
-*
-* An implementation may choose not to support writing to this bit.
-* The debugger must read back the value it writes to check whether
-* the feature is supported.
+ * 0: Increment timers as usual.
+ *
+ * 1: Don't increment any hart-local timers while in Debug Mode.
+ *
+ * An implementation may hardwire this bit to 0 or 1.
  */
 #define CSR_DCSR_STOPTIME_OFFSET            9
 #define CSR_DCSR_STOPTIME_LENGTH            1
 #define CSR_DCSR_STOPTIME                   (0x1U << CSR_DCSR_STOPTIME_OFFSET)
 /*
-* Explains why Debug Mode was entered.
-*
-* When there are multiple reasons to enter Debug Mode in a single
-* cycle, hardware should set \Fcause to the cause with the highest
-* priority.
-*
-* 1: An {\tt ebreak} instruction was executed. (priority 3)
-*
-* 2: The Trigger Module caused a breakpoint exception. (priority 4)
-*
-* 3: The debugger requested entry to Debug Mode. (priority 2)
-*
-* 4: The hart single stepped because \Fstep was set. (priority 1)
-*
-* Other values are reserved for future use.
+ * Explains why Debug Mode was entered.
+ *
+ * When there are multiple reasons to enter Debug Mode in a single
+ * cycle, hardware should set \FcsrDcsrCause to the cause with the highest
+ * priority.
+ *
+ * 1: An {\tt ebreak} instruction was executed. (priority 3)
+ *
+ * 2: The Trigger Module caused a breakpoint exception. (priority 4)
+ *
+ * 3: The debugger requested entry to Debug Mode using \FdmDmcontrolHaltreq.
+ * (priority 1)
+ *
+ * 4: The hart single stepped because \FcsrDcsrStep was set. (priority 0, lowest)
+ *
+ * 5: The hart halted directly out of reset due to \Fresethaltreq. It
+ * is also acceptable to report 3 when this happens. (priority 2)
+ *
+ * 6: The hart halted because it's part of a halt group. (priority 5,
+ * highest) Harts may report 3 for this cause instead.
+ *
+ * Other values are reserved for future use.
  */
 #define CSR_DCSR_CAUSE_OFFSET               6
 #define CSR_DCSR_CAUSE_LENGTH               3
 #define CSR_DCSR_CAUSE                      (0x7U << CSR_DCSR_CAUSE_OFFSET)
 /*
-* When 1, \Fmprv in \Rmstatus takes effect during debug mode.
-* When 0, it is ignored during debug mode.
-* Implementing this bit is optional.
-* If not implemented it should be tied to 0.
+ * 0: \FcsrMcontrolMprv in \Rmstatus is ignored in Debug Mode.
+ *
+ * 1: \FcsrMcontrolMprv in \Rmstatus takes effect in Debug Mode.
+ *
+ * Implementing this bit is optional. It may be tied to either 0 or 1.
  */
 #define CSR_DCSR_MPRVEN_OFFSET              4
 #define CSR_DCSR_MPRVEN_LENGTH              1
 #define CSR_DCSR_MPRVEN                     (0x1U << CSR_DCSR_MPRVEN_OFFSET)
 /*
-* When set, there is a Non-Maskable-Interrupt (NMI) pending for the hart.
-*
-* Since an NMI can indicate a hardware error condition,
-* reliable debugging may no longer be possible once this bit becomes set.
-* This is implementation-dependent.
+ * When set, there is a Non-Maskable-Interrupt (NMI) pending for the hart.
+ *
+ * Since an NMI can indicate a hardware error condition,
+ * reliable debugging may no longer be possible once this bit becomes set.
+ * This is implementation-dependent.
  */
 #define CSR_DCSR_NMIP_OFFSET                3
 #define CSR_DCSR_NMIP_LENGTH                1
 #define CSR_DCSR_NMIP                       (0x1U << CSR_DCSR_NMIP_OFFSET)
 /*
-* When set and not in Debug Mode, the hart will only execute a single
-* instruction and then enter Debug Mode.
-* If the instruction does not complete due to an exception,
-* the hart will immediately enter Debug Mode before executing
-* the trap handler, with appropriate exception registers set.
+ * When set and not in Debug Mode, the hart will only execute a single
+ * instruction and then enter Debug Mode. See Section~\ref{stepBit}
+ * for details.
+ *
+ * The debugger must not change the value of this bit while the hart
+ * is running.
  */
 #define CSR_DCSR_STEP_OFFSET                2
 #define CSR_DCSR_STEP_LENGTH                1
 #define CSR_DCSR_STEP                       (0x1U << CSR_DCSR_STEP_OFFSET)
 /*
-* Contains the privilege level the hart was operating in when Debug
-* Mode was entered. The encoding is described in Table
-* \ref{tab:privlevel}.  A debugger can change this value to change
-* the hart's privilege level when exiting Debug Mode.
-*
-* Not all privilege levels are supported on all harts. If the
-* encoding written is not supported or the debugger is not allowed to
-* change to it, the hart may change to any supported privilege level.
+ * Contains the privilege level the hart was operating in when Debug
+ * Mode was entered. The encoding is described in Table
+ * \ref{tab:privlevel}.  A debugger can change this value to change
+ * the hart's privilege level when exiting Debug Mode.
+ *
+ * Not all privilege levels are supported on all harts. If the
+ * encoding written is not supported or the debugger is not allowed to
+ * change to it, the hart may change to any supported privilege level.
  */
 #define CSR_DCSR_PRV_OFFSET                 0
 #define CSR_DCSR_PRV_LENGTH                 2
 #define CSR_DCSR_PRV                        (0x3U << CSR_DCSR_PRV_OFFSET)
 #define CSR_DPC                             0x7b1
 #define CSR_DPC_DPC_OFFSET                  0
-#define CSR_DPC_DPC_LENGTH                  MXLEN
-#define CSR_DPC_DPC                         (((1L<<MXLEN)-1) << CSR_DPC_DPC_OFFSET)
+#define CSR_DPC_DPC_LENGTH                  DXLEN
+#define CSR_DPC_DPC                         (((1L << DXLEN) - 1) << CSR_DPC_DPC_OFFSET)
 #define CSR_DSCRATCH0                       0x7b2
 #define CSR_DSCRATCH1                       0x7b3
 #define CSR_TSELECT                         0x7a0
 #define CSR_TSELECT_INDEX_OFFSET            0
-#define CSR_TSELECT_INDEX_LENGTH            MXLEN
-#define CSR_TSELECT_INDEX                   (((1L<<MXLEN)-1) << CSR_TSELECT_INDEX_OFFSET)
+#define CSR_TSELECT_INDEX_LENGTH            XLEN
+#define CSR_TSELECT_INDEX                   (((1L << XLEN) - 1) << CSR_TSELECT_INDEX_OFFSET)
 #define CSR_TDATA1                          0x7a1
 /*
-* 0: There is no trigger at this \Rtselect.
-*
-* 1: The trigger is a legacy SiFive address match trigger. These
-* should not be implemented and aren't further documented here.
-*
-* 2: The trigger is an address/data match trigger. The remaining bits
-* in this register act as described in \Rmcontrol.
-*
-* 3: The trigger is an instruction count trigger. The remaining bits
-* in this register act as described in \Ricount.
-*
-* 4: The trigger is an interrupt trigger. The remaining bits
-* in this register act as described in \Ritrigger.
-*
-* 5: The trigger is an exception trigger. The remaining bits
-* in this register act as described in \Retrigger.
-*
-* 15: This trigger exists (so enumeration shouldn't terminate), but
-* is not currently available.
-*
-* Other values are reserved for future use.
-*
-* When this field is written to an unsupported value, it takes on its
-* reset value instead. The reset value is any one of the types
-* supported by the trigger selected by \Rtselect.
- */
-#define CSR_TDATA1_TYPE_OFFSET              (MXLEN-4)
+ * 0: There is no trigger at this \RcsrTselect.
+ *
+ * 1: The trigger is a legacy SiFive address match trigger. These
+ * should not be implemented and aren't further documented here.
+ *
+ * 2: The trigger is an address/data match trigger. The remaining bits
+ * in this register act as described in \RcsrMcontrol.
+ *
+ * 3: The trigger is an instruction count trigger. The remaining bits
+ * in this register act as described in \RcsrIcount.
+ *
+ * 4: The trigger is an interrupt trigger. The remaining bits
+ * in this register act as described in \RcsrItrigger.
+ *
+ * 5: The trigger is an exception trigger. The remaining bits
+ * in this register act as described in \RcsrEtrigger.
+ *
+ * 12--14: These trigger types are available for non-standard use.
+ *
+ * 15: This trigger exists (so enumeration shouldn't terminate), but
+ * is not currently available.
+ *
+ * Other values are reserved for future use.
+ */
+#define CSR_TDATA1_TYPE_OFFSET              (XLEN-4)
 #define CSR_TDATA1_TYPE_LENGTH              4
 #define CSR_TDATA1_TYPE                     (0xfULL << CSR_TDATA1_TYPE_OFFSET)
 /*
-* 0: Both Debug and M Mode can write the {\tt tdata} registers at the
-* selected \Rtselect.
-*
-* 1: Only Debug Mode can write the {\tt tdata} registers at the
-* selected \Rtselect.  Writes from other modes are ignored.
-*
-* This bit is only writable from Debug Mode.
- */
-#define CSR_TDATA1_DMODE_OFFSET             (MXLEN-5)
+ * If \FcsrTdataOneType is 0, then this bit is hard-wired to 0.
+ *
+ * 0: Both Debug and M-mode can write the {\tt tdata} registers at the
+ * selected \RcsrTselect.
+ *
+ * 1: Only Debug Mode can write the {\tt tdata} registers at the
+ * selected \RcsrTselect.  Writes from other modes are ignored.
+ *
+ * This bit is only writable from Debug Mode.
+ * When clearing this bit, the debugger should also clear the action field
+ * (whose location depends on \FcsrTdataOneType).
+ */
+#define CSR_TDATA1_DMODE_OFFSET             (XLEN-5)
 #define CSR_TDATA1_DMODE_LENGTH             1
 #define CSR_TDATA1_DMODE                    (0x1ULL << CSR_TDATA1_DMODE_OFFSET)
 /*
-* Trigger-specific data.
+ * If \FcsrTdataOneType is 0, then this field is hard-wired to 0.
+ *
+ * Trigger-specific data.
  */
 #define CSR_TDATA1_DATA_OFFSET              0
-#define CSR_TDATA1_DATA_LENGTH              (MXLEN - 5)
-#define CSR_TDATA1_DATA                     (((1L<<MXLEN - 5)-1) << CSR_TDATA1_DATA_OFFSET)
+#define CSR_TDATA1_DATA_LENGTH              (XLEN - 5)
+#define CSR_TDATA1_DATA                     (((1L << XLEN - 5) - 1) << CSR_TDATA1_DATA_OFFSET)
 #define CSR_TDATA2                          0x7a2
 #define CSR_TDATA2_DATA_OFFSET              0
-#define CSR_TDATA2_DATA_LENGTH              MXLEN
-#define CSR_TDATA2_DATA                     (((1L<<MXLEN)-1) << CSR_TDATA2_DATA_OFFSET)
+#define CSR_TDATA2_DATA_LENGTH              XLEN
+#define CSR_TDATA2_DATA                     (((1L << XLEN) - 1) << CSR_TDATA2_DATA_OFFSET)
 #define CSR_TDATA3                          0x7a3
 #define CSR_TDATA3_DATA_OFFSET              0
-#define CSR_TDATA3_DATA_LENGTH              MXLEN
-#define CSR_TDATA3_DATA                     (((1L<<MXLEN)-1) << CSR_TDATA3_DATA_OFFSET)
+#define CSR_TDATA3_DATA_LENGTH              XLEN
+#define CSR_TDATA3_DATA                     (((1L << XLEN) - 1) << CSR_TDATA3_DATA_OFFSET)
 #define CSR_TINFO                           0x7a4
 /*
-* One bit for each possible \Ftype enumerated in \Rtdataone. Bit N
-* corresponds to type N. If the bit is set, then that type is
-* supported by the currently selected trigger.
-*
-* If the currently selected trigger doesn't exist, this field
-* contains 1.
-*
-* If \Ftype is not writable, this register may be unimplemented, in
-* which case reading it causes an illegal instruction exception. In
-* this case the debugger can read the only supported type from
-* \Rtdataone.
+ * One bit for each possible \FcsrTdataOneType enumerated in \RcsrTdataOne. Bit N
+ * corresponds to type N. If the bit is set, then that type is
+ * supported by the currently selected trigger.
+ *
+ * If the currently selected trigger doesn't exist, this field
+ * contains 1.
  */
 #define CSR_TINFO_INFO_OFFSET               0
 #define CSR_TINFO_INFO_LENGTH               16
 #define CSR_TINFO_INFO                      (0xffffULL << CSR_TINFO_INFO_OFFSET)
+#define CSR_TCONTROL                        0x7a5
+/*
+ * M-mode previous trigger enable field.
+ *
+ * When a trap into M-mode is taken, \FcsrTcontrolMpte is set to the value of
+ * \FcsrTcontrolMte.
+ */
+#define CSR_TCONTROL_MPTE_OFFSET            7
+#define CSR_TCONTROL_MPTE_LENGTH            1
+#define CSR_TCONTROL_MPTE                   (0x1ULL << CSR_TCONTROL_MPTE_OFFSET)
+/*
+ * M-mode trigger enable field.
+ *
+ * 0: Triggers with action=0 do not match/fire while the hart is in M-mode.
+ *
+ * 1: Triggers do match/fire while the hart is in M-mode.
+ *
+ * When a trap into M-mode is taken, \FcsrTcontrolMte is set to 0. When {\tt
+ * mret} is executed, \FcsrTcontrolMte is set to the value of \FcsrTcontrolMpte.
+ */
+#define CSR_TCONTROL_MTE_OFFSET             3
+#define CSR_TCONTROL_MTE_LENGTH             1
+#define CSR_TCONTROL_MTE                    (0x1ULL << CSR_TCONTROL_MTE_OFFSET)
+#define CSR_MCONTEXT                        0x7a8
+/*
+ * Machine mode software can write a context number to this register,
+ * which can be used to set triggers that only fire in that specific
+ * context.
+ *
+ * An implementation may tie any number of upper bits in this field to
+ * 0. It's recommended to implement no more than 6 bits on RV32, and
+ * 13 on RV64.
+ */
+#define CSR_MCONTEXT_MCONTEXT_OFFSET        0
+#define CSR_MCONTEXT_MCONTEXT_LENGTH        XLEN
+#define CSR_MCONTEXT_MCONTEXT               (((1L << XLEN) - 1) << CSR_MCONTEXT_MCONTEXT_OFFSET)
+#define CSR_SCONTEXT                        0x7aa
+/*
+ * Supervisor mode software can write a context number to this
+ * register, which can be used to set triggers that only fire in that
+ * specific context.
+ *
+ * An implementation may tie any number of high bits in this field to
+ * 0. It's recommended to implement no more than 16 bits on RV32, and
+ * 34 on RV64.
+ */
+#define CSR_SCONTEXT_DATA_OFFSET            0
+#define CSR_SCONTEXT_DATA_LENGTH            XLEN
+#define CSR_SCONTEXT_DATA                   (((1L << XLEN) - 1) << CSR_SCONTEXT_DATA_OFFSET)
 #define CSR_MCONTROL                        0x7a1
-#define CSR_MCONTROL_TYPE_OFFSET            (MXLEN-4)
+#define CSR_MCONTROL_TYPE_OFFSET            (XLEN-4)
 #define CSR_MCONTROL_TYPE_LENGTH            4
 #define CSR_MCONTROL_TYPE                   (0xfULL << CSR_MCONTROL_TYPE_OFFSET)
-#define CSR_MCONTROL_DMODE_OFFSET           (MXLEN-5)
+#define CSR_MCONTROL_DMODE_OFFSET           (XLEN-5)
 #define CSR_MCONTROL_DMODE_LENGTH           1
 #define CSR_MCONTROL_DMODE                  (0x1ULL << CSR_MCONTROL_DMODE_OFFSET)
 /*
-* Specifies the largest naturally aligned powers-of-two (NAPOT) range
-* supported by the hardware when \Fmatch is 1. The value is the
-* logarithm base 2 of the
-* number of bytes in that range.  A value of 0 indicates that only
-* exact value matches are supported (one byte range). A value of 63
-* corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in
-* size.
+ * Specifies the largest naturally aligned powers-of-two (NAPOT) range
+ * supported by the hardware when \FcsrMcontrolMatch is 1. The value is the
+ * logarithm base 2 of the
+ * number of bytes in that range.  A value of 0 indicates that only
+ * exact value matches are supported (one byte range). A value of 63
+ * corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in
+ * size.
  */
-#define CSR_MCONTROL_MASKMAX_OFFSET         (MXLEN-11)
+#define CSR_MCONTROL_MASKMAX_OFFSET         (XLEN-11)
 #define CSR_MCONTROL_MASKMAX_LENGTH         6
 #define CSR_MCONTROL_MASKMAX                (0x3fULL << CSR_MCONTROL_MASKMAX_OFFSET)
 /*
-* If this optional bit is implemented, the hardware sets it when this
-* trigger matches. The trigger's user can set or clear it at any
-* time. The trigger's user can use this bit to determine which
-* trigger(s) matched.  If the bit is not implemented, it is always 0
-* and writing it has no effect.
+ * This field only exists when XLEN is at least 64.
+ * It contains the 2 high bits of the access size. The low bits
+ * come from \FcsrMcontrolSizelo. See \FcsrMcontrolSizelo for how this
+ * is used.
+ */
+#define CSR_MCONTROL_SIZEHI_OFFSET          21
+#define CSR_MCONTROL_SIZEHI_LENGTH          2
+#define CSR_MCONTROL_SIZEHI                 (0x3ULL << CSR_MCONTROL_SIZEHI_OFFSET)
+/*
+ * If this bit is implemented, the hardware sets it when this
+ * trigger matches. The trigger's user can set or clear it at any
+ * time. It is used to determine which
+ * trigger(s) matched.  If the bit is not implemented, it is always 0
+ * and writing it has no effect.
  */
 #define CSR_MCONTROL_HIT_OFFSET             20
 #define CSR_MCONTROL_HIT_LENGTH             1
 #define CSR_MCONTROL_HIT                    (0x1ULL << CSR_MCONTROL_HIT_OFFSET)
 /*
-* 0: Perform a match on the virtual address.
-*
-* 1: Perform a match on the data value loaded/stored, or the
-* instruction executed.
+ * 0: Perform a match on the lowest virtual address of the access.  In
+ * addition, it is recommended that the trigger also fires if any of
+ * the other accessed virtual addresses match.
+ * (E.g. on a 32-bit read from 0x4000, the lowest address is 0x4000
+ * and the other addresses are 0x4001, 0x4002, and 0x4003.)
+ *
+ * 1: Perform a match on the data value loaded or stored, or the
+ * instruction executed.
  */
 #define CSR_MCONTROL_SELECT_OFFSET          19
 #define CSR_MCONTROL_SELECT_LENGTH          1
 #define CSR_MCONTROL_SELECT                 (0x1ULL << CSR_MCONTROL_SELECT_OFFSET)
 /*
-* 0: The action for this trigger will be taken just before the
-* instruction that triggered it is executed, but after all preceding
-* instructions are are committed.
-*
-* 1: The action for this trigger will be taken after the instruction
-* that triggered it is executed. It should be taken before the next
-* instruction is executed, but it is better to implement triggers and
-* not implement that suggestion than to not implement them at all.
-*
-* Most hardware will only implement one timing or the other, possibly
-* dependent on \Fselect, \Fexecute, \Fload, and \Fstore. This bit
-* primarily exists for the hardware to communicate to the debugger
-* what will happen. Hardware may implement the bit fully writable, in
-* which case the debugger has a little more control.
-*
-* Data load triggers with \Ftiming of 0 will result in the same load
-* happening again when the debugger lets the hart run. For data load
-* triggers, debuggers must first attempt to set the breakpoint with
-* \Ftiming of 1.
-*
-* A chain of triggers that don't all have the same \Ftiming value
-* will never fire (unless consecutive instructions match the
-* appropriate triggers).
+ * 0: The action for this trigger will be taken just before the
+ * instruction that triggered it is executed, but after all preceding
+ * instructions are committed. \Rmepc or \RcsrDpc (depending on
+ * \FcsrMcontrolAction) must be set to the virtual address of the
+ * instruction that matched.
+ *
+ * If this is combined with \FcsrMcontrolLoad then a memory access will be
+ * performed (including any side effects of performing such an access) even
+ * though the load will not update its destination register. Debuggers
+ * should consider this when setting such breakpoints on, for example,
+ * memory-mapped I/O addresses.
+ *
+ * 1: The action for this trigger will be taken after the instruction
+ * that triggered it is executed. It should be taken before the next
+ * instruction is executed, but it is better to implement triggers imprecisely
+ * than to not implement them at all.
+ * \Rmepc or \RcsrDpc (depending on \FcsrMcontrolAction) must be set to
+ * the virtual address of the next instruction that must be executed to
+ * preserve the program flow.
+ *
+ * Most hardware will only implement one timing or the other, possibly
+ * dependent on \FcsrMcontrolSelect, \FcsrMcontrolExecute,
+ * \FcsrMcontrolLoad, and \FcsrMcontrolStore. This bit
+ * primarily exists for the hardware to communicate to the debugger
+ * what will happen. Hardware may implement the bit fully writable, in
+ * which case the debugger has a little more control.
+ *
+ * Data load triggers with \FcsrMcontrolTiming of 0 will result in the same load
+ * happening again when the debugger lets the hart run. For data load
+ * triggers, debuggers must first attempt to set the breakpoint with
+ * \FcsrMcontrolTiming of 1.
+ *
+ * If a trigger with \FcsrMcontrolTiming of 0 matches, it is
+ * implementation-dependent whether that prevents a trigger with
+ * \FcsrMcontrolTiming of 1 matching as well.
  */
 #define CSR_MCONTROL_TIMING_OFFSET          18
 #define CSR_MCONTROL_TIMING_LENGTH          1
 #define CSR_MCONTROL_TIMING                 (0x1ULL << CSR_MCONTROL_TIMING_OFFSET)
 /*
-* The action to take when the trigger fires. The values are explained
-* in Table~\ref{tab:action}.
+ * This field contains the 2 low bits of the access size. The high bits come
+ * from \FcsrMcontrolSizehi. The combined value is interpreted as follows:
+ *
+ * 0: The trigger will attempt to match against an access of any size.
+ * The behavior is only well-defined if $|select|=0$, or if the access
+ * size is XLEN.
+ *
+ * 1: The trigger will only match against 8-bit memory accesses.
+ *
+ * 2: The trigger will only match against 16-bit memory accesses or
+ * execution of 16-bit instructions.
+ *
+ * 3: The trigger will only match against 32-bit memory accesses or
+ * execution of 32-bit instructions.
+ *
+ * 4: The trigger will only match against execution of 48-bit instructions.
+ *
+ * 5: The trigger will only match against 64-bit memory accesses or
+ * execution of 64-bit instructions.
+ *
+ * 6: The trigger will only match against execution of 80-bit instructions.
+ *
+ * 7: The trigger will only match against execution of 96-bit instructions.
+ *
+ * 8: The trigger will only match against execution of 112-bit instructions.
+ *
+ * 9: The trigger will only match against 128-bit memory accesses or
+ * execution of 128-bit instructions.
+ *
+ * An implementation must support the value of 0, but all other values
+ * are optional. It is recommended to support triggers for every
+ * access size the hart supports, as well as for every instruction
+ * size the hart supports.
+ */
+#define CSR_MCONTROL_SIZELO_OFFSET          16
+#define CSR_MCONTROL_SIZELO_LENGTH          2
+#define CSR_MCONTROL_SIZELO                 (0x3ULL << CSR_MCONTROL_SIZELO_OFFSET)
+/*
+ * The action to take when the trigger fires. The values are explained
+ * in Table~\ref{tab:action}.
  */
 #define CSR_MCONTROL_ACTION_OFFSET          12
-#define CSR_MCONTROL_ACTION_LENGTH          6
-#define CSR_MCONTROL_ACTION                 (0x3fULL << CSR_MCONTROL_ACTION_OFFSET)
-/*
-* 0: When this trigger matches, the configured action is taken.
-*
-* 1: While this trigger does not match, it prevents the trigger with
-* the next index from matching.
-*
-* Because \Fchain affects the next trigger, hardware must zero it in
-* writes to \Rmcontrol that set \Fdmode to 0 if the next trigger has
-* \Fdmode of 1.
-* In addition hardware should ignore writes to \Rmcontrol that set
-* \Fdmode to 1 if the previous trigger has both \Fdmode of 0 and
-* \Fchain of 1. Debuggers must avoid the latter case by checking
-* \Fchain on the previous trigger if they're writing \Rmcontrol.
-*
-* Implementations that wish to limit the maximum length of a trigger
-* chain (eg. to meet timing requirements) may do so by zeroing
-* \Fchain in writes to \Rmcontrol that would make the chain too long.
+#define CSR_MCONTROL_ACTION_LENGTH          4
+#define CSR_MCONTROL_ACTION                 (0xfULL << CSR_MCONTROL_ACTION_OFFSET)
+/*
+ * 0: When this trigger matches, the configured action is taken.
+ *
+ * 1: While this trigger does not match, it prevents the trigger with
+ * the next index from matching.
+ *
+ * A trigger chain starts on the first trigger with $|chain|=1$ after
+ * a trigger with $|chain|=0$, or simply on the first trigger if that
+ * has $|chain|=1$. It ends on the first trigger after that which has
+ * $|chain|=0$. This final trigger is part of the chain. The action
+ * on all but the final trigger is ignored.  The action on that final
+ * trigger will be taken if and only if all the triggers in the chain
+ * match at the same time.
+ *
+ * Because \FcsrMcontrolChain affects the next trigger, hardware must zero it in
+ * writes to \RcsrMcontrol that set \FcsrTdataOneDmode to 0 if the next trigger has
+ * \FcsrTdataOneDmode of 1.
+ * In addition hardware should ignore writes to \RcsrMcontrol that set
+ * \FcsrTdataOneDmode to 1 if the previous trigger has both \FcsrTdataOneDmode of 0 and
+ * \FcsrMcontrolChain of 1. Debuggers must avoid the latter case by checking
+ * \FcsrMcontrolChain on the previous trigger if they're writing \RcsrMcontrol.
+ *
+ * Implementations that wish to limit the maximum length of a trigger
+ * chain (eg. to meet timing requirements) may do so by zeroing
+ * \FcsrMcontrolChain in writes to \RcsrMcontrol that would make the chain too long.
  */
 #define CSR_MCONTROL_CHAIN_OFFSET           11
 #define CSR_MCONTROL_CHAIN_LENGTH           1
 #define CSR_MCONTROL_CHAIN                  (0x1ULL << CSR_MCONTROL_CHAIN_OFFSET)
 /*
-* 0: Matches when the value equals \Rtdatatwo.
-*
-* 1: Matches when the top M bits of the value match the top M bits of
-* \Rtdatatwo. M is MXLEN-1 minus the index of the least-significant
-* bit containing 0 in \Rtdatatwo.
-*
-* 2: Matches when the value is greater than (unsigned) or equal to
-* \Rtdatatwo.
-*
-* 3: Matches when the value is less than (unsigned) \Rtdatatwo.
-*
-* 4: Matches when the lower half of the value equals the lower half
-* of \Rtdatatwo after the lower half of the value is ANDed with the
-* upper half of \Rtdatatwo.
-*
-* 5: Matches when the upper half of the value equals the lower half
-* of \Rtdatatwo after the upper half of the value is ANDed with the
-* upper half of \Rtdatatwo.
-*
-* Other values are reserved for future use.
+ * 0: Matches when the value equals \RcsrTdataTwo.
+ *
+ * 1: Matches when the top M bits of the value match the top M bits of
+ * \RcsrTdataTwo. M is XLEN-1 minus the index of the least-significant
+ * bit containing 0 in \RcsrTdataTwo. Debuggers should only write values
+ * to \RcsrTdataTwo such that M + \FcsrMcontrolMaskmax $\geq$ XLEN, otherwise it's
+ * undefined on what conditions the trigger will fire.
+ *
+ * 2: Matches when the value is greater than (unsigned) or equal to
+ * \RcsrTdataTwo.
+ *
+ * 3: Matches when the value is less than (unsigned) \RcsrTdataTwo.
+ *
+ * 4: Matches when the lower half of the value equals the lower half
+ * of \RcsrTdataTwo after the lower half of the value is ANDed with the
+ * upper half of \RcsrTdataTwo.
+ *
+ * 5: Matches when the upper half of the value equals the lower half
+ * of \RcsrTdataTwo after the upper half of the value is ANDed with the
+ * upper half of \RcsrTdataTwo.
+ *
+ * 8: Matches when \FcsrMcontrolMatch$=0$ would not match.
+ *
+ * 9: Matches when \FcsrMcontrolMatch$=1$ would not match.
+ *
+ * 12: Matches when \FcsrMcontrolMatch$=4$ would not match.
+ *
+ * 13: Matches when \FcsrMcontrolMatch$=5$ would not match.
+ *
+ * Other values are reserved for future use.
  */
 #define CSR_MCONTROL_MATCH_OFFSET           7
 #define CSR_MCONTROL_MATCH_LENGTH           4
 #define CSR_MCONTROL_MATCH                  (0xfULL << CSR_MCONTROL_MATCH_OFFSET)
 /*
-* When set, enable this trigger in M mode.
+ * When set, enable this trigger in M-mode.
  */
 #define CSR_MCONTROL_M_OFFSET               6
 #define CSR_MCONTROL_M_LENGTH               1
 #define CSR_MCONTROL_M                      (0x1ULL << CSR_MCONTROL_M_OFFSET)
 /*
-* When set, enable this trigger in S mode.
+ * When set, enable this trigger in S-mode.
  */
 #define CSR_MCONTROL_S_OFFSET               4
 #define CSR_MCONTROL_S_LENGTH               1
 #define CSR_MCONTROL_S                      (0x1ULL << CSR_MCONTROL_S_OFFSET)
 /*
-* When set, enable this trigger in U mode.
+ * When set, enable this trigger in U-mode.
  */
 #define CSR_MCONTROL_U_OFFSET               3
 #define CSR_MCONTROL_U_LENGTH               1
 #define CSR_MCONTROL_U                      (0x1ULL << CSR_MCONTROL_U_OFFSET)
 /*
-* When set, the trigger fires on the virtual address or opcode of an
-* instruction that is executed.
+ * When set, the trigger fires on the virtual address or opcode of an
+ * instruction that is executed.
  */
 #define CSR_MCONTROL_EXECUTE_OFFSET         2
 #define CSR_MCONTROL_EXECUTE_LENGTH         1
 #define CSR_MCONTROL_EXECUTE                (0x1ULL << CSR_MCONTROL_EXECUTE_OFFSET)
 /*
-* When set, the trigger fires on the virtual address or data of a store.
+ * When set, the trigger fires on the virtual address or data of any
+ * store.
  */
 #define CSR_MCONTROL_STORE_OFFSET           1
 #define CSR_MCONTROL_STORE_LENGTH           1
 #define CSR_MCONTROL_STORE                  (0x1ULL << CSR_MCONTROL_STORE_OFFSET)
 /*
-* When set, the trigger fires on the virtual address or data of a load.
+ * When set, the trigger fires on the virtual address or data of any
+ * load.
  */
 #define CSR_MCONTROL_LOAD_OFFSET            0
 #define CSR_MCONTROL_LOAD_LENGTH            1
 #define CSR_MCONTROL_LOAD                   (0x1ULL << CSR_MCONTROL_LOAD_OFFSET)
 #define CSR_ICOUNT                          0x7a1
-#define CSR_ICOUNT_TYPE_OFFSET              (MXLEN-4)
+#define CSR_ICOUNT_TYPE_OFFSET              (XLEN-4)
 #define CSR_ICOUNT_TYPE_LENGTH              4
 #define CSR_ICOUNT_TYPE                     (0xfULL << CSR_ICOUNT_TYPE_OFFSET)
-#define CSR_ICOUNT_DMODE_OFFSET             (MXLEN-5)
+#define CSR_ICOUNT_DMODE_OFFSET             (XLEN-5)
 #define CSR_ICOUNT_DMODE_LENGTH             1
 #define CSR_ICOUNT_DMODE                    (0x1ULL << CSR_ICOUNT_DMODE_OFFSET)
 /*
-* If this optional bit is implemented, the hardware sets it when this
-* trigger matches. The trigger's user can set or clear it at any
-* time. The trigger's user can use this bit to determine which
-* trigger(s) matched.  If the bit is not implemented, it is always 0
-* and writing it has no effect.
+ * If this bit is implemented, the hardware sets it when this
+ * trigger matches. The trigger's user can set or clear it at any
+ * time. It is used to determine which
+ * trigger(s) matched.  If the bit is not implemented, it is always 0
+ * and writing it has no effect.
  */
 #define CSR_ICOUNT_HIT_OFFSET               24
 #define CSR_ICOUNT_HIT_LENGTH               1
 #define CSR_ICOUNT_HIT                      (0x1ULL << CSR_ICOUNT_HIT_OFFSET)
 /*
-* When count is decremented to 0, the trigger fires. Instead of
-* changing \Fcount from 1 to 0, it is also acceptable for hardware to
-* clear \Fm, \Fs, and \Fu. This allows \Fcount to be hard-wired
-* to 1 if this register just exists for single step.
+ * When count is decremented to 0, the trigger fires. Instead of
+ * changing \FcsrIcountCount from 1 to 0, it is also acceptable for hardware to
+ * clear \FcsrMcontrolM, \FcsrMcontrolS, and \FcsrMcontrolU. This allows \FcsrIcountCount to be hard-wired
+ * to 1 if this register just exists for single step.
  */
 #define CSR_ICOUNT_COUNT_OFFSET             10
 #define CSR_ICOUNT_COUNT_LENGTH             14
 #define CSR_ICOUNT_COUNT                    (0x3fffULL << CSR_ICOUNT_COUNT_OFFSET)
 /*
-* When set, every instruction completed or exception taken in M mode decrements \Fcount
-* by 1.
+ * When set, every instruction completed in or trap taken from
+ * M-mode decrements \FcsrIcountCount by 1.
  */
 #define CSR_ICOUNT_M_OFFSET                 9
 #define CSR_ICOUNT_M_LENGTH                 1
 #define CSR_ICOUNT_M                        (0x1ULL << CSR_ICOUNT_M_OFFSET)
 /*
-* When set, every instruction completed or exception taken in S mode decrements \Fcount
-* by 1.
+ * When set, every instruction completed in or trap taken from
+ * S-mode decrements \FcsrIcountCount by 1.
  */
 #define CSR_ICOUNT_S_OFFSET                 7
 #define CSR_ICOUNT_S_LENGTH                 1
 #define CSR_ICOUNT_S                        (0x1ULL << CSR_ICOUNT_S_OFFSET)
 /*
-* When set, every instruction completed or exception taken in U mode decrements \Fcount
-* by 1.
+ * When set, every instruction completed in or trap taken from
+ * U-mode decrements \FcsrIcountCount by 1.
  */
 #define CSR_ICOUNT_U_OFFSET                 6
 #define CSR_ICOUNT_U_LENGTH                 1
 #define CSR_ICOUNT_U                        (0x1ULL << CSR_ICOUNT_U_OFFSET)
 /*
-* The action to take when the trigger fires. The values are explained
-* in Table~\ref{tab:action}.
+ * The action to take when the trigger fires. The values are explained
+ * in Table~\ref{tab:action}.
  */
 #define CSR_ICOUNT_ACTION_OFFSET            0
 #define CSR_ICOUNT_ACTION_LENGTH            6
 #define CSR_ICOUNT_ACTION                   (0x3fULL << CSR_ICOUNT_ACTION_OFFSET)
 #define CSR_ITRIGGER                        0x7a1
-#define CSR_ITRIGGER_TYPE_OFFSET            (MXLEN-4)
+#define CSR_ITRIGGER_TYPE_OFFSET            (XLEN-4)
 #define CSR_ITRIGGER_TYPE_LENGTH            4
 #define CSR_ITRIGGER_TYPE                   (0xfULL << CSR_ITRIGGER_TYPE_OFFSET)
-#define CSR_ITRIGGER_DMODE_OFFSET           (MXLEN-5)
+#define CSR_ITRIGGER_DMODE_OFFSET           (XLEN-5)
 #define CSR_ITRIGGER_DMODE_LENGTH           1
 #define CSR_ITRIGGER_DMODE                  (0x1ULL << CSR_ITRIGGER_DMODE_OFFSET)
 /*
-* If this optional bit is implemented, the hardware sets it when this
-* trigger matches. The trigger's user can set or clear it at any
-* time. The trigger's user can use this bit to determine which
-* trigger(s) matched.  If the bit is not implemented, it is always 0
-* and writing it has no effect.
+ * If this bit is implemented, the hardware sets it when this
+ * trigger matches. The trigger's user can set or clear it at any
+ * time. It is used to determine which
+ * trigger(s) matched.  If the bit is not implemented, it is always 0
+ * and writing it has no effect.
  */
-#define CSR_ITRIGGER_HIT_OFFSET             (MXLEN-6)
+#define CSR_ITRIGGER_HIT_OFFSET             (XLEN-6)
 #define CSR_ITRIGGER_HIT_LENGTH             1
 #define CSR_ITRIGGER_HIT                    (0x1ULL << CSR_ITRIGGER_HIT_OFFSET)
 /*
-* When set, enable this trigger for interrupts that are taken from M
-* mode.
+ * When set, enable this trigger for interrupts that are taken from M
+ * mode.
  */
 #define CSR_ITRIGGER_M_OFFSET               9
 #define CSR_ITRIGGER_M_LENGTH               1
 #define CSR_ITRIGGER_M                      (0x1ULL << CSR_ITRIGGER_M_OFFSET)
 /*
-* When set, enable this trigger for interrupts that are taken from S
-* mode.
+ * When set, enable this trigger for interrupts that are taken from S
+ * mode.
  */
 #define CSR_ITRIGGER_S_OFFSET               7
 #define CSR_ITRIGGER_S_LENGTH               1
 #define CSR_ITRIGGER_S                      (0x1ULL << CSR_ITRIGGER_S_OFFSET)
 /*
-* When set, enable this trigger for interrupts that are taken from U
-* mode.
+ * When set, enable this trigger for interrupts that are taken from U
+ * mode.
  */
 #define CSR_ITRIGGER_U_OFFSET               6
 #define CSR_ITRIGGER_U_LENGTH               1
 #define CSR_ITRIGGER_U                      (0x1ULL << CSR_ITRIGGER_U_OFFSET)
 /*
-* The action to take when the trigger fires. The values are explained
-* in Table~\ref{tab:action}.
+ * The action to take when the trigger fires. The values are explained
+ * in Table~\ref{tab:action}.
  */
 #define CSR_ITRIGGER_ACTION_OFFSET          0
 #define CSR_ITRIGGER_ACTION_LENGTH          6
 #define CSR_ITRIGGER_ACTION                 (0x3fULL << CSR_ITRIGGER_ACTION_OFFSET)
 #define CSR_ETRIGGER                        0x7a1
-#define CSR_ETRIGGER_TYPE_OFFSET            (MXLEN-4)
+#define CSR_ETRIGGER_TYPE_OFFSET            (XLEN-4)
 #define CSR_ETRIGGER_TYPE_LENGTH            4
 #define CSR_ETRIGGER_TYPE                   (0xfULL << CSR_ETRIGGER_TYPE_OFFSET)
-#define CSR_ETRIGGER_DMODE_OFFSET           (MXLEN-5)
+#define CSR_ETRIGGER_DMODE_OFFSET           (XLEN-5)
 #define CSR_ETRIGGER_DMODE_LENGTH           1
 #define CSR_ETRIGGER_DMODE                  (0x1ULL << CSR_ETRIGGER_DMODE_OFFSET)
 /*
-* If this optional bit is implemented, the hardware sets it when this
-* trigger matches. The trigger's user can set or clear it at any
-* time. The trigger's user can use this bit to determine which
-* trigger(s) matched.  If the bit is not implemented, it is always 0
-* and writing it has no effect.
+ * If this bit is implemented, the hardware sets it when this
+ * trigger matches. The trigger's user can set or clear it at any
+ * time. It is used to determine which
+ * trigger(s) matched.  If the bit is not implemented, it is always 0
+ * and writing it has no effect.
  */
-#define CSR_ETRIGGER_HIT_OFFSET             (MXLEN-6)
+#define CSR_ETRIGGER_HIT_OFFSET             (XLEN-6)
 #define CSR_ETRIGGER_HIT_LENGTH             1
 #define CSR_ETRIGGER_HIT                    (0x1ULL << CSR_ETRIGGER_HIT_OFFSET)
 /*
-* When set, enable this trigger for exceptions that are taken from M
-* mode.
+ * When set, non-maskable interrupts cause this
+ * trigger to fire, regardless of the values of \FcsrMcontrolM, \FcsrMcontrolS, and \FcsrMcontrolU.
+ */
+#define CSR_ETRIGGER_NMI_OFFSET             10
+#define CSR_ETRIGGER_NMI_LENGTH             1
+#define CSR_ETRIGGER_NMI                    (0x1ULL << CSR_ETRIGGER_NMI_OFFSET)
+/*
+ * When set, enable this trigger for exceptions that are taken from M
+ * mode.
  */
 #define CSR_ETRIGGER_M_OFFSET               9
 #define CSR_ETRIGGER_M_LENGTH               1
 #define CSR_ETRIGGER_M                      (0x1ULL << CSR_ETRIGGER_M_OFFSET)
 /*
-* When set, enable this trigger for exceptions that are taken from S
-* mode.
+ * When set, enable this trigger for exceptions that are taken from S
+ * mode.
  */
 #define CSR_ETRIGGER_S_OFFSET               7
 #define CSR_ETRIGGER_S_LENGTH               1
 #define CSR_ETRIGGER_S                      (0x1ULL << CSR_ETRIGGER_S_OFFSET)
 /*
-* When set, enable this trigger for exceptions that are taken from U
-* mode.
+ * When set, enable this trigger for exceptions that are taken from U
+ * mode.
  */
 #define CSR_ETRIGGER_U_OFFSET               6
 #define CSR_ETRIGGER_U_LENGTH               1
 #define CSR_ETRIGGER_U                      (0x1ULL << CSR_ETRIGGER_U_OFFSET)
 /*
-* The action to take when the trigger fires. The values are explained
-* in Table~\ref{tab:action}.
+ * The action to take when the trigger fires. The values are explained
+ * in Table~\ref{tab:action}.
  */
 #define CSR_ETRIGGER_ACTION_OFFSET          0
 #define CSR_ETRIGGER_ACTION_LENGTH          6
 #define CSR_ETRIGGER_ACTION                 (0x3fULL << CSR_ETRIGGER_ACTION_OFFSET)
-#define DMI_DMSTATUS                        0x11
-/*
-* If 1, then there is an implicit {\tt ebreak} instruction at the
-* non-existent word immediately after the Program Buffer. This saves
-* the debugger from having to write the {\tt ebreak} itself, and
-* allows the Program Buffer to be one word smaller.
-*
-* This must be 1 when \Fprogbufsize is 1.
- */
-#define DMI_DMSTATUS_IMPEBREAK_OFFSET       22
-#define DMI_DMSTATUS_IMPEBREAK_LENGTH       1
-#define DMI_DMSTATUS_IMPEBREAK              (0x1U << DMI_DMSTATUS_IMPEBREAK_OFFSET)
-/*
-* This field is 1 when all currently selected harts have been reset but the reset has not been acknowledged.
- */
-#define DMI_DMSTATUS_ALLHAVERESET_OFFSET    19
-#define DMI_DMSTATUS_ALLHAVERESET_LENGTH    1
-#define DMI_DMSTATUS_ALLHAVERESET           (0x1U << DMI_DMSTATUS_ALLHAVERESET_OFFSET)
-/*
-* This field is 1 when any currently selected hart has been reset but the reset has not been acknowledged.
- */
-#define DMI_DMSTATUS_ANYHAVERESET_OFFSET    18
-#define DMI_DMSTATUS_ANYHAVERESET_LENGTH    1
-#define DMI_DMSTATUS_ANYHAVERESET           (0x1U << DMI_DMSTATUS_ANYHAVERESET_OFFSET)
-/*
-* This field is 1 when all currently selected harts have acknowledged
-* the previous resume request.
- */
-#define DMI_DMSTATUS_ALLRESUMEACK_OFFSET    17
-#define DMI_DMSTATUS_ALLRESUMEACK_LENGTH    1
-#define DMI_DMSTATUS_ALLRESUMEACK           (0x1U << DMI_DMSTATUS_ALLRESUMEACK_OFFSET)
-/*
-* This field is 1 when any currently selected hart has acknowledged
-* the previous resume request.
- */
-#define DMI_DMSTATUS_ANYRESUMEACK_OFFSET    16
-#define DMI_DMSTATUS_ANYRESUMEACK_LENGTH    1
-#define DMI_DMSTATUS_ANYRESUMEACK           (0x1U << DMI_DMSTATUS_ANYRESUMEACK_OFFSET)
-/*
-* This field is 1 when all currently selected harts do not exist in this system.
- */
-#define DMI_DMSTATUS_ALLNONEXISTENT_OFFSET  15
-#define DMI_DMSTATUS_ALLNONEXISTENT_LENGTH  1
-#define DMI_DMSTATUS_ALLNONEXISTENT         (0x1U << DMI_DMSTATUS_ALLNONEXISTENT_OFFSET)
-/*
-* This field is 1 when any currently selected hart does not exist in this system.
- */
-#define DMI_DMSTATUS_ANYNONEXISTENT_OFFSET  14
-#define DMI_DMSTATUS_ANYNONEXISTENT_LENGTH  1
-#define DMI_DMSTATUS_ANYNONEXISTENT         (0x1U << DMI_DMSTATUS_ANYNONEXISTENT_OFFSET)
+#define CSR_TEXTRA32                        0x7a3
+/*
+ * Data used together with \FcsrTextraThirtytwoMselect.
+ */
+#define CSR_TEXTRA32_MVALUE_OFFSET          26
+#define CSR_TEXTRA32_MVALUE_LENGTH          6
+#define CSR_TEXTRA32_MVALUE                 (0x3fU << CSR_TEXTRA32_MVALUE_OFFSET)
+/*
+ * 0: Ignore \FcsrTextraThirtytwoMvalue.
+ *
+ * 1: This trigger will only match if the low bits of
+ * \RcsrMcontext equal \FcsrTextraThirtytwoMvalue.
+ */
+#define CSR_TEXTRA32_MSELECT_OFFSET         25
+#define CSR_TEXTRA32_MSELECT_LENGTH         1
+#define CSR_TEXTRA32_MSELECT                (0x1U << CSR_TEXTRA32_MSELECT_OFFSET)
+/*
+ * Data used together with \FcsrTextraThirtytwoSselect.
+ *
+ * This field should be tied to 0 when S-mode is not supported.
+ */
+#define CSR_TEXTRA32_SVALUE_OFFSET          2
+#define CSR_TEXTRA32_SVALUE_LENGTH          16
+#define CSR_TEXTRA32_SVALUE                 (0xffffU << CSR_TEXTRA32_SVALUE_OFFSET)
+/*
+ * 0: Ignore \FcsrTextraThirtytwoSvalue.
+ *
+ * 1: This trigger will only match if the low bits of
+ * \RcsrScontext equal \FcsrTextraThirtytwoSvalue.
+ *
+ * 2: This trigger will only match if \Fasid in \Rsatp
+ * equals the lower ASIDMAX (defined in the Privileged Spec) bits of
+ * \FcsrTextraThirtytwoSvalue.
+ *
+ * This field should be tied to 0 when S-mode is not supported.
+ */
+#define CSR_TEXTRA32_SSELECT_OFFSET         0
+#define CSR_TEXTRA32_SSELECT_LENGTH         2
+#define CSR_TEXTRA32_SSELECT                (0x3U << CSR_TEXTRA32_SSELECT_OFFSET)
+#define CSR_TEXTRA64                        0x7a3
+#define CSR_TEXTRA64_MVALUE_OFFSET          51
+#define CSR_TEXTRA64_MVALUE_LENGTH          13
+#define CSR_TEXTRA64_MVALUE                 (0x1fffULL << CSR_TEXTRA64_MVALUE_OFFSET)
+#define CSR_TEXTRA64_MSELECT_OFFSET         50
+#define CSR_TEXTRA64_MSELECT_LENGTH         1
+#define CSR_TEXTRA64_MSELECT                (0x1ULL << CSR_TEXTRA64_MSELECT_OFFSET)
+#define CSR_TEXTRA64_SVALUE_OFFSET          2
+#define CSR_TEXTRA64_SVALUE_LENGTH          34
+#define CSR_TEXTRA64_SVALUE                 (0x3ffffffffULL << CSR_TEXTRA64_SVALUE_OFFSET)
+#define CSR_TEXTRA64_SSELECT_OFFSET         0
+#define CSR_TEXTRA64_SSELECT_LENGTH         2
+#define CSR_TEXTRA64_SSELECT                (0x3ULL << CSR_TEXTRA64_SSELECT_OFFSET)
+#define DM_DMSTATUS                         0x11
+/*
+ * If 1, then there is an implicit {\tt ebreak} instruction at the
+ * non-existent word immediately after the Program Buffer. This saves
+ * the debugger from having to write the {\tt ebreak} itself, and
+ * allows the Program Buffer to be one word smaller.
+ *
+ * This must be 1 when \FdmAbstractcsProgbufsize is 1.
+ */
+#define DM_DMSTATUS_IMPEBREAK_OFFSET        22
+#define DM_DMSTATUS_IMPEBREAK_LENGTH        1
+#define DM_DMSTATUS_IMPEBREAK               (0x1U << DM_DMSTATUS_IMPEBREAK_OFFSET)
+/*
+ * This field is 1 when all currently selected harts have been reset
+ * and reset has not been acknowledged for any of them.
+ */
+#define DM_DMSTATUS_ALLHAVERESET_OFFSET     19
+#define DM_DMSTATUS_ALLHAVERESET_LENGTH     1
+#define DM_DMSTATUS_ALLHAVERESET            (0x1U << DM_DMSTATUS_ALLHAVERESET_OFFSET)
+/*
+ * This field is 1 when at least one currently selected hart has been
+ * reset and reset has not been acknowledged for that hart.
+ */
+#define DM_DMSTATUS_ANYHAVERESET_OFFSET     18
+#define DM_DMSTATUS_ANYHAVERESET_LENGTH     1
+#define DM_DMSTATUS_ANYHAVERESET            (0x1U << DM_DMSTATUS_ANYHAVERESET_OFFSET)
+/*
+ * This field is 1 when all currently selected harts have acknowledged
+ * their last resume request.
+ */
+#define DM_DMSTATUS_ALLRESUMEACK_OFFSET     17
+#define DM_DMSTATUS_ALLRESUMEACK_LENGTH     1
+#define DM_DMSTATUS_ALLRESUMEACK            (0x1U << DM_DMSTATUS_ALLRESUMEACK_OFFSET)
+/*
+ * This field is 1 when any currently selected hart has acknowledged
+ * its last resume request.
+ */
+#define DM_DMSTATUS_ANYRESUMEACK_OFFSET     16
+#define DM_DMSTATUS_ANYRESUMEACK_LENGTH     1
+#define DM_DMSTATUS_ANYRESUMEACK            (0x1U << DM_DMSTATUS_ANYRESUMEACK_OFFSET)
+/*
+ * This field is 1 when all currently selected harts do not exist in
+ * this platform.
+ */
+#define DM_DMSTATUS_ALLNONEXISTENT_OFFSET   15
+#define DM_DMSTATUS_ALLNONEXISTENT_LENGTH   1
+#define DM_DMSTATUS_ALLNONEXISTENT          (0x1U << DM_DMSTATUS_ALLNONEXISTENT_OFFSET)
+/*
+ * This field is 1 when any currently selected hart does not exist in
+ * this platform.
+ */
+#define DM_DMSTATUS_ANYNONEXISTENT_OFFSET   14
+#define DM_DMSTATUS_ANYNONEXISTENT_LENGTH   1
+#define DM_DMSTATUS_ANYNONEXISTENT          (0x1U << DM_DMSTATUS_ANYNONEXISTENT_OFFSET)
+/*
+ * This field is 1 when all currently selected harts are unavailable.
+ */
+#define DM_DMSTATUS_ALLUNAVAIL_OFFSET       13
+#define DM_DMSTATUS_ALLUNAVAIL_LENGTH       1
+#define DM_DMSTATUS_ALLUNAVAIL              (0x1U << DM_DMSTATUS_ALLUNAVAIL_OFFSET)
+/*
+ * This field is 1 when any currently selected hart is unavailable.
+ */
+#define DM_DMSTATUS_ANYUNAVAIL_OFFSET       12
+#define DM_DMSTATUS_ANYUNAVAIL_LENGTH       1
+#define DM_DMSTATUS_ANYUNAVAIL              (0x1U << DM_DMSTATUS_ANYUNAVAIL_OFFSET)
+/*
+ * This field is 1 when all currently selected harts are running.
+ */
+#define DM_DMSTATUS_ALLRUNNING_OFFSET       11
+#define DM_DMSTATUS_ALLRUNNING_LENGTH       1
+#define DM_DMSTATUS_ALLRUNNING              (0x1U << DM_DMSTATUS_ALLRUNNING_OFFSET)
+/*
+ * This field is 1 when any currently selected hart is running.
+ */
+#define DM_DMSTATUS_ANYRUNNING_OFFSET       10
+#define DM_DMSTATUS_ANYRUNNING_LENGTH       1
+#define DM_DMSTATUS_ANYRUNNING              (0x1U << DM_DMSTATUS_ANYRUNNING_OFFSET)
+/*
+ * This field is 1 when all currently selected harts are halted.
+ */
+#define DM_DMSTATUS_ALLHALTED_OFFSET        9
+#define DM_DMSTATUS_ALLHALTED_LENGTH        1
+#define DM_DMSTATUS_ALLHALTED               (0x1U << DM_DMSTATUS_ALLHALTED_OFFSET)
+/*
+ * This field is 1 when any currently selected hart is halted.
+ */
+#define DM_DMSTATUS_ANYHALTED_OFFSET        8
+#define DM_DMSTATUS_ANYHALTED_LENGTH        1
+#define DM_DMSTATUS_ANYHALTED               (0x1U << DM_DMSTATUS_ANYHALTED_OFFSET)
+/*
+ * 0: Authentication is required before using the DM.
+ *
+ * 1: The authentication check has passed.
+ *
+ * On components that don't implement authentication, this bit must be
+ * preset as 1.
+ */
+#define DM_DMSTATUS_AUTHENTICATED_OFFSET    7
+#define DM_DMSTATUS_AUTHENTICATED_LENGTH    1
+#define DM_DMSTATUS_AUTHENTICATED           (0x1U << DM_DMSTATUS_AUTHENTICATED_OFFSET)
+/*
+ * 0: The authentication module is ready to process the next
+ * read/write to \RdmAuthdata.
+ *
+ * 1: The authentication module is busy. Accessing \RdmAuthdata results
+ * in unspecified behavior.
+ *
+ * \FdmDmstatusAuthbusy only becomes set in immediate response to an access to
+ * \RdmAuthdata.
+ */
+#define DM_DMSTATUS_AUTHBUSY_OFFSET         6
+#define DM_DMSTATUS_AUTHBUSY_LENGTH         1
+#define DM_DMSTATUS_AUTHBUSY                (0x1U << DM_DMSTATUS_AUTHBUSY_OFFSET)
+/*
+ * 1 if this Debug Module supports halt-on-reset functionality
+ * controllable by the \FdmDmcontrolSetresethaltreq and \FdmDmcontrolClrresethaltreq bits.
+ * 0 otherwise.
+ */
+#define DM_DMSTATUS_HASRESETHALTREQ_OFFSET  5
+#define DM_DMSTATUS_HASRESETHALTREQ_LENGTH  1
+#define DM_DMSTATUS_HASRESETHALTREQ         (0x1U << DM_DMSTATUS_HASRESETHALTREQ_OFFSET)
+/*
+ * 0: \RdmConfstrptrZero--\RdmConfstrptrThree hold information which
+ * is not relevant to the configuration string.
+ *
+ * 1: \RdmConfstrptrZero--\RdmConfstrptrThree hold the address of the
+ * configuration string.
+ */
+#define DM_DMSTATUS_CONFSTRPTRVALID_OFFSET  4
+#define DM_DMSTATUS_CONFSTRPTRVALID_LENGTH  1
+#define DM_DMSTATUS_CONFSTRPTRVALID         (0x1U << DM_DMSTATUS_CONFSTRPTRVALID_OFFSET)
+/*
+ * 0: There is no Debug Module present.
+ *
+ * 1: There is a Debug Module and it conforms to version 0.11 of this
+ * specification.
+ *
+ * 2: There is a Debug Module and it conforms to version 0.13 of this
+ * specification.
+ *
+ * 3: There is a Debug Module and it conforms to version 0.14 of this
+ * specification.
+ *
+ * 15: There is a Debug Module but it does not conform to any
+ * available version of this spec.
+ */
+#define DM_DMSTATUS_VERSION_OFFSET          0
+#define DM_DMSTATUS_VERSION_LENGTH          4
+#define DM_DMSTATUS_VERSION                 (0xfU << DM_DMSTATUS_VERSION_OFFSET)
+#define DM_DMCONTROL                        0x10
+/*
+ * Writing 0 clears the halt request bit for all currently selected
+ * harts. This may cancel outstanding halt requests for those harts.
+ *
+ * Writing 1 sets the halt request bit for all currently selected
+ * harts. Running harts will halt whenever their halt request bit is
+ * set.
+ *
+ * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel.
+ */
+#define DM_DMCONTROL_HALTREQ_OFFSET         31
+#define DM_DMCONTROL_HALTREQ_LENGTH         1
+#define DM_DMCONTROL_HALTREQ                (0x1U << DM_DMCONTROL_HALTREQ_OFFSET)
+/*
+ * Writing 1 causes the currently selected harts to resume once, if
+ * they are halted when the write occurs. It also clears the resume
+ * ack bit for those harts.
+ *
+ * \FdmDmcontrolResumereq is ignored if \FdmDmcontrolHaltreq is set.
+ *
+ * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel.
+ */
+#define DM_DMCONTROL_RESUMEREQ_OFFSET       30
+#define DM_DMCONTROL_RESUMEREQ_LENGTH       1
+#define DM_DMCONTROL_RESUMEREQ              (0x1U << DM_DMCONTROL_RESUMEREQ_OFFSET)
+/*
+ * This optional field writes the reset bit for all the currently
+ * selected harts.  To perform a reset the debugger writes 1, and then
+ * writes 0 to deassert the reset signal.
+ *
+ * While this bit is 1, the debugger must not change which harts are
+ * selected.
+ *
+ * If this feature is not implemented, the bit always stays 0, so
+ * after writing 1 the debugger can read the register back to see if
+ * the feature is supported.
+ *
+ * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel.
+ */
+#define DM_DMCONTROL_HARTRESET_OFFSET       29
+#define DM_DMCONTROL_HARTRESET_LENGTH       1
+#define DM_DMCONTROL_HARTRESET              (0x1U << DM_DMCONTROL_HARTRESET_OFFSET)
+/*
+ * 0: No effect.
+ *
+ * 1: Clears {\tt havereset} for any selected harts.
+ *
+ * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel.
+ */
+#define DM_DMCONTROL_ACKHAVERESET_OFFSET    28
+#define DM_DMCONTROL_ACKHAVERESET_LENGTH    1
+#define DM_DMCONTROL_ACKHAVERESET           (0x1U << DM_DMCONTROL_ACKHAVERESET_OFFSET)
+/*
+ * Selects the definition of currently selected harts.
+ *
+ * 0: There is a single currently selected hart, that is selected by \Fhartsel.
+ *
+ * 1: There may be multiple currently selected harts -- the hart
+ * selected by \Fhartsel, plus those selected by the hart array mask
+ * register.
+ *
+ * An implementation which does not implement the hart array mask register
+ * must tie this field to 0. A debugger which wishes to use the hart array
+ * mask register feature should set this bit and read back to see if the functionality
+ * is supported.
+ */
+#define DM_DMCONTROL_HASEL_OFFSET           26
+#define DM_DMCONTROL_HASEL_LENGTH           1
+#define DM_DMCONTROL_HASEL                  (0x1U << DM_DMCONTROL_HASEL_OFFSET)
+/*
+ * The low 10 bits of \Fhartsel: the DM-specific index of the hart to
+ * select. This hart is always part of the currently selected harts.
+ */
+#define DM_DMCONTROL_HARTSELLO_OFFSET       16
+#define DM_DMCONTROL_HARTSELLO_LENGTH       10
+#define DM_DMCONTROL_HARTSELLO              (0x3ffU << DM_DMCONTROL_HARTSELLO_OFFSET)
+/*
+ * The high 10 bits of \Fhartsel: the DM-specific index of the hart to
+ * select. This hart is always part of the currently selected harts.
+ */
+#define DM_DMCONTROL_HARTSELHI_OFFSET       6
+#define DM_DMCONTROL_HARTSELHI_LENGTH       10
+#define DM_DMCONTROL_HARTSELHI              (0x3ffU << DM_DMCONTROL_HARTSELHI_OFFSET)
+/*
+ * This optional field writes the halt-on-reset request bit for all
+ * currently selected harts, unless \FdmDmcontrolClrresethaltreq is
+ * simultaneously set to 1.
+ * When set to 1, each selected hart will halt upon the next deassertion
+ * of its reset. The halt-on-reset request bit is not automatically
+ * cleared. The debugger must write to \FdmDmcontrolClrresethaltreq to clear it.
+ *
+ * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel.
+ *
+ * If \FdmDmstatusHasresethaltreq is 0, this field is not implemented.
+ */
+#define DM_DMCONTROL_SETRESETHALTREQ_OFFSET 3
+#define DM_DMCONTROL_SETRESETHALTREQ_LENGTH 1
+#define DM_DMCONTROL_SETRESETHALTREQ        (0x1U << DM_DMCONTROL_SETRESETHALTREQ_OFFSET)
+/*
+ * This optional field clears the halt-on-reset request bit for all
+ * currently selected harts.
+ *
+ * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel.
+ */
+#define DM_DMCONTROL_CLRRESETHALTREQ_OFFSET 2
+#define DM_DMCONTROL_CLRRESETHALTREQ_LENGTH 1
+#define DM_DMCONTROL_CLRRESETHALTREQ        (0x1U << DM_DMCONTROL_CLRRESETHALTREQ_OFFSET)
+/*
+ * This bit controls the reset signal from the DM to the rest of the
+ * system. The signal should reset every part of the system, including
+ * every hart, except for the DM and any logic required to access the
+ * DM.
+ * To perform a system reset the debugger writes 1,
+ * and then writes 0
+ * to deassert the reset.
+ */
+#define DM_DMCONTROL_NDMRESET_OFFSET        1
+#define DM_DMCONTROL_NDMRESET_LENGTH        1
+#define DM_DMCONTROL_NDMRESET               (0x1U << DM_DMCONTROL_NDMRESET_OFFSET)
+/*
+ * This bit serves as a reset signal for the Debug Module itself.
+ *
+ * 0: The module's state, including authentication mechanism,
+ * takes its reset values (the \FdmDmcontrolDmactive bit is the only bit which can
+ * be written to something other than its reset value). Any accesses
+ * to the module may fail. Specifically, \FdmDmstatusVersion may not return
+ * correct data.
+ *
+ * 1: The module functions normally. After writing 1, the debugger should
+ * poll \RdmDmcontrol until \FdmDmcontrolDmactive is high. Hardware may
+ * take an arbitrarily long time to initialize and will indicate completion
+ * by setting dmactive to 1.
+ *
+ * No other mechanism should exist that may result in resetting the
+ * Debug Module after power up.
+ *
+ * A debugger may pulse this bit low to get the Debug Module into a
+ * known state.
+ *
+ * Implementations may pay attention to this bit to further aid
+ * debugging, for example by preventing the Debug Module from being
+ * power gated while debugging is active.
+ */
+#define DM_DMCONTROL_DMACTIVE_OFFSET        0
+#define DM_DMCONTROL_DMACTIVE_LENGTH        1
+#define DM_DMCONTROL_DMACTIVE               (0x1U << DM_DMCONTROL_DMACTIVE_OFFSET)
+#define DM_HARTINFO                         0x12
+/*
+ * Number of {\tt dscratch} registers available for the debugger
+ * to use during program buffer execution, starting from \RcsrDscratchZero.
+ * The debugger can make no assumptions about the contents of these
+ * registers between commands.
+ */
+#define DM_HARTINFO_NSCRATCH_OFFSET         20
+#define DM_HARTINFO_NSCRATCH_LENGTH         4
+#define DM_HARTINFO_NSCRATCH                (0xfU << DM_HARTINFO_NSCRATCH_OFFSET)
+/*
+ * 0: The {\tt data} registers are shadowed in the hart by CSRs.
+ * Each CSR is DXLEN bits in size, and corresponds
+ * to a single argument, per Table~\ref{tab:datareg}.
+ *
+ * 1: The {\tt data} registers are shadowed in the hart's memory map.
+ * Each register takes up 4 bytes in the memory map.
+ */
+#define DM_HARTINFO_DATAACCESS_OFFSET       16
+#define DM_HARTINFO_DATAACCESS_LENGTH       1
+#define DM_HARTINFO_DATAACCESS              (0x1U << DM_HARTINFO_DATAACCESS_OFFSET)
+/*
+ * If \FdmHartinfoDataaccess is 0: Number of CSRs dedicated to
+ * shadowing the {\tt data} registers.
+ *
+ * If \FdmHartinfoDataaccess is 1: Number of 32-bit words in the memory map
+ * dedicated to shadowing the {\tt data} registers.
+ *
+ * Since there are at most 12 {\tt data} registers, the value in this
+ * register must be 12 or smaller.
+ */
+#define DM_HARTINFO_DATASIZE_OFFSET         12
+#define DM_HARTINFO_DATASIZE_LENGTH         4
+#define DM_HARTINFO_DATASIZE                (0xfU << DM_HARTINFO_DATASIZE_OFFSET)
+/*
+ * If \FdmHartinfoDataaccess is 0: The number of the first CSR dedicated to
+ * shadowing the {\tt data} registers.
+ *
+ * If \FdmHartinfoDataaccess is 1: Address of RAM where the data
+ * registers are shadowed. This address is sign extended giving a
+ * range of -2048 to 2047, easily addressed with a load or store using
+ * \Xzero as the address register.
+ */
+#define DM_HARTINFO_DATAADDR_OFFSET         0
+#define DM_HARTINFO_DATAADDR_LENGTH         12
+#define DM_HARTINFO_DATAADDR                (0xfffU << DM_HARTINFO_DATAADDR_OFFSET)
+#define DM_HAWINDOWSEL                      0x14
+/*
+ * The high bits of this field may be tied to 0, depending on how large
+ * the array mask register is.  E.g.\ on a system with 48 harts only bit 0
+ * of this field may actually be writable.
+ */
+#define DM_HAWINDOWSEL_HAWINDOWSEL_OFFSET   0
+#define DM_HAWINDOWSEL_HAWINDOWSEL_LENGTH   15
+#define DM_HAWINDOWSEL_HAWINDOWSEL          (0x7fffU << DM_HAWINDOWSEL_HAWINDOWSEL_OFFSET)
+#define DM_HAWINDOW                         0x15
+#define DM_HAWINDOW_MASKDATA_OFFSET         0
+#define DM_HAWINDOW_MASKDATA_LENGTH         32
+#define DM_HAWINDOW_MASKDATA                (0xffffffffU << DM_HAWINDOW_MASKDATA_OFFSET)
+#define DM_ABSTRACTCS                       0x16
+/*
+ * Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16.
+ */
+#define DM_ABSTRACTCS_PROGBUFSIZE_OFFSET    24
+#define DM_ABSTRACTCS_PROGBUFSIZE_LENGTH    5
+#define DM_ABSTRACTCS_PROGBUFSIZE           (0x1fU << DM_ABSTRACTCS_PROGBUFSIZE_OFFSET)
+/*
+ * 1: An abstract command is currently being executed.
+ *
+ * This bit is set as soon as \RdmCommand is written, and is
+ * not cleared until that command has completed.
+ */
+#define DM_ABSTRACTCS_BUSY_OFFSET           12
+#define DM_ABSTRACTCS_BUSY_LENGTH           1
+#define DM_ABSTRACTCS_BUSY                  (0x1U << DM_ABSTRACTCS_BUSY_OFFSET)
+/*
+ * This optional bit controls whether program buffer and abstract
+ * memory accesses are performed with the exact and full set of
+ * permission checks that apply based on the current architectural
+ * state of the hart performing the access, or with a relaxed set of
+ * permission checks (e.g. PMP restrictions are ignored).  The
+ * details of the latter are implementation-specific.  When set to 0,
+ * full permissions apply; when set to 1, relaxed permissions apply.
+ */
+#define DM_ABSTRACTCS_RELAXEDPRIV_OFFSET    11
+#define DM_ABSTRACTCS_RELAXEDPRIV_LENGTH    1
+#define DM_ABSTRACTCS_RELAXEDPRIV           (0x1U << DM_ABSTRACTCS_RELAXEDPRIV_OFFSET)
+/*
+ * Gets set if an abstract command fails. The bits in this field remain set until
+ * they are cleared by writing 1 to them. No abstract command is
+ * started until the value is reset to 0.
+ *
+ * This field only contains a valid value if \FdmAbstractcsBusy is 0.
+ *
+ * 0 (none): No error.
+ *
+ * 1 (busy): An abstract command was executing while \RdmCommand,
+ * \RdmAbstractcs, or \RdmAbstractauto was written, or when one
+ * of the {\tt data} or {\tt progbuf} registers was read or written.
+ * This status is only written if \FdmAbstractcsCmderr contains 0.
+ *
+ * 2 (not supported): The command in \RdmCommand is not supported.  It
+ * may be supported with different options set, but it will not be
+ * supported at a later time when the hart or system state are
+ * different.
+ *
+ * 3 (exception): An exception occurred while executing the command
+ * (e.g.\ while executing the Program Buffer).
+ *
+ * 4 (halt/resume): The abstract command couldn't execute because the
+ * hart wasn't in the required state (running/halted), or unavailable.
+ *
+ * 5 (bus): The abstract command failed due to a bus error (e.g.\
+ * alignment, access size, or timeout).
+ *
+ * 6: Reserved for future use.
+ *
+ * 7 (other): The command failed for another reason.
+ */
+#define DM_ABSTRACTCS_CMDERR_OFFSET         8
+#define DM_ABSTRACTCS_CMDERR_LENGTH         3
+#define DM_ABSTRACTCS_CMDERR                (0x7U << DM_ABSTRACTCS_CMDERR_OFFSET)
+/*
+ * Number of {\tt data} registers that are implemented as part of the
+ * abstract command interface. Valid sizes are 1 -- 12.
+ */
+#define DM_ABSTRACTCS_DATACOUNT_OFFSET      0
+#define DM_ABSTRACTCS_DATACOUNT_LENGTH      4
+#define DM_ABSTRACTCS_DATACOUNT             (0xfU << DM_ABSTRACTCS_DATACOUNT_OFFSET)
+#define DM_COMMAND                          0x17
+/*
+ * The type determines the overall functionality of this
+ * abstract command.
+ */
+#define DM_COMMAND_CMDTYPE_OFFSET           24
+#define DM_COMMAND_CMDTYPE_LENGTH           8
+#define DM_COMMAND_CMDTYPE                  (0xffU << DM_COMMAND_CMDTYPE_OFFSET)
+/*
+ * This field is interpreted in a command-specific manner,
+ * described for each abstract command.
+ */
+#define DM_COMMAND_CONTROL_OFFSET           0
+#define DM_COMMAND_CONTROL_LENGTH           24
+#define DM_COMMAND_CONTROL                  (0xffffffU << DM_COMMAND_CONTROL_OFFSET)
+#define DM_ABSTRACTAUTO                     0x18
+/*
+ * When a bit in this field is 1, read or write accesses to the
+ * corresponding {\tt progbuf} word cause the command in \RdmCommand to
+ * be executed again.
+ */
+#define DM_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 16
+#define DM_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 16
+#define DM_ABSTRACTAUTO_AUTOEXECPROGBUF     (0xffffU << DM_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET)
+/*
+ * When a bit in this field is 1, read or write accesses to the
+ * corresponding {\tt data} word cause the command in \RdmCommand to be
+ * executed again.
+ */
+#define DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0
+#define DM_ABSTRACTAUTO_AUTOEXECDATA_LENGTH 12
+#define DM_ABSTRACTAUTO_AUTOEXECDATA        (0xfffU << DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET)
+#define DM_CONFSTRPTR0                      0x19
+#define DM_CONFSTRPTR0_ADDR_OFFSET          0
+#define DM_CONFSTRPTR0_ADDR_LENGTH          32
+#define DM_CONFSTRPTR0_ADDR                 (0xffffffffU << DM_CONFSTRPTR0_ADDR_OFFSET)
+#define DM_CONFSTRPTR1                      0x1a
+#define DM_CONFSTRPTR1_ADDR_OFFSET          0
+#define DM_CONFSTRPTR1_ADDR_LENGTH          32
+#define DM_CONFSTRPTR1_ADDR                 (0xffffffffU << DM_CONFSTRPTR1_ADDR_OFFSET)
+#define DM_CONFSTRPTR2                      0x1b
+#define DM_CONFSTRPTR2_ADDR_OFFSET          0
+#define DM_CONFSTRPTR2_ADDR_LENGTH          32
+#define DM_CONFSTRPTR2_ADDR                 (0xffffffffU << DM_CONFSTRPTR2_ADDR_OFFSET)
+#define DM_CONFSTRPTR3                      0x1c
+#define DM_CONFSTRPTR3_ADDR_OFFSET          0
+#define DM_CONFSTRPTR3_ADDR_LENGTH          32
+#define DM_CONFSTRPTR3_ADDR                 (0xffffffffU << DM_CONFSTRPTR3_ADDR_OFFSET)
+#define DM_NEXTDM                           0x1d
+#define DM_NEXTDM_ADDR_OFFSET               0
+#define DM_NEXTDM_ADDR_LENGTH               32
+#define DM_NEXTDM_ADDR                      (0xffffffffU << DM_NEXTDM_ADDR_OFFSET)
+#define DM_DATA0                            0x04
+#define DM_DATA0_DATA_OFFSET                0
+#define DM_DATA0_DATA_LENGTH                32
+#define DM_DATA0_DATA                       (0xffffffffU << DM_DATA0_DATA_OFFSET)
+#define DM_DATA11                           0x0f
+#define DM_PROGBUF0                         0x20
+#define DM_PROGBUF0_DATA_OFFSET             0
+#define DM_PROGBUF0_DATA_LENGTH             32
+#define DM_PROGBUF0_DATA                    (0xffffffffU << DM_PROGBUF0_DATA_OFFSET)
+#define DM_PROGBUF15                        0x2f
+#define DM_AUTHDATA                         0x30
+#define DM_AUTHDATA_DATA_OFFSET             0
+#define DM_AUTHDATA_DATA_LENGTH             32
+#define DM_AUTHDATA_DATA                    (0xffffffffU << DM_AUTHDATA_DATA_OFFSET)
+#define DM_DMCS2                            0x32
+/*
+ * 0: The remaining fields in this register configure halt groups.
+ *
+ * 1: The remaining fields in this register configure resume groups.
+ */
+#define DM_DMCS2_GROUPTYPE_OFFSET           11
+#define DM_DMCS2_GROUPTYPE_LENGTH           1
+#define DM_DMCS2_GROUPTYPE                  (0x1U << DM_DMCS2_GROUPTYPE_OFFSET)
+/*
+ * This field contains the currently selected external trigger.
+ *
+ * If a non-existent trigger value is written here, the hardware will
+ * change it to a valid one or 0 if no external triggers exist.
+ */
+#define DM_DMCS2_EXTTRIGGER_OFFSET          7
+#define DM_DMCS2_EXTTRIGGER_LENGTH          4
+#define DM_DMCS2_EXTTRIGGER                 (0xfU << DM_DMCS2_EXTTRIGGER_OFFSET)
+/*
+ * When \FdmDmcsTwoHgselect is 0, contains the group of the hart
+ * specified by \Fhartsel.
+ *
+ * When \FdmDmcsTwoHgselect is 1, contains the group of the external
+ * trigger selected by \FdmDmcsTwoExttrigger.
+ *
+ * Writes only have an effect if \FdmDmcsTwoHgwrite is also written 1.
+ *
+ * Group numbers are contiguous starting at 0, with the highest number
+ * being implementation-dependent, and possibly different between
+ * different group types. Debuggers should read back this field after
+ * writing to confirm they are using a hart group that is supported.
+ *
+ * If groups aren't implemented, then this entire field is 0.
+ */
+#define DM_DMCS2_GROUP_OFFSET               2
+#define DM_DMCS2_GROUP_LENGTH               5
+#define DM_DMCS2_GROUP                      (0x1fU << DM_DMCS2_GROUP_OFFSET)
+/*
+ * When \FdmDmcsTwoHgselect is 0, writing 1 changes the group of all
+ * selected harts to the value written to \FdmDmcsTwoGroup.
+ *
+ * When 1 is written and \FdmDmcsTwoHgselect is 0, for every selected
+ * hart the DM will change its group to the value written to \FdmDmcsTwoGroup,
+ * if the hardware supports that group for that hart.
+ *
+ * When 1 is written and \FdmDmcsTwoHgselect is 1, the DM will change
+ * the group of the external trigger selected by \FdmDmcsTwoExttrigger
+ * to the value written to \FdmDmcsTwoGroup, if the hardware supports
+ * that group for that trigger.
+ *
+ * Writing 0 has no effect.
+ */
+#define DM_DMCS2_HGWRITE_OFFSET             1
+#define DM_DMCS2_HGWRITE_LENGTH             1
+#define DM_DMCS2_HGWRITE                    (0x1U << DM_DMCS2_HGWRITE_OFFSET)
+/*
+ * 0: Operate on harts.
+ *
+ * 1: Operate on external triggers.
+ *
+ * If there are no external triggers, this field must be tied to 0.
+ */
+#define DM_DMCS2_HGSELECT_OFFSET            0
+#define DM_DMCS2_HGSELECT_LENGTH            1
+#define DM_DMCS2_HGSELECT                   (0x1U << DM_DMCS2_HGSELECT_OFFSET)
+#define DM_HALTSUM0                         0x40
+#define DM_HALTSUM0_HALTSUM0_OFFSET         0
+#define DM_HALTSUM0_HALTSUM0_LENGTH         32
+#define DM_HALTSUM0_HALTSUM0                (0xffffffffU << DM_HALTSUM0_HALTSUM0_OFFSET)
+#define DM_HALTSUM1                         0x13
+#define DM_HALTSUM1_HALTSUM1_OFFSET         0
+#define DM_HALTSUM1_HALTSUM1_LENGTH         32
+#define DM_HALTSUM1_HALTSUM1                (0xffffffffU << DM_HALTSUM1_HALTSUM1_OFFSET)
+#define DM_HALTSUM2                         0x34
+#define DM_HALTSUM2_HALTSUM2_OFFSET         0
+#define DM_HALTSUM2_HALTSUM2_LENGTH         32
+#define DM_HALTSUM2_HALTSUM2                (0xffffffffU << DM_HALTSUM2_HALTSUM2_OFFSET)
+#define DM_HALTSUM3                         0x35
+#define DM_HALTSUM3_HALTSUM3_OFFSET         0
+#define DM_HALTSUM3_HALTSUM3_LENGTH         32
+#define DM_HALTSUM3_HALTSUM3                (0xffffffffU << DM_HALTSUM3_HALTSUM3_OFFSET)
+#define DM_SBCS                             0x38
+/*
+ * 0: The System Bus interface conforms to mainline drafts of this
+ * spec older than 1 January, 2018.
+ *
+ * 1: The System Bus interface conforms to this version of the spec.
+ *
+ * Other values are reserved for future versions.
+ */
+#define DM_SBCS_SBVERSION_OFFSET            29
+#define DM_SBCS_SBVERSION_LENGTH            3
+#define DM_SBCS_SBVERSION                   (0x7U << DM_SBCS_SBVERSION_OFFSET)
+/*
+ * Set when the debugger attempts to read data while a read is in
+ * progress, or when the debugger initiates a new access while one is
+ * already in progress (while \FdmSbcsSbbusy is set). It remains set until
+ * it's explicitly cleared by the debugger.
+ *
+ * While this field is set, no more system bus accesses can be
+ * initiated by the Debug Module.
+ */
+#define DM_SBCS_SBBUSYERROR_OFFSET          22
+#define DM_SBCS_SBBUSYERROR_LENGTH          1
+#define DM_SBCS_SBBUSYERROR                 (0x1U << DM_SBCS_SBBUSYERROR_OFFSET)
+/*
+ * When 1, indicates the system bus master is busy. (Whether the
+ * system bus itself is busy is related, but not the same thing.) This
+ * bit goes high immediately when a read or write is requested for any
+ * reason, and does not go low until the access is fully completed.
+ *
+ * Writes to \RdmSbcs while \FdmSbcsSbbusy is high result in undefined
+ * behavior.  A debugger must not write to \RdmSbcs until it reads
+ * \FdmSbcsSbbusy as 0.
+ */
+#define DM_SBCS_SBBUSY_OFFSET               21
+#define DM_SBCS_SBBUSY_LENGTH               1
+#define DM_SBCS_SBBUSY                      (0x1U << DM_SBCS_SBBUSY_OFFSET)
+/*
+ * When 1, every write to \RdmSbaddressZero automatically triggers a
+ * system bus read at the new address.
+ */
+#define DM_SBCS_SBREADONADDR_OFFSET         20
+#define DM_SBCS_SBREADONADDR_LENGTH         1
+#define DM_SBCS_SBREADONADDR                (0x1U << DM_SBCS_SBREADONADDR_OFFSET)
+/*
+ * Select the access size to use for system bus accesses.
+ *
+ * 0: 8-bit
+ *
+ * 1: 16-bit
+ *
+ * 2: 32-bit
+ *
+ * 3: 64-bit
+ *
+ * 4: 128-bit
+ *
+ * If \FdmSbcsSbaccess has an unsupported value when the DM starts a bus
+ * access, the access is not performed and \FdmSbcsSberror is set to 4.
+ */
+#define DM_SBCS_SBACCESS_OFFSET             17
+#define DM_SBCS_SBACCESS_LENGTH             3
+#define DM_SBCS_SBACCESS                    (0x7U << DM_SBCS_SBACCESS_OFFSET)
+/*
+ * When 1, {\tt sbaddress} is incremented by the access size (in
+ * bytes) selected in \FdmSbcsSbaccess after every system bus access.
+ */
+#define DM_SBCS_SBAUTOINCREMENT_OFFSET      16
+#define DM_SBCS_SBAUTOINCREMENT_LENGTH      1
+#define DM_SBCS_SBAUTOINCREMENT             (0x1U << DM_SBCS_SBAUTOINCREMENT_OFFSET)
+/*
+ * When 1, every read from \RdmSbdataZero automatically triggers a
+ * system bus read at the (possibly auto-incremented) address.
+ */
+#define DM_SBCS_SBREADONDATA_OFFSET         15
+#define DM_SBCS_SBREADONDATA_LENGTH         1
+#define DM_SBCS_SBREADONDATA                (0x1U << DM_SBCS_SBREADONDATA_OFFSET)
+/*
+ * When the Debug Module's system bus
+ * master encounters an error, this field gets set. The bits in this
+ * field remain set until they are cleared by writing 1 to them.
+ * While this field is non-zero, no more system bus accesses can be
+ * initiated by the Debug Module.
+ *
+ * An implementation may report ``Other'' (7) for any error condition.
+ *
+ * 0: There was no bus error.
+ *
+ * 1: There was a timeout.
+ *
+ * 2: A bad address was accessed.
+ *
+ * 3: There was an alignment error.
+ *
+ * 4: An access of unsupported size was requested.
+ *
+ * 7: Other.
+ */
+#define DM_SBCS_SBERROR_OFFSET              12
+#define DM_SBCS_SBERROR_LENGTH              3
+#define DM_SBCS_SBERROR                     (0x7U << DM_SBCS_SBERROR_OFFSET)
+/*
+ * Width of system bus addresses in bits. (0 indicates there is no bus
+ * access support.)
+ */
+#define DM_SBCS_SBASIZE_OFFSET              5
+#define DM_SBCS_SBASIZE_LENGTH              7
+#define DM_SBCS_SBASIZE                     (0x7fU << DM_SBCS_SBASIZE_OFFSET)
+/*
+ * 1 when 128-bit system bus accesses are supported.
+ */
+#define DM_SBCS_SBACCESS128_OFFSET          4
+#define DM_SBCS_SBACCESS128_LENGTH          1
+#define DM_SBCS_SBACCESS128                 (0x1U << DM_SBCS_SBACCESS128_OFFSET)
+/*
+ * 1 when 64-bit system bus accesses are supported.
+ */
+#define DM_SBCS_SBACCESS64_OFFSET           3
+#define DM_SBCS_SBACCESS64_LENGTH           1
+#define DM_SBCS_SBACCESS64                  (0x1U << DM_SBCS_SBACCESS64_OFFSET)
+/*
+ * 1 when 32-bit system bus accesses are supported.
+ */
+#define DM_SBCS_SBACCESS32_OFFSET           2
+#define DM_SBCS_SBACCESS32_LENGTH           1
+#define DM_SBCS_SBACCESS32                  (0x1U << DM_SBCS_SBACCESS32_OFFSET)
+/*
+ * 1 when 16-bit system bus accesses are supported.
+ */
+#define DM_SBCS_SBACCESS16_OFFSET           1
+#define DM_SBCS_SBACCESS16_LENGTH           1
+#define DM_SBCS_SBACCESS16                  (0x1U << DM_SBCS_SBACCESS16_OFFSET)
+/*
+ * 1 when 8-bit system bus accesses are supported.
+ */
+#define DM_SBCS_SBACCESS8_OFFSET            0
+#define DM_SBCS_SBACCESS8_LENGTH            1
+#define DM_SBCS_SBACCESS8                   (0x1U << DM_SBCS_SBACCESS8_OFFSET)
+#define DM_SBADDRESS0                       0x39
+/*
+ * Accesses bits 31:0 of the physical address in {\tt sbaddress}.
+ */
+#define DM_SBADDRESS0_ADDRESS_OFFSET        0
+#define DM_SBADDRESS0_ADDRESS_LENGTH        32
+#define DM_SBADDRESS0_ADDRESS               (0xffffffffU << DM_SBADDRESS0_ADDRESS_OFFSET)
+#define DM_SBADDRESS1                       0x3a
+/*
+ * Accesses bits 63:32 of the physical address in {\tt sbaddress} (if
+ * the system address bus is that wide).
+ */
+#define DM_SBADDRESS1_ADDRESS_OFFSET        0
+#define DM_SBADDRESS1_ADDRESS_LENGTH        32
+#define DM_SBADDRESS1_ADDRESS               (0xffffffffU << DM_SBADDRESS1_ADDRESS_OFFSET)
+#define DM_SBADDRESS2                       0x3b
+/*
+ * Accesses bits 95:64 of the physical address in {\tt sbaddress} (if
+ * the system address bus is that wide).
+ */
+#define DM_SBADDRESS2_ADDRESS_OFFSET        0
+#define DM_SBADDRESS2_ADDRESS_LENGTH        32
+#define DM_SBADDRESS2_ADDRESS               (0xffffffffU << DM_SBADDRESS2_ADDRESS_OFFSET)
+#define DM_SBADDRESS3                       0x37
+/*
+ * Accesses bits 127:96 of the physical address in {\tt sbaddress} (if
+ * the system address bus is that wide).
+ */
+#define DM_SBADDRESS3_ADDRESS_OFFSET        0
+#define DM_SBADDRESS3_ADDRESS_LENGTH        32
+#define DM_SBADDRESS3_ADDRESS               (0xffffffffU << DM_SBADDRESS3_ADDRESS_OFFSET)
+#define DM_SBDATA0                          0x3c
+/*
+ * Accesses bits 31:0 of {\tt sbdata}.
+ */
+#define DM_SBDATA0_DATA_OFFSET              0
+#define DM_SBDATA0_DATA_LENGTH              32
+#define DM_SBDATA0_DATA                     (0xffffffffU << DM_SBDATA0_DATA_OFFSET)
+#define DM_SBDATA1                          0x3d
+/*
+ * Accesses bits 63:32 of {\tt sbdata} (if the system bus is that
+ * wide).
+ */
+#define DM_SBDATA1_DATA_OFFSET              0
+#define DM_SBDATA1_DATA_LENGTH              32
+#define DM_SBDATA1_DATA                     (0xffffffffU << DM_SBDATA1_DATA_OFFSET)
+#define DM_SBDATA2                          0x3e
 /*
-* This field is 1 when all currently selected harts are unavailable.
+ * Accesses bits 95:64 of {\tt sbdata} (if the system bus is that
+ * wide).
  */
-#define DMI_DMSTATUS_ALLUNAVAIL_OFFSET      13
-#define DMI_DMSTATUS_ALLUNAVAIL_LENGTH      1
-#define DMI_DMSTATUS_ALLUNAVAIL             (0x1U << DMI_DMSTATUS_ALLUNAVAIL_OFFSET)
+#define DM_SBDATA2_DATA_OFFSET              0
+#define DM_SBDATA2_DATA_LENGTH              32
+#define DM_SBDATA2_DATA                     (0xffffffffU << DM_SBDATA2_DATA_OFFSET)
+#define DM_SBDATA3                          0x3f
 /*
-* This field is 1 when any currently selected hart is unavailable.
+ * Accesses bits 127:96 of {\tt sbdata} (if the system bus is that
+ * wide).
  */
-#define DMI_DMSTATUS_ANYUNAVAIL_OFFSET      12
-#define DMI_DMSTATUS_ANYUNAVAIL_LENGTH      1
-#define DMI_DMSTATUS_ANYUNAVAIL             (0x1U << DMI_DMSTATUS_ANYUNAVAIL_OFFSET)
-/*
-* This field is 1 when all currently selected harts are running.
- */
-#define DMI_DMSTATUS_ALLRUNNING_OFFSET      11
-#define DMI_DMSTATUS_ALLRUNNING_LENGTH      1
-#define DMI_DMSTATUS_ALLRUNNING             (0x1U << DMI_DMSTATUS_ALLRUNNING_OFFSET)
-/*
-* This field is 1 when any currently selected hart is running.
- */
-#define DMI_DMSTATUS_ANYRUNNING_OFFSET      10
-#define DMI_DMSTATUS_ANYRUNNING_LENGTH      1
-#define DMI_DMSTATUS_ANYRUNNING             (0x1U << DMI_DMSTATUS_ANYRUNNING_OFFSET)
-/*
-* This field is 1 when all currently selected harts are halted.
- */
-#define DMI_DMSTATUS_ALLHALTED_OFFSET       9
-#define DMI_DMSTATUS_ALLHALTED_LENGTH       1
-#define DMI_DMSTATUS_ALLHALTED              (0x1U << DMI_DMSTATUS_ALLHALTED_OFFSET)
-/*
-* This field is 1 when any currently selected hart is halted.
- */
-#define DMI_DMSTATUS_ANYHALTED_OFFSET       8
-#define DMI_DMSTATUS_ANYHALTED_LENGTH       1
-#define DMI_DMSTATUS_ANYHALTED              (0x1U << DMI_DMSTATUS_ANYHALTED_OFFSET)
-/*
-* 0 when authentication is required before using the DM.  1 when the
-* authentication check has passed. On components that don't implement
-* authentication, this bit must be preset as 1.
- */
-#define DMI_DMSTATUS_AUTHENTICATED_OFFSET   7
-#define DMI_DMSTATUS_AUTHENTICATED_LENGTH   1
-#define DMI_DMSTATUS_AUTHENTICATED          (0x1U << DMI_DMSTATUS_AUTHENTICATED_OFFSET)
-/*
-* 0: The authentication module is ready to process the next
-* read/write to \Rauthdata.
-*
-* 1: The authentication module is busy. Accessing \Rauthdata results
-* in unspecified behavior.
-*
-* \Fauthbusy only becomes set in immediate response to an access to
-* \Rauthdata.
- */
-#define DMI_DMSTATUS_AUTHBUSY_OFFSET        6
-#define DMI_DMSTATUS_AUTHBUSY_LENGTH        1
-#define DMI_DMSTATUS_AUTHBUSY               (0x1U << DMI_DMSTATUS_AUTHBUSY_OFFSET)
-/*
-* 1 if this Debug Module supports halt-on-reset functionality
-* controllable by the \Fsetresethaltreq and \Fclrresethaltreq bits.
-* 0 otherwise.
- */
-#define DMI_DMSTATUS_HASRESETHALTREQ_OFFSET 5
-#define DMI_DMSTATUS_HASRESETHALTREQ_LENGTH 1
-#define DMI_DMSTATUS_HASRESETHALTREQ        (0x1U << DMI_DMSTATUS_HASRESETHALTREQ_OFFSET)
-/*
-* 0: \Rdevtreeaddrzero--\Rdevtreeaddrthree hold information which
-* is not relevant to the Device Tree.
-*
-* 1: \Rdevtreeaddrzero--\Rdevtreeaddrthree registers hold the address of the
-* Device Tree.
- */
-#define DMI_DMSTATUS_DEVTREEVALID_OFFSET    4
-#define DMI_DMSTATUS_DEVTREEVALID_LENGTH    1
-#define DMI_DMSTATUS_DEVTREEVALID           (0x1U << DMI_DMSTATUS_DEVTREEVALID_OFFSET)
-/*
-* 0: There is no Debug Module present.
-*
-* 1: There is a Debug Module and it conforms to version 0.11 of this
-* specification.
-*
-* 2: There is a Debug Module and it conforms to version 0.13 of this
-* specification.
-*
-* 15: There is a Debug Module but it does not conform to any
-* available version of this spec.
- */
-#define DMI_DMSTATUS_VERSION_OFFSET         0
-#define DMI_DMSTATUS_VERSION_LENGTH         4
-#define DMI_DMSTATUS_VERSION                (0xfU << DMI_DMSTATUS_VERSION_OFFSET)
-#define DMI_DMCONTROL                       0x10
-/*
-* Writes the halt request bit for all currently selected harts.
-* When set to 1, each selected hart will halt if it is not currently
-* halted.
-*
-* Writing 1 or 0 has no effect on a hart which is already halted, but
-* the bit must be cleared to 0 before the hart is resumed.
-*
-* Writes apply to the new value of \Fhartsel and \Fhasel.
- */
-#define DMI_DMCONTROL_HALTREQ_OFFSET        31
-#define DMI_DMCONTROL_HALTREQ_LENGTH        1
-#define DMI_DMCONTROL_HALTREQ               (0x1U << DMI_DMCONTROL_HALTREQ_OFFSET)
-/*
-* Writes the resume request bit for all currently selected harts.
-* When set to 1, each selected hart will resume if it is currently
-* halted.
-*
-* The resume request bit is ignored while the halt request bit is
-* set.
-*
-* Writes apply to the new value of \Fhartsel and \Fhasel.
- */
-#define DMI_DMCONTROL_RESUMEREQ_OFFSET      30
-#define DMI_DMCONTROL_RESUMEREQ_LENGTH      1
-#define DMI_DMCONTROL_RESUMEREQ             (0x1U << DMI_DMCONTROL_RESUMEREQ_OFFSET)
-/*
-* This optional field writes the reset bit for all the currently
-* selected harts.  To perform a reset the debugger writes 1, and then
-* writes 0 to deassert the reset signal.
-*
-* If this feature is not implemented, the bit always stays 0, so
-* after writing 1 the debugger can read the register back to see if
-* the feature is supported.
-*
-* Writes apply to the new value of \Fhartsel and \Fhasel.
- */
-#define DMI_DMCONTROL_HARTRESET_OFFSET      29
-#define DMI_DMCONTROL_HARTRESET_LENGTH      1
-#define DMI_DMCONTROL_HARTRESET             (0x1U << DMI_DMCONTROL_HARTRESET_OFFSET)
-/*
-* Writing 1 to this bit clears the {\tt havereset} bits for
-* any selected harts.
-*
-* Writes apply to the new value of \Fhartsel and \Fhasel.
- */
-#define DMI_DMCONTROL_ACKHAVERESET_OFFSET   28
-#define DMI_DMCONTROL_ACKHAVERESET_LENGTH   1
-#define DMI_DMCONTROL_ACKHAVERESET          (0x1U << DMI_DMCONTROL_ACKHAVERESET_OFFSET)
-/*
-* Selects the  definition of currently selected harts.
-*
-* 0: There is a single currently selected hart, that selected by \Fhartsel.
-*
-* 1: There may be multiple currently selected harts -- that selected by \Fhartsel,
-* plus those selected by the hart array mask register.
-*
-* An implementation which does not implement the hart array mask register
-* must tie this field to 0. A debugger which wishes to use the hart array
-* mask register feature should set this bit and read back to see if the functionality
-* is supported.
- */
-#define DMI_DMCONTROL_HASEL_OFFSET          26
-#define DMI_DMCONTROL_HASEL_LENGTH          1
-#define DMI_DMCONTROL_HASEL                 (0x1U << DMI_DMCONTROL_HASEL_OFFSET)
-/*
-* The low 10 bits of \Fhartsel: the DM-specific index of the hart to
-* select. This hart is always part of the currently selected harts.
- */
-#define DMI_DMCONTROL_HARTSELLO_OFFSET      16
-#define DMI_DMCONTROL_HARTSELLO_LENGTH      10
-#define DMI_DMCONTROL_HARTSELLO             (0x3ffU << DMI_DMCONTROL_HARTSELLO_OFFSET)
-/*
-* The high 10 bits of \Fhartsel: the DM-specific index of the hart to
-* select. This hart is always part of the currently selected harts.
- */
-#define DMI_DMCONTROL_HARTSELHI_OFFSET      6
-#define DMI_DMCONTROL_HARTSELHI_LENGTH      10
-#define DMI_DMCONTROL_HARTSELHI             (0x3ffU << DMI_DMCONTROL_HARTSELHI_OFFSET)
-/*
-* This optional field writes the halt-on-reset request bit for all
-* currently selected harts.
-* When set to 1, each selected hart will halt upon the next deassertion
-* of its reset. The halt-on-reset request bit is not automatically
-* cleared. The debugger must write to \Fclrresethaltreq to clear it.
-*
-* Writes apply to the new value of \Fhartsel and \Fhasel.
-*
-* If \Fhasresethaltreq is 0, this field is not implemented.
- */
-#define DMI_DMCONTROL_SETRESETHALTREQ_OFFSET 3
-#define DMI_DMCONTROL_SETRESETHALTREQ_LENGTH 1
-#define DMI_DMCONTROL_SETRESETHALTREQ       (0x1U << DMI_DMCONTROL_SETRESETHALTREQ_OFFSET)
-/*
-* This optional field clears the halt-on-reset request bit for all
-* currently selected harts.
-*
-* Writes apply to the new value of \Fhartsel and \Fhasel.
- */
-#define DMI_DMCONTROL_CLRRESETHALTREQ_OFFSET 2
-#define DMI_DMCONTROL_CLRRESETHALTREQ_LENGTH 1
-#define DMI_DMCONTROL_CLRRESETHALTREQ       (0x1U << DMI_DMCONTROL_CLRRESETHALTREQ_OFFSET)
-/*
-* This bit controls the reset signal from the DM to the rest of the
-* system. The signal should reset every part of the system, including
-* every hart, except for the DM and any logic required to access the
-* DM.
-* To perform a system reset the debugger writes 1,
-* and then writes 0
-* to deassert the reset.
- */
-#define DMI_DMCONTROL_NDMRESET_OFFSET       1
-#define DMI_DMCONTROL_NDMRESET_LENGTH       1
-#define DMI_DMCONTROL_NDMRESET              (0x1U << DMI_DMCONTROL_NDMRESET_OFFSET)
-/*
-* This bit serves as a reset signal for the Debug Module itself.
-*
-* 0: The module's state, including authentication mechanism,
-* takes its reset values (the \Fdmactive bit is the only bit which can
-* be written to something other than its reset value).
-*
-* 1: The module functions normally.
-*
-* No other mechanism should exist that may result in resetting the
-* Debug Module after power up, including the platform's system reset
-* or Debug Transport reset signals.
-*
-* A debugger may pulse this bit low to get the Debug Module into a
-* known state.
-*
-* Implementations may use this bit to aid debugging, for example by
-* preventing the Debug Module from being power gated while debugging
-* is active.
- */
-#define DMI_DMCONTROL_DMACTIVE_OFFSET       0
-#define DMI_DMCONTROL_DMACTIVE_LENGTH       1
-#define DMI_DMCONTROL_DMACTIVE              (0x1U << DMI_DMCONTROL_DMACTIVE_OFFSET)
-#define DMI_HARTINFO                        0x12
-/*
-* Number of {\tt dscratch} registers available for the debugger
-* to use during program buffer execution, starting from \Rdscratchzero.
-* The debugger can make no assumptions about the contents of these
-* registers between commands.
- */
-#define DMI_HARTINFO_NSCRATCH_OFFSET        20
-#define DMI_HARTINFO_NSCRATCH_LENGTH        4
-#define DMI_HARTINFO_NSCRATCH               (0xfU << DMI_HARTINFO_NSCRATCH_OFFSET)
-/*
-* 0: The {\tt data} registers are shadowed in the hart by CSR
-* registers. Each CSR register is MXLEN bits in size, and corresponds
-* to a single argument, per Table~\ref{tab:datareg}.
-*
-* 1: The {\tt data} registers are shadowed in the hart's memory map.
-* Each register takes up 4 bytes in the memory map.
- */
-#define DMI_HARTINFO_DATAACCESS_OFFSET      16
-#define DMI_HARTINFO_DATAACCESS_LENGTH      1
-#define DMI_HARTINFO_DATAACCESS             (0x1U << DMI_HARTINFO_DATAACCESS_OFFSET)
-/*
-* If \Fdataaccess is 0: Number of CSR registers dedicated to
-* shadowing the {\tt data} registers.
-*
-* If \Fdataaccess is 1: Number of 32-bit words in the memory map
-* dedicated to shadowing the {\tt data} registers.
-*
-* Since there are at most 12 {\tt data} registers, the value in this
-* register must be 12 or smaller.
- */
-#define DMI_HARTINFO_DATASIZE_OFFSET        12
-#define DMI_HARTINFO_DATASIZE_LENGTH        4
-#define DMI_HARTINFO_DATASIZE               (0xfU << DMI_HARTINFO_DATASIZE_OFFSET)
-/*
-* If \Fdataaccess is 0: The number of the first CSR dedicated to
-* shadowing the {\tt data} registers.
-*
-* If \Fdataaccess is 1: Signed address of RAM where the {\tt data}
-* registers are shadowed, to be used to access relative to \Rzero.
- */
-#define DMI_HARTINFO_DATAADDR_OFFSET        0
-#define DMI_HARTINFO_DATAADDR_LENGTH        12
-#define DMI_HARTINFO_DATAADDR               (0xfffU << DMI_HARTINFO_DATAADDR_OFFSET)
-#define DMI_HAWINDOWSEL                     0x14
-/*
-* The high bits of this field may be tied to 0, depending on how large
-* the array mask register is.  Eg. on a system with 48 harts only bit 0
-* of this field may actually be writable.
- */
-#define DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET  0
-#define DMI_HAWINDOWSEL_HAWINDOWSEL_LENGTH  15
-#define DMI_HAWINDOWSEL_HAWINDOWSEL         (0x7fffU << DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET)
-#define DMI_HAWINDOW                        0x15
-#define DMI_HAWINDOW_MASKDATA_OFFSET        0
-#define DMI_HAWINDOW_MASKDATA_LENGTH        32
-#define DMI_HAWINDOW_MASKDATA               (0xffffffffU << DMI_HAWINDOW_MASKDATA_OFFSET)
-#define DMI_ABSTRACTCS                      0x16
-/*
-* Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16.
- */
-#define DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET   24
-#define DMI_ABSTRACTCS_PROGBUFSIZE_LENGTH   5
-#define DMI_ABSTRACTCS_PROGBUFSIZE          (0x1fU << DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET)
-/*
-* 1: An abstract command is currently being executed.
-*
-* This bit is set as soon as \Rcommand is written, and is
-* not cleared until that command has completed.
- */
-#define DMI_ABSTRACTCS_BUSY_OFFSET          12
-#define DMI_ABSTRACTCS_BUSY_LENGTH          1
-#define DMI_ABSTRACTCS_BUSY                 (0x1U << DMI_ABSTRACTCS_BUSY_OFFSET)
-/*
-* Gets set if an abstract command fails. The bits in this field remain set until
-* they are cleared by writing 1 to them. No abstract command is
-* started until the value is reset to 0.
-*
-* 0 (none): No error.
-*
-* 1 (busy): An abstract command was executing while \Rcommand,
-* \Rabstractcs, \Rabstractauto was written, or when one
-* of the {\tt data} or {\tt progbuf} registers was read or written.
-*
-* 2 (not supported): The requested command is not supported,
-* regardless of whether the hart is running or not.
-*
-* 3 (exception): An exception occurred while executing the command
-* (eg. while executing the Program Buffer).
-*
-* 4 (halt/resume): The abstract command couldn't execute because the
-* hart wasn't in the required state (running/halted).
-*
-* 7 (other): The command failed for another reason.
- */
-#define DMI_ABSTRACTCS_CMDERR_OFFSET        8
-#define DMI_ABSTRACTCS_CMDERR_LENGTH        3
-#define DMI_ABSTRACTCS_CMDERR               (0x7U << DMI_ABSTRACTCS_CMDERR_OFFSET)
-/*
-* Number of {\tt data} registers that are implemented as part of the
-* abstract command interface. Valid sizes are 0 - 12.
- */
-#define DMI_ABSTRACTCS_DATACOUNT_OFFSET     0
-#define DMI_ABSTRACTCS_DATACOUNT_LENGTH     4
-#define DMI_ABSTRACTCS_DATACOUNT            (0xfU << DMI_ABSTRACTCS_DATACOUNT_OFFSET)
-#define DMI_COMMAND                         0x17
-/*
-* The type determines the overall functionality of this
-* abstract command.
- */
-#define DMI_COMMAND_CMDTYPE_OFFSET          24
-#define DMI_COMMAND_CMDTYPE_LENGTH          8
-#define DMI_COMMAND_CMDTYPE                 (0xffU << DMI_COMMAND_CMDTYPE_OFFSET)
-/*
-* This field is interpreted in a command-specific manner,
-* described for each abstract command.
- */
-#define DMI_COMMAND_CONTROL_OFFSET          0
-#define DMI_COMMAND_CONTROL_LENGTH          24
-#define DMI_COMMAND_CONTROL                 (0xffffffU << DMI_COMMAND_CONTROL_OFFSET)
-#define DMI_ABSTRACTAUTO                    0x18
-/*
-* When a bit in this field is 1, read or write accesses to the corresponding {\tt progbuf} word
-* cause the command in \Rcommand to be executed again.
- */
-#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 16
-#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 16
-#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF    (0xffffU << DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET)
-/*
-* When a bit in this field is 1, read or write accesses to the corresponding {\tt data} word
-* cause the command in \Rcommand to be executed again.
- */
-#define DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0
-#define DMI_ABSTRACTAUTO_AUTOEXECDATA_LENGTH 12
-#define DMI_ABSTRACTAUTO_AUTOEXECDATA       (0xfffU << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET)
-#define DMI_DEVTREEADDR0                    0x19
-#define DMI_DEVTREEADDR0_ADDR_OFFSET        0
-#define DMI_DEVTREEADDR0_ADDR_LENGTH        32
-#define DMI_DEVTREEADDR0_ADDR               (0xffffffffU << DMI_DEVTREEADDR0_ADDR_OFFSET)
-#define DMI_DEVTREEADDR1                    0x1a
-#define DMI_DEVTREEADDR2                    0x1b
-#define DMI_DEVTREEADDR3                    0x1c
-#define DMI_NEXTDM                          0x1d
-#define DMI_NEXTDM_ADDR_OFFSET              0
-#define DMI_NEXTDM_ADDR_LENGTH              32
-#define DMI_NEXTDM_ADDR                     (0xffffffffU << DMI_NEXTDM_ADDR_OFFSET)
-#define DMI_DATA0                           0x04
-#define DMI_DATA0_DATA_OFFSET               0
-#define DMI_DATA0_DATA_LENGTH               32
-#define DMI_DATA0_DATA                      (0xffffffffU << DMI_DATA0_DATA_OFFSET)
-#define DMI_DATA11                          0x0f
-#define DMI_PROGBUF0                        0x20
-#define DMI_PROGBUF0_DATA_OFFSET            0
-#define DMI_PROGBUF0_DATA_LENGTH            32
-#define DMI_PROGBUF0_DATA                   (0xffffffffU << DMI_PROGBUF0_DATA_OFFSET)
-#define DMI_PROGBUF15                       0x2f
-#define DMI_AUTHDATA                        0x30
-#define DMI_AUTHDATA_DATA_OFFSET            0
-#define DMI_AUTHDATA_DATA_LENGTH            32
-#define DMI_AUTHDATA_DATA                   (0xffffffffU << DMI_AUTHDATA_DATA_OFFSET)
-#define DMI_HALTSUM0                        0x40
-#define DMI_HALTSUM0_HALTSUM0_OFFSET        0
-#define DMI_HALTSUM0_HALTSUM0_LENGTH        32
-#define DMI_HALTSUM0_HALTSUM0               (0xffffffffU << DMI_HALTSUM0_HALTSUM0_OFFSET)
-#define DMI_HALTSUM1                        0x13
-#define DMI_HALTSUM1_HALTSUM1_OFFSET        0
-#define DMI_HALTSUM1_HALTSUM1_LENGTH        32
-#define DMI_HALTSUM1_HALTSUM1               (0xffffffffU << DMI_HALTSUM1_HALTSUM1_OFFSET)
-#define DMI_HALTSUM2                        0x34
-#define DMI_HALTSUM2_HALTSUM2_OFFSET        0
-#define DMI_HALTSUM2_HALTSUM2_LENGTH        32
-#define DMI_HALTSUM2_HALTSUM2               (0xffffffffU << DMI_HALTSUM2_HALTSUM2_OFFSET)
-#define DMI_HALTSUM3                        0x35
-#define DMI_HALTSUM3_HALTSUM3_OFFSET        0
-#define DMI_HALTSUM3_HALTSUM3_LENGTH        32
-#define DMI_HALTSUM3_HALTSUM3               (0xffffffffU << DMI_HALTSUM3_HALTSUM3_OFFSET)
-#define DMI_SBADDRESS3                      0x37
-/*
-* Accesses bits 127:96 of the physical address in {\tt sbaddress} (if
-* the system address bus is that wide).
- */
-#define DMI_SBADDRESS3_ADDRESS_OFFSET       0
-#define DMI_SBADDRESS3_ADDRESS_LENGTH       32
-#define DMI_SBADDRESS3_ADDRESS              (0xffffffffU << DMI_SBADDRESS3_ADDRESS_OFFSET)
-#define DMI_SBCS                            0x38
-/*
-* 0: The System Bus interface conforms to mainline drafts of this
-* spec older than 1 January, 2018.
-*
-* 1: The System Bus interface conforms to this version of the spec.
-*
-* Other values are reserved for future versions.
- */
-#define DMI_SBCS_SBVERSION_OFFSET           29
-#define DMI_SBCS_SBVERSION_LENGTH           3
-#define DMI_SBCS_SBVERSION                  (0x7U << DMI_SBCS_SBVERSION_OFFSET)
-/*
-* Set when the debugger attempts to read data while a read is in
-* progress, or when the debugger initiates a new access while one is
-* already in progress (while \Fsbbusy is set). It remains set until
-* it's explicitly cleared by the debugger.
-*
-* While this field is non-zero, no more system bus accesses can be
-* initiated by the Debug Module.
- */
-#define DMI_SBCS_SBBUSYERROR_OFFSET         22
-#define DMI_SBCS_SBBUSYERROR_LENGTH         1
-#define DMI_SBCS_SBBUSYERROR                (0x1U << DMI_SBCS_SBBUSYERROR_OFFSET)
-/*
-* When 1, indicates the system bus master is busy. (Whether the
-* system bus itself is busy is related, but not the same thing.) This
-* bit goes high immediately when a read or write is requested for any
-* reason, and does not go low until the access is fully completed.
-*
-* Writes to \Rsbcs while \Fsbbusy is high result in undefined
-* behavior.  A debugger must not write to \Rsbcs until it reads
-* \Fsbbusy as 0.
- */
-#define DMI_SBCS_SBBUSY_OFFSET              21
-#define DMI_SBCS_SBBUSY_LENGTH              1
-#define DMI_SBCS_SBBUSY                     (0x1U << DMI_SBCS_SBBUSY_OFFSET)
-/*
-* When 1, every write to \Rsbaddresszero automatically triggers a
-* system bus read at the new address.
- */
-#define DMI_SBCS_SBREADONADDR_OFFSET        20
-#define DMI_SBCS_SBREADONADDR_LENGTH        1
-#define DMI_SBCS_SBREADONADDR               (0x1U << DMI_SBCS_SBREADONADDR_OFFSET)
-/*
-* Select the access size to use for system bus accesses.
-*
-* 0: 8-bit
-*
-* 1: 16-bit
-*
-* 2: 32-bit
-*
-* 3: 64-bit
-*
-* 4: 128-bit
-*
-* If \Fsbaccess has an unsupported value when the DM starts a bus
-* access, the access is not performed and \Fsberror is set to 3.
- */
-#define DMI_SBCS_SBACCESS_OFFSET            17
-#define DMI_SBCS_SBACCESS_LENGTH            3
-#define DMI_SBCS_SBACCESS                   (0x7U << DMI_SBCS_SBACCESS_OFFSET)
-/*
-* When 1, {\tt sbaddress} is incremented by the access size (in
-* bytes) selected in \Fsbaccess after every system bus access.
- */
-#define DMI_SBCS_SBAUTOINCREMENT_OFFSET     16
-#define DMI_SBCS_SBAUTOINCREMENT_LENGTH     1
-#define DMI_SBCS_SBAUTOINCREMENT            (0x1U << DMI_SBCS_SBAUTOINCREMENT_OFFSET)
-/*
-* When 1, every read from \Rsbdatazero automatically triggers a
-* system bus read at the (possibly auto-incremented) address.
- */
-#define DMI_SBCS_SBREADONDATA_OFFSET        15
-#define DMI_SBCS_SBREADONDATA_LENGTH        1
-#define DMI_SBCS_SBREADONDATA               (0x1U << DMI_SBCS_SBREADONDATA_OFFSET)
-/*
-* When the Debug Module's system bus
-* master causes a bus error, this field gets set. The bits in this
-* field remain set until they are cleared by writing 1 to them.
-* While this field is non-zero, no more system bus accesses can be
-* initiated by the Debug Module.
-*
-* An implementation may report "Other" (7) for any error condition.
-*
-* 0: There was no bus error.
-*
-* 1: There was a timeout.
-*
-* 2: A bad address was accessed.
-*
-* 3: There was an alignment error.
-*
-* 4: An access of unsupported size was requested.
-*
-* 7: Other.
- */
-#define DMI_SBCS_SBERROR_OFFSET             12
-#define DMI_SBCS_SBERROR_LENGTH             3
-#define DMI_SBCS_SBERROR                    (0x7U << DMI_SBCS_SBERROR_OFFSET)
-/*
-* Width of system bus addresses in bits. (0 indicates there is no bus
-* access support.)
- */
-#define DMI_SBCS_SBASIZE_OFFSET             5
-#define DMI_SBCS_SBASIZE_LENGTH             7
-#define DMI_SBCS_SBASIZE                    (0x7fU << DMI_SBCS_SBASIZE_OFFSET)
-/*
-* 1 when 128-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS128_OFFSET         4
-#define DMI_SBCS_SBACCESS128_LENGTH         1
-#define DMI_SBCS_SBACCESS128                (0x1U << DMI_SBCS_SBACCESS128_OFFSET)
-/*
-* 1 when 64-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS64_OFFSET          3
-#define DMI_SBCS_SBACCESS64_LENGTH          1
-#define DMI_SBCS_SBACCESS64                 (0x1U << DMI_SBCS_SBACCESS64_OFFSET)
-/*
-* 1 when 32-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS32_OFFSET          2
-#define DMI_SBCS_SBACCESS32_LENGTH          1
-#define DMI_SBCS_SBACCESS32                 (0x1U << DMI_SBCS_SBACCESS32_OFFSET)
-/*
-* 1 when 16-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS16_OFFSET          1
-#define DMI_SBCS_SBACCESS16_LENGTH          1
-#define DMI_SBCS_SBACCESS16                 (0x1U << DMI_SBCS_SBACCESS16_OFFSET)
-/*
-* 1 when 8-bit system bus accesses are supported.
- */
-#define DMI_SBCS_SBACCESS8_OFFSET           0
-#define DMI_SBCS_SBACCESS8_LENGTH           1
-#define DMI_SBCS_SBACCESS8                  (0x1U << DMI_SBCS_SBACCESS8_OFFSET)
-#define DMI_SBADDRESS0                      0x39
-/*
-* Accesses bits 31:0 of the physical address in {\tt sbaddress}.
- */
-#define DMI_SBADDRESS0_ADDRESS_OFFSET       0
-#define DMI_SBADDRESS0_ADDRESS_LENGTH       32
-#define DMI_SBADDRESS0_ADDRESS              (0xffffffffU << DMI_SBADDRESS0_ADDRESS_OFFSET)
-#define DMI_SBADDRESS1                      0x3a
-/*
-* Accesses bits 63:32 of the physical address in {\tt sbaddress} (if
-* the system address bus is that wide).
- */
-#define DMI_SBADDRESS1_ADDRESS_OFFSET       0
-#define DMI_SBADDRESS1_ADDRESS_LENGTH       32
-#define DMI_SBADDRESS1_ADDRESS              (0xffffffffU << DMI_SBADDRESS1_ADDRESS_OFFSET)
-#define DMI_SBADDRESS2                      0x3b
-/*
-* Accesses bits 95:64 of the physical address in {\tt sbaddress} (if
-* the system address bus is that wide).
- */
-#define DMI_SBADDRESS2_ADDRESS_OFFSET       0
-#define DMI_SBADDRESS2_ADDRESS_LENGTH       32
-#define DMI_SBADDRESS2_ADDRESS              (0xffffffffU << DMI_SBADDRESS2_ADDRESS_OFFSET)
-#define DMI_SBDATA0                         0x3c
-/*
-* Accesses bits 31:0 of {\tt sbdata}.
- */
-#define DMI_SBDATA0_DATA_OFFSET             0
-#define DMI_SBDATA0_DATA_LENGTH             32
-#define DMI_SBDATA0_DATA                    (0xffffffffU << DMI_SBDATA0_DATA_OFFSET)
-#define DMI_SBDATA1                         0x3d
-/*
-* Accesses bits 63:32 of {\tt sbdata} (if the system bus is that
-* wide).
- */
-#define DMI_SBDATA1_DATA_OFFSET             0
-#define DMI_SBDATA1_DATA_LENGTH             32
-#define DMI_SBDATA1_DATA                    (0xffffffffU << DMI_SBDATA1_DATA_OFFSET)
-#define DMI_SBDATA2                         0x3e
-/*
-* Accesses bits 95:64 of {\tt sbdata} (if the system bus is that
-* wide).
- */
-#define DMI_SBDATA2_DATA_OFFSET             0
-#define DMI_SBDATA2_DATA_LENGTH             32
-#define DMI_SBDATA2_DATA                    (0xffffffffU << DMI_SBDATA2_DATA_OFFSET)
-#define DMI_SBDATA3                         0x3f
-/*
-* Accesses bits 127:96 of {\tt sbdata} (if the system bus is that
-* wide).
- */
-#define DMI_SBDATA3_DATA_OFFSET             0
-#define DMI_SBDATA3_DATA_LENGTH             32
-#define DMI_SBDATA3_DATA                    (0xffffffffU << DMI_SBDATA3_DATA_OFFSET)
+#define DM_SBDATA3_DATA_OFFSET              0
+#define DM_SBDATA3_DATA_LENGTH              32
+#define DM_SBDATA3_DATA                     (0xffffffffU << DM_SBDATA3_DATA_OFFSET)
+#define DM_CUSTOM                           0x1f
+#define DM_CUSTOM0                          0x70
+#define DM_CUSTOM15                         0x7f
 #define SHORTNAME                           0x123
 /*
-* Description of what this field is used for.
+ * Description of what this field is used for.
  */
 #define SHORTNAME_FIELD_OFFSET              0
 #define SHORTNAME_FIELD_LENGTH              8
 #define SHORTNAME_FIELD                     (0xffU << SHORTNAME_FIELD_OFFSET)
-#define AC_ACCESS_REGISTER                  None
 /*
-* This is 0 to indicate Access Register Command.
+ * This is 0 to indicate Access Register Command.
  */
 #define AC_ACCESS_REGISTER_CMDTYPE_OFFSET   24
 #define AC_ACCESS_REGISTER_CMDTYPE_LENGTH   8
 #define AC_ACCESS_REGISTER_CMDTYPE          (0xffU << AC_ACCESS_REGISTER_CMDTYPE_OFFSET)
 /*
-* 2: Access the lowest 32 bits of the register.
-*
-* 3: Access the lowest 64 bits of the register.
-*
-* 4: Access the lowest 128 bits of the register.
-*
-* If \Fsize specifies a size larger than the register's actual size,
-* then the access must fail. If a register is accessible, then reads of \Fsize
-* less than or equal to the register's actual size must be supported.
-*
-* This field controls the Argument Width as referenced in
-* Table~\ref{tab:datareg}.
- */
-#define AC_ACCESS_REGISTER_SIZE_OFFSET      20
-#define AC_ACCESS_REGISTER_SIZE_LENGTH      3
-#define AC_ACCESS_REGISTER_SIZE             (0x7U << AC_ACCESS_REGISTER_SIZE_OFFSET)
-/*
-* When 1, execute the program in the Program Buffer exactly once
-* after performing the transfer, if any.
+ * 2: Access the lowest 32 bits of the register.
+ *
+ * 3: Access the lowest 64 bits of the register.
+ *
+ * 4: Access the lowest 128 bits of the register.
+ *
+ * If \FacAccessregisterAarsize specifies a size larger than the register's actual size,
+ * then the access must fail. If a register is accessible, then reads of \FacAccessregisterAarsize
+ * less than or equal to the register's actual size must be supported.
+ *
+ * This field controls the Argument Width as referenced in
+ * Table~\ref{tab:datareg}.
+ */
+#define AC_ACCESS_REGISTER_AARSIZE_OFFSET   20
+#define AC_ACCESS_REGISTER_AARSIZE_LENGTH   3
+#define AC_ACCESS_REGISTER_AARSIZE          (0x7U << AC_ACCESS_REGISTER_AARSIZE_OFFSET)
+/*
+ * 0: No effect. This variant must be supported.
+ *
+ * 1: After a successful register access, \FacAccessregisterRegno is
+ * incremented (wrapping around to 0). Supporting this variant is
+ * optional. It is undefined whether the increment happens when
+ * \FacAccessregisterTransfer is 0.
+ */
+#define AC_ACCESS_REGISTER_AARPOSTINCREMENT_OFFSET 19
+#define AC_ACCESS_REGISTER_AARPOSTINCREMENT_LENGTH 1
+#define AC_ACCESS_REGISTER_AARPOSTINCREMENT (0x1U << AC_ACCESS_REGISTER_AARPOSTINCREMENT_OFFSET)
+/*
+ * 0: No effect. This variant must be supported, and is the only
+ * supported one if \FdmAbstractcsProgbufsize is 0.
+ *
+ * 1: Execute the program in the Program Buffer exactly once after
+ * performing the transfer, if any. Supporting this variant is
+ * optional.
  */
 #define AC_ACCESS_REGISTER_POSTEXEC_OFFSET  18
 #define AC_ACCESS_REGISTER_POSTEXEC_LENGTH  1
 #define AC_ACCESS_REGISTER_POSTEXEC         (0x1U << AC_ACCESS_REGISTER_POSTEXEC_OFFSET)
 /*
-* 0: Don't do the operation specified by \Fwrite.
-*
-* 1: Do the operation specified by \Fwrite.
-*
-* This bit can be used to just execute the Program Buffer without
-* having to worry about placing valid values into \Fsize or \Fregno.
+ * 0: Don't do the operation specified by \FacAccessregisterWrite.
+ *
+ * 1: Do the operation specified by \FacAccessregisterWrite.
+ *
+ * This bit can be used to just execute the Program Buffer without
+ * having to worry about placing valid values into \FacAccessregisterAarsize or \FacAccessregisterRegno.
  */
 #define AC_ACCESS_REGISTER_TRANSFER_OFFSET  17
 #define AC_ACCESS_REGISTER_TRANSFER_LENGTH  1
 #define AC_ACCESS_REGISTER_TRANSFER         (0x1U << AC_ACCESS_REGISTER_TRANSFER_OFFSET)
 /*
-* When \Ftransfer is set:
-* 0: Copy data from the specified register into {\tt arg0} portion
-* of {\tt data}.
-*
-* 1: Copy data from {\tt arg0} portion of {\tt data} into the
-* specified register.
+ * When \FacAccessregisterTransfer is set:
+ * 0: Copy data from the specified register into {\tt arg0} portion
+ * of {\tt data}.
+ *
+ * 1: Copy data from {\tt arg0} portion of {\tt data} into the
+ * specified register.
  */
 #define AC_ACCESS_REGISTER_WRITE_OFFSET     16
 #define AC_ACCESS_REGISTER_WRITE_LENGTH     1
 #define AC_ACCESS_REGISTER_WRITE            (0x1U << AC_ACCESS_REGISTER_WRITE_OFFSET)
 /*
-* Number of the register to access, as described in
-* Table~\ref{tab:regno}.
-* \Rdpc may be used as an alias for PC if this command is
-* supported on a non-halted hart.
+ * Number of the register to access, as described in
+ * Table~\ref{tab:regno}.
+ * \RcsrDpc may be used as an alias for PC if this command is
+ * supported on a non-halted hart.
  */
 #define AC_ACCESS_REGISTER_REGNO_OFFSET     0
 #define AC_ACCESS_REGISTER_REGNO_LENGTH     16
 #define AC_ACCESS_REGISTER_REGNO            (0xffffU << AC_ACCESS_REGISTER_REGNO_OFFSET)
-#define AC_QUICK_ACCESS                     None
 /*
-* This is 1 to indicate Quick Access command.
+ * This is 1 to indicate Quick Access command.
  */
 #define AC_QUICK_ACCESS_CMDTYPE_OFFSET      24
 #define AC_QUICK_ACCESS_CMDTYPE_LENGTH      8
 #define AC_QUICK_ACCESS_CMDTYPE             (0xffU << AC_QUICK_ACCESS_CMDTYPE_OFFSET)
+/*
+ * This is 2 to indicate Access Memory Command.
+ */
+#define AC_ACCESS_MEMORY_CMDTYPE_OFFSET     24
+#define AC_ACCESS_MEMORY_CMDTYPE_LENGTH     8
+#define AC_ACCESS_MEMORY_CMDTYPE            (0xffU << AC_ACCESS_MEMORY_CMDTYPE_OFFSET)
+/*
+ * An implementation does not have to implement both virtual and
+ * physical accesses, but it must fail accesses that it doesn't
+ * support.
+ *
+ * 0: Addresses are physical (to the hart they are performed on).
+ *
+ * 1: Addresses are virtual, and translated the way they would be from
+ * M-mode, with \FcsrMcontrolMprv set.
+ */
+#define AC_ACCESS_MEMORY_AAMVIRTUAL_OFFSET  23
+#define AC_ACCESS_MEMORY_AAMVIRTUAL_LENGTH  1
+#define AC_ACCESS_MEMORY_AAMVIRTUAL         (0x1U << AC_ACCESS_MEMORY_AAMVIRTUAL_OFFSET)
+/*
+ * 0: Access the lowest 8 bits of the memory location.
+ *
+ * 1: Access the lowest 16 bits of the memory location.
+ *
+ * 2: Access the lowest 32 bits of the memory location.
+ *
+ * 3: Access the lowest 64 bits of the memory location.
+ *
+ * 4: Access the lowest 128 bits of the memory location.
+ */
+#define AC_ACCESS_MEMORY_AAMSIZE_OFFSET     20
+#define AC_ACCESS_MEMORY_AAMSIZE_LENGTH     3
+#define AC_ACCESS_MEMORY_AAMSIZE            (0x7U << AC_ACCESS_MEMORY_AAMSIZE_OFFSET)
+/*
+ * After a memory access has completed, if this bit is 1, increment
+ * {\tt arg1} (which contains the address used) by the number of bytes
+ * encoded in \FacAccessmemoryAamsize.
+ *
+ * Supporting this variant is optional, but highly recommended for
+ * performance reasons.
+ */
+#define AC_ACCESS_MEMORY_AAMPOSTINCREMENT_OFFSET 19
+#define AC_ACCESS_MEMORY_AAMPOSTINCREMENT_LENGTH 1
+#define AC_ACCESS_MEMORY_AAMPOSTINCREMENT   (0x1U << AC_ACCESS_MEMORY_AAMPOSTINCREMENT_OFFSET)
+/*
+ * 0: Copy data from the memory location specified in {\tt arg1} into
+ * the low bits of {\tt arg0}. Any remaining bits of {\tt arg0} now
+ * have an undefined value.
+ *
+ * 1: Copy data&nbs