This is an automated email from Gerrit.

"Name of user not set <liam.fletc...@microchip.com>" just uploaded a new patch 
set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8872

-- gerrit

commit 025ecc353018af2215d4e0821094b481e24b06c8
Author: Liam Fletcher <liam.fletc...@microchip.com>
Date:   Thu Apr 10 14:01:30 2025 +0100

    target/riscv: support multiple DMs
    
    Introduces the handling of more than one Debug Module(DM) per Debug
    Module Interface(DMI) for RISC-V. Creates a DM layer to allow access to
    the registers of the DM. Creates a -dbgbase argument to specify the
    first DM address in a DM chain. Checks the nextdm register of the
    current DM which contains the address of the next DM in a chain. A
    nextdm address of 0 indicates the end of a DM chain.
    See RISC-V Debug Specification v1.0 chapter 3.1:
    [https://github.com/riscv/riscv-debug-spec/releases/download/1.0/
    riscv-debug-specification.pdf]
    
    Ported from 3 commits in riscv-openocd:
    [https://github.com/riscv-collab/riscv-openocd/pull/875/]
    
    target/riscv: add dm layer
    original commit: [895185caffac591e923bfeaa42672fa604eb642f]
    prepare for support multiple DMs
    
    target/riscv: support multiple DMs
    original commit: [80a8aa9e195757f082919108f71511b76bd7ca92]
    Support assign DMI address of the debug module by pass
    -dbgbase to the target create command
    
    target/riscv: support check dbgbase exist
    original commit: [a9f28dafd7a67bf6f0a734f087fc9de283d001f1]
    
    Change-Id: I91df626a9c68aa28344728ceceb55f7b69c719dc
    Signed-off-by: Liam Fletcher <liam.fletc...@microchip.com>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 32a2895ecf..8213608bbc 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -11593,15 +11593,28 @@ Write the 32-bit value to authdata.
 
 @subsection RISC-V DMI Commands
 
-The following commands allow direct access to the Debug Module Interface, which
-can be used to interact with custom debug features.
+The following commands allow for direct low-level access to the registers
+of the Debug Module (DM). They can be useful to access custom features in the 
DM.
+
+@deffn {Command} {riscv dm_read} reg_address
+Perform a 32-bit read from the register indicated by reg_address from the DM 
of the
+current target.
+@end deffn
+
+@deffn {Command} {riscv dm_write} reg_address value
+Write the 32-bit value to the register indicated by reg_address from the DM of 
the
+current target.
+@end deffn
+
+The following commands allow for direct low-level access to the Debug Module
+Interface (DMI). They can be useful to access any device that resides on the 
DMI.
 
 @deffn {Command} {riscv dmi_read} address
-Perform a 32-bit DMI read at address, returning the value.
+Perform a 32-bit read from the given DMI address, returning the value.
 @end deffn
 
 @deffn {Command} {riscv dmi_write} address value
-Perform a 32-bit DMI write of value at address.
+Perform a 32-bit write to the given DMI address.
 @end deffn
 
 @section ARC Architecture
diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c
index e3f8ff3d4b..b339d17e8e 100644
--- a/src/target/riscv/batch.c
+++ b/src/target/riscv/batch.c
@@ -127,28 +127,28 @@ int riscv_batch_run(struct riscv_batch *batch)
        return ERROR_OK;
 }
 
-void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned int 
address, uint64_t data)
+void riscv_batch_add_dm_write(struct riscv_batch *batch, unsigned int address, 
uint64_t data)
 {
        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 * 
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);
+       field->in_value = (void *)(batch->data_in + batch->used_scans * 
DMI_SCAN_BUF_SIZE);
+       riscv_fill_dm_write_u64(batch->target, (char *)field->out_value, 
address, data);
+       riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value);
        batch->last_scan = RISCV_SCAN_TYPE_WRITE;
        batch->used_scans++;
 }
 
-size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned int 
address)
+size_t riscv_batch_add_dm_read(struct riscv_batch *batch, unsigned int 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 * 
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);
+       field->in_value = (void *)(batch->data_in + batch->used_scans * 
DMI_SCAN_BUF_SIZE);
+       riscv_fill_dm_read_u64(batch->target, (char *)field->out_value, 
address);
+       riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value);
        batch->last_scan = RISCV_SCAN_TYPE_READ;
        batch->used_scans++;
 
@@ -183,8 +183,8 @@ void riscv_batch_add_nop(struct riscv_batch *batch)
        field->num_bits = riscv_dmi_write_u64_bits(batch->target);
        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);
+       riscv_fill_dm_nop_u64(batch->target, (char *)field->out_value);
+       riscv_fill_dm_nop_u64(batch->target, (char *)field->in_value);
        batch->last_scan = RISCV_SCAN_TYPE_NOP;
        batch->used_scans++;
 }
diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h
index 537fa59233..8b7bf74a50 100644
--- a/src/target/riscv/batch.h
+++ b/src/target/riscv/batch.h
@@ -58,13 +58,13 @@ bool riscv_batch_full(struct riscv_batch *batch);
 /* Executes this scan batch. */
 int riscv_batch_run(struct riscv_batch *batch);
 
-/* Adds a DMI write to this batch. */
-void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned int 
address, uint64_t data);
+/* Adds a DM register write to this batch. */
+void riscv_batch_add_dm_write(struct riscv_batch *batch, unsigned int address, 
uint64_t data);
 
-/* DMI reads must be handled in two parts: the first one schedules a read and
+/* DM register reads must be handled in two parts: the first one schedules a 
read and
  * 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 int 
address);
+size_t riscv_batch_add_dm_read(struct riscv_batch *batch, unsigned int 
address);
 uint32_t 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);
 
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index bb450ce623..52030b746b 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -53,9 +53,12 @@ static int riscv013_write_debug_buffer(struct target 
*target, unsigned int index
 static riscv_insn_t riscv013_read_debug_buffer(struct target *target, unsigned 
int index);
 static int riscv013_execute_debug_buffer(struct target *target);
 static void riscv013_fill_dmi_write_u64(struct target *target, char *buf, int 
a, uint64_t d);
+static void riscv013_fill_dm_write_u64(struct target *target, char *buf, int 
a, uint64_t d);
 static void riscv013_fill_dmi_read_u64(struct target *target, char *buf, int 
a);
+static void riscv013_fill_dm_read_u64(struct target *target, char *buf, int a);
 static int riscv013_dmi_write_u64_bits(struct target *target);
 static void riscv013_fill_dmi_nop_u64(struct target *target, char *buf);
+static void riscv013_fill_dm_nop_u64(struct target *target, char *buf);
 static int register_read(struct target *target, uint64_t *value, uint32_t 
number);
 static int register_read_direct(struct target *target, uint64_t *value, 
uint32_t number);
 static int register_write_direct(struct target *target, unsigned int number,
@@ -132,7 +135,8 @@ typedef enum {
 typedef struct {
        struct list_head list;
        unsigned int abs_chain_position;
-
+       /* The base address to access this DM on DMI */
+       uint32_t base;
        /* The number of harts connected to this DM. */
        int hart_count;
        /* Indicates we already reset this DM, so don't need to do it again. */
@@ -240,7 +244,8 @@ static dm013_info_t *get_dm(struct target *target)
        dm013_info_t *entry;
        dm013_info_t *dm = NULL;
        list_for_each_entry(entry, &dm_list, list) {
-               if (entry->abs_chain_position == abs_chain_position) {
+               if (entry->abs_chain_position == abs_chain_position
+                               && entry->base == target->dbgbase) {
                        dm = entry;
                        break;
                }
@@ -252,6 +257,11 @@ static dm013_info_t *get_dm(struct target *target)
                if (!dm)
                        return NULL;
                dm->abs_chain_position = abs_chain_position;
+
+               /* Safety check for dbgbase */
+               assert(target->dbgbase_set || target->dbgbase == 0);
+
+               dm->base = target->dbgbase;
                dm->current_hartid = -1;
                dm->hart_count = -1;
                INIT_LIST_HEAD(&dm->target_list);
@@ -289,7 +299,7 @@ static uint32_t set_hartsel(uint32_t initial, uint32_t 
index)
        return initial;
 }
 
-static void decode_dmi(char *text, unsigned int address, unsigned int data)
+static void decode_dm(char *text, unsigned int address, unsigned int data)
 {
        static const struct {
                unsigned int address;
@@ -368,7 +378,15 @@ static void decode_dmi(char *text, unsigned int address, 
unsigned int data)
        }
 }
 
-static void dump_field(int idle, const struct scan_field *field)
+static void decode_dmi(struct target *target, char *text, unsigned int 
address, unsigned int data)
+{
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
+               return;
+       decode_dm(text, address - dm->base, data);
+}
+
+static void dump_field(struct target *target, int idle, const struct 
scan_field *field)
 {
        static const char * const op_string[] = {"-", "r", "w", "?"};
        static const char * const status_string[] = {"+", "?", "F", "b"};
@@ -394,8 +412,8 @@ static void dump_field(int idle, const struct scan_field 
*field)
 
        char out_text[500];
        char in_text[500];
-       decode_dmi(out_text, out_address, out_data);
-       decode_dmi(in_text, in_address, in_data);
+       decode_dmi(target, out_text, out_address, out_data);
+       decode_dmi(target, in_text, in_address, in_data);
        if (in_text[0] || out_text[0]) {
                log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, "scan", "%s -> 
%s",
                                out_text, in_text);
@@ -533,7 +551,7 @@ static dmi_status_t dmi_scan(struct target *target, 
uint32_t *address_in,
 
        if (address_in)
                *address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, 
info->abits);
-       dump_field(idle_count, &field);
+       dump_field(target, idle_count, &field);
        return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
 }
 
@@ -543,7 +561,7 @@ static dmi_status_t dmi_scan(struct target *target, 
uint32_t *address_in,
  * @param dmi_busy_encountered
  *                 If non-NULL, will be updated to reflect whether DMI busy was
  *                 encountered while executing this operation or not.
- * @param dmi_op   The operation to perform (read/write/nop).
+ * @param op       The operation to perform (read/write/nop).
  * @param address  The address argument to that operation.
  * @param data_out The data to send to the target.
  * @param timeout_sec
@@ -554,7 +572,7 @@ static dmi_status_t dmi_scan(struct target *target, 
uint32_t *address_in,
  *                 DMI operation succeeded.
  */
 static int dmi_op_timeout(struct target *target, uint32_t *data_in,
-               bool *dmi_busy_encountered, int dmi_op, uint32_t address,
+               bool *dmi_busy_encountered, int op, uint32_t address,
                uint32_t data_out, int timeout_sec, bool exec, bool 
ensure_success)
 {
        select_dmi(target);
@@ -566,7 +584,7 @@ static int dmi_op_timeout(struct target *target, uint32_t 
*data_in,
                *dmi_busy_encountered = false;
 
        const char *op_name;
-       switch (dmi_op) {
+       switch (op) {
                case DMI_OP_NOP:
                        op_name = "nop";
                        break;
@@ -577,7 +595,7 @@ static int dmi_op_timeout(struct target *target, uint32_t 
*data_in,
                        op_name = "write";
                        break;
                default:
-                       LOG_ERROR("Invalid DMI operation: %d", dmi_op);
+                       LOG_ERROR("Invalid DMI operation: %d", op);
                        return ERROR_FAIL;
        }
 
@@ -587,7 +605,7 @@ static int dmi_op_timeout(struct target *target, uint32_t 
*data_in,
        /* This first loop performs the request.  Note that if for some reason 
this
         * stays busy, it is actually due to the previous access. */
        while (1) {
-               status = dmi_scan(target, NULL, NULL, dmi_op, address, data_out,
+               status = dmi_scan(target, NULL, NULL, op, address, data_out,
                                exec);
                if (status == DMI_STATUS_BUSY) {
                        increase_dmi_busy_delay(target);
@@ -642,10 +660,10 @@ static int dmi_op_timeout(struct target *target, uint32_t 
*data_in,
 }
 
 static int dmi_op(struct target *target, uint32_t *data_in,
-               bool *dmi_busy_encountered, int dmi_op, uint32_t address,
+               bool *dmi_busy_encountered, int op, uint32_t address,
                uint32_t data_out, bool exec, bool ensure_success)
 {
-       int result = dmi_op_timeout(target, data_in, dmi_busy_encountered, 
dmi_op,
+       int result = dmi_op_timeout(target, data_in, dmi_busy_encountered, op,
                        address, data_out, riscv_command_timeout_sec, exec, 
ensure_success);
        if (result == ERROR_TIMEOUT_REACHED) {
                LOG_ERROR("DMI operation didn't complete in %d seconds. The 
target is "
@@ -678,10 +696,92 @@ static int dmi_write_exec(struct target *target, uint32_t 
address,
        return dmi_op(target, NULL, NULL, DMI_OP_WRITE, address, value, true, 
ensure_success);
 }
 
+static int dm_op_timeout(struct target *target, uint32_t *data_in,
+               bool *dmi_busy_encountered, int op, uint32_t address,
+               uint32_t data_out, int timeout_sec, bool exec, bool 
ensure_success)
+{
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
+               return ERROR_FAIL;
+       return dmi_op_timeout(target, data_in, dmi_busy_encountered, op, 
address + dm->base,
+               data_out, timeout_sec, exec, ensure_success);
+}
+
+static int dm_op(struct target *target, uint32_t *data_in,
+               bool *dmi_busy_encountered, int op, uint32_t address,
+               uint32_t data_out, bool exec, bool ensure_success)
+{
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
+               return ERROR_FAIL;
+       return dmi_op(target, data_in, dmi_busy_encountered, op, address + 
dm->base,
+                       data_out, exec, ensure_success);
+}
+
+static int dm_read(struct target *target, uint32_t *value, uint32_t address)
+{
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
+               return ERROR_FAIL;
+       return dmi_read(target, value, address + dm->base);
+}
+
+static int dm_read_exec(struct target *target, uint32_t *value, uint32_t 
address)
+{
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
+               return ERROR_FAIL;
+       return dmi_read_exec(target, value, address + dm->base);
+}
+
+static int dm_write(struct target *target, uint32_t address, uint32_t value)
+{
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
+               return ERROR_FAIL;
+       return dmi_write(target, address + dm->base, value);
+}
+
+static int dm_write_exec(struct target *target, uint32_t address,
+               uint32_t value, bool ensure_success)
+{
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
+               return ERROR_FAIL;
+       return dmi_write_exec(target, address + dm->base, value, 
ensure_success);
+}
+
+static bool check_dbgbase_exists(struct target *target)
+{
+       uint32_t next_dm = 0;
+       unsigned int count = 1;
+
+       LOG_TARGET_DEBUG(target, "Searching for DM with DMI base address 
(dbgbase) = 0x%x", target->dbgbase);
+       while (1) {
+               uint32_t current_dm = next_dm;
+               if (current_dm == target->dbgbase)
+                       return true;
+               if (dmi_read(target, &next_dm, DM_NEXTDM + current_dm) != 
ERROR_OK)
+                       break;
+               LOG_TARGET_DEBUG(target, "dm @ 0x%x --> nextdm=0x%x", 
current_dm, next_dm);
+               /* Check if it's last one in the chain. */
+               if (next_dm == 0) {
+                       LOG_TARGET_ERROR(target, "Reached the end of DM chain 
(detected %u DMs in total).", count);
+                       break;
+               }
+               /* Safety: Avoid looping forever in case of buggy nextdm values 
in the hardware. */
+               if (count++ > RISCV_MAX_DMS) {
+                       LOG_TARGET_ERROR(target, "Supporting no more than %d 
DMs on a DMI bus. Aborting", RISCV_MAX_DMS);
+                       break;
+               }
+       }
+       return false;
+}
+
 static int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus,
                bool authenticated, unsigned int timeout_sec)
 {
-       int result = dmi_op_timeout(target, dmstatus, NULL, DMI_OP_READ,
+       int result = dm_op_timeout(target, dmstatus, NULL, DMI_OP_READ,
                        DM_DMSTATUS, 0, timeout_sec, false, true);
        if (result != ERROR_OK)
                return result;
@@ -736,7 +836,7 @@ static int wait_for_idle(struct target *target, uint32_t 
*abstractcs)
        RISCV013_INFO(info);
        time_t start = time(NULL);
        while (1) {
-               if (dmi_read(target, abstractcs, DM_ABSTRACTCS) != ERROR_OK)
+               if (dm_read(target, abstractcs, DM_ABSTRACTCS) != ERROR_OK)
                        return ERROR_FAIL;
 
                if (get_field(*abstractcs, DM_ABSTRACTCS_BUSY) == 0)
@@ -789,7 +889,7 @@ static int execute_abstract_command(struct target *target, 
uint32_t command)
                }
        }
 
-       if (dmi_write_exec(target, DM_COMMAND, command, false) != ERROR_OK)
+       if (dm_write_exec(target, DM_COMMAND, command, false) != ERROR_OK)
                return ERROR_FAIL;
 
        uint32_t abstractcs = 0;
@@ -799,7 +899,7 @@ static int execute_abstract_command(struct target *target, 
uint32_t command)
        if (info->cmderr != 0 || result != ERROR_OK) {
                LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, 
abstractcs);
                /* Clear the error. */
-               dmi_write(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
+               dm_write(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
                return ERROR_FAIL;
        }
 
@@ -817,11 +917,11 @@ static riscv_reg_t read_abstract_arg(struct target 
*target, unsigned int index,
                        LOG_ERROR("Unsupported size: %d bits", size_bits);
                        return ~0;
                case 64:
-                       dmi_read(target, &v, DM_DATA0 + offset + 1);
+                       dm_read(target, &v, DM_DATA0 + offset + 1);
                        value |= ((uint64_t) v) << 32;
                        /* falls through */
                case 32:
-                       dmi_read(target, &v, DM_DATA0 + offset);
+                       dm_read(target, &v, DM_DATA0 + offset);
                        value |= v;
        }
        return value;
@@ -836,10 +936,10 @@ static int write_abstract_arg(struct target *target, 
unsigned int index,
                        LOG_ERROR("Unsupported size: %d bits", size_bits);
                        return ERROR_FAIL;
                case 64:
-                       dmi_write(target, DM_DATA0 + offset + 1, value >> 32);
+                       dm_write(target, DM_DATA0 + offset + 1, value >> 32);
                        /* falls through */
                case 32:
-                       dmi_write(target, DM_DATA0 + offset, value);
+                       dm_write(target, DM_DATA0 + offset, value);
        }
        return ERROR_OK;
 }
@@ -1045,7 +1145,7 @@ static int examine_progbuf(struct target *target)
        }
 
        uint32_t written;
-       if (dmi_read(target, &written, DM_PROGBUF0) != ERROR_OK)
+       if (dm_read(target, &written, DM_PROGBUF0) != ERROR_OK)
                return ERROR_FAIL;
        if (written == (uint32_t) info->progbuf_address) {
                LOG_INFO("progbuf is writable at 0x%" PRIx64,
@@ -1203,18 +1303,18 @@ static int scratch_read64(struct target *target, 
scratch_mem_t *scratch,
        uint32_t v;
        switch (scratch->memory_space) {
                case SPACE_DM_DATA:
-                       if (dmi_read(target, &v, DM_DATA0 + 
scratch->debug_address) != ERROR_OK)
+                       if (dm_read(target, &v, DM_DATA0 + 
scratch->debug_address) != ERROR_OK)
                                return ERROR_FAIL;
                        *value = v;
-                       if (dmi_read(target, &v, DM_DATA1 + 
scratch->debug_address) != ERROR_OK)
+                       if (dm_read(target, &v, DM_DATA1 + 
scratch->debug_address) != ERROR_OK)
                                return ERROR_FAIL;
                        *value |= ((uint64_t) v) << 32;
                        break;
                case SPACE_DMI_PROGBUF:
-                       if (dmi_read(target, &v, DM_PROGBUF0 + 
scratch->debug_address) != ERROR_OK)
+                       if (dm_read(target, &v, DM_PROGBUF0 + 
scratch->debug_address) != ERROR_OK)
                                return ERROR_FAIL;
                        *value = v;
-                       if (dmi_read(target, &v, DM_PROGBUF1 + 
scratch->debug_address) != ERROR_OK)
+                       if (dm_read(target, &v, DM_PROGBUF1 + 
scratch->debug_address) != ERROR_OK)
                                return ERROR_FAIL;
                        *value |= ((uint64_t) v) << 32;
                        break;
@@ -1242,12 +1342,12 @@ static int scratch_write64(struct target *target, 
scratch_mem_t *scratch,
 {
        switch (scratch->memory_space) {
                case SPACE_DM_DATA:
-                       dmi_write(target, DM_DATA0 + scratch->debug_address, 
value);
-                       dmi_write(target, DM_DATA1 + scratch->debug_address, 
value >> 32);
+                       dm_write(target, DM_DATA0 + scratch->debug_address, 
value);
+                       dm_write(target, DM_DATA1 + scratch->debug_address, 
value >> 32);
                        break;
                case SPACE_DMI_PROGBUF:
-                       dmi_write(target, DM_PROGBUF0 + scratch->debug_address, 
value);
-                       dmi_write(target, DM_PROGBUF1 + scratch->debug_address, 
value >> 32);
+                       dm_write(target, DM_PROGBUF0 + scratch->debug_address, 
value);
+                       dm_write(target, DM_PROGBUF1 + scratch->debug_address, 
value >> 32);
                        break;
                case SPACE_DMI_RAM:
                        {
@@ -1562,6 +1662,8 @@ static int examine(struct target *target)
 {
        /* Don't need to select dbus, since the first thing we do is read 
dtmcontrol. */
 
+       LOG_DEBUG("dbgbase=0x%x", target->dbgbase);
+
        uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
        LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol);
        LOG_DEBUG("  dmireset=%d", get_field(dtmcontrol, DTM_DTMCS_DMIRESET));
@@ -1580,26 +1682,31 @@ static int examine(struct target *target)
        }
 
        riscv013_info_t *info = get_info(target);
-       /* TODO: This won't be true if there are multiple DMs. */
+
        info->index = target->coreid;
        info->abits = get_field(dtmcontrol, DTM_DTMCS_ABITS);
        info->dtmcs_idle = get_field(dtmcontrol, DTM_DTMCS_IDLE);
 
+       if (!check_dbgbase_exists(target)) {
+               LOG_TARGET_ERROR(target, "Could not find debug module with DMI 
base address (dbgbase) = 0x%x", target->dbgbase);
+               return ERROR_FAIL;
+       }
+
        /* Reset the Debug Module. */
        dm013_info_t *dm = get_dm(target);
        if (!dm)
                return ERROR_FAIL;
        if (!dm->was_reset) {
-               dmi_write(target, DM_DMCONTROL, 0);
-               dmi_write(target, DM_DMCONTROL, DM_DMCONTROL_DMACTIVE);
+               dm_write(target, DM_DMCONTROL, 0);
+               dm_write(target, DM_DMCONTROL, DM_DMCONTROL_DMACTIVE);
                dm->was_reset = true;
        }
 
-       dmi_write(target, DM_DMCONTROL, DM_DMCONTROL_HARTSELLO |
+       dm_write(target, DM_DMCONTROL, DM_DMCONTROL_HARTSELLO |
                        DM_DMCONTROL_HARTSELHI | DM_DMCONTROL_DMACTIVE |
                        DM_DMCONTROL_HASEL);
        uint32_t dmcontrol;
-       if (dmi_read(target, &dmcontrol, DM_DMCONTROL) != ERROR_OK)
+       if (dm_read(target, &dmcontrol, DM_DMCONTROL) != ERROR_OK)
                return ERROR_FAIL;
 
        if (!get_field(dmcontrol, DM_DMCONTROL_DMACTIVE)) {
@@ -1632,7 +1739,7 @@ static int examine(struct target *target)
        LOG_DEBUG("hartsellen=%d", info->hartsellen);
 
        uint32_t hartinfo;
-       if (dmi_read(target, &hartinfo, DM_HARTINFO) != ERROR_OK)
+       if (dm_read(target, &hartinfo, DM_HARTINFO) != ERROR_OK)
                return ERROR_FAIL;
 
        info->datasize = get_field(hartinfo, DM_HARTINFO_DATASIZE);
@@ -1650,12 +1757,12 @@ static int examine(struct target *target)
                return ERROR_OK;
        }
 
-       if (dmi_read(target, &info->sbcs, DM_SBCS) != ERROR_OK)
+       if (dm_read(target, &info->sbcs, DM_SBCS) != ERROR_OK)
                return ERROR_FAIL;
 
        /* Check that abstract data registers are accessible. */
        uint32_t abstractcs;
-       if (dmi_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK)
+       if (dm_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK)
                return ERROR_FAIL;
        info->datacount = get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT);
        info->progbufsize = get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE);
@@ -1694,7 +1801,7 @@ static int examine(struct target *target)
                        dm->hart_count = i + 1;
 
                        if (get_field(s, DM_DMSTATUS_ANYHAVERESET))
-                               dmi_write(target, DM_DMCONTROL,
+                               dm_write(target, DM_DMCONTROL,
                                                
set_hartsel(DM_DMCONTROL_DMACTIVE | DM_DMCONTROL_ACKHAVERESET, i));
                }
 
@@ -1788,7 +1895,7 @@ static int riscv013_authdata_read(struct target *target, 
uint32_t *value, unsign
        if (wait_for_authbusy(target, NULL) != ERROR_OK)
                return ERROR_FAIL;
 
-       return dmi_read(target, value, DM_AUTHDATA);
+       return dm_read(target, value, DM_AUTHDATA);
 }
 
 static int riscv013_authdata_write(struct target *target, uint32_t value, 
unsigned int index)
@@ -1802,7 +1909,7 @@ static int riscv013_authdata_write(struct target *target, 
uint32_t value, unsign
        if (wait_for_authbusy(target, &before) != ERROR_OK)
                return ERROR_FAIL;
 
-       dmi_write(target, DM_AUTHDATA, value);
+       dm_write(target, DM_AUTHDATA, value);
 
        if (wait_for_authbusy(target, &after) != ERROR_OK)
                return ERROR_FAIL;
@@ -2079,12 +2186,12 @@ static int sb_write_address(struct target *target, 
target_addr_t address,
        unsigned int sbasize = get_field(info->sbcs, DM_SBCS_SBASIZE);
        /* There currently is no support for >64-bit addresses in OpenOCD. */
        if (sbasize > 96)
-               dmi_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS3, 0, 
false, false);
+               dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS3, 0, 
false, false);
        if (sbasize > 64)
-               dmi_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS2, 0, 
false, false);
+               dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS2, 0, 
false, false);
        if (sbasize > 32)
-               dmi_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS1, address 
>> 32, false, false);
-       return dmi_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS0, address,
+               dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS1, address 
>> 32, false, false);
+       return dm_op(target, NULL, NULL, DMI_OP_WRITE, DM_SBADDRESS0, address,
                                  false, ensure_success);
 }
 
@@ -2183,7 +2290,7 @@ static int sample_memory_bus_v1(struct target *target,
                                                sbcs_write |= 
DM_SBCS_SBREADONDATA;
                                        sbcs_write |= 
sb_sbaccess(config->bucket[i].size_bytes);
                                        if (!sbcs_valid || sbcs_write != sbcs) {
-                                               
riscv_batch_add_dmi_write(batch, DM_SBCS, sbcs_write);
+                                               riscv_batch_add_dm_write(batch, 
DM_SBCS, sbcs_write);
                                                sbcs = sbcs_write;
                                                sbcs_valid = true;
                                        }
@@ -2192,18 +2299,18 @@ static int sample_memory_bus_v1(struct target *target,
                                                        (!sbaddress1_valid ||
                                                        sbaddress1 != 
config->bucket[i].address >> 32)) {
                                                sbaddress1 = 
config->bucket[i].address >> 32;
-                                               
riscv_batch_add_dmi_write(batch, DM_SBADDRESS1, sbaddress1);
+                                               riscv_batch_add_dm_write(batch, 
DM_SBADDRESS1, sbaddress1);
                                                sbaddress1_valid = true;
                                        }
                                        if (!sbaddress0_valid ||
                                                        sbaddress0 != 
(config->bucket[i].address & 0xffffffff)) {
                                                sbaddress0 = 
config->bucket[i].address;
-                                               
riscv_batch_add_dmi_write(batch, DM_SBADDRESS0, sbaddress0);
+                                               riscv_batch_add_dm_write(batch, 
DM_SBADDRESS0, sbaddress0);
                                                sbaddress0_valid = true;
                                        }
                                        if (config->bucket[i].size_bytes > 4)
-                                               riscv_batch_add_dmi_read(batch, 
DM_SBDATA1);
-                                       riscv_batch_add_dmi_read(batch, 
DM_SBDATA0);
+                                               riscv_batch_add_dm_read(batch, 
DM_SBDATA1);
+                                       riscv_batch_add_dm_read(batch, 
DM_SBDATA0);
                                        result_bytes += 1 + 
config->bucket[i].size_bytes;
                                }
                        }
@@ -2214,7 +2321,7 @@ static int sample_memory_bus_v1(struct target *target,
                        break;
                }
 
-               size_t sbcs_key = riscv_batch_add_dmi_read(batch, DM_SBCS);
+               size_t sbcs_key = riscv_batch_add_dm_read(batch, DM_SBCS);
 
                int result = batch_run(target, batch);
                if (result != ERROR_OK)
@@ -2225,13 +2332,13 @@ static int sample_memory_bus_v1(struct target *target,
                        /* Discard this batch (too much hassle to try to 
recover partial
                         * data) and try again with a larger delay. */
                        info->bus_master_read_delay += 
info->bus_master_read_delay / 10 + 1;
-                       dmi_write(target, DM_SBCS, sbcs_read | 
DM_SBCS_SBBUSYERROR | DM_SBCS_SBERROR);
+                       dm_write(target, DM_SBCS, sbcs_read | 
DM_SBCS_SBBUSYERROR | DM_SBCS_SBERROR);
                        riscv_batch_free(batch);
                        continue;
                }
                if (get_field(sbcs_read, DM_SBCS_SBERROR)) {
                        /* The memory we're sampling was unreadable, somehow. 
Give up. */
-                       dmi_write(target, DM_SBCS, DM_SBCS_SBBUSYERROR | 
DM_SBCS_SBERROR);
+                       dm_write(target, DM_SBCS, DM_SBCS_SBBUSYERROR | 
DM_SBCS_SBERROR);
                        riscv_batch_free(batch);
                        return ERROR_FAIL;
                }
@@ -2293,14 +2400,16 @@ static int init_target(struct command_context *cmd_ctx,
        generic_info->read_debug_buffer = &riscv013_read_debug_buffer;
        generic_info->write_debug_buffer = &riscv013_write_debug_buffer;
        generic_info->execute_debug_buffer = &riscv013_execute_debug_buffer;
-       generic_info->fill_dmi_write_u64 = &riscv013_fill_dmi_write_u64;
-       generic_info->fill_dmi_read_u64 = &riscv013_fill_dmi_read_u64;
-       generic_info->fill_dmi_nop_u64 = &riscv013_fill_dmi_nop_u64;
+       generic_info->fill_dm_write_u64 = &riscv013_fill_dm_write_u64;
+       generic_info->fill_dm_read_u64 = &riscv013_fill_dm_read_u64;
+       generic_info->fill_dm_nop_u64 = &riscv013_fill_dm_nop_u64;
        generic_info->dmi_write_u64_bits = &riscv013_dmi_write_u64_bits;
        generic_info->authdata_read = &riscv013_authdata_read;
        generic_info->authdata_write = &riscv013_authdata_write;
        generic_info->dmi_read = &dmi_read;
        generic_info->dmi_write = &dmi_write;
+       generic_info->dm_read = &dm_read;
+       generic_info->dm_write = &dm_write;
        generic_info->read_memory = read_memory;
        generic_info->hart_count = &riscv013_hart_count;
        generic_info->data_bits = &riscv013_data_bits;
@@ -2356,11 +2465,11 @@ static int assert_reset(struct target *target)
                uint32_t control = set_hartsel(control_base, target->coreid);
                control = set_field(control, DM_DMCONTROL_HALTREQ,
                                target->reset_halt ? 1 : 0);
-               dmi_write(target, DM_DMCONTROL, control);
+               dm_write(target, DM_DMCONTROL, control);
 
                /* Assert ndmreset */
                control = set_field(control, DM_DMCONTROL_NDMRESET, 1);
-               dmi_write(target, DM_DMCONTROL, control);
+               dm_write(target, DM_DMCONTROL, control);
 
        } else {
                /* Reset just this hart. */
@@ -2368,7 +2477,7 @@ static int assert_reset(struct target *target)
                control = set_field(control, DM_DMCONTROL_HALTREQ,
                                target->reset_halt ? 1 : 0);
                control = set_field(control, DM_DMCONTROL_NDMRESET, 1);
-               dmi_write(target, DM_DMCONTROL, control);
+               dm_write(target, DM_DMCONTROL, control);
        }
 
        target->state = TARGET_RESET;
@@ -2395,7 +2504,7 @@ static int deassert_reset(struct target *target)
        uint32_t control = 0, control_haltreq;
        control = set_field(control, DM_DMCONTROL_DMACTIVE, 1);
        control_haltreq = set_field(control, DM_DMCONTROL_HALTREQ, 
target->reset_halt ? 1 : 0);
-       dmi_write(target, DM_DMCONTROL,
+       dm_write(target, DM_DMCONTROL,
                        set_hartsel(control_haltreq, r->current_hartid));
 
        uint32_t dmstatus;
@@ -2407,7 +2516,7 @@ static int deassert_reset(struct target *target)
                if (target->rtos) {
                        if (index != target->coreid)
                                continue;
-                       dmi_write(target, DM_DMCONTROL,
+                       dm_write(target, DM_DMCONTROL,
                                        set_hartsel(control_haltreq, index));
                } else {
                        index = r->current_hartid;
@@ -2445,7 +2554,7 @@ static int deassert_reset(struct target *target)
 
                if (get_field(dmstatus, DM_DMSTATUS_ALLHAVERESET)) {
                        /* Ack reset and clear DM_DMCONTROL_HALTREQ if 
previously set */
-                       dmi_write(target, DM_DMCONTROL,
+                       dm_write(target, DM_DMCONTROL,
                                        set_hartsel(control, index) |
                                        DM_DMCONTROL_ACKHAVERESET);
                }
@@ -2511,7 +2620,7 @@ static int read_memory_bus_word(struct target *target, 
target_addr_t address,
        static int sbdata[4] = { DM_SBDATA0, DM_SBDATA1, DM_SBDATA2, DM_SBDATA3 
};
        assert(size <= 16);
        for (int i = (size - 1) / 4; i >= 0; i--) {
-               result = dmi_op(target, &value, NULL, DMI_OP_READ, sbdata[i], 
0, false, true);
+               result = dm_op(target, &value, NULL, DMI_OP_READ, sbdata[i], 0, 
false, true);
                if (result != ERROR_OK)
                        return result;
                buf_set_u32(buffer + i * 4, 0, 8 * MIN(size, 4), value);
@@ -2527,11 +2636,11 @@ static target_addr_t sb_read_address(struct target 
*target)
        target_addr_t address = 0;
        uint32_t v;
        if (sbasize > 32) {
-               dmi_read(target, &v, DM_SBADDRESS1);
+               dm_read(target, &v, DM_SBADDRESS1);
                address |= v;
                address <<= 32;
        }
-       dmi_read(target, &v, DM_SBADDRESS0);
+       dm_read(target, &v, DM_SBADDRESS0);
        address |= v;
        return address;
 }
@@ -2540,7 +2649,7 @@ static int read_sbcs_nonbusy(struct target *target, 
uint32_t *sbcs)
 {
        time_t start = time(NULL);
        while (1) {
-               if (dmi_read(target, sbcs, DM_SBCS) != ERROR_OK)
+               if (dm_read(target, sbcs, DM_SBCS) != ERROR_OK)
                        return ERROR_FAIL;
                if (!get_field(*sbcs, DM_SBCS_SBBUSY))
                        return ERROR_OK;
@@ -2608,17 +2717,17 @@ static int read_memory_bus_v0(struct target *target, 
target_addr_t address,
        /* ww favorise one off reading if there is an issue */
        if (count == 1) {
                for (uint32_t i = 0; i < count; i++) {
-                       if (dmi_read(target, &access, DM_SBCS) != ERROR_OK)
+                       if (dm_read(target, &access, DM_SBCS) != ERROR_OK)
                                return ERROR_FAIL;
-                       dmi_write(target, DM_SBADDRESS0, cur_addr);
+                       dm_write(target, DM_SBADDRESS0, cur_addr);
                        /* size/2 matching the bit access of the spec 0.13 */
                        access = set_field(access, DM_SBCS_SBACCESS, size/2);
                        access = set_field(access, DM_SBCS_SBSINGLEREAD, 1);
                        LOG_DEBUG("\r\nread_memory: sab: access:  0x%08x", 
access);
-                       dmi_write(target, DM_SBCS, access);
+                       dm_write(target, DM_SBCS, access);
                        /* 3) read */
                        uint32_t value;
-                       if (dmi_read(target, &value, DM_SBDATA0) != ERROR_OK)
+                       if (dm_read(target, &value, DM_SBDATA0) != ERROR_OK)
                                return ERROR_FAIL;
                        LOG_DEBUG("\r\nread_memory: sab: value:  0x%08x", 
value);
                        buf_set_u32(t_buffer, 0, 8 * size, value);
@@ -2630,10 +2739,10 @@ static int read_memory_bus_v0(struct target *target, 
target_addr_t address,
 
        /* has to be the same size if we want to read a block */
        LOG_DEBUG("reading block until final address 0x%" PRIx64, fin_addr);
-       if (dmi_read(target, &access, DM_SBCS) != ERROR_OK)
+       if (dm_read(target, &access, DM_SBCS) != ERROR_OK)
                return ERROR_FAIL;
        /* set current address */
-       dmi_write(target, DM_SBADDRESS0, cur_addr);
+       dm_write(target, DM_SBADDRESS0, cur_addr);
        /* 2) write sbaccess=2, sbsingleread,sbautoread,sbautoincrement
         * size/2 matching the bit access of the spec 0.13 */
        access = set_field(access, DM_SBCS_SBACCESS, size/2);
@@ -2641,14 +2750,14 @@ static int read_memory_bus_v0(struct target *target, 
target_addr_t address,
        access = set_field(access, DM_SBCS_SBSINGLEREAD, 1);
        access = set_field(access, DM_SBCS_SBAUTOINCREMENT, 1);
        LOG_DEBUG("\r\naccess:  0x%08x", access);
-       dmi_write(target, DM_SBCS, access);
+       dm_write(target, DM_SBCS, access);
 
        while (cur_addr < fin_addr) {
                LOG_DEBUG("\r\nsab:autoincrement: \r\n size: 
%d\tcount:%d\taddress: 0x%08"
                                PRIx64, size, count, cur_addr);
                /* read */
                uint32_t value;
-               if (dmi_read(target, &value, DM_SBDATA0) != ERROR_OK)
+               if (dm_read(target, &value, DM_SBDATA0) != ERROR_OK)
                        return ERROR_FAIL;
                buf_set_u32(t_buffer, 0, 8 * size, value);
                cur_addr += size;
@@ -2656,15 +2765,15 @@ static int read_memory_bus_v0(struct target *target, 
target_addr_t address,
 
                /* if we are reaching last address, we must clear autoread */
                if (cur_addr == fin_addr && count != 1) {
-                       dmi_write(target, DM_SBCS, 0);
-                       if (dmi_read(target, &value, DM_SBDATA0) != ERROR_OK)
+                       dm_write(target, DM_SBCS, 0);
+                       if (dm_read(target, &value, DM_SBDATA0) != ERROR_OK)
                                return ERROR_FAIL;
                        buf_set_u32(t_buffer, 0, 8 * size, value);
                }
        }
 
        uint32_t sbcs;
-       if (dmi_read(target, &sbcs, DM_SBCS) != ERROR_OK)
+       if (dm_read(target, &sbcs, DM_SBCS) != ERROR_OK)
                return ERROR_FAIL;
 
        return ERROR_OK;
@@ -2692,7 +2801,7 @@ static int read_memory_bus_v1(struct target *target, 
target_addr_t address,
                        sbcs_write = set_field(sbcs_write, 
DM_SBCS_SBAUTOINCREMENT, 1);
                if (count > 1)
                        sbcs_write = set_field(sbcs_write, 
DM_SBCS_SBREADONDATA, count > 1);
-               if (dmi_write(target, DM_SBCS, sbcs_write) != ERROR_OK)
+               if (dm_write(target, DM_SBCS, sbcs_write) != ERROR_OK)
                        return ERROR_FAIL;
 
                /* This address write will trigger the first read. */
@@ -2768,7 +2877,7 @@ static int read_memory_bus_v1(struct target *target, 
target_addr_t address,
                                return ERROR_FAIL;
 
                        sbcs_write = set_field(sbcs_write, 
DM_SBCS_SBREADONDATA, 0);
-                       if (dmi_write(target, DM_SBCS, sbcs_write) != ERROR_OK)
+                       if (dm_write(target, DM_SBCS, sbcs_write) != ERROR_OK)
                                return ERROR_FAIL;
                }
 
@@ -2785,7 +2894,7 @@ static int read_memory_bus_v1(struct target *target, 
target_addr_t address,
 
                if (get_field(sbcs_read, DM_SBCS_SBBUSYERROR)) {
                        /* We read while the target was busy. Slow down and try 
again. */
-                       if (dmi_write(target, DM_SBCS, sbcs_read | 
DM_SBCS_SBBUSYERROR) != ERROR_OK)
+                       if (dm_write(target, DM_SBCS, sbcs_read | 
DM_SBCS_SBBUSYERROR) != ERROR_OK)
                                return ERROR_FAIL;
                        next_address = sb_read_address(target);
                        info->bus_master_read_delay += 
info->bus_master_read_delay / 10 + 1;
@@ -2798,7 +2907,7 @@ static int read_memory_bus_v1(struct target *target, 
target_addr_t address,
                } else {
                        /* Some error indicating the bus access failed, but not 
because of
                         * something we did wrong. */
-                       if (dmi_write(target, DM_SBCS, DM_SBCS_SBERROR) != 
ERROR_OK)
+                       if (dm_write(target, DM_SBCS, DM_SBCS_SBERROR) != 
ERROR_OK)
                                return ERROR_FAIL;
                        return ERROR_FAIL;
                }
@@ -3133,13 +3242,13 @@ static int read_memory_progbuf_inner(struct target 
*target, target_addr_t addres
                return ERROR_OK;
        }
 
-       if (dmi_write(target, DM_ABSTRACTAUTO,
+       if (dm_write(target, DM_ABSTRACTAUTO,
                        1 << DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET) != ERROR_OK)
                goto error;
        /* Read garbage from dmi_data0, which triggers another execution of the
         * program. Now dmi_data0 contains the first good result, and s1 the 
next
         * memory value. */
-       if (dmi_read_exec(target, NULL, DM_DATA0) != ERROR_OK)
+       if (dm_read_exec(target, NULL, DM_DATA0) != ERROR_OK)
                goto error;
 
        /* read_addr is the next address that the hart will read from, which is 
the
@@ -3164,8 +3273,8 @@ static int read_memory_progbuf_inner(struct target 
*target, target_addr_t addres
                unsigned int reads = 0;
                for (unsigned int j = index; j < count; j++) {
                        if (size > 4)
-                               riscv_batch_add_dmi_read(batch, DM_DATA1);
-                       riscv_batch_add_dmi_read(batch, DM_DATA0);
+                               riscv_batch_add_dm_read(batch, DM_DATA1);
+                       riscv_batch_add_dm_read(batch, DM_DATA0);
 
                        reads++;
                        if (riscv_batch_full(batch))
@@ -3178,10 +3287,10 @@ static int read_memory_progbuf_inner(struct target 
*target, target_addr_t addres
                 * and update our copy of cmderr. If we see that DMI is busy 
here,
                 * dmi_busy_delay will be incremented. */
                uint32_t abstractcs;
-               if (dmi_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK)
+               if (dm_read(target, &abstractcs, DM_ABSTRACTCS) != ERROR_OK)
                        return ERROR_FAIL;
                while (get_field(abstractcs, DM_ABSTRACTCS_BUSY))
-                       if (dmi_read(target, &abstractcs, DM_ABSTRACTCS) != 
ERROR_OK)
+                       if (dm_read(target, &abstractcs, DM_ABSTRACTCS) != 
ERROR_OK)
                                return ERROR_FAIL;
                info->cmderr = get_field(abstractcs, DM_ABSTRACTCS_CMDERR);
 
@@ -3198,13 +3307,13 @@ static int read_memory_progbuf_inner(struct target 
*target, target_addr_t addres
                                increase_ac_busy_delay(target);
                                riscv013_clear_abstract_error(target);
 
-                               dmi_write(target, DM_ABSTRACTAUTO, 0);
+                               dm_write(target, DM_ABSTRACTAUTO, 0);
 
                                uint32_t dmi_data0, dmi_data1 = 0;
                                /* This is definitely a good version of the 
value that we
                                 * attempted to read when we discovered that 
the target was
                                 * busy. */
-                               if (dmi_read(target, &dmi_data0, DM_DATA0) != 
ERROR_OK) {
+                               if (dm_read(target, &dmi_data0, DM_DATA0) != 
ERROR_OK) {
                                        riscv_batch_free(batch);
                                        goto error;
                                }
@@ -3239,7 +3348,7 @@ static int read_memory_progbuf_inner(struct target 
*target, target_addr_t addres
                                dmi_write_exec(target, DM_COMMAND, command, 
true);
                                next_index++;
 
-                               dmi_write(target, DM_ABSTRACTAUTO,
+                               dm_write(target, DM_ABSTRACTAUTO,
                                                1 << 
DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
 
                                ignore_last = 1;
@@ -3305,7 +3414,7 @@ static int read_memory_progbuf_inner(struct target 
*target, target_addr_t addres
                riscv_batch_free(batch);
        }
 
-       dmi_write(target, DM_ABSTRACTAUTO, 0);
+       dm_write(target, DM_ABSTRACTAUTO, 0);
 
        if (count > 1) {
                /* Read the penultimate word. */
@@ -3330,7 +3439,7 @@ static int read_memory_progbuf_inner(struct target 
*target, target_addr_t addres
        return ERROR_OK;
 
 error:
-       dmi_write(target, DM_ABSTRACTAUTO, 0);
+       dm_write(target, DM_ABSTRACTAUTO, 0);
 
        return result;
 }
@@ -3598,7 +3707,7 @@ static int write_memory_bus_v0(struct target *target, 
target_addr_t address,
        /*1) write sbaddress: for singlewrite and autoincrement, we need to 
write the address once*/
        LOG_DEBUG("System Bus Access: size: %d\tcount:%d\tstart address: 0x%08"
                        TARGET_PRIxADDR, size, count, address);
-       dmi_write(target, DM_SBADDRESS0, address);
+       dm_write(target, DM_SBADDRESS0, address);
        int64_t value = 0;
        int64_t access = 0;
        riscv_addr_t offset = 0;
@@ -3611,10 +3720,10 @@ static int write_memory_bus_v0(struct target *target, 
target_addr_t address,
 
                access = 0;
                access = set_field(access, DM_SBCS_SBACCESS, size/2);
-               dmi_write(target, DM_SBCS, access);
+               dm_write(target, DM_SBCS, access);
                LOG_DEBUG("\r\naccess:  0x%08" PRIx64, access);
                LOG_DEBUG("\r\nwrite_memory:SAB: ONE OFF: value 0x%08" PRIx64, 
value);
-               dmi_write(target, DM_SBDATA0, value);
+               dm_write(target, DM_SBDATA0, value);
                return ERROR_OK;
        }
 
@@ -3624,7 +3733,7 @@ static int write_memory_bus_v0(struct target *target, 
target_addr_t address,
        access = set_field(access, DM_SBCS_SBACCESS, size/2);
        access = set_field(access, DM_SBCS_SBAUTOINCREMENT, 1);
        LOG_DEBUG("\r\naccess:  0x%08" PRIx64, access);
-       dmi_write(target, DM_SBCS, access);
+       dm_write(target, DM_SBCS, access);
 
        /*2)set the value according to the size required and write*/
        for (riscv_addr_t i = 0; i < count; ++i) {
@@ -3636,11 +3745,11 @@ static int write_memory_bus_v0(struct target *target, 
target_addr_t address,
                value = buf_get_u64(t_buffer, 0, 8 * size);
                LOG_DEBUG("SAB:autoincrement: expected address: 0x%08x value: 
0x%08x"
                                PRIx64, (uint32_t)t_addr, (uint32_t)value);
-               dmi_write(target, DM_SBDATA0, value);
+               dm_write(target, DM_SBDATA0, value);
        }
        /*reset the autoincrement when finished (something weird is happening 
if this is not done at the end*/
        access = set_field(access, DM_SBCS_SBAUTOINCREMENT, 0);
-       dmi_write(target, DM_SBCS, access);
+       dm_write(target, DM_SBCS, access);
 
        return ERROR_OK;
 }
@@ -3651,7 +3760,7 @@ static int write_memory_bus_v1(struct target *target, 
target_addr_t address,
        RISCV013_INFO(info);
        uint32_t sbcs = sb_sbaccess(size);
        sbcs = set_field(sbcs, DM_SBCS_SBAUTOINCREMENT, 1);
-       dmi_write(target, DM_SBCS, sbcs);
+       dm_write(target, DM_SBCS, sbcs);
 
        target_addr_t next_address = address;
        target_addr_t end_address = address + count * size;
@@ -3677,20 +3786,20 @@ static int write_memory_bus_v1(struct target *target, 
target_addr_t address,
                                break;
 
                        if (size > 12)
-                               riscv_batch_add_dmi_write(batch, DM_SBDATA3,
+                               riscv_batch_add_dm_write(batch, DM_SBDATA3,
                                                ((uint32_t) p[12]) |
                                                (((uint32_t) p[13]) << 8) |
                                                (((uint32_t) p[14]) << 16) |
                                                (((uint32_t) p[15]) << 24));
 
                        if (size > 8)
-                               riscv_batch_add_dmi_write(batch, DM_SBDATA2,
+                               riscv_batch_add_dm_write(batch, DM_SBDATA2,
                                                ((uint32_t) p[8]) |
                                                (((uint32_t) p[9]) << 8) |
                                                (((uint32_t) p[10]) << 16) |
                                                (((uint32_t) p[11]) << 24));
                        if (size > 4)
-                               riscv_batch_add_dmi_write(batch, DM_SBDATA1,
+                               riscv_batch_add_dm_write(batch, DM_SBDATA1,
                                                ((uint32_t) p[4]) |
                                                (((uint32_t) p[5]) << 8) |
                                                (((uint32_t) p[6]) << 16) |
@@ -3702,7 +3811,7 @@ static int write_memory_bus_v1(struct target *target, 
target_addr_t address,
                        }
                        if (size > 1)
                                value |= ((uint32_t) p[1]) << 8;
-                       riscv_batch_add_dmi_write(batch, DM_SBDATA0, value);
+                       riscv_batch_add_dm_write(batch, DM_SBDATA0, value);
 
                        log_memory_access(address + i * size, value, size, 
false);
                        next_address += size;
@@ -3717,7 +3826,7 @@ static int write_memory_bus_v1(struct target *target, 
target_addr_t address,
                /* Read sbcs value.
                 * At the same time, detect if DMI busy has occurred during the 
batch write. */
                bool dmi_busy_encountered;
-               if (dmi_op(target, &sbcs, &dmi_busy_encountered, DMI_OP_READ,
+               if (dm_op(target, &sbcs, &dmi_busy_encountered, DMI_OP_READ,
                                DM_SBCS, 0, false, true) != ERROR_OK)
                        return ERROR_FAIL;
                if (dmi_busy_encountered)
@@ -3732,7 +3841,7 @@ static int write_memory_bus_v1(struct target *target, 
target_addr_t address,
                                                  riscv_command_timeout_sec, 
sbcs);
                                return ERROR_FAIL;
                        }
-                       if (dmi_read(target, &sbcs, DM_SBCS) != ERROR_OK)
+                       if (dm_read(target, &sbcs, DM_SBCS) != ERROR_OK)
                                return ERROR_FAIL;
                }
 
@@ -3740,7 +3849,7 @@ static int write_memory_bus_v1(struct target *target, 
target_addr_t address,
                        /* We wrote while the target was busy. */
                        LOG_DEBUG("Sbbusyerror encountered during system bus 
write.");
                        /* Clear the sticky error flag. */
-                       dmi_write(target, DM_SBCS, sbcs | DM_SBCS_SBBUSYERROR);
+                       dm_write(target, DM_SBCS, sbcs | DM_SBCS_SBBUSYERROR);
                        /* Slow down before trying again. */
                        info->bus_master_write_delay += 
info->bus_master_write_delay / 10 + 1;
                }
@@ -3776,7 +3885,7 @@ static int write_memory_bus_v1(struct target *target, 
target_addr_t address,
                                                  " - buggy sbautoincrement in 
hw?", next_address);
                        }
                        /* Clear the sticky error flag */
-                       dmi_write(target, DM_SBCS, DM_SBCS_SBERROR);
+                       dm_write(target, DM_SBCS, DM_SBCS_SBERROR);
                        /* Fail the whole operation */
                        return ERROR_FAIL;
                }
@@ -3886,8 +3995,8 @@ static int write_memory_progbuf(struct target *target, 
target_addr_t address,
 
                                /* Write value. */
                                if (size > 4)
-                                       dmi_write(target, DM_DATA1, value >> 
32);
-                               dmi_write(target, DM_DATA0, value);
+                                       dm_write(target, DM_DATA1, value >> 32);
+                               dm_write(target, DM_DATA0, value);
 
                                /* Write and execute command that moves value 
into S1 and
                                 * executes program buffer. */
@@ -3903,14 +4012,14 @@ static int write_memory_progbuf(struct target *target, 
target_addr_t address,
                                }
 
                                /* Turn on autoexec */
-                               dmi_write(target, DM_ABSTRACTAUTO,
+                               dm_write(target, DM_ABSTRACTAUTO,
                                                1 << 
DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
 
                                setup_needed = false;
                        } else {
                                if (size > 4)
-                                       riscv_batch_add_dmi_write(batch, 
DM_DATA1, value >> 32);
-                               riscv_batch_add_dmi_write(batch, DM_DATA0, 
value);
+                                       riscv_batch_add_dm_write(batch, 
DM_DATA1, value >> 32);
+                               riscv_batch_add_dm_write(batch, DM_DATA0, 
value);
                                if (riscv_batch_full(batch))
                                        break;
                        }
@@ -3927,12 +4036,12 @@ static int write_memory_progbuf(struct target *target, 
target_addr_t address,
 
                uint32_t abstractcs;
                bool dmi_busy_encountered;
-               result = dmi_op(target, &abstractcs, &dmi_busy_encountered,
+               result = dm_op(target, &abstractcs, &dmi_busy_encountered,
                                DMI_OP_READ, DM_ABSTRACTCS, 0, false, true);
                if (result != ERROR_OK)
                        goto error;
                while (get_field(abstractcs, DM_ABSTRACTCS_BUSY))
-                       if (dmi_read(target, &abstractcs, DM_ABSTRACTCS) != 
ERROR_OK)
+                       if (dm_read(target, &abstractcs, DM_ABSTRACTCS) != 
ERROR_OK)
                                return ERROR_FAIL;
                info->cmderr = get_field(abstractcs, DM_ABSTRACTCS_CMDERR);
                if (info->cmderr == CMDERR_NONE && !dmi_busy_encountered) {
@@ -3945,7 +4054,7 @@ static int write_memory_progbuf(struct target *target, 
target_addr_t address,
                        riscv013_clear_abstract_error(target);
                        increase_ac_busy_delay(target);
 
-                       dmi_write(target, DM_ABSTRACTAUTO, 0);
+                       dm_write(target, DM_ABSTRACTAUTO, 0);
                        result = register_read_direct(target, &cur_addr, 
GDB_REGNO_S0);
                        if (result != ERROR_OK)
                                goto error;
@@ -3959,7 +4068,7 @@ static int write_memory_progbuf(struct target *target, 
target_addr_t address,
        }
 
 error:
-       dmi_write(target, DM_ABSTRACTAUTO, 0);
+       dm_write(target, DM_ABSTRACTAUTO, 0);
 
        if (register_write_direct(target, GDB_REGNO_S1, s1) != ERROR_OK)
                return ERROR_FAIL;
@@ -4188,9 +4297,9 @@ static int select_prepped_harts(struct target *target, 
bool *use_hasel)
        }
 
        for (unsigned int i = 0; i < hawindow_count; i++) {
-               if (dmi_write(target, DM_HAWINDOWSEL, i) != ERROR_OK)
+               if (dm_write(target, DM_HAWINDOWSEL, i) != ERROR_OK)
                        return ERROR_FAIL;
-               if (dmi_write(target, DM_HAWINDOW, hawindow[i]) != ERROR_OK)
+               if (dm_write(target, DM_HAWINDOW, hawindow[i]) != ERROR_OK)
                        return ERROR_FAIL;
        }
 
@@ -4217,7 +4326,7 @@ static int riscv013_halt_go(struct target *target)
        if (use_hasel)
                dmcontrol |= DM_DMCONTROL_HASEL;
        dmcontrol = set_hartsel(dmcontrol, r->current_hartid);
-       dmi_write(target, DM_DMCONTROL, dmcontrol);
+       dm_write(target, DM_DMCONTROL, dmcontrol);
        for (size_t i = 0; i < 256; ++i)
                if (riscv_is_halted(target))
                        break;
@@ -4226,7 +4335,7 @@ static int riscv013_halt_go(struct target *target)
                uint32_t dmstatus;
                if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
                        return ERROR_FAIL;
-               if (dmi_read(target, &dmcontrol, DM_DMCONTROL) != ERROR_OK)
+               if (dm_read(target, &dmcontrol, DM_DMCONTROL) != ERROR_OK)
                        return ERROR_FAIL;
 
                LOG_ERROR("unable to halt hart %d", r->current_hartid);
@@ -4236,7 +4345,7 @@ static int riscv013_halt_go(struct target *target)
        }
 
        dmcontrol = set_field(dmcontrol, DM_DMCONTROL_HALTREQ, 0);
-       dmi_write(target, DM_DMCONTROL, dmcontrol);
+       dm_write(target, DM_DMCONTROL, dmcontrol);
 
        if (use_hasel) {
                target_list_t *entry;
@@ -4307,7 +4416,7 @@ static bool riscv013_is_halted(struct target *target)
                 */
                if (target->state == TARGET_HALTED)
                        dmcontrol |= DM_DMCONTROL_HALTREQ;
-               dmi_write(target, DM_DMCONTROL, dmcontrol);
+               dm_write(target, DM_DMCONTROL, dmcontrol);
        }
        return get_field(dmstatus, DM_DMSTATUS_ALLHALTED);
 }
@@ -4351,7 +4460,7 @@ int riscv013_write_debug_buffer(struct target *target, 
unsigned int index, riscv
        if (!dm)
                return ERROR_FAIL;
        if (dm->progbuf_cache[index] != data) {
-               if (dmi_write(target, DM_PROGBUF0 + index, data) != ERROR_OK)
+               if (dm_write(target, DM_PROGBUF0 + index, data) != ERROR_OK)
                        return ERROR_FAIL;
                dm->progbuf_cache[index] = data;
        } else {
@@ -4408,6 +4517,27 @@ int riscv013_dmi_write_u64_bits(struct target *target)
        return info->abits + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH;
 }
 
+void riscv013_fill_dm_write_u64(struct target *target, char *buf, int a, 
uint64_t d)
+{
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
+               return;
+       riscv013_fill_dmi_write_u64(target, buf, a + dm->base, d);
+}
+
+void riscv013_fill_dm_read_u64(struct target *target, char *buf, int a)
+{
+       dm013_info_t *dm = get_dm(target);
+       if (!dm)
+               return;
+       riscv013_fill_dmi_read_u64(target, buf, a + dm->base);
+}
+
+void riscv013_fill_dm_nop_u64(struct target *target, char *buf)
+{
+       riscv013_fill_dmi_nop_u64(target, buf);
+}
+
 static int maybe_execute_fence_i(struct target *target)
 {
        if (has_sufficient_progbuf(target, 3))
@@ -4448,7 +4578,7 @@ static int riscv013_step_or_resume_current_hart(struct 
target *target,
        if (use_hasel)
                dmcontrol |= DM_DMCONTROL_HASEL;
        dmcontrol = set_hartsel(dmcontrol, r->current_hartid);
-       dmi_write(target, DM_DMCONTROL, dmcontrol);
+       dm_write(target, DM_DMCONTROL, dmcontrol);
 
        dmcontrol = set_field(dmcontrol, DM_DMCONTROL_HASEL, 0);
        dmcontrol = set_field(dmcontrol, DM_DMCONTROL_RESUMEREQ, 0);
@@ -4463,11 +4593,11 @@ static int riscv013_step_or_resume_current_hart(struct 
target *target,
                if (step && get_field(dmstatus, DM_DMSTATUS_ALLHALTED) == 0)
                        continue;
 
-               dmi_write(target, DM_DMCONTROL, dmcontrol);
+               dm_write(target, DM_DMCONTROL, dmcontrol);
                return ERROR_OK;
        }
 
-       dmi_write(target, DM_DMCONTROL, dmcontrol);
+       dm_write(target, DM_DMCONTROL, dmcontrol);
 
        LOG_ERROR("unable to resume hart %d", r->current_hartid);
        if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
@@ -4488,9 +4618,9 @@ void riscv013_clear_abstract_error(struct target *target)
        /* Wait for busy to go away. */
        time_t start = time(NULL);
        uint32_t abstractcs;
-       dmi_read(target, &abstractcs, DM_ABSTRACTCS);
+       dm_read(target, &abstractcs, DM_ABSTRACTCS);
        while (get_field(abstractcs, DM_ABSTRACTCS_BUSY)) {
-               dmi_read(target, &abstractcs, DM_ABSTRACTCS);
+               dm_read(target, &abstractcs, DM_ABSTRACTCS);
 
                if (time(NULL) - start > riscv_command_timeout_sec) {
                        LOG_ERROR("abstractcs.busy is not going low after %d 
seconds "
@@ -4502,5 +4632,5 @@ void riscv013_clear_abstract_error(struct target *target)
                }
        }
        /* Clear the error status. */
-       dmi_write(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
+       dm_write(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
 }
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 11ef8f9b92..7c3bab7958 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -2677,14 +2677,13 @@ COMMAND_HANDLER(riscv_dmi_read)
                if (r->dmi_read(target, &value, address) != ERROR_OK)
                        return ERROR_FAIL;
                command_print(CMD, "0x%" PRIx32, value);
-               return ERROR_OK;
        } else {
                LOG_ERROR("dmi_read is not implemented for this target.");
                return ERROR_FAIL;
        }
+       return ERROR_OK;
 }
 
-
 COMMAND_HANDLER(riscv_dmi_write)
 {
        if (CMD_ARGC != 2) {
@@ -2707,6 +2706,75 @@ COMMAND_HANDLER(riscv_dmi_write)
        }
 }
 
+COMMAND_HANDLER(riscv_dm_read)
+{
+       if (CMD_ARGC != 1) {
+               LOG_ERROR("Command takes 1 parameter");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       struct target *target = get_current_target(CMD_CTX);
+       if (!target) {
+               LOG_ERROR("target is NULL!");
+               return ERROR_FAIL;
+       }
+
+       RISCV_INFO(r);
+       if (!r) {
+               LOG_TARGET_ERROR(target, "riscv_info is NULL!");
+               return ERROR_FAIL;
+       }
+
+       if (r->dm_read) {
+               uint32_t address, value;
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
+               if (r->dm_read(target, &value, address) != ERROR_OK)
+                       return ERROR_FAIL;
+               command_print(CMD, "0x%" PRIx32, value);
+       } else {
+               LOG_TARGET_ERROR(target, "dm_read is not implemented for this 
target.");
+               return ERROR_FAIL;
+       }
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(riscv_dm_write)
+{
+       if (CMD_ARGC != 2) {
+               LOG_ERROR("Command takes exactly 2 arguments");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       struct target *target = get_current_target(CMD_CTX);
+       RISCV_INFO(r);
+
+       uint32_t address, value;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
+
+       if (r->dm_write) {
+               /* Perform the DM write */
+               int retval = r->dm_write(target, address, value);
+
+               /* Invalidate our cached progbuf copy:
+                  - if the user tinkered directly with a progbuf register
+                  - if debug module was reset, in which case progbuf registers
+                    may not retain their value.
+               */
+               bool progbuf_touched = (address >= DM_PROGBUF0 && address <= 
DM_PROGBUF15);
+               bool dm_deactivated = (address == DM_DMCONTROL && (value & 
DM_DMCONTROL_DMACTIVE) == 0);
+               if (progbuf_touched || dm_deactivated) {
+                       if (r->invalidate_cached_debug_buffer)
+                               r->invalidate_cached_debug_buffer(target);
+               }
+
+               return retval;
+       }
+
+       LOG_TARGET_ERROR(target, "dm_write is not implemented for this 
target.");
+       return ERROR_FAIL;
+}
+
 COMMAND_HANDLER(riscv_reset_delays)
 {
        int wait = 0;
@@ -2946,6 +3014,20 @@ static const struct command_registration 
riscv_exec_command_handlers[] = {
                .usage = "address value",
                .help = "Perform a 32-bit DMI write of value at address."
        },
+       {
+               .name = "dm_read",
+               .handler = riscv_dm_read,
+               .mode = COMMAND_ANY,
+               .usage = "reg_address",
+               .help = "Perform a 32-bit read from DM register at reg_address, 
returning the value."
+       },
+       {
+               .name = "dm_write",
+               .handler = riscv_dm_write,
+               .mode = COMMAND_ANY,
+               .usage = "reg_address value",
+               .help = "Write a 32-bit value to the DM register at 
reg_address."
+       },
        {
                .name = "reset_delays",
                .handler = riscv_reset_delays,
@@ -3411,22 +3493,22 @@ int riscv_execute_debug_buffer(struct target *target)
        return r->execute_debug_buffer(target);
 }
 
-void riscv_fill_dmi_write_u64(struct target *target, char *buf, int a, 
uint64_t d)
+void riscv_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t 
d)
 {
        RISCV_INFO(r);
-       r->fill_dmi_write_u64(target, buf, a, d);
+       r->fill_dm_write_u64(target, buf, a, d);
 }
 
-void riscv_fill_dmi_read_u64(struct target *target, char *buf, int a)
+void riscv_fill_dm_read_u64(struct target *target, char *buf, int a)
 {
        RISCV_INFO(r);
-       r->fill_dmi_read_u64(target, buf, a);
+       r->fill_dm_read_u64(target, buf, a);
 }
 
-void riscv_fill_dmi_nop_u64(struct target *target, char *buf)
+void riscv_fill_dm_nop_u64(struct target *target, char *buf)
 {
        RISCV_INFO(r);
-       r->fill_dmi_nop_u64(target, buf);
+       r->fill_dm_nop_u64(target, buf);
 }
 
 int riscv_dmi_write_u64_bits(struct target *target)
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index f06b5f516d..43eb7647f3 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -20,6 +20,7 @@ struct riscv_program;
 #define RISCV_MAX_REGISTERS 5000
 #define RISCV_MAX_TRIGGERS 32
 #define RISCV_MAX_HWBPS 16
+#define RISCV_MAX_DMS 100
 
 #define DEFAULT_COMMAND_TIMEOUT_SEC            2
 #define DEFAULT_RESET_TIMEOUT_SEC              30
@@ -163,10 +164,11 @@ struct riscv_info {
                        riscv_insn_t d);
        riscv_insn_t (*read_debug_buffer)(struct target *target, unsigned int 
index);
        int (*execute_debug_buffer)(struct target *target);
+       int (*invalidate_cached_debug_buffer)(struct target *target);
        int (*dmi_write_u64_bits)(struct target *target);
-       void (*fill_dmi_write_u64)(struct target *target, char *buf, int a, 
uint64_t d);
-       void (*fill_dmi_read_u64)(struct target *target, char *buf, int a);
-       void (*fill_dmi_nop_u64)(struct target *target, char *buf);
+       void (*fill_dm_write_u64)(struct target *target, char *buf, int a, 
uint64_t d);
+       void (*fill_dm_read_u64)(struct target *target, char *buf, int a);
+       void (*fill_dm_nop_u64)(struct target *target, char *buf);
 
        int (*authdata_read)(struct target *target, uint32_t *value, unsigned 
int index);
        int (*authdata_write)(struct target *target, uint32_t value, unsigned 
int index);
@@ -174,6 +176,9 @@ struct riscv_info {
        int (*dmi_read)(struct target *target, uint32_t *value, uint32_t 
address);
        int (*dmi_write)(struct target *target, uint32_t address, uint32_t 
value);
 
+       int (*dm_read)(struct target *target, uint32_t *value, uint32_t 
address);
+       int (*dm_write)(struct target *target, uint32_t address, uint32_t 
value);
+
        int (*sample_memory)(struct target *target,
                                                 struct riscv_sample_buf *buf,
                                                 riscv_sample_config_t *config,
@@ -341,9 +346,9 @@ riscv_insn_t riscv_read_debug_buffer(struct target *target, 
int index);
 int riscv_write_debug_buffer(struct target *target, int index, riscv_insn_t 
insn);
 int riscv_execute_debug_buffer(struct target *target);
 
-void riscv_fill_dmi_nop_u64(struct target *target, char *buf);
-void riscv_fill_dmi_write_u64(struct target *target, char *buf, int a, 
uint64_t d);
-void riscv_fill_dmi_read_u64(struct target *target, char *buf, int a);
+void riscv_fill_dm_nop_u64(struct target *target, char *buf);
+void riscv_fill_dm_write_u64(struct target *target, char *buf, int a, uint64_t 
d);
+void riscv_fill_dm_read_u64(struct target *target, char *buf, int a);
 int riscv_dmi_write_u64_bits(struct target *target);
 
 int riscv_enumerate_triggers(struct target *target);

-- 

Reply via email to