This is an automated email from Gerrit.

"Bjorn Schouteten <b_schoute...@hotmail.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7151

-- gerrit

commit 7364f3e47f20de84ee9fb64897e329fc72cb87ba
Author: Bjorn Schouteten <b_schoute...@hotmail.com>
Date:   Wed Aug 31 21:38:52 2022 +0200

    target/roalogic: Add roalogic RV12 support
    
    Added support for the RV12 processor of RoaLogic. The RV12 is a highly 
configurable single-issue, single-core RV32I, RV64I compliant RISC CPU intended 
for the embedded market. The debugging interface is based on advance debug 
interface from OpenCores.
    
    Signed-off-by: Bjorn Schouteten <b_schoute...@hotmail.com>
    Change-Id: Ia9a2474c06c095cde41f3dad641671ec0509ea9b

diff --git a/src/target/Makefile.am b/src/target/Makefile.am
index 46870922af..3f566466e0 100644
--- a/src/target/Makefile.am
+++ b/src/target/Makefile.am
@@ -3,7 +3,8 @@
 %C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la \
        %D%/riscv/libriscv.la \
        %D%/xtensa/libxtensa.la \
-       %D%/espressif/libespressif.la
+       %D%/espressif/libespressif.la \
+       %D%/roalogic/libroalogic.la
 
 %C%_libtarget_la_CPPFLAGS = $(AM_CPPFLAGS)
 
@@ -265,4 +266,5 @@ ARC_SRC = \
 include %D%/openrisc/Makefile.am
 include %D%/riscv/Makefile.am
 include %D%/xtensa/Makefile.am
-include %D%/espressif/Makefile.am
\ No newline at end of file
+include %D%/espressif/Makefile.am
+include %D%/roalogic/Makefile.am
\ No newline at end of file
diff --git a/src/target/roalogic/Makefile.am b/src/target/roalogic/Makefile.am
new file mode 100644
index 0000000000..c12137c336
--- /dev/null
+++ b/src/target/roalogic/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LTLIBRARIES += %D%/libroalogic.la
+%C%_libroalogic_la_SOURCES = \
+       %D%/rv12.c \
+       %D%/rl_dbg_adv.c \
+       %D%/rl_universal_tap.c \
+       %D%/jsp_server.c \
+       %D%/rv12.h \
+       %D%/rl_dbg_adv.h \
+       %D%/jsp_server.h 
diff --git a/src/target/roalogic/jsp_server.c b/src/target/roalogic/jsp_server.c
new file mode 100644
index 0000000000..7803ca4a3a
--- /dev/null
+++ b/src/target/roalogic/jsp_server.c
@@ -0,0 +1,247 @@
+/***************************************************************************
+ *   Copyright (C) 2022 by Richard Herveille                               *
+ *   richard.hervei...@roalogic.com                                            
                                   *
+ *                                                                             
                               *
+ *   Copyright (C) 2022 by Bjorn Schouteten                                *
+ *   bjorn.schoute...@roalogic.com                                             
                           *
+ *                                                                             
                                                                   *
+ *   Based on OR1K version                                                 *
+ *   Based on ./src/server/telnet_server.c                                 *
+ *                                                                         *
+ *   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 <server/telnet_server.h>
+
+#include "rl_tap.h"
+#include "rl_dbg_adv.h"
+#include "jsp_server.h"
+
+static char *jsp_port;
+
+/**A skim of the relevant RFCs suggests that if my application simply sent the
+ * characters IAC DONT LINEMODE (\377\376\042) as soon as the client connects,
+ * the client should be forced into character mode. However it doesn't make 
any difference.
+ */
+
+static const char * const negotiate =
+       "\xFF\xFB\x03"                  /* IAC WILL Suppress Go Ahead */
+       "\xFF\xFB\x01"                  /* IAC WILL Echo */
+       "\xFF\xFD\x03"                  /* IAC DO Suppress Go Ahead */
+       "\xFF\xFE\x01";                 /* IAC DON'T Echo */
+
+/* The only way we can detect that the socket is closed is the first time
+ * we write to it, we will fail. Subsequent write operations will
+ * succeed. Shudder!
+ */
+static int telnet_write(struct connection *connection, const void *data, int 
len)
+{
+       struct telnet_connection *t_con = connection->priv;
+       if (t_con->closed)
+               return ERROR_SERVER_REMOTE_CLOSED;
+
+       if (connection_write(connection, data, len) == len)
+               return ERROR_OK;
+       t_con->closed = 1;
+       return ERROR_SERVER_REMOTE_CLOSED;
+}
+
+static int jsp_poll_read(void *priv)
+{
+       struct jsp_service *jsp_service = (struct jsp_service *)priv;
+       unsigned char out_buffer[10];
+       unsigned char in_buffer[10];
+       int out_len = 0;
+       int in_len;
+
+       if (!jsp_service->connection)
+               return ERROR_FAIL;
+
+       memset(out_buffer, 0, 10);
+
+       rl_adv_jtag_jsp_xfer(jsp_service->jtag_info, &out_len, out_buffer, 
&in_len, in_buffer);
+       if (in_len)
+               telnet_write(jsp_service->connection, in_buffer, in_len);
+
+       return ERROR_OK;
+}
+
+static int jsp_new_connection(struct connection *connection)
+{
+       struct telnet_connection *telnet_connection = malloc(sizeof(struct 
telnet_connection));
+       struct jsp_service *jsp_service = connection->service->priv;
+
+       connection->priv = telnet_connection;
+
+       /* initialize telnet connection information */
+       telnet_connection->closed = 0;
+       telnet_connection->line_size = 0;
+       telnet_connection->line_cursor = 0;
+       telnet_connection->state = TELNET_STATE_DATA;
+
+       /* negotiate telnet options */
+       telnet_write(connection, negotiate, strlen(negotiate));
+
+       /* print connection banner */
+       if (jsp_service->banner) {
+               telnet_write(connection, jsp_service->banner, 
strlen(jsp_service->banner));
+               telnet_write(connection, "\r\n", 2);
+       }
+
+       jsp_service->connection = connection;
+
+       int retval = target_register_timer_callback(&jsp_poll_read, 1,
+               TARGET_TIMER_TYPE_PERIODIC, jsp_service);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return ERROR_OK;
+}
+
+static int jsp_input(struct connection *connection)
+{
+       int bytes_read;
+       unsigned char buffer[TELNET_BUFFER_SIZE];
+       unsigned char *buf_p;
+       struct telnet_connection *t_con = connection->priv;
+       struct jsp_service *jsp_service = connection->service->priv;
+
+       bytes_read = connection_read(connection, buffer, TELNET_BUFFER_SIZE);
+
+       if (bytes_read == 0)
+               return ERROR_SERVER_REMOTE_CLOSED;
+       else if (bytes_read == -1) {
+               LOG_ERROR("error during read: %s", strerror(errno));
+               return ERROR_SERVER_REMOTE_CLOSED;
+       }
+
+       buf_p = buffer;
+       while (bytes_read) {
+               switch (t_con->state) {
+                       case TELNET_STATE_DATA:
+                               if (*buf_p == 0xff)
+                                       t_con->state = TELNET_STATE_IAC;
+                               else {
+                                       int out_len = 1;
+                                       int in_len;
+                                       unsigned char in_buffer[10];
+                                       
rl_adv_jtag_jsp_xfer(jsp_service->jtag_info,
+                                                            &out_len, buf_p, 
&in_len,
+                                                            in_buffer);
+                                       if (in_len)
+                                               telnet_write(connection,
+                                                            in_buffer, in_len);
+                               }
+                               break;
+                       case TELNET_STATE_IAC:
+                               switch (*buf_p) {
+                               case 0xfe:
+                                       t_con->state = TELNET_STATE_DONT;
+                                       break;
+                               case 0xfd:
+                                       t_con->state = TELNET_STATE_DO;
+                                       break;
+                               case 0xfc:
+                                       t_con->state = TELNET_STATE_WONT;
+                                       break;
+                               case 0xfb:
+                                       t_con->state = TELNET_STATE_WILL;
+                                       break;
+                               }
+                               break;
+                       case TELNET_STATE_SB:
+                               break;
+                       case TELNET_STATE_SE:
+                               break;
+                       case TELNET_STATE_WILL:
+                       case TELNET_STATE_WONT:
+                       case TELNET_STATE_DO:
+                       case TELNET_STATE_DONT:
+                               t_con->state = TELNET_STATE_DATA;
+                               break;
+                       default:
+                               LOG_ERROR("unknown telnet state");
+                               exit(-1);
+               }
+
+               bytes_read--;
+               buf_p++;
+       }
+
+       return ERROR_OK;
+}
+
+static int jsp_connection_closed(struct connection *connection)
+{
+       struct jsp_service *jsp_service = connection->service->priv;
+
+       int retval = target_unregister_timer_callback(&jsp_poll_read, 
jsp_service);
+       if (retval != ERROR_OK)
+               return retval;
+
+       free(connection->priv);
+       connection->priv = NULL;
+       return ERROR_OK;
+}
+
+static const struct service_driver jsp_service_driver = {
+       .name = "jsp",
+       .new_connection_during_keep_alive_handler = NULL,
+       .new_connection_handler = jsp_new_connection,
+       .input_handler = jsp_input,
+       .connection_closed_handler = jsp_connection_closed,
+       .keep_client_alive_handler = NULL,
+};
+
+
+int jsp_init(struct rl_jtag *jtag_info, char *banner)
+{
+       struct jsp_service *jsp_service = malloc(sizeof(struct jsp_service));
+       jsp_service->banner = banner;
+       jsp_service->jtag_info = jtag_info;
+
+       return add_service(&jsp_service_driver, jsp_port, 1, jsp_service);
+}
+
+COMMAND_HANDLER(handle_jsp_port_command)
+{
+       return CALL_COMMAND_HANDLER(server_pipe_command, &jsp_port);
+}
+
+static const struct command_registration jsp_command_handlers[] = {
+       {
+               .name = "jsp_port",
+               .handler = handle_jsp_port_command,
+               .mode = COMMAND_ANY,
+               .help = "Specify port on which to listen "
+                       "for incoming JSP telnet connections.",
+               .usage = "[port_num]",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+int jsp_register_commands(struct command_context *cmd_ctx)
+{
+       jsp_port = strdup("7777");
+       return register_commands(cmd_ctx, NULL, jsp_command_handlers);
+}
+
+void jsp_service_free(void)
+{
+       free(jsp_port);
+}
diff --git a/src/target/roalogic/jsp_server.h b/src/target/roalogic/jsp_server.h
new file mode 100644
index 0000000000..d412ff8bac
--- /dev/null
+++ b/src/target/roalogic/jsp_server.h
@@ -0,0 +1,18 @@
+#ifndef OPENOCD_TARGET_ROALOGIC_JSP_SERVER_H
+#define OPENOCD_TARGET_ROALOGIC_JSP_SERVER_H
+
+#include "rl_tap.h"
+#include "rv12.h"
+#include "rl_dbg_adv.h"
+
+struct jsp_service {
+       char *banner;
+       struct rl_jtag *jtag_info;
+       struct connection *connection;
+};
+
+int jsp_init(struct rl_jtag *jtag_info, char *banner);
+int jsp_register_commands(struct command_context *cmd_ctx);
+void jsp_service_free(void);
+
+#endif /* OPENOCD_TARGET_ROALOGIC_JSP_SERVER_H */
diff --git a/src/target/roalogic/rl_dbg_adv.c b/src/target/roalogic/rl_dbg_adv.c
new file mode 100644
index 0000000000..07354436c9
--- /dev/null
+++ b/src/target/roalogic/rl_dbg_adv.c
@@ -0,0 +1,1154 @@
+/***************************************************************************
+ *   Copyright (C) 2022 by Richard Herveille                               *
+ *   richard.hervei...@roalogic.com                                        *
+ *                                                                         *
+ *   Copyright (C) 2022 by Bjorn Schouteten                                *
+ *   bjorn.schoute...@roalogic.com                                         *
+ *                                                                         * 
+ *   Based on OR1K version                                                 *
+ *                                                                         *
+ *   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 "rl_tap.h"
+#include "rv12.h"
+#include "rl_dbg_adv.h"
+#include "jsp_server.h"
+
+#include <target/target.h>
+#include <jtag/jtag.h>
+
+#define JSP_BANNER "\n\r" \
+                  "******************************\n\r" \
+                  "**     JTAG Serial Port     **\n\r" \
+                  "******************************\n\r" \
+                  "\n\r"
+
+#define NO_OPTION                      0
+
+/* This an option to the adv debug unit.
+ * If this is defined, status bits will be skipped on burst
+ * reads and writes to improve download speeds.
+ * This option must match the RTL configured option.
+ */
+#define USE_HISPEED                    1
+
+
+/* This an option to the adv debug unit.
+ * If this is defined, the JTAG Serial Port Server is started.
+ * This option must match the RTL configured option.
+ */
+#define ENABLE_JSP_SERVER              2
+
+
+/* Define this if you intend to use the JSP in a system with multiple
+ * devices on the JTAG chain
+ */
+#define ENABLE_JSP_MULTI               4
+
+
+/* Definitions for the top-level debug unit.  This really just consists
+ * of a single register, used to select the active debug module ("chain").
+ */
+#define DBG_MODULE_SELECT_REG_SIZE     2
+#define DBG_MAX_MODULES                        4
+
+#define DC_NONE                                -1
+#define DC_SYSBUS                      0
+#define DC_CPU                         1
+#define DC_JSP                         2
+
+
+/* CPU control register bits mask */
+#define DBG_CPU_CR_STALL               0x01
+#define DBG_CPU_CR_RESET               0x02
+
+
+/* Polynomial for the CRC calculation
+ * Yes, it's backwards.  Yes, this is on purpose.
+ * The hardware is designed this way to save on logic and routing,
+ * and it's really all the same to us here.
+ */
+#define ADBG_CRC_POLY                  0xedb88320
+
+
+/* These are for the internal registers in the SystemBus module
+ * The first is the length of the index register,
+ * the indexes of the various registers are defined after that.
+ */
+#define DBG_SYSBUS_REG_SEL_LEN         1
+#define DBG_SYSBUS_REG_ERROR           0
+
+
+/* Opcode definitions for the SystemBus module. */
+#define DBG_SYSBUS_OPCODE_LEN          4
+#define DBG_SYSBUS_CMD_NOP             0x0
+#define DBG_SYSBUS_CMD_BWRITE8         0x1
+#define DBG_SYSBUS_CMD_BWRITE16                0x2
+#define DBG_SYSBUS_CMD_BWRITE32                0x3
+#define DBG_SYSBUS_CMD_BWRITE64                0x4
+#define DBG_SYSBUS_CMD_BREAD8          0x5
+#define DBG_SYSBUS_CMD_BREAD16         0x6
+#define DBG_SYSBUS_CMD_BREAD32         0x7
+#define DBG_SYSBUS_CMD_BREAD64         0x8
+#define DBG_SYSBUS_CMD_IREG_WR         0x9
+#define DBG_SYSBUS_CMD_IREG_SEL                0xd
+
+
+/* Internal register definitions for the CP module. */
+#define DBG_CPU_REG_SEL_LEN            1
+#define DBG_CPU_REG_STATUS             0
+
+
+/* CPU Select */
+#define DBG_CPU_CPUSEL_LEN             4
+
+
+/* Opcode definitions for the CPU module. */
+#define DBG_CPU_OPCODE_LEN             4
+#define DBG_CPU_CMD_NOP                        0x0
+#define DBG_CPU_CMD_BWRITE32           0x3
+#define DBG_CPU_CMD_BREAD32            0x7
+#define DBG_CPU_CMD_IREG_WR            0x9
+#define DBG_CPU_CMD_IREG_SEL           0xd
+
+
+#define MAX_READ_STATUS_WAIT           10
+#define MAX_READ_BUSY_RETRY            2
+#define MAX_READ_CRC_RETRY             2
+#define MAX_WRITE_CRC_RETRY            2
+#define BURST_READ_READY               1
+#define MAX_BUS_ERRORS                 2
+
+#define MAX_BURST_SIZE                 (4 * 1024)
+
+#define STATUS_BYTES                   1
+#define CRC_LEN                                4
+
+static struct rl_du rl_dbg_adv;
+
+static const char * const chain_name[] = {"SYSBUS", "CPU", "JSP"};
+
+static uint32_t adbg_compute_crc(uint32_t crc, uint32_t data_in,
+                               int length_bits)
+{
+       for (int i = 0; i < length_bits; i++) {
+               uint32_t d, c;
+               d = ((data_in >> i) & 0x1) ? 0xffffffff : 0;
+               c = (crc & 0x1) ? 0xffffffff : 0;
+               crc = crc >> 1;
+               crc = crc ^ ((d ^ c) & ADBG_CRC_POLY);
+       }
+
+       return crc;
+}
+
+static int find_status_bit(void *_buf, int len)
+{
+       int i = 0;
+       int count = 0;
+       int ret = -1;
+       uint8_t *buf = _buf;
+
+       while (!(buf[i] & (1 << count++)) && (i < len)) {
+               if (count == 8) {
+                       count = 0;
+                       i++;
+               }
+       }
+
+       if (i < len)
+               ret = (i * 8) + count;
+
+       return ret;
+}
+
+static int rl_adv_jtag_init(struct rl_jtag *jtag_info)
+{
+       struct rl_tap_ip *tap_ip = jtag_info->tap_ip;
+
+       int retval = tap_ip->init(jtag_info);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("TAP initialization failed");
+               return retval;
+       }
+
+       /* TAP is now configured to communicate with debug interface */
+       jtag_info->rl_jtag_inited = 1;
+
+       /* TODO hardcoded HW parameters */
+    jtag_info->rl_jtag_address_size = 32;
+//     jtag_info->cpu_size = 4;
+       jtag_info->rl_jtag_cpu_selected = 0;
+       
+       /* TAP reset - not sure what state debug module chain is in now */
+       jtag_info->rl_jtag_module_selected = DC_NONE;
+
+       jtag_info->current_reg_idx = malloc(DBG_MAX_MODULES * sizeof(uint8_t));
+       memset(jtag_info->current_reg_idx, 0, DBG_MAX_MODULES * 
sizeof(uint8_t));
+
+       if (rl_dbg_adv.options & USE_HISPEED)
+               LOG_INFO("Roa Logic adv debug unit is configured with option 
USE_HISPEED");
+
+       if (rl_dbg_adv.options & ENABLE_JSP_SERVER) {
+               if (rl_dbg_adv.options & ENABLE_JSP_MULTI)
+                       LOG_INFO("Roa Logic adv debug unit is configured with 
option ENABLE_JSP_MULTI");
+               LOG_INFO("Roa Logic adv debug unit is configured with option 
ENABLE_JSP_SERVER");
+               retval = jsp_init(jtag_info, JSP_BANNER);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Couldn't start the JSP server");
+                       return retval;
+               }
+       }
+
+       LOG_DEBUG("Init done");
+
+       return ERROR_OK;
+
+}
+
+/* Selects one of the modules in the debug unit
+ * (e.g. SYSBUS, CPU, JSP)
+ */
+static int adbg_select_module(struct rl_jtag *jtag_info, int chain)
+{
+       if (jtag_info->rl_jtag_module_selected == chain)
+               return ERROR_OK;
+
+       /* MSB of the data out must be set to 1, indicating a module
+        * select command
+        */
+       uint8_t data = chain | (1 << DBG_MODULE_SELECT_REG_SIZE);
+
+       LOG_DEBUG("Select module: %s", chain_name[chain]);
+
+       struct scan_field field;
+
+       field.num_bits = (DBG_MODULE_SELECT_REG_SIZE + 1);
+       field.out_value = &data;
+       field.in_value = NULL;
+       jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
+
+       int retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       jtag_info->rl_jtag_module_selected = chain;
+
+       return ERROR_OK;
+}
+
+/* Set the index of the desired register in the currently selected module
+ * 1 bit module select command
+ * 4 bits opcode
+ * n bits index
+ */
+static int adbg_select_ctrl_reg(struct rl_jtag *jtag_info, uint8_t regidx)
+{
+       int index_len;
+       uint32_t opcode;
+       uint32_t opcode_len;
+
+       /* If this reg is already selected, don't do a JTAG transaction */
+       if (jtag_info->current_reg_idx[jtag_info->rl_jtag_module_selected] == 
regidx)
+               return ERROR_OK;
+
+       switch (jtag_info->rl_jtag_module_selected) {
+       case DC_SYSBUS:
+               index_len = DBG_SYSBUS_REG_SEL_LEN;
+               opcode = DBG_SYSBUS_CMD_IREG_SEL;
+               opcode_len = DBG_SYSBUS_OPCODE_LEN;
+               break;
+       case DC_CPU:
+               index_len = DBG_CPU_REG_SEL_LEN;
+               opcode = DBG_CPU_CMD_IREG_SEL;
+               opcode_len = DBG_CPU_OPCODE_LEN;
+               break;
+       default:
+               LOG_ERROR("Illegal debug chain selected (%i) while selecting 
control register",
+                         jtag_info->rl_jtag_module_selected);
+               return ERROR_FAIL;
+       }
+
+       /* MSB must be 0 to access modules */
+       uint32_t data = (opcode & ~(1 << opcode_len)) << index_len;
+       data |= regidx;
+
+       struct scan_field field;
+
+       field.num_bits = (opcode_len + 1) + index_len;
+       field.out_value = (uint8_t *)&data;
+       field.in_value = NULL;
+       jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
+
+       int retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       jtag_info->current_reg_idx[jtag_info->rl_jtag_module_selected] = regidx;
+
+       return ERROR_OK;
+}
+
+/* Write control register (internal to the debug unit) */
+static int adbg_ctrl_write(struct rl_jtag *jtag_info, uint8_t regidx,
+                          uint32_t *cmd_data, int length_bits)
+{
+       int index_len;
+       int cpusel_len;
+       int cpusel;
+       uint32_t opcode;
+       uint32_t opcode_len;
+
+       LOG_DEBUG("Write control register %" PRId8 ": 0x%08" PRIx32, regidx, 
cmd_data[0]);
+
+       int retval = adbg_select_ctrl_reg(jtag_info, regidx);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while calling adbg_select_ctrl_reg");
+               return retval;
+       }
+
+       switch (jtag_info->rl_jtag_module_selected) {
+       case DC_SYSBUS:
+               index_len  = DBG_SYSBUS_REG_SEL_LEN;
+               cpusel     = 0;
+               cpusel_len = 0;
+               opcode     = DBG_SYSBUS_CMD_IREG_WR;
+               opcode_len = DBG_SYSBUS_OPCODE_LEN;
+               break;
+       case DC_CPU:
+               index_len  = DBG_CPU_REG_SEL_LEN;
+               cpusel     = jtag_info->rl_jtag_cpu_selected;
+               cpusel_len = DBG_CPU_CPUSEL_LEN;
+               opcode     = DBG_CPU_CMD_IREG_WR;
+               opcode_len = DBG_CPU_OPCODE_LEN;
+               break;
+       default:
+               LOG_ERROR("Illegal debug chain selected (%i) while doing 
control write",
+                         jtag_info->rl_jtag_module_selected);
+               return ERROR_FAIL;
+       }
+
+       struct scan_field field[2];
+
+       /* MSB must be 0 to access modules */
+       uint32_t data = ~(1 << (opcode_len + cpusel_len + index_len));
+       data &= (((opcode << cpusel_len) | cpusel ) << index_len);
+       data |= regidx;
+
+       field[0].num_bits  = length_bits;
+       field[0].out_value = (uint8_t *)cmd_data;
+       field[0].in_value  = NULL;
+
+       field[1].num_bits  = 1+ opcode_len + cpusel_len + index_len;
+       field[1].out_value = (uint8_t *)&data;
+       field[1].in_value  = NULL;
+
+       jtag_add_dr_scan(jtag_info->tap, 2, field, TAP_IDLE);
+
+       return jtag_execute_queue();
+}
+
+/* Reads control register (internal to the debug unit) */
+static int adbg_ctrl_read(struct rl_jtag *jtag_info, uint32_t regidx,
+                         uint32_t *data, int length_bits)
+{
+
+       int retval = adbg_select_ctrl_reg(jtag_info, regidx);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while calling adbg_select_ctrl_reg");
+               return retval;
+       }
+
+       int cpusel = 0;
+       int cpusel_len;
+       int opcode_len;
+       uint32_t opcode;
+
+       /* There is no 'read' command, We write a NOP to read */
+       switch (jtag_info->rl_jtag_module_selected) {
+       case DC_SYSBUS:
+               cpusel_len = 0;
+               opcode     = DBG_SYSBUS_CMD_NOP;
+               opcode_len = DBG_SYSBUS_OPCODE_LEN;
+               break;
+       case DC_CPU:
+               cpusel     = jtag_info->rl_jtag_cpu_selected;
+               cpusel_len = DBG_CPU_CPUSEL_LEN;
+               opcode     = DBG_CPU_CMD_NOP;
+               opcode_len = DBG_CPU_OPCODE_LEN;
+               break;
+       default:
+               LOG_ERROR("Illegal debug chain selected (%i) while doing 
control read",
+                         jtag_info->rl_jtag_module_selected);
+               return ERROR_FAIL;
+       }
+
+       /* Zero MSB = op for module, not top-level debug unit */
+       uint32_t outdata = ~(1 << (opcode_len + cpusel_len));
+       outdata &= (opcode << cpusel_len) | cpusel;
+
+       struct scan_field field[2];
+
+       field[0].num_bits  = length_bits;
+       field[0].out_value = NULL;
+       field[0].in_value  = (uint8_t *)data;
+
+       field[1].num_bits  = opcode_len + cpusel_len + 1;
+       field[1].out_value = (uint8_t *)&outdata;
+       field[1].in_value  = NULL;
+
+       jtag_add_dr_scan(jtag_info->tap, 2, field, TAP_IDLE);
+
+       return jtag_execute_queue();
+}
+
+/* sends out a burst command to the selected module in the debug unit (MSB to 
LSB):
+ * 1-bit module command
+ * 4-bit opcode
+ * 4-bit CPU (optional)
+ * 32/64-bit address
+ * 16-bit length (of the burst, in words)
+ */
+static int adbg_burst_command(struct rl_jtag *jtag_info,
+                             uint32_t opcode, uint8_t opcode_len,
+                             uint64_t address, uint8_t address_len,
+                             uint32_t cpusel, uint8_t cpusel_len,
+                             uint16_t length_words)
+{
+       uint32_t bitcount;
+       uint32_t data[3];
+
+       /* Total bitcount */
+       bitcount  = 1;            //1bit module command
+       bitcount += opcode_len;   //4bit opcode
+       bitcount += cpusel_len;   //4bit CPU select
+       bitcount += address_len;  //Address
+       bitcount += 16;           //Burst Length
+       
+       /* Set up the data */
+       switch (address_len) {
+       case 32: 
+               data[0] = (address << 16) | length_words;
+               data[1] = opcode;
+               if (cpusel_len) {
+                       data[1] = (data[1] << cpusel_len) | cpusel;
+               }
+               data[1] = (data[1] << 16) | (address >> 16);
+
+               /* MSB must be 0 to access modules */           
+               data[1] &= ~(1 << (16 + cpusel_len + opcode_len));
+               break;
+       case 64:
+               data[0] = (address << 16) | length_words;
+               data[1] = address >> 16;
+               data[2] = opcode;
+               if (cpusel_len) {
+                       data[2] = (data[2] << cpusel_len) | cpusel;
+               }
+               data[2] = (data[2] << 16) | (address >> 48);
+               
+               data[2] &= ~(1 << (16 + cpusel_len + opcode_len));
+               break;
+       default:
+               LOG_ERROR("Unsupported address-length (%i)", address_len);
+               return ERROR_FAIL;
+       }
+       
+       struct scan_field field;
+
+       field.num_bits  = bitcount;
+       field.out_value = (uint8_t *)&data[0];
+       field.in_value  = NULL;
+
+       jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
+
+       return jtag_execute_queue();
+}
+
+static int adbg_sysbus_burst_read(struct rl_jtag *jtag_info, int size,
+                                 int count, uint32_t start_address, uint8_t 
*data)
+{
+       int retry_full_crc = 0;
+       int retry_full_busy = 0;
+       int retval;
+
+       uint8_t opcode;
+       uint8_t opcode_len;
+       uint8_t cpusel = 0;
+       uint8_t cpusel_len;
+       uint8_t address_len;
+
+       LOG_DEBUG("Doing burst read, word size %d, word count %d, start address 
0x%08" PRIx32,
+                 size, count, start_address);
+
+       /* Select the appropriate opcode */
+       switch (jtag_info->rl_jtag_module_selected) {
+       case DC_SYSBUS:
+               if (size == 1)
+                       opcode = DBG_SYSBUS_CMD_BREAD8;
+               else if (size == 2)
+                       opcode = DBG_SYSBUS_CMD_BREAD16;
+               else if (size == 4)
+                       opcode = DBG_SYSBUS_CMD_BREAD32;
+               else if (size == 8)
+                       opcode = DBG_SYSBUS_CMD_BREAD64;
+               else {
+                       LOG_WARNING("Tried burst read with invalid word size 
(%d),"
+                                 "defaulting to 4-byte words", size);
+                       opcode = DBG_SYSBUS_CMD_BREAD32;
+               }
+               opcode_len = DBG_SYSBUS_OPCODE_LEN;
+               cpusel_len = 0;
+               break;
+       case DC_CPU:
+               if (size == 4)
+                       opcode = DBG_CPU_CMD_BREAD32;
+               else {
+                       LOG_WARNING("Tried burst read with invalid word size 
(%d),"
+                                 "defaulting to 4-byte words", size);
+                       opcode = DBG_CPU_CMD_BREAD32;
+               }
+               opcode_len = DBG_CPU_OPCODE_LEN;
+               cpusel     = jtag_info->rl_jtag_cpu_selected;
+                cpusel_len = DBG_CPU_CPUSEL_LEN;
+               break;
+       default:
+               LOG_ERROR("Illegal debug chain selected (%i) while doing burst 
read",
+                         jtag_info->rl_jtag_module_selected);
+               return ERROR_FAIL;
+       }
+       address_len = jtag_info->rl_jtag_address_size;
+
+
+       int total_size_bytes = count * size;
+       struct scan_field field;
+       uint8_t *in_buffer = malloc(total_size_bytes + CRC_LEN + STATUS_BYTES);
+
+retry_read_full:
+
+       /* Send the BURST READ command, returns TAP to idle state */
+       retval = adbg_burst_command(jtag_info, opcode, opcode_len,
+                                   start_address, address_len, cpusel, 
cpusel_len, count);
+
+       if (retval != ERROR_OK)
+               goto out;
+
+       field.num_bits = (total_size_bytes + CRC_LEN + STATUS_BYTES) * 8;
+       field.out_value = NULL;
+       field.in_value = in_buffer;
+
+       jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
+
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               goto out;
+
+       /* Look for the start bit in the first (STATUS_BYTES * 8) bits */
+       int shift = find_status_bit(in_buffer, STATUS_BYTES);
+
+       /* We expect the status bit to be in the first byte */
+       if (shift < 0) {
+               if (retry_full_busy++ < MAX_READ_BUSY_RETRY) {
+                       LOG_WARNING("Burst read timed out");
+                       goto retry_read_full;
+               } else {
+                       LOG_ERROR("Burst read failed");
+                       retval = ERROR_FAIL;
+                       goto out;
+               }
+       }
+
+       buffer_shr(in_buffer, total_size_bytes + CRC_LEN + STATUS_BYTES, shift);
+
+       uint32_t crc_read;
+       memcpy(data, in_buffer, total_size_bytes);
+       memcpy(&crc_read, &in_buffer[total_size_bytes], 4);
+
+       uint32_t crc_calc = 0xffffffff;
+       for (int i = 0; i < total_size_bytes; i++)
+               crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
+
+       if (crc_calc != crc_read) {
+               LOG_WARNING("CRC ERROR! Computed 0x%08" PRIx32 ", read CRC 
0x%08" PRIx32, crc_calc, crc_read);
+               if (retry_full_crc++ < MAX_READ_CRC_RETRY)
+                       goto retry_read_full;
+               else {
+                       LOG_ERROR("Burst read failed");
+                       retval = ERROR_FAIL;
+                       goto out;
+               }
+       } else
+               LOG_DEBUG("CRC OK!");
+
+       /* Now, read the error register, and retry/recompute as necessary */
+       if (jtag_info->rl_jtag_module_selected == DC_SYSBUS &&
+           !(rl_dbg_adv.options & USE_HISPEED)) {
+
+               uint32_t err_data[2] = {0, 0};
+               uint32_t addr;
+               int bus_error_retries = 0;
+
+               /* First, just get 1 bit...read address only if necessary */
+               retval = adbg_ctrl_read(jtag_info, DBG_SYSBUS_REG_ERROR, 
err_data, 1);
+               if (retval != ERROR_OK)
+                       goto out;
+
+               /* Then we have a problem */
+               if (err_data[0] & 0x1) {
+
+                       retval = adbg_ctrl_read(jtag_info, 
DBG_SYSBUS_REG_ERROR, err_data, 33);
+                       if (retval != ERROR_OK)
+                               goto out;
+
+                       addr = (err_data[0] >> 1) | (err_data[1] << 31);
+                       LOG_WARNING("SYSBUS bus error during burst read, 
address 0x%08" PRIx32 ", retrying!", addr);
+
+                       bus_error_retries++;
+                       if (bus_error_retries > MAX_BUS_ERRORS) {
+                               LOG_ERROR("Max SYSBUS bus errors reached during 
burst read");
+                               retval = ERROR_FAIL;
+                               goto out;
+                       }
+
+                       /* Don't call retry_do(), a JTAG reset won't help a 
SYSBUS bus error */
+                       /* Write 1 bit, to reset the error register */
+                       err_data[0] = 1;
+                       retval = adbg_ctrl_write(jtag_info, 
DBG_SYSBUS_REG_ERROR, err_data, 1);
+                       if (retval != ERROR_OK)
+                               goto out;
+
+                       goto retry_read_full;
+               }
+       }
+
+out:
+       free(in_buffer);
+
+       return retval;
+}
+
+/* Set up and execute a burst write to a contiguous set of addresses */
+static int adbg_sysbus_burst_write(struct rl_jtag *jtag_info, const uint8_t 
*data, int size,
+                                   int count, unsigned long start_address)
+{
+       int retry_full_crc = 0;
+       int retval;
+
+       uint8_t opcode;
+       uint8_t opcode_len;
+       uint8_t cpusel = 0;
+       uint8_t cpusel_len;
+       uint8_t address_len;
+
+       LOG_DEBUG("Doing burst write, word size %d, word count %d,"
+                 "start address 0x%08lx", size, count, start_address);
+
+       /* Select the appropriate opcode */
+       switch (jtag_info->rl_jtag_module_selected) {
+       case DC_SYSBUS:
+               if (size == 1)
+                       opcode = DBG_SYSBUS_CMD_BWRITE8;
+               else if (size == 2)
+                       opcode = DBG_SYSBUS_CMD_BWRITE16;
+               else if (size == 4)
+                       opcode = DBG_SYSBUS_CMD_BWRITE32;
+               else if (size == 8)
+                       opcode = DBG_SYSBUS_CMD_BWRITE64;
+               else {
+                       LOG_DEBUG("Tried SYSBUS burst write with invalid word 
size (%d),"
+                                 "defaulting to 4-byte words", size);
+                       opcode = DBG_SYSBUS_CMD_BWRITE32;
+               }
+               opcode_len = DBG_SYSBUS_OPCODE_LEN;
+               cpusel_len = 0;
+               break;
+       case DC_CPU:
+               if (size == 4)
+                       opcode = DBG_CPU_CMD_BWRITE32;
+               else {
+                       LOG_DEBUG("Tried CPU burst write with invalid word size 
(%d),"
+                                 "defaulting to 4-byte words", size);
+                       opcode = DBG_CPU_CMD_BWRITE32;
+               }
+               opcode_len = DBG_CPU_OPCODE_LEN;
+               cpusel     = jtag_info->rl_jtag_cpu_selected;
+               cpusel_len = DBG_CPU_CPUSEL_LEN;
+               break;
+       default:
+               LOG_ERROR("Illegal debug chain selected (%i) while doing burst 
write",
+                         jtag_info->rl_jtag_module_selected);
+               return ERROR_FAIL;
+       }
+       address_len = jtag_info->rl_jtag_address_size;
+
+
+retry_full_write:
+
+       /* Send the BURST WRITE command, returns TAP to idle state */
+       retval = adbg_burst_command(jtag_info, opcode, opcode_len,
+                               start_address, address_len, cpusel, cpusel_len, 
count);
+
+       if (retval != ERROR_OK)
+               return retval;
+
+       struct scan_field field[3];
+
+       /* Write a start bit so it knows when to start counting */
+       uint8_t value = 1;
+       field[0].num_bits = 1;
+       field[0].out_value = &value;
+       field[0].in_value = NULL;
+
+       uint32_t crc_calc = 0xffffffff;
+       for (int i = 0; i < (count * size); i++)
+               crc_calc = adbg_compute_crc(crc_calc, data[i], 8);
+
+       field[1].num_bits = count * size * 8;
+       field[1].out_value = data;
+       field[1].in_value = NULL;
+
+       field[2].num_bits = 32;
+       field[2].out_value = (uint8_t *)&crc_calc;
+       field[2].in_value = NULL;
+
+       jtag_add_dr_scan(jtag_info->tap, 3, field, TAP_DRSHIFT);
+
+       /* Read the 'CRC match' bit, and go to idle */
+       field[0].num_bits = 1;
+       field[0].out_value = NULL;
+       field[0].in_value = &value;
+       jtag_add_dr_scan(jtag_info->tap, 1, field, TAP_IDLE);
+
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (!value) {
+               LOG_WARNING("CRC ERROR! match bit after write is %" PRIi8 " 
(computed CRC 0x%08" PRIx32 ")", value, crc_calc);
+               if (retry_full_crc++ < MAX_WRITE_CRC_RETRY)
+                       goto retry_full_write;
+               else
+                       return ERROR_FAIL;
+       } else
+               LOG_DEBUG("CRC OK!\n");
+
+       /* Now, read the error register, and retry/recompute as necessary */
+       if (jtag_info->rl_jtag_module_selected == DC_SYSBUS &&
+           !(rl_dbg_adv.options & USE_HISPEED)) {
+               uint32_t addr;
+               int bus_error_retries = 0;
+               uint32_t err_data[2] = {0, 0};
+
+               /* First, just get 1 bit...read address only if necessary */
+               retval = adbg_ctrl_read(jtag_info, DBG_SYSBUS_REG_ERROR, 
err_data, 1);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               /* Then we have a problem */
+               if (err_data[0] & 0x1) {
+
+                       retval = adbg_ctrl_read(jtag_info, 
DBG_SYSBUS_REG_ERROR, err_data, 33);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       addr = (err_data[0] >> 1) | (err_data[1] << 31);
+                       LOG_WARNING("SYSBUS bus error during burst write, 
address 0x%08" PRIx32 ", retrying!", addr);
+
+                       bus_error_retries++;
+                       if (bus_error_retries > MAX_BUS_ERRORS) {
+                               LOG_ERROR("Max SYSBUS bus errors reached during 
burst read");
+                               retval = ERROR_FAIL;
+                               return retval;
+                       }
+
+                       /* Don't call retry_do(), a JTAG reset won't help a 
SYSBUS bus error */
+                       /* Write 1 bit, to reset the error register */
+                       err_data[0] = 1;
+                       retval = adbg_ctrl_write(jtag_info, 
DBG_SYSBUS_REG_ERROR, err_data, 1);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       goto retry_full_write;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+/* Currently hard set in functions to 32-bits */
+static int rl_adv_jtag_read_cpu(struct rl_jtag *jtag_info,
+               uint32_t addr, int count, uint32_t *value)
+{
+       int retval;
+       if (!jtag_info->rl_jtag_inited) {
+               retval = rl_adv_jtag_init(jtag_info);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       retval = adbg_select_module(jtag_info, DC_CPU);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return adbg_sysbus_burst_read(jtag_info, 4, count, addr, (uint8_t 
*)value);
+}
+
+static int rl_adv_jtag_write_cpu(struct rl_jtag *jtag_info,
+               uint32_t addr, int count, const uint32_t *value)
+{
+       int retval;
+       if (!jtag_info->rl_jtag_inited) {
+               retval = rl_adv_jtag_init(jtag_info);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       retval = adbg_select_module(jtag_info, DC_CPU);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return adbg_sysbus_burst_write(jtag_info, (uint8_t *)value, 4, count, 
addr);
+}
+
+static int rl_adv_cpu_stall(struct rl_jtag *jtag_info, int action)
+{
+       int retval;
+       if (!jtag_info->rl_jtag_inited) {
+               retval = rl_adv_jtag_init(jtag_info);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       retval = adbg_select_module(jtag_info, DC_CPU);
+       if (retval != ERROR_OK)
+               return retval;
+
+       //TODO: the '2' length should be NumberOfCPU
+       uint32_t cpu_cr;
+       retval = adbg_ctrl_read(jtag_info, DBG_CPU_REG_STATUS, &cpu_cr, 2);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (action == CPU_STALL)
+               cpu_cr |= DBG_CPU_CR_STALL;
+       else
+               cpu_cr &= ~DBG_CPU_CR_STALL;
+
+       retval = adbg_select_module(jtag_info, DC_CPU);
+       if (retval != ERROR_OK)
+               return retval;
+
+        //TODO: the '2' length should be number of CPUs
+       return adbg_ctrl_write(jtag_info, DBG_CPU_REG_STATUS, &cpu_cr, 2);
+}
+
+static int rl_adv_is_cpu_running(struct rl_jtag *jtag_info, int *running)
+{
+       int retval;
+       if (!jtag_info->rl_jtag_inited) {
+               retval = rl_adv_jtag_init(jtag_info);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       int current = jtag_info->rl_jtag_module_selected;
+
+       retval = adbg_select_module(jtag_info, DC_CPU);
+       if (retval != ERROR_OK)
+               return retval;
+
+       uint32_t cpu_cr = 0;
+       retval = adbg_ctrl_read(jtag_info, DBG_CPU_REG_STATUS, &cpu_cr, 2);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (cpu_cr & DBG_CPU_CR_STALL)
+               *running = 0;
+       else
+               *running = 1;
+
+       if (current != DC_NONE) {
+               retval = adbg_select_module(jtag_info, current);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
+
+static int rl_adv_cpu_reset(struct rl_jtag *jtag_info, int action)
+{
+       int retval;
+       if (!jtag_info->rl_jtag_inited) {
+               retval = rl_adv_jtag_init(jtag_info);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       retval = adbg_select_module(jtag_info, DC_CPU);
+       if (retval != ERROR_OK)
+               return retval;
+
+       uint32_t cpu_cr;
+       retval = adbg_ctrl_read(jtag_info, DBG_CPU_REG_STATUS, &cpu_cr, 2);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (action == CPU_RESET)
+               cpu_cr |= DBG_CPU_CR_RESET;
+       else
+               cpu_cr &= ~DBG_CPU_CR_RESET;
+
+       retval = adbg_select_module(jtag_info, DC_CPU);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return adbg_ctrl_write(jtag_info, DBG_CPU_REG_STATUS, &cpu_cr, 2);
+}
+
+static int rl_adv_jtag_read_memory(struct rl_jtag *jtag_info,
+                           uint32_t addr, uint32_t size, int count, uint8_t 
*buffer)
+{
+       LOG_DEBUG("Reading SYSBUS%" PRIu32 " at 0x%08" PRIx32, size * 8, addr);
+
+       int retval;
+       if (!jtag_info->rl_jtag_inited) {
+               retval = rl_adv_jtag_init(jtag_info);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       retval = adbg_select_module(jtag_info, DC_SYSBUS);
+       if (retval != ERROR_OK)
+               return retval;
+
+       int block_count_left = count;
+       uint32_t block_count_address = addr;
+       uint8_t *block_count_buffer = buffer;
+
+       while (block_count_left) {
+
+               int blocks_this_round = (block_count_left > MAX_BURST_SIZE) ?
+                       MAX_BURST_SIZE : block_count_left;
+
+               retval = adbg_sysbus_burst_read(jtag_info, size, 
blocks_this_round,
+                                               block_count_address, 
block_count_buffer);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               block_count_left    -= blocks_this_round;
+               block_count_address += size * MAX_BURST_SIZE;
+               block_count_buffer  += size * MAX_BURST_SIZE;
+       }
+
+       /* The adv_debug_if always return words and half words in
+        * little-endian order no matter what the target endian is.
+        * So if the target endian is big, change the order.
+        */
+
+       struct target *target = jtag_info->target;
+       if ((target->endianness == TARGET_BIG_ENDIAN) && (size != 1)) {
+               switch (size) {
+               case 4:
+                       buf_bswap32(buffer, buffer, size * count);
+                       break;
+               case 2:
+                       buf_bswap16(buffer, buffer, size * count);
+                       break;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int rl_adv_jtag_write_memory(struct rl_jtag *jtag_info,
+                            uint32_t addr, uint32_t size, int count, const 
uint8_t *buffer)
+{
+       LOG_DEBUG("Writing SYSBUS%" PRIu32 " at 0x%08" PRIx32, size * 8, addr);
+
+       int retval;
+       if (!jtag_info->rl_jtag_inited) {
+               retval = rl_adv_jtag_init(jtag_info);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       retval = adbg_select_module(jtag_info, DC_SYSBUS);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* The adv_debug_if wants words and half words in little-endian
+        * order no matter what the target endian is. So if the target
+        * endian is big, change the order.
+        */
+
+       void *t = NULL;
+       struct target *target = jtag_info->target;
+       if ((target->endianness == TARGET_BIG_ENDIAN) && (size != 1)) {
+               t = malloc(count * size * sizeof(uint8_t));
+               if (!t) {
+                       LOG_ERROR("Out of memory");
+                       return ERROR_FAIL;
+               }
+
+               switch (size) {
+               // case 8:
+               //      bus_bswap64(t, buffer, size * count);
+               //      break;
+               case 4:
+                       buf_bswap32(t, buffer, size * count);
+                       break;
+               case 2:
+                       buf_bswap16(t, buffer, size * count);
+                       break;
+               }
+               buffer = t;
+       }
+
+       int block_count_left = count;
+       uint32_t block_count_address = addr;
+       uint8_t *block_count_buffer = (uint8_t *)buffer;
+
+       while (block_count_left) {
+
+               int blocks_this_round = (block_count_left > MAX_BURST_SIZE) ?
+                       MAX_BURST_SIZE : block_count_left;
+
+               retval = adbg_sysbus_burst_write(jtag_info, block_count_buffer,
+                                                size, blocks_this_round,
+                                                block_count_address);
+               if (retval != ERROR_OK) {
+                       free(t);
+                       return retval;
+               }
+
+               block_count_left    -= blocks_this_round;
+               block_count_address += size * MAX_BURST_SIZE;
+               block_count_buffer  += size * MAX_BURST_SIZE;
+       }
+
+       free(t);
+       return ERROR_OK;
+}
+
+int rl_adv_jtag_jsp_xfer(struct rl_jtag *jtag_info,
+                                 int *out_len, unsigned char *out_buffer,
+                                 int *in_len, unsigned char *in_buffer)
+{
+       LOG_DEBUG("JSP transfer");
+
+       int retval;
+       if (!jtag_info->rl_jtag_inited)
+               return ERROR_OK;
+
+       retval = adbg_select_module(jtag_info, DC_JSP);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* return nb char xmit */
+       int xmitsize;
+       if (*out_len > 8)
+               xmitsize = 8;
+       else
+               xmitsize = *out_len;
+
+       uint8_t out_data[10];
+       uint8_t in_data[10];
+       struct scan_field field;
+       int startbit, stopbit, wrapbit;
+
+       memset(out_data, 0, 10);
+
+       if (rl_dbg_adv.options & ENABLE_JSP_MULTI) {
+
+               startbit = 1;
+               wrapbit = (xmitsize >> 3) & 0x1;
+               out_data[0] = (xmitsize << 5) | 0x1;  /* set the start bit */
+
+               int i;
+               /* don't copy off the end of the input array */
+               for (i = 0; i < xmitsize; i++) {
+                       out_data[i + 1] = (out_buffer[i] << 1) | wrapbit;
+                       wrapbit = (out_buffer[i] >> 7) & 0x1;
+               }
+
+               if (i < 8)
+                       out_data[i + 1] = wrapbit;
+               else
+                       out_data[9] = wrapbit;
+
+               /* If the last data bit is a '1', then we need to append a '0' 
so the top-level module
+                * won't treat the burst as a 'module select' command.
+                */
+               stopbit = !!(out_data[9] & 0x01);
+
+       } else {
+               startbit = 0;
+               /* First byte out has write count in upper nibble */
+               out_data[0] = 0x0 | (xmitsize << 4);
+               if (xmitsize > 0)
+                       memcpy(&out_data[1], out_buffer, xmitsize);
+
+               /* If the last data bit is a '1', then we need to append a '0' 
so the top-level module
+                * won't treat the burst as a 'module select' command.
+                */
+               stopbit = !!(out_data[8] & 0x80);
+       }
+
+       field.num_bits = 72 + startbit + stopbit;
+       field.out_value = out_data;
+       field.in_value = in_data;
+
+       jtag_add_dr_scan(jtag_info->tap, 1, &field, TAP_IDLE);
+
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* bytes available is in the upper nibble */
+       *in_len = (in_data[0] >> 4) & 0xF;
+       memcpy(in_buffer, &in_data[1], *in_len);
+
+       int bytes_free = in_data[0] & 0x0F;
+       *out_len = (bytes_free < xmitsize) ? bytes_free : xmitsize;
+
+       return ERROR_OK;
+}
+
+static struct rl_du rl_dbg_adv = {
+       .name                   = "rl_dbg_adv",
+       .options                = NO_OPTION,
+       .rl_jtag_init           = rl_adv_jtag_init,
+
+       .rl_is_cpu_running      = rl_adv_is_cpu_running,
+       .rl_cpu_stall           = rl_adv_cpu_stall,
+       .rl_cpu_reset           = rl_adv_cpu_reset,
+
+       .rl_jtag_read_cpu       = rl_adv_jtag_read_cpu,
+       .rl_jtag_write_cpu      = rl_adv_jtag_write_cpu,
+
+       .rl_jtag_read_memory    = rl_adv_jtag_read_memory,
+       .rl_jtag_write_memory   = rl_adv_jtag_write_memory
+};
+
+int rl_dbg_adv_register(void)
+{
+       list_add_tail(&rl_dbg_adv.list, &rl_du_list);
+       return 0;
+}
diff --git a/src/target/roalogic/rl_dbg_adv.h b/src/target/roalogic/rl_dbg_adv.h
new file mode 100644
index 0000000000..44a84ca090
--- /dev/null
+++ b/src/target/roalogic/rl_dbg_adv.h
@@ -0,0 +1,81 @@
+/***************************************************************************
+ *   Copyright (C) 2022 Richard Herveille                                  *
+ *   richard.hervei...@roalogic.com                                        *
+ *                                                                         *
+ *   Copyright (C) 2022 by Bjorn Schouteten                                *
+ *   bjorn.schoute...@roalogic.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_ROALOGIC_DBG_ADV_H
+#define OPENOCD_TARGET_ROALOGIC_DBG_ADV_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CPU_STALL      0
+#define CPU_UNSTALL    1
+
+#define CPU_RESET      0
+#define CPU_NOT_RESET  1
+
+int rl_dbg_adv_register(void);
+
+/* Linear list over all available or1k debug unit */
+extern struct list_head rl_du_list;
+
+struct rl_du {
+       const char *name;
+       struct list_head list;
+       int options;
+
+       int (*rl_jtag_init)(struct rl_jtag *jtag_info);
+
+       int (*rl_is_cpu_running)(struct rl_jtag *jtag_info, int *running);
+
+       int (*rl_cpu_stall)(struct rl_jtag *jtag_info, int action);
+
+       int (*rl_cpu_reset)(struct rl_jtag *jtag_info, int action);
+    
+       int (*rl_jtag_read_cpu)(struct rl_jtag *jtag_info,
+                               uint32_t addr, int count, uint32_t *value);
+
+       int (*rl_jtag_write_cpu)(struct rl_jtag *jtag_info,
+                                uint32_t addr, int count, const uint32_t 
*value);
+
+       int (*rl_jtag_read_memory)(struct rl_jtag *jtag_info, uint32_t addr, 
uint32_t size,
+                                  int count, uint8_t *buffer);
+
+       int (*rl_jtag_write_memory)(struct rl_jtag *jtag_info, uint32_t addr, 
uint32_t size,
+                                   int count, const uint8_t *buffer);
+};
+
+static inline struct rl_du *rl_jtag_to_du(struct rl_jtag *jtag_info)
+{
+       return (struct rl_du *)jtag_info->du_core;
+}
+
+static inline struct rl_du *rl_to_du(struct rv12_common *rvl)
+{
+       struct rl_jtag *jtag = &rvl->jtag;
+       return (struct rl_du *)jtag->du_core;
+}
+
+int rl_adv_jtag_jsp_xfer(struct rl_jtag *jtag_info,
+                       int *out_len, unsigned char *out_buffer,
+                       int *in_len, unsigned char *in_buffer);
+
+#endif /* OPENOCD_TARGET_ROALOGIC_DBG_ADV_H */
diff --git a/src/target/roalogic/rl_tap.h b/src/target/roalogic/rl_tap.h
new file mode 100644
index 0000000000..70baa213ea
--- /dev/null
+++ b/src/target/roalogic/rl_tap.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ *   Copyright (C) 2022 by Richard Herveille                               *
+ *   richard.hervei...@roalogic.com                                        *
+ *                                                                         *
+ *   Copyright (C) 2022 by Bjorn Schouteten                                *
+ *   bjorn.schoute...@roalogic.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_ROALOGIC_RL_TAP_H
+#define OPENOCD_TARGET_ROALOGIC_RL_TAP_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/list.h>
+#include "rv12.h"
+
+int rl_tap_vjtag_register(void);
+int rl_universal_tap_register(void);
+
+/* Linear list over all available Roa Logic TAPs */
+extern struct list_head rl_tap_list;
+
+struct rl_tap_ip {
+       struct list_head list;
+       int (*init)(struct rl_jtag *jtag_info);
+       const char *name;
+};
+
+#endif /* OPENOCD_TARGET_ROALOGIC_RL_TAP_H */
diff --git a/src/target/roalogic/rl_universal_tap.c 
b/src/target/roalogic/rl_universal_tap.c
new file mode 100644
index 0000000000..3675ea93ae
--- /dev/null
+++ b/src/target/roalogic/rl_universal_tap.c
@@ -0,0 +1,69 @@
+/***************************************************************************
+ *   Copyright (C) 2022 by Richard Herveille                               *
+ *   richard.hervei...@roalogic.com                                        *
+ *                                                                         *
+ *   Copyright (C) 2022 by Bjorn Schouteten                                *
+ *   bjorn.schoute...@roalogic.com                                         *
+ *                                                                         * 
+ *                                                                         *
+ *   Based on OR1k Version                                                 *
+ *                                                                         *
+ *   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 "rl_tap.h"
+#include "rv12.h"
+
+#include <jtag/jtag.h>
+
+#define RL_TAP_INST_DEBUG      0x8
+
+static int rl_universal_tap_init(struct rl_jtag *jtag_info)
+{
+       LOG_DEBUG("Initialising Roa Logic Universal JTAG TAP");
+
+       /* Put TAP into state where it can talk to the debug interface
+        * by shifting in correct value to IR.
+        */
+
+       /* Ensure TAP is reset - maybe not necessary*/
+       jtag_add_tlr();
+
+       struct jtag_tap *tap = jtag_info->tap;
+       struct scan_field field;
+       uint8_t ir_value = RL_TAP_INST_DEBUG;
+
+       field.num_bits = tap->ir_length;
+       field.out_value = &ir_value;
+       field.in_value = NULL;
+
+       jtag_add_ir_scan(tap, &field, TAP_IDLE);
+
+       return jtag_execute_queue();
+}
+
+static struct rl_tap_ip universal_tap = {
+       .name = "rl_universal_tap",
+       .init = rl_universal_tap_init,
+};
+
+int rl_universal_tap_register(void)
+{
+       list_add_tail(&universal_tap.list, &rl_tap_list);
+       return 0;
+}
diff --git a/src/target/roalogic/rv12.c b/src/target/roalogic/rv12.c
new file mode 100644
index 0000000000..6393a755d9
--- /dev/null
+++ b/src/target/roalogic/rv12.c
@@ -0,0 +1,1884 @@
+/***************************************************************************
+ *   Copyright (C) 2022 by Richard Herveille                               *
+ *   richard.hervei...@roalogic.com                                        *
+ *                                                                         *
+ *   Copyright (C) 2022 by Bjorn Schouteten                                *
+ *   bjorn.schoute...@roalogic.com                                         *
+ *                                                                         * 
+ *   Based on OR1K version                                                 *
+ *                                                                         *
+ *                                                                         *
+ *   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/jtag.h>
+#include <target/register.h>
+#include <target/target.h>
+#include <target/breakpoints.h>
+#include <target/target_type.h>
+#include <helper/time_support.h>
+#include <helper/fileio.h>
+#include "rl_tap.h"
+#include "rv12.h"
+#include "rl_dbg_adv.h"
+
+LIST_HEAD(rl_tap_list);
+LIST_HEAD(rl_du_list);
+
+static int rv12_remove_breakpoint(struct target *target,
+                                        struct breakpoint *breakpoint);
+
+static int rv12_read_core_reg(struct target *target, int num);
+static int rv12_write_core_reg(struct target *target, int num);
+
+static struct rv12_core_reg *rv12_core_reg_list_arch_info;
+
+/* Combination of RISC-V and rv12 names
+ * until rv12 uses RISC-V debug spec */
+static const struct rv12_core_reg_init rv12_init_reg_list[] = {
+       /* Integer Register File */
+       {"zero",          GROUP_RF   +  0,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"ra",            GROUP_RF   +  1,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"sp",            GROUP_RF   +  2,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"gp",            GROUP_RF   +  3,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"tp",            GROUP_RF   +  4,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"t0",            GROUP_RF   +  5,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"t1",            GROUP_RF   +  6,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"t2",            GROUP_RF   +  7,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s0",            GROUP_RF   +  8,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s1",            GROUP_RF   +  9,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"a0",            GROUP_RF   + 10,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"a1",            GROUP_RF   + 11,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"a2",            GROUP_RF   + 12,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"a3",            GROUP_RF   + 13,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"a4",            GROUP_RF   + 14,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"a5",            GROUP_RF   + 15,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"a6",            GROUP_RF   + 16,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"a7",            GROUP_RF   + 17,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s2",            GROUP_RF   + 18,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s3",            GROUP_RF   + 19,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s4",            GROUP_RF   + 20,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s5",            GROUP_RF   + 21,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s6",            GROUP_RF   + 22,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s7",            GROUP_RF   + 23,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s8",            GROUP_RF   + 24,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s9",            GROUP_RF   + 25,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s10",           GROUP_RF   + 26,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"s11",           GROUP_RF   + 27,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"t3",            GROUP_RF   + 28,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"t4",            GROUP_RF   + 29,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"t5",            GROUP_RF   + 30,             "org.gnu.gdb.riscv.cpu", 
NULL},
+       {"t6",            GROUP_RF   + 31,             "org.gnu.gdb.riscv.cpu", 
NULL},
+
+
+       /* PC */
+        {"pc",            GROUP_GPRS + 0x201,          "org.gnu.gdb.rv12.dbg", 
  NULL},
+
+
+       /* Floating Point Register File */
+       
+
+       /* CSRs */
+        {"ustatus",       GROUP_CSR  + CSR_USTATUS,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"uie",           GROUP_CSR  + CSR_UIE,        
"org.gnu.gdb.riscv.csr", NULL},
+        {"utvec",         GROUP_CSR  + CSR_UTVEC,      
"org.gnu.gdb.riscv.csr", NULL},
+        {"uscratch",      GROUP_CSR  + CSR_USCRATCH,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"uepc",          GROUP_CSR  + CSR_UEPC,       
"org.gnu.gdb.riscv.csr", NULL},
+        {"ucause",        GROUP_CSR  + CSR_UCAUSE,     
"org.gnu.gdb.riscv.csr", NULL},
+        {"utval",         GROUP_CSR  + CSR_UTVAL,      
"org.gnu.gdb.riscv.csr", NULL},
+        {"uip",           GROUP_CSR  + CSR_UIP,        
"org.gnu.gdb.riscv.csr", NULL},
+        {"fflags",        GROUP_CSR  + CSR_FFLAGS,     
"org.gnu.gdb.riscv.csr", NULL},
+        {"frm",           GROUP_CSR  + CSR_FRM,        
"org.gnu.gdb.riscv.csr", NULL},
+        {"fcsr",          GROUP_CSR  + CSR_FCSR,       
"org.gnu.gdb.riscv.csr", NULL},
+        {"cycle",         GROUP_CSR  + CSR_CYCLE,      
"org.gnu.gdb.riscv.csr", NULL},
+        {"time",          GROUP_CSR  + CSR_TIME,       
"org.gnu.gdb.riscv.csr", NULL},
+        {"instret",       GROUP_CSR  + CSR_INSTRET,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"cycleh",        GROUP_CSR  + CSR_CYCLEH,     
"org.gnu.gdb.riscv.csr", NULL},
+        {"timeh",         GROUP_CSR  + CSR_TIMEH,      
"org.gnu.gdb.riscv.csr", NULL},
+        {"instreth",      GROUP_CSR  + CSR_INSTRETH,   
"org.gnu.gdb.riscv.csr", NULL},
+
+        {"sstatus",       GROUP_CSR  + CSR_SSTATUS,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"sedeleg",       GROUP_CSR  + CSR_SEDELEG,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"sideleg",       GROUP_CSR  + CSR_SIDELEG,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"sie",           GROUP_CSR  + CSR_SIE,        
"org.gnu.gdb.riscv.csr", NULL},
+        {"stvec",         GROUP_CSR  + CSR_STVEC,      
"org.gnu.gdb.riscv.csr", NULL},
+        {"scounteren",    GROUP_CSR  + CSR_SCOUNTEREN, 
"org.gnu.gdb.riscv.csr", NULL},
+        {"sscratch",      GROUP_CSR  + CSR_SSCRATCH,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"sepc",          GROUP_CSR  + CSR_SEPC,       
"org.gnu.gdb.riscv.csr", NULL},
+        {"scause",        GROUP_CSR  + CSR_SCAUSE,     
"org.gnu.gdb.riscv.csr", NULL},
+        {"stval",         GROUP_CSR  + CSR_STVAL,      
"org.gnu.gdb.riscv.csr", NULL},
+        {"sip",           GROUP_CSR  + CSR_SIP,        
"org.gnu.gdb.riscv.csr", NULL},
+        {"satp",          GROUP_CSR  + CSR_SATP,       
"org.gnu.gdb.riscv.csr", NULL},
+
+        {"mvendorid",     GROUP_CSR  + CSR_MVENDORID,  
"org.gnu.gdb.riscv.csr", NULL},
+        {"marchid",       GROUP_CSR  + CSR_MARCHID,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"mimpid",        GROUP_CSR  + CSR_MIMPID,     
"org.gnu.gdb.riscv.csr", NULL},
+        {"mhartid",       GROUP_CSR  + CSR_MHARTID,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"mstatus",       GROUP_CSR  + CSR_MSTATUS,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"misa",          GROUP_CSR  + CSR_MISA,       
"org.gnu.gdb.riscv.csr", NULL},
+        {"medeleg",       GROUP_CSR  + CSR_MEDELEG,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"mideleg",       GROUP_CSR  + CSR_MIDELEG,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"mie",           GROUP_CSR  + CSR_MIE,        
"org.gnu.gdb.riscv.csr", NULL},
+        {"mnmivec",       GROUP_CSR  + CSR_MNMIVEC,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"mtvec",         GROUP_CSR  + CSR_MTVEC,      
"org.gnu.gdb.riscv.csr", NULL},
+        {"mcounteren",    GROUP_CSR  + CSR_MCOUNTEREN, 
"org.gnu.gdb.riscv.csr", NULL},
+        {"mscratch",      GROUP_CSR  + CSR_MSCRATCH,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"mepc",          GROUP_CSR  + CSR_MEPC,       
"org.gnu.gdb.riscv.csr", NULL},
+        {"mcause",        GROUP_CSR  + CSR_MCAUSE,     
"org.gnu.gdb.riscv.csr", NULL},
+        {"mtval",         GROUP_CSR  + CSR_MTVAL,      
"org.gnu.gdb.riscv.csr", NULL},
+        {"mip",           GROUP_CSR  + CSR_MIP,        
"org.gnu.gdb.riscv.csr", NULL},
+
+        {"pmpcfg0",       GROUP_CSR  + CSR_PMPCFG0,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpcfg1",       GROUP_CSR  + CSR_PMPCFG1,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpcfg2",       GROUP_CSR  + CSR_PMPCFG2,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpcfg3",       GROUP_CSR  + CSR_PMPCFG3,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr0",       GROUP_CSR  + CSR_PMPADDR0,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr1",       GROUP_CSR  + CSR_PMPADDR1,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr2",       GROUP_CSR  + CSR_PMPADDR2,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr3",       GROUP_CSR  + CSR_PMPADDR3,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr4",       GROUP_CSR  + CSR_PMPADDR4,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr5",       GROUP_CSR  + CSR_PMPADDR5,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr6",       GROUP_CSR  + CSR_PMPADDR6,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr7",       GROUP_CSR  + CSR_PMPADDR7,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr8",       GROUP_CSR  + CSR_PMPADDR8,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr9",       GROUP_CSR  + CSR_PMPADDR9,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr10",      GROUP_CSR  + CSR_PMPADDR10,  
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr11",      GROUP_CSR  + CSR_PMPADDR11,  
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr12",      GROUP_CSR  + CSR_PMPADDR12,  
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr13",      GROUP_CSR  + CSR_PMPADDR13,  
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr14",      GROUP_CSR  + CSR_PMPADDR14,  
"org.gnu.gdb.riscv.csr", NULL},
+        {"pmpadr15",      GROUP_CSR  + CSR_PMPADDR15,  
"org.gnu.gdb.riscv.csr", NULL},
+
+        {"mcycle",        GROUP_CSR  + CSR_MCYCLE,     
"org.gnu.gdb.riscv.csr", NULL},
+        {"minstret",      GROUP_CSR  + CSR_MINSTRET,   
"org.gnu.gdb.riscv.csr", NULL},
+        {"mcycleh",       GROUP_CSR  + CSR_MCYCLEH,    
"org.gnu.gdb.riscv.csr", NULL},
+        {"minstreth",     GROUP_CSR  + CSR_MINSTRETH,  
"org.gnu.gdb.riscv.csr", NULL},
+
+
+       /* Debug Unit Internals */
+       {"npc",           GROUP_GPRS + 0x200,          "org.gnu.gdb.rv12.dbg", 
NULL},
+       {"dbgctrl",       GROUP_DBG  +  0x00,          "org.gnu.gdb.rv12.dbg", 
NULL},
+       {"dbghit",        GROUP_DBG  +  0x01,          "org.gnu.gdb.rv12.dbg", 
NULL},
+       {"dbgie",         GROUP_DBG  +  0x02,          "org.gnu.gdb.rv12.dbg", 
NULL},
+       {"dbgcause",      GROUP_DBG  +  0x03,          "org.gnu.gdb.rv12.dbg", 
NULL},
+       {"dbg.bpctrl0",   GROUP_DBG  +  0x10,          "org.gnu.gdb.rv12.dbg", 
NULL},
+       {"dbg.bpdata0",   GROUP_DBG  +  0x11,          "org.gnu.gdb.rv12.dbg", 
NULL},
+       {"dbg.bpctrl1",   GROUP_DBG  +  0x12,          "org.gnu.gbd.rv12.dbg", 
NULL},
+       {"dbg.bpdata1",   GROUP_DBG  +  0x13,          "org.gnu.gdb.rv12.dbg", 
NULL},
+       {"dbg.bpctrl2",   GROUP_DBG  +  0x14,          "org.gnu.gdb.rv12.dbg", 
NULL},
+       {"dbg.bpdata2",   GROUP_DBG  +  0x15,          "org.gnu.gdb.rv12.dbg", 
NULL},
+};
+
+static int rv12_add_reg(struct target *target, struct rv12_core_reg *new_reg)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       int reg_list_size = rv12->nb_regs * sizeof(struct rv12_core_reg);
+
+       rv12_core_reg_list_arch_info = realloc(rv12_core_reg_list_arch_info,
+                               reg_list_size + sizeof(struct rv12_core_reg));
+
+       memcpy(&rv12_core_reg_list_arch_info[rv12->nb_regs], new_reg,
+               sizeof(struct rv12_core_reg));
+
+       rv12_core_reg_list_arch_info[rv12->nb_regs].list_num = rv12->nb_regs;
+
+       rv12->nb_regs++;
+
+       return ERROR_OK;
+}
+
+static int rv12_create_reg_list(struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+
+       LOG_DEBUG("-");
+
+       rv12_core_reg_list_arch_info = malloc(ARRAY_SIZE(rv12_init_reg_list) *
+                                      sizeof(struct rv12_core_reg));
+
+       for (int i = 0; i < (int)ARRAY_SIZE(rv12_init_reg_list); i++) {
+               rv12_core_reg_list_arch_info[i].name = 
rv12_init_reg_list[i].name;
+               rv12_core_reg_list_arch_info[i].spr_num = 
rv12_init_reg_list[i].spr_num;
+               rv12_core_reg_list_arch_info[i].group = 
rv12_init_reg_list[i].group;
+               rv12_core_reg_list_arch_info[i].feature = 
rv12_init_reg_list[i].feature;
+               rv12_core_reg_list_arch_info[i].list_num = i;
+               rv12_core_reg_list_arch_info[i].target = NULL;
+               rv12_core_reg_list_arch_info[i].rv12_common = NULL;
+       }
+
+       rv12->nb_regs = ARRAY_SIZE(rv12_init_reg_list);
+
+       return ERROR_OK;
+}
+
+static int rv12_jtag_read_regs(struct rv12_common *rv12, uint32_t *regs)
+{
+       struct rl_du *du_core = rl_jtag_to_du(&rv12->jtag);
+
+       LOG_DEBUG("-");
+
+       return du_core->rl_jtag_read_cpu(&rv12->jtag,
+                       rv12->arch_info[GDB_REGNO_ZERO].spr_num, 
GDB_REGNO_XPR31 + 1,
+                       regs + GDB_REGNO_ZERO);
+}
+
+static int rv12_jtag_write_regs(struct rv12_common *rv12, uint32_t *regs)
+{
+       struct rl_du *du_core = rl_jtag_to_du(&rv12->jtag);
+
+       LOG_DEBUG("-");
+
+       return du_core->rl_jtag_write_cpu(&rv12->jtag,
+                       rv12->arch_info[GDB_REGNO_ZERO].spr_num, 
GDB_REGNO_XPR31 + 1,
+                       &regs[GDB_REGNO_ZERO]);
+}
+
+static int rv12_save_context(struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       int regs_read = 0;
+       int retval;
+
+       LOG_DEBUG("-");
+
+       for (int i = 0; i < GDB_REGNO_FPR0; i++) 
+       {
+               if (!rv12->core_cache->reg_list[i].valid) 
+               {
+                       // Read the PC for the PPC
+                       if (i == GDB_REGNO_PC) 
+               {
+                               // Read the PPC register
+                               retval = du_core->rl_jtag_read_cpu(&rv12->jtag,
+                                               (GROUP_GPRS + 0x201), 1,
+                                               &rv12->core_regs[i]);
+
+                LOG_DEBUG("Read PC: Value: %08x\n", rv12->core_regs[i]);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       } 
+            else if (!regs_read) 
+            {
+                               /* read gpr registers at once (but only one 
time in this loop) */
+                               retval = rv12_jtag_read_regs(rv12, 
rv12->core_regs);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                               /* prevent next reads in this loop */
+                               regs_read = 1;
+                       }
+                       /* We've just updated the core_reg[i], now update
+                          the core cache */
+                       rv12_read_core_reg(target, i);
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_restore_context(struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       int reg_write = 0;
+       int retval;
+
+       LOG_DEBUG("-");
+
+       for (int i = 0; i < GDB_REGNO_FPR0; i++) {
+               if (rv12->core_cache->reg_list[i].dirty) {
+                       rv12_write_core_reg(target, i);
+
+                       if (i == GDB_REGNO_PC) {
+                               retval = du_core->rl_jtag_write_cpu(&rv12->jtag,
+                                               // Write the PC to the NPC reg
+                                               (GROUP_GPRS + 0x200), 1,
+                                               &rv12->core_regs[i]);
+                               if (retval != ERROR_OK) {
+                                       LOG_ERROR("Error while restoring 
context");
+                                       return retval;
+                               }
+                       } else
+                               reg_write = 1;
+               }
+       }
+
+       if (reg_write) {
+               /* read gpr registers at once (but only one time in this loop) 
*/
+               retval = rv12_jtag_write_regs(rv12, rv12->core_regs);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Error while restoring context");
+                       return retval;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_read_core_reg(struct target *target, int num)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       uint32_t reg_value;
+
+       LOG_DEBUG("-");
+
+       if ((num < 0) || (num >= rv12->nb_regs))
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if ((num >= 0) && (num < GDB_REGNO_COUNT)) {
+               reg_value = rv12->core_regs[num];
+               buf_set_u32(rv12->core_cache->reg_list[num].value, 0, 32, 
reg_value);
+               LOG_DEBUG("Read core reg %i value 0x%08" PRIx32, num, 
reg_value);
+               rv12->core_cache->reg_list[num].valid = true;
+               rv12->core_cache->reg_list[num].dirty = false;
+       } else  {
+               /* This is an spr, always read value from HW */
+               int retval = du_core->rl_jtag_read_cpu(&rv12->jtag,
+                                                        
rv12->arch_info[num].spr_num, 1, &reg_value);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Error while reading spr 0x%08" PRIx32, 
rv12->arch_info[num].spr_num);
+                       return retval;
+               }
+               buf_set_u32(rv12->core_cache->reg_list[num].value, 0, 32, 
reg_value);
+               LOG_DEBUG("Read spr reg %i value 0x%08" PRIx32, num, reg_value);
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_write_core_reg(struct target *target, int num)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+
+       LOG_DEBUG("-");
+
+       if ((num < 0) || (num >= GDB_REGNO_COUNT))
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       uint32_t reg_value = buf_get_u32(rv12->core_cache->reg_list[num].value, 
0, 32);
+       rv12->core_regs[num] = reg_value;
+       LOG_DEBUG("Write core reg %i value 0x%08" PRIx32, num, reg_value);
+       rv12->core_cache->reg_list[num].valid = true;
+       rv12->core_cache->reg_list[num].dirty = false;
+
+       return ERROR_OK;
+}
+
+static int rv12_get_core_reg(struct reg *reg)
+{
+       struct rv12_core_reg *rv12_reg = reg->arch_info;
+       struct target *target = rv12_reg->target;
+
+       LOG_DEBUG("-");
+
+       if (target->state != TARGET_HALTED)
+               return ERROR_TARGET_NOT_HALTED;
+
+    // First get the register before returning the values
+    int retval = rv12_save_context(target);
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while calling rv12_save_context");
+               return retval;
+       }
+
+       return rv12_read_core_reg(target, rv12_reg->list_num);
+}
+
+static int rv12_set_core_reg(struct reg *reg, uint8_t *buf)
+{
+       struct rv12_core_reg *rv12_reg = reg->arch_info;
+       struct target *target = rv12_reg->target;
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       uint32_t value = buf_get_u32(buf, 0, 32);
+
+       LOG_DEBUG("-");
+    LOG_DEBUG("Set core reg: %u, value: %08x\n", rv12_reg->list_num, value);
+
+       if (target->state != TARGET_HALTED)
+               return ERROR_TARGET_NOT_HALTED;
+
+    // If the register is lower then the Floating Point registers, write it to 
the cache
+    // At the moment a continue or a step is provoked, it shall be written to 
the CPU
+    if (rv12_reg->list_num < GDB_REGNO_FPR0) {
+        buf_set_u32(rv12->core_cache->reg_list[rv12_reg->list_num].value, 0, 
32, value);
+               rv12->core_cache->reg_list[rv12_reg->list_num].dirty = true;
+               rv12->core_cache->reg_list[rv12_reg->list_num].valid = true;
+       } else {
+               /* Non cached register, so write to CPU immediately */
+        int retval = du_core->rl_jtag_write_cpu(&rv12->jtag, 
rv12_reg->spr_num, 1, &value);
+        
+        if (retval != ERROR_OK) {
+            LOG_ERROR("Error while writing spr 0x%08" PRIx32, 
rv12_reg->spr_num);
+            return retval;
+        }
+       }
+
+       return ERROR_OK;
+}
+
+static const struct reg_arch_type rv12_reg_type = {
+       .get = rv12_get_core_reg,
+       .set = rv12_set_core_reg,
+};
+
+static struct reg_cache *rv12_build_reg_cache(struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct reg_cache **cache_p = 
register_get_last_cache_p(&target->reg_cache);
+       struct reg_cache *cache = malloc(sizeof(struct reg_cache));
+       struct reg *reg_list = calloc(rv12->nb_regs, sizeof(struct reg));
+       struct rv12_core_reg *arch_info = malloc((rv12->nb_regs) * 
sizeof(struct rv12_core_reg));
+       struct reg_feature *feature;
+
+       LOG_DEBUG("-");
+
+       /* Build the process context cache */
+       cache->name = "Roa Logic RISC-V Registers";
+       cache->next = NULL;
+       cache->reg_list = reg_list;
+       cache->num_regs = rv12->nb_regs;
+       (*cache_p) = cache;
+       rv12->core_cache = cache;
+       rv12->arch_info = arch_info;
+
+       for (int i = 0; i < rv12->nb_regs; i++) {
+               arch_info[i] = rv12_core_reg_list_arch_info[i];
+               arch_info[i].target = target;
+               arch_info[i].rv12_common = rv12;
+               reg_list[i].name = rv12_core_reg_list_arch_info[i].name;
+
+               feature = malloc(sizeof(struct reg_feature));
+               feature->name = rv12_core_reg_list_arch_info[i].feature;
+               reg_list[i].feature = feature;
+
+               reg_list[i].group = rv12_core_reg_list_arch_info[i].group;
+               reg_list[i].size = 32;
+               reg_list[i].value = calloc(1, 4);
+               reg_list[i].dirty = false;
+               reg_list[i].valid = false;
+               reg_list[i].type = &rv12_reg_type;
+               reg_list[i].arch_info = &arch_info[i];
+               reg_list[i].number = i;
+               reg_list[i].exist = true;
+       }
+
+       return cache;
+}
+
+static int rv12_debug_entry(struct target *target)
+{
+       LOG_DEBUG("-");
+    uint32_t value = 0;
+
+       int retval = rv12_save_context(target);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while calling rv12_save_context");
+               return retval;
+       }
+
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       uint32_t addr = rv12->core_regs[GDB_REGNO_PC];
+
+       //value |= DBG_IE_INST_MISALIGNED | DBG_IE_ILLEGAL | DBG_IE_BREAKPOINT 
| DBG_IE_LOAD_MISALIGNED | DBG_IE_AMO_MISALIGNED;
+       value |= DBG_IE_BREAKPOINT;
+
+       // printf("Set DBG IE with value: %08x\n", value);
+       if(du_core->rl_jtag_write_cpu(&rv12->jtag, (GROUP_DBG + 0x02), 1, 
&value) != ERROR_OK) {
+               LOG_ERROR("Error: cannot set DBG IE reg\n");
+               return ERROR_FAIL;
+       }
+
+       if (breakpoint_find(target, addr)) {
+               buf_set_u32(rv12->core_cache->reg_list[GDB_REGNO_PC].value, 0, 
32, addr);
+               rv12->core_cache->reg_list[GDB_REGNO_PC].dirty = true;
+               rv12->core_cache->reg_list[GDB_REGNO_PC].valid = true;
+       }
+
+       return retval;
+}
+
+static int rv12_halt(struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+
+       LOG_DEBUG("target->state: %s", target_state_name(target));
+
+       if (target->state == TARGET_HALTED) {
+               LOG_DEBUG("Target was already halted");
+               return ERROR_OK;
+       }
+
+       if (target->state == TARGET_UNKNOWN)
+               LOG_WARNING("Target was in unknown state when halt was 
requested");
+
+       if (target->state == TARGET_RESET) {
+               if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && 
jtag_get_srst()) {
+                       LOG_ERROR("Can't request a halt while in reset if nSRST 
pulls nTRST");
+                       return ERROR_TARGET_FAILURE;
+               } else {
+                       target->debug_reason = DBG_REASON_DBGRQ;
+                       return ERROR_OK;
+               }
+       }
+
+       int retval = du_core->rl_cpu_stall(&rv12->jtag, CPU_STALL);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Impossible to stall the CPU");
+               return retval;
+       }
+
+       target->debug_reason = DBG_REASON_DBGRQ;
+
+       return ERROR_OK;
+}
+
+static int rl_is_cpu_running(struct target *target, int *running)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       int retval;
+       int tries = 0;
+       const int RETRIES_MAX = 5;
+
+       /* Have a retry loop to determine of the CPU is running.
+          If target has been hard reset for any reason, it might take a couple
+          of goes before it's ready again.
+       */
+       while (tries < RETRIES_MAX) {
+
+               tries++;
+
+               retval = du_core->rl_is_cpu_running(&rv12->jtag, running);
+               if (retval != ERROR_OK) {
+                       LOG_WARNING("Debug IF CPU control reg read failure.");
+                       /* Try once to restart the JTAG infrastructure -
+                          quite possibly the board has just been reset. */
+                       LOG_WARNING("Resetting JTAG TAP state and reconnecting 
to debug IF.");
+                       du_core->rl_jtag_init(&rv12->jtag);
+
+                       LOG_WARNING("...attempt %d of %d", tries, RETRIES_MAX);
+
+                       alive_sleep(2);
+
+                       continue;
+               } else
+                       return ERROR_OK;
+       }
+
+       LOG_ERROR("Could not re-establish communication with target");
+       return retval;
+}
+
+static int rv12_poll(struct target *target)
+{
+       int retval;
+       int running;
+
+       retval = rl_is_cpu_running(target, &running);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while calling rl_is_cpu_running");
+               return retval;
+       }
+
+       /* check for processor halted */
+       if (!running) {
+               /* It's actually stalled, so update our software's state */
+               if ((target->state == TARGET_RUNNING) ||
+                   (target->state == TARGET_RESET)) {
+
+                       target->state = TARGET_HALTED;
+
+                       retval = rv12_debug_entry(target);
+                       if (retval != ERROR_OK) 
+            {
+                               LOG_ERROR("Error while calling 
rv12_debug_entry");
+                               return retval;
+                       }
+
+                       target_call_event_callbacks(target, 
TARGET_EVENT_HALTED);
+               } else if (target->state == TARGET_DEBUG_RUNNING) {
+                       target->state = TARGET_HALTED;
+
+                       retval = rv12_debug_entry(target);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("Error while calling 
rv12_debug_entry");
+                               return retval;
+                       }
+
+                       target_call_event_callbacks(target, 
TARGET_EVENT_DEBUG_HALTED);
+               }
+       } else { /* ... target is running */
+
+               /* If target was supposed to be stalled, stall it again */
+               if  (target->state == TARGET_HALTED) {
+                       target->state = TARGET_RUNNING;
+
+                       retval = rv12_halt(target);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("Error while calling rv12_halt");
+                               return retval;
+                       }
+
+                       retval = rv12_debug_entry(target);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("Error while calling 
rv12_debug_entry");
+                               return retval;
+                       }
+
+                       target_call_event_callbacks(target, 
TARGET_EVENT_DEBUG_HALTED);
+               }
+
+               target->state = TARGET_RUNNING;
+
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_assert_reset(struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+
+       LOG_DEBUG("Assert reset \n");
+
+       int retval = du_core->rl_cpu_reset(&rv12->jtag, CPU_RESET);
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while asserting RESET");
+               return retval;
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_deassert_reset(struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+
+       LOG_DEBUG("-");
+
+       int retval = du_core->rl_cpu_reset(&rv12->jtag, CPU_NOT_RESET);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while deasserting RESET");
+               return retval;
+       }
+
+       // Set the correpsponding debug flags again, since those are cleared
+       retval = rv12_debug_entry(target);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while calling rv12_debug_entry");
+               return retval;
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_soft_reset_halt(struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+
+       LOG_DEBUG("Soft reset \n");
+
+       int retval = du_core->rl_cpu_stall(&rv12->jtag, CPU_STALL);
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while stalling the CPU");
+               return retval;
+       }
+
+       retval = rv12_assert_reset(target);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = rv12_deassert_reset(target);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return ERROR_OK;
+}
+
+static int rv12_resume_or_step(struct target *target, int current,
+                              uint32_t address, int handle_breakpoints,
+                              int debug_execution, int step)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       struct breakpoint *breakpoint = NULL;
+       uint32_t resume_pc = 0;
+       uint32_t tempReg = 0;
+       uint32_t tempMStatusReg = 0;
+       bool globalInterruptActive = false;
+       int retval;
+
+       LOG_DEBUG("Addr: 0x%" PRIx32 ", stepping: %s, handle breakpoints %s\n",
+                 address, step ? "yes" : "no", handle_breakpoints ? "yes" : 
"no");
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       // Free memory
+       if (!debug_execution)
+               target_free_all_working_areas(target);
+
+       /* current ? continue on current pc : continue at <address> */
+       if (!current) 
+       buf_set_u32(rv12->core_cache->reg_list[GDB_REGNO_PC].value, 0, 32, 
address);
+
+       retval = rv12_restore_context(target);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while calling rv12_restore_context");
+               return retval;
+       }
+       
+       // Clear DBG HIT reg
+       tempReg = 0;
+
+    if(du_core->rl_jtag_write_cpu(&rv12->jtag, (GROUP_DBG + 0x01), 1, 
&tempReg) != ERROR_OK) {
+               printf("Error: cannot clear HIT reg\n");
+               return ERROR_FAIL;
+       }
+
+       if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_DBG + 0x00), 1, 
&tempReg) != ERROR_OK) {
+               printf("Error: cannot read DBG ctrl reg\n");
+               return ERROR_FAIL;
+       }
+
+       if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_CSR  + CSR_MSTATUS), 
1, &tempMStatusReg) != ERROR_OK) {
+               printf("Error: cannot read MSTATUS reg\n");
+               return ERROR_FAIL;
+       }
+
+       if(tempMStatusReg & DBG_CSR_MSTASUS_MIE) {
+               globalInterruptActive = true;
+       }
+
+       if (step) {
+               /* Set the single step trigger in Debug Mode Register 1 (DMR1) 
*/
+               tempReg |= DBG_CTRL_SINGLE_STEP_TRACE;
+
+               if(globalInterruptActive) {
+                       tempMStatusReg &= ~DBG_CSR_MSTASUS_MIE;
+
+                       if(du_core->rl_jtag_write_cpu(&rv12->jtag, (GROUP_CSR  
+ CSR_MSTATUS), 1, &tempMStatusReg) != ERROR_OK) {
+                               printf("Error: cannot read MSTATUS reg\n");
+                               return ERROR_FAIL;
+                       }
+               }
+       } else { 
+               /* Clear the single step trigger in Debug Mode Register 1 
(DMR1) */
+               tempReg &= ~DBG_CTRL_SINGLE_STEP_TRACE;
+       }
+
+
+
+       if(du_core->rl_jtag_write_cpu(&rv12->jtag, (GROUP_DBG + 0x00), 1, 
&tempReg) != ERROR_OK) {
+               printf("Error: cannot write DBG ctrl reg\n");
+               return ERROR_FAIL;
+       }
+
+       resume_pc = buf_get_u32(rv12->core_cache->reg_list[GDB_REGNO_PC].value, 
0, 32);
+
+       /* The front-end may request us not to handle breakpoints */
+       if (handle_breakpoints) {
+               /* Single step past breakpoint at current address */
+               breakpoint = breakpoint_find(target, resume_pc);
+               if (breakpoint) {
+                       LOG_DEBUG("Unset breakpoint at 0x%08" TARGET_PRIxADDR, 
breakpoint->address);
+                       retval = rv12_remove_breakpoint(target, breakpoint);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
+       }
+
+       /* Unstall time */
+       retval = du_core->rl_cpu_stall(&rv12->jtag, CPU_UNSTALL);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while unstalling the CPU");
+               return retval;
+       }
+
+       if (step) {
+               target->debug_reason = DBG_REASON_SINGLESTEP;
+
+               if(globalInterruptActive) {
+                       if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_CSR  + 
CSR_MSTATUS), 1, &tempMStatusReg) != ERROR_OK) {
+                               printf("Error: cannot read MSTATUS reg\n");
+                               return ERROR_FAIL;
+                       }
+                       tempMStatusReg |= DBG_CSR_MSTASUS_MIE;
+
+                       if(du_core->rl_jtag_write_cpu(&rv12->jtag, (GROUP_CSR  
+ CSR_MSTATUS), 1, &tempMStatusReg) != ERROR_OK) {
+                               printf("Error: cannot read MSTATUS reg\n");
+                               return ERROR_FAIL;
+                       }
+               }
+       } else
+               target->debug_reason = DBG_REASON_NOTHALTED;
+
+       // Invalidate current registers in local cache
+       // Nothing to do with CPU cache
+       register_cache_invalidate(rv12->core_cache);
+
+       if (!debug_execution) {
+               target->state = TARGET_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+               LOG_DEBUG("Target resumed at 0x%08" PRIx32, resume_pc);
+       } else {
+               target->state = TARGET_DEBUG_RUNNING;
+               target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
+               LOG_DEBUG("Target debug resumed at 0x%08" PRIx32, resume_pc);
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_resume(struct target *target, int current,
+                               target_addr_t address, int handle_breakpoints,
+                               int debug_execution)
+{
+       return rv12_resume_or_step(target, current, address,
+                                  handle_breakpoints,
+                                  debug_execution,
+                                  NO_SINGLE_STEP);
+}
+
+static int rv12_step(struct target *target, int current,
+                    target_addr_t address, int handle_breakpoints)
+{
+       return rv12_resume_or_step(target, current, address,
+                                  handle_breakpoints,
+                                  0,
+                                  SINGLE_STEP);
+
+}
+
+static int rv12_add_breakpoint(struct target *target,
+                              struct breakpoint *breakpoint)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       uint32_t data;
+       int retval;
+
+       LOG_DEBUG("Adding breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, 
type %d, set: %d, id: %" PRIu32,
+                 breakpoint->address, breakpoint->length, breakpoint->type,
+                 breakpoint->is_set, breakpoint->unique_id);
+
+       /* Only support SW breakpoints for now. */
+       if(breakpoint->type != BKPT_SOFT) {
+               LOG_ERROR("HW breakpoints not supported for now\n");
+               return ERROR_FAIL;
+       }
+
+       if(breakpoint->length != 2 && breakpoint->length != 4) {
+               LOG_ERROR("Breakpoint unsupported length\n");
+               return ERROR_FAIL;
+       }
+
+       if(breakpoint->length == 2) {
+               /* Read and save the instruction */
+               retval = du_core->rl_jtag_read_memory(&rv12->jtag,
+                                               breakpoint->address,
+                                               2,
+                                               1,
+                                               (uint8_t*)&data);
+       } else {
+               /* Read and save the instruction */
+               retval = du_core->rl_jtag_read_memory(&rv12->jtag,
+                                               breakpoint->address,
+                                               4,
+                                               1,
+                                               (uint8_t*)&data);
+       }
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while reading the instruction at 0x%08" 
TARGET_PRIxADDR,
+                          breakpoint->address);
+               return retval;
+       }
+   
+       free(breakpoint->orig_instr);
+
+       breakpoint->orig_instr = malloc(breakpoint->length);
+       memcpy(breakpoint->orig_instr, &data, breakpoint->length);
+
+       if(breakpoint->length == 2) {
+               uint16_t rv12_trap_insn16 = RV_EBREAK16_INSTR;
+               //target_buffer_set_u32(target, rv12_trap_insn, 
RV_EBREAK16_INSTR);
+               retval = du_core->rl_jtag_write_memory(&rv12->jtag,
+                                               breakpoint->address,
+                                               2,
+                                               1,
+                                               (uint8_t*)&rv12_trap_insn16);
+       } else {
+               uint32_t rv12_trap_insn = RV_EBREAK_INSTR;
+               //target_buffer_set_u32(target, rv12_trap_insn, 
RV_EBREAK_INSTR);
+               retval = du_core->rl_jtag_write_memory(&rv12->jtag,
+                                               breakpoint->address,
+                                               4,
+                                               1,
+                                               (uint8_t*)&rv12_trap_insn);
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_remove_breakpoint(struct target *target,
+                                 struct breakpoint *breakpoint)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       int retval;
+
+       LOG_DEBUG("Removing breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, 
type %d, set: %d, id: %" PRIu32,
+                 breakpoint->address, breakpoint->length, breakpoint->type,
+                 breakpoint->is_set, breakpoint->unique_id);
+
+       /* Only support SW breakpoints for now. */
+       if(breakpoint->type != BKPT_SOFT) {
+               LOG_ERROR("HW breakpoints not supported for now\n");
+               return ERROR_FAIL;
+       }
+
+       if(breakpoint->length != 2 && breakpoint->length != 4) {
+               LOG_ERROR("Breakpoint unsupported length\n");
+               return ERROR_FAIL;
+       }
+
+       if(breakpoint->length == 2) {
+               /* Replace the removed instruction */
+               retval = du_core->rl_jtag_write_memory(&rv12->jtag,
+                                               breakpoint->address,
+                                               2,
+                                               1,
+                                               breakpoint->orig_instr);
+       } else {
+               /* Replace the removed instruction */
+               retval = du_core->rl_jtag_write_memory(&rv12->jtag,
+                                               breakpoint->address,
+                                               4,
+                                               1,
+                                               breakpoint->orig_instr);
+       }
+
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while writing back the instruction at 0x%08" 
TARGET_PRIxADDR,
+                          breakpoint->address);
+               return retval;
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_add_watchpoint(struct target *target,
+                              struct watchpoint *watchpoint)
+{
+       LOG_ERROR("%s: implement me", __func__);
+       return ERROR_OK;
+}
+
+static int rv12_remove_watchpoint(struct target *target,
+                                 struct watchpoint *watchpoint)
+{
+       LOG_ERROR("%s: implement me", __func__);
+       return ERROR_OK;
+}
+
+static int rv12_read_memory(struct target *target, target_addr_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+
+       LOG_DEBUG("Read memory at 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", 
count: 0x%08" PRIx32, address, size, count);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+
+       //TODO: 64bit accesses (for 64bit CPU)
+       /* Sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || 
!buffer) {
+               LOG_ERROR("Bad arguments");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 
0x1u))) {
+               LOG_ERROR("Unaligned memory access not supported");
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+       }
+
+       return du_core->rl_jtag_read_memory(&rv12->jtag, address, size, count, 
buffer);
+}
+
+static int rv12_write_memory(struct target *target, target_addr_t address,
+               uint32_t size, uint32_t count, const uint8_t *buffer)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+
+       LOG_DEBUG("Write memory at 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", 
count: 0x%08" PRIx32, address, size, count);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_WARNING("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+
+       //TODO: 64bit accesses for 64bit CPU
+       /* Sanitize arguments */
+       if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || 
!buffer) {
+               LOG_ERROR("Bad arguments");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 
0x1u))) {
+               LOG_ERROR("Unaligned memory access not supported");
+               return ERROR_TARGET_UNALIGNED_ACCESS;
+       }
+
+       return du_core->rl_jtag_write_memory(&rv12->jtag, address, size, count, 
buffer);
+}
+
+static int rv12_init_target(struct command_context *cmd_ctx,
+               struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       struct rl_jtag *jtag = &rv12->jtag;
+
+       if (!du_core) {
+               LOG_ERROR("No debug unit selected");
+               return ERROR_FAIL;
+       }
+
+       if (!jtag->tap_ip) {
+               LOG_ERROR("No tap selected");
+               return ERROR_FAIL;
+       }
+
+       rv12->jtag.tap = target->tap;
+       rv12->jtag.rl_jtag_inited = 0;
+       rv12->jtag.rl_jtag_module_selected = -1;
+       rv12->jtag.target = target;
+
+       rv12_build_reg_cache(target);
+
+       return ERROR_OK;
+}
+
+static int rv12_target_create(struct target *target, Jim_Interp *interp)
+{
+       if (!target->tap)
+               return ERROR_FAIL;
+
+       struct rv12_common *rv12 = calloc(1, sizeof(struct rv12_common));
+
+       target->arch_info = rv12;
+
+       rv12_create_reg_list(target);
+
+       rl_universal_tap_register();
+
+       rl_dbg_adv_register();
+
+       return ERROR_OK;
+}
+
+static int rv12_examine(struct target *target)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+
+       if (!target_was_examined(target)) {
+
+               target_set_examined(target);
+
+               int running;
+
+               int retval = du_core->rl_is_cpu_running(&rv12->jtag, &running);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Couldn't read the CPU state");
+                       return retval;
+               } else {
+                       if (running)
+                               target->state = TARGET_RUNNING;
+                       else {
+                               LOG_DEBUG("Target is halted");
+
+                               /* This is the first time we examine the target,
+                                * it is stalled and we don't know why. Let's
+                                * assume this is because of a debug reason.
+                                */
+                               if (target->state == TARGET_UNKNOWN)
+                                       target->debug_reason = DBG_REASON_DBGRQ;
+
+                               target->state = TARGET_HALTED;
+                       }
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int rv12_arch_state(struct target *target)
+{
+       return ERROR_OK;
+}
+
+static int rv12_get_gdb_reg_list(struct target *target, struct reg 
**reg_list[],
+                         int *reg_list_size, enum target_register_class 
reg_class)
+{
+       struct rv12_common *rv12 = target_to_rv12(target);
+
+       if (reg_class == REG_CLASS_GENERAL) {
+               /* We will have this called whenever GDB connects. */
+               int retval = rv12_save_context(target);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Error while calling rv12_save_context");
+                       return retval;
+               }
+
+               //TODO Load FPR when the CPU has a FPU
+               *reg_list_size = GDB_REGNO_FPR0;
+               /* this is free()'d back in gdb_server.c's 
gdb_get_register_packet() */
+               *reg_list = malloc((*reg_list_size) * sizeof(struct reg *));
+
+               for (int i = 0; i < GDB_REGNO_FPR0; i++)
+                       (*reg_list)[i] = &rv12->core_cache->reg_list[i];
+       } else {
+               *reg_list_size = rv12->nb_regs;
+               *reg_list = malloc((*reg_list_size) * sizeof(struct reg *));
+
+               for (int i = 0; i < rv12->nb_regs; i++)
+                       (*reg_list)[i] = &rv12->core_cache->reg_list[i];
+       }
+
+       return ERROR_OK;
+
+}
+
+static int rv12_get_gdb_fileio_info(struct target *target, struct 
gdb_fileio_info *fileio_info)
+{
+       return ERROR_FAIL;
+}
+
+static int rv12_checksum_memory(struct target *target, target_addr_t address,
+               uint32_t count, uint32_t *checksum)
+{
+       return ERROR_FAIL;
+}
+
+static int rv12_profiling(struct target *target, uint32_t *samples,
+               uint32_t max_num_samples, uint32_t *num_samples, uint32_t 
seconds)
+{
+       struct timeval timeout, now;
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_du *du_core = rl_to_du(rv12);
+       int retval = ERROR_OK;
+
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, seconds, 0);
+
+       LOG_INFO("Starting rv12 profiling. Sampling npc as fast as we can...");
+
+       /* Make sure the target is running */
+       target_poll(target);
+       if (target->state == TARGET_HALTED)
+               retval = target_resume(target, 1, 0, 0, 0);
+
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Error while resuming target");
+               return retval;
+       }
+
+       uint32_t sample_count = 0;
+
+       for (;;) {
+               uint32_t reg_value;
+               retval = du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_GPRS + 
0x201) /* PPC */, 1, &reg_value);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("Error while reading NPC");
+                       return retval;
+               }
+
+               samples[sample_count++] = reg_value;
+
+               gettimeofday(&now, NULL);
+               if ((sample_count >= max_num_samples) || timeval_compare(&now, 
&timeout) > 0) {
+                       LOG_INFO("Profiling completed. %" PRIu32 " samples.", 
sample_count);
+                       break;
+               }
+       }
+
+       *num_samples = sample_count;
+       return retval;
+}
+
+static int rv12_soc_test_sram(struct target *target)
+{
+    uint32_t baseAddress = 0x00010000;
+    uint32_t ins;
+    uint32_t insn[9];
+    uint32_t address;
+
+    insn[0] = 0x11112222;
+    insn[1] = 0x33334444;
+    insn[2] = 0x55556666;
+    insn[3] = 0x77778888;
+    insn[4] = 0x9999aaaa;
+    insn[5] = 0xbbbbcccc;
+    insn[6] = 0xddddeeee;
+    insn[7] = 0xffff0000;
+    insn[8] = 0xdedababa;
+
+    if(rv12_poll(target) != ERROR_OK)
+    {
+        printf("Error while polling target\n");
+        return ERROR_FAIL;
+    }
+
+    for(int i = 0; i < 9; i++)
+    {
+        address = baseAddress + (i * 4);
+
+        printf("Write address: %08x, with: %08x\n",address, insn[i]);
+        if(rv12_write_memory(target, address, 4, 1, (uint8_t*)&insn[i]) 
!=ERROR_OK)
+        {
+            printf("Error: Cannot write memory\n");
+            return ERROR_FAIL;
+        } 
+    }
+
+    for(int i = 0; i < 9; i++)
+    {
+        address = baseAddress + (i * 4);
+
+        printf("Read address: %08x\n",address);
+        if(rv12_read_memory(target, address, 4, 1, (uint8_t*)&ins) == ERROR_OK)
+        {
+            if(ins != insn[i])
+            {
+                printf("Error: Expected: %08x, received: %08x\n", insn[i], 
ins);
+                return ERROR_FAIL;
+            }
+        }
+        else
+        {
+            printf("Error: Reading memory\n");
+            return ERROR_FAIL;
+        }
+    }
+
+    return ERROR_OK;
+}
+
+static int rv12_soc_test_cpu(struct target *target)
+{
+    uint32_t baseAddress = 0x00010000;
+    uint32_t insn[11];
+    uint32_t illIns = 0x00000000;    
+    uint32_t address;
+    uint32_t r1, npc, ppc;
+    int state;
+    //uint32_t insRead;
+
+    struct rv12_common *rv12 = target_to_rv12(target);
+    struct rl_du *du_core = rl_jtag_to_du(&rv12->jtag);
+
+    printf("\n-- Testing rv12-SoC CPU\n");
+    printf("writing instructions\n");
+
+    insn[0]  = 0x00004033; /* xor   x0,x0,x0               */
+    insn[1]  = 0x00000093; /* addi  x1,x0,0x0              */
+    insn[2]  = 0x00010137; /* lui   x2,0x00010  (RAM_BASE) */
+    insn[3]  = 0x03016113; /* ori   x2,x2,0x30             */
+    insn[4]  = 0x00108093; /* addi  x1,x1,1                */
+    insn[5]  = 0x00108093; /* addi  x1,x1,1                */
+    insn[6]  = 0x00112023; /* sw    0(x2),x1               */
+    insn[7]  = 0x00108093; /* addi  x1,x1,1                */
+    insn[8]  = 0x00012183; /* lw    x3,0(x2)               */
+    insn[9]  = 0x003080b3; /* add   x1,x1,x3               */
+    insn[10] = 0xfe9ff06f; /* j     (base+0x10)            */
+
+    if(rv12_poll(target) != ERROR_OK)
+    {
+        printf("Error while polling target\n");
+    }
+
+
+    for(int i = 0; i < 11; i++)
+    {
+        address = baseAddress + (i * 4);
+        if(rv12_write_memory(target, address, 4, 1, (uint8_t*)&insn[i]) 
!=ERROR_OK)
+        {
+            printf("Error: Cannot write memory\n");
+            return ERROR_FAIL;
+        } 
+    }
+
+    //Fill rest of memory with 0x00 (C.ILLEGAL). Avoid CPU going nuts on 
0xxxxxx
+    for (uint32_t i = baseAddress+0x2c; i < baseAddress+0x4c; i=i+4)
+    {
+        if(rv12_write_memory(target, i, 4, 1, (uint8_t*)&illIns) !=ERROR_OK)
+        {
+            printf("Error: Cannot write memory\n");
+            return ERROR_FAIL;
+        }
+    }
+
+    printf("Setting up CPU\n");
+
+    /*
+    * Test 1
+    */
+    printf("- Test 1, save context\n");
+
+    if(rv12_save_context(target) == ERROR_OK)
+    {
+        printf("Success: Saved context\n");
+        for (int i = 0; i < GDB_REGNO_FPR0; i++) 
+       {
+            printf("reg: %s, value: %08x\n",rv12_init_reg_list[i].name, 
rv12->core_regs[i]);
+        }
+    }
+    else
+    {
+        printf("Error: cannot save context\n");
+        return ERROR_FAIL;
+    }
+    
+    /*
+     * Test 2
+     */
+    printf("- Test 2, Single stepping\n");
+
+    printf("Write NPC: %08x\n", baseAddress);
+    if(du_core->rl_jtag_write_cpu(&rv12->jtag, (GROUP_GPRS + 0x200), 1, 
&baseAddress) != ERROR_OK)
+    {
+        printf("Error: cannot set NPC\n");
+        return ERROR_FAIL;
+    }
+
+    for(int i = 0; i < 11; i++)
+    {            
+        if(rv12_poll(target) != ERROR_OK)
+        {
+            printf("Error while polling target\n");
+            return ERROR_FAIL;
+        }
+
+        printf("Starting CPU, waiting for breakpoint... \n");
+
+        if(rv12_step(target, 1, 0x00, 0) != ERROR_OK)
+        {
+            printf("Error: stepping\n");
+            return ERROR_FAIL;
+        }
+
+        do
+        {
+            if (rl_is_cpu_running(target, &state) != ERROR_OK) {
+                LOG_ERROR("Error while calling rl_is_cpu_running");
+                return ERROR_FAIL;
+            }
+            
+        } while(!state);
+
+        printf("Got breakpoint \n");
+    }
+
+    if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_GPRS + 0x200), 1, &npc) 
!= ERROR_OK)
+    {
+        printf("Error: cannot read NPC\n");
+        return ERROR_FAIL;
+    }
+
+    if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_GPRS + 0x201), 1, &ppc) 
!= ERROR_OK)
+    {
+        printf("Error: cannot read PPC\n");
+        return ERROR_FAIL;
+    }
+
+    if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_RF   +  1), 1, &r1) != 
ERROR_OK)
+    {
+        printf("Error: cannot read PPC\n");
+        return ERROR_FAIL;
+    }
+    printf("Read:     npc: %08x, ppc: %08x, r1: %08x\n", npc, ppc, r1);
+    printf("Expected: npc: %08x, ppc: %08x, r1: %08x\n", 0x00010010, 
0x00010028, 5);
+
+    if(npc != 0x00010010 || ppc !=  0x00010028 || r1 != 5)
+    {
+        return ERROR_FAIL;
+    }
+
+    printf("Passed test 2\n");
+
+    /*
+     * Test 3
+     */
+    printf("- Test 3, Breakpoint hit\n");
+
+    struct breakpoint testBreakPoint = {0};
+
+    testBreakPoint.type = BKPT_SOFT;
+    testBreakPoint.address = (baseAddress + 0x24);
+    testBreakPoint.length = 4;
+
+    printf("Add breakpoint\n");
+    rv12_add_breakpoint(target, &testBreakPoint);
+
+    if(rv12_poll(target) != ERROR_OK)
+    {
+        printf("Error while polling target\n");
+        return ERROR_FAIL;
+    }
+
+    if(rv12_read_memory(target, (baseAddress + 0x24), 4, 1, (uint8_t*)&r1) 
!=ERROR_OK)
+    {
+        printf("Cannot read back memory!\n");
+        return ERROR_FAIL;
+    } 
+
+    if(r1 != RV_EBREAK_INSTR)
+    {
+        printf("SW breakpoint not set!\n");
+        return ERROR_FAIL;
+    }
+
+    printf("Resuming target\n");
+    rv12_resume(target,1, 0, 0, 0);    
+    
+    do
+    {
+        if (rl_is_cpu_running(target, &state) != ERROR_OK) {
+            LOG_ERROR("Error while calling rl_is_cpu_running");
+            return ERROR_FAIL;
+        }
+        
+    } while(!state);
+
+    printf("Remove breakpoint\n");
+    rv12_remove_breakpoint(target, &testBreakPoint);
+
+    if(rv12_poll(target) != ERROR_OK)
+    {
+        printf("Error while polling target\n");
+        return ERROR_FAIL;
+    }
+
+    if(rv12_read_memory(target, (baseAddress + 0x24), 4, 1, (uint8_t*)&r1) != 
ERROR_OK)
+    {
+        printf("Cannot read back memory!\n");
+        return ERROR_FAIL;
+    }
+
+    if(r1 != insn[9])
+    {
+        printf("Breakpoing not removed: Expected: %08x, Received: %08x\n", 
insn[9], r1);
+        return ERROR_FAIL;
+    }
+
+    if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_GPRS + 0x200), 1, &npc) 
!= ERROR_OK)
+    {
+        printf("Error: cannot read NPC\n");
+        return ERROR_FAIL;
+    }
+
+    if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_GPRS + 0x201), 1, &ppc) 
!= ERROR_OK)
+    {
+        printf("Error: cannot read PPC\n");
+        return ERROR_FAIL;
+    }
+
+    if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_RF   +  1), 1, &r1) != 
ERROR_OK)
+    {
+        printf("Error: cannot read PPC\n");
+        return ERROR_FAIL;
+    }
+
+    printf("Read:     npc: %08x, ppc: %08x, r1: %08x\n", npc, ppc, r1);
+    printf("Expected: npc: %08x, ppc: %08x, r1: %08x\n", 0x00010028, 
0x00010024, 8);
+
+    if(ppc !=  0x00010024 || r1 != 8)
+    {
+        return ERROR_FAIL;
+    }
+
+
+    printf("Passed test 3\n");
+
+    printf("- Test 4, Breakpoint hit2\n");
+
+    testBreakPoint.type = BKPT_SOFT;
+    testBreakPoint.address = (baseAddress + 0x28);
+    testBreakPoint.length = 4;
+
+    printf("Add breakpoint\n");
+    rv12_add_breakpoint(target, &testBreakPoint);
+
+    if(rv12_poll(target) != ERROR_OK)
+    {
+        printf("Error while polling target\n");
+        return ERROR_FAIL;
+    }
+
+    ppc = (baseAddress + 0x10);
+    printf("Write NPC: %08x\n", ppc);
+    if(du_core->rl_jtag_write_cpu(&rv12->jtag, (GROUP_GPRS + 0x200), 1, &ppc) 
!= ERROR_OK)
+    {
+        printf("Error: cannot set NPC\n");
+        return ERROR_FAIL;
+    }
+
+    printf("Resuming target\n");
+    rv12_resume(target,1, 0, 0, 0);    
+    
+    do
+    {
+        if (rl_is_cpu_running(target, &state) != ERROR_OK) {
+            LOG_ERROR("Error while calling rl_is_cpu_running");
+            return ERROR_FAIL;
+        }
+        
+    } while(!state);
+
+    printf("Remove breakpoint\n");
+    rv12_remove_breakpoint(target, &testBreakPoint);
+
+        if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_GPRS + 0x200), 1, 
&npc) != ERROR_OK)
+    {
+        printf("Error: cannot read NPC\n");
+        return ERROR_FAIL;
+    }
+
+    if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_GPRS + 0x201), 1, &ppc) 
!= ERROR_OK)
+    {
+        printf("Error: cannot read PPC\n");
+        return ERROR_FAIL;
+    }
+
+    if(du_core->rl_jtag_read_cpu(&rv12->jtag, (GROUP_RF   +  1), 1, &r1) != 
ERROR_OK)
+    {
+        printf("Error: cannot read PPC\n");
+        return ERROR_FAIL;
+    }
+
+    printf("Read:     npc: %08x, ppc: %08x, r1: %08x\n", npc, ppc, r1);
+    printf("Expected: npc: %08x, ppc: %08x, r1: %08x\n", 0x0001002C, 
0x00010028, 21);
+
+    if(ppc !=  0x00010028 || r1 != 21)
+    {
+        return ERROR_FAIL;
+    }
+
+
+    printf("Passed test 4\n");
+
+    return ERROR_OK;
+}
+
+COMMAND_HANDLER(rl_tap_select_command_handler)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_jtag *jtag = &rv12->jtag;
+       struct rl_tap_ip *rl_tap;
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       list_for_each_entry(rl_tap, &rl_tap_list, list) {
+               if (rl_tap->name) {
+                       if (!strcmp(CMD_ARGV[0], rl_tap->name)) {
+                               jtag->tap_ip = rl_tap;
+                               LOG_INFO("%s tap selected", rl_tap->name);
+                               return ERROR_OK;
+                       }
+               }
+       }
+
+       LOG_ERROR("%s unknown, no tap selected", CMD_ARGV[0]);
+       return ERROR_COMMAND_SYNTAX_ERROR;
+}
+
+COMMAND_HANDLER(rl_tap_list_command_handler)
+{
+       struct rl_tap_ip *rl_tap;
+
+       if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       list_for_each_entry(rl_tap, &rl_tap_list, list) {
+               if (rl_tap->name)
+                       command_print(CMD, "%s", rl_tap->name);
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(rl_du_select_command_handler)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct rv12_common *rv12 = target_to_rv12(target);
+       struct rl_jtag *jtag = &rv12->jtag;
+       struct rl_du *rl_du;
+
+       if (CMD_ARGC > 2)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       list_for_each_entry(rl_du, &rl_du_list, list) {
+               if (rl_du->name) {
+                       if (!strcmp(CMD_ARGV[0], rl_du->name)) {
+                               jtag->du_core = rl_du;
+                               LOG_INFO("%s debug unit selected", rl_du->name);
+
+                               if (CMD_ARGC == 2) {
+                                       int options;
+                                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], 
options);
+                                       rl_du->options = options;
+                                       LOG_INFO("Option %x is passed to %s 
debug unit"
+                                                , options, rl_du->name);
+                               }
+
+                               return ERROR_OK;
+                       }
+               }
+       }
+
+       LOG_ERROR("%s unknown, no debug unit selected", CMD_ARGV[0]);
+       return ERROR_COMMAND_SYNTAX_ERROR;
+}
+
+COMMAND_HANDLER(rl_du_list_command_handler)
+{
+       struct rl_du *rl_du;
+
+       if (CMD_ARGC != 0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       list_for_each_entry(rl_du, &rl_du_list, list) {
+               if (rl_du->name)
+                       command_print(CMD, "%s", rl_du->name);
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(rv12_addreg_command_handler)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct rv12_core_reg new_reg;
+
+       if (CMD_ARGC != 4)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       new_reg.target = NULL;
+       new_reg.rv12_common = NULL;
+
+       uint32_t addr;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
+
+       new_reg.name = strdup(CMD_ARGV[0]);
+       new_reg.spr_num = addr;
+       new_reg.feature = strdup(CMD_ARGV[2]);
+       new_reg.group = strdup(CMD_ARGV[3]);
+
+       rv12_add_reg(target, &new_reg);
+
+       LOG_DEBUG("Add reg \"%s\" @ 0x%08" PRIx32 ", group \"%s\", feature 
\"%s\"",
+                 new_reg.name, addr, new_reg.group, new_reg.feature);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(rv12_test_handler)
+{
+    struct target *target = get_current_target(CMD_CTX);
+
+    if (CMD_ARGC == 0 || CMD_ARGC > 1)
+        return ERROR_COMMAND_SYNTAX_ERROR;
+
+    int options;
+       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], options);
+
+    printf("rv12 Test\n");
+
+    printf("Testing options: %u\n", options);
+
+    printf("\n rv12-SoC Stalling CPU\n");
+
+    if(rv12_halt(target) == ERROR_OK)
+    {
+        printf("Success: CPU(s) stalled\n");
+    }
+    else
+    {
+        printf("Error: CPU(s) not stalled!\n");
+        return ERROR_FAIL;
+    }
+
+    if((options & 0x00000001) >  0)
+    {
+        printf("\n rv12 SoC on-chip SRAM test: \n");
+
+        if(rv12_soc_test_sram(target) == ERROR_OK)
+        {
+            printf("Success: sram test success\n");
+        }
+        else
+        {
+            printf("Error: sram test failed!\n");
+            return ERROR_FAIL;
+        }
+    }
+    else
+    {
+        printf("\n rv12 SoC SRAM test disabled\n");
+    }
+
+    if((options & 0x00000002) > 0)
+    {      
+        if(rv12_soc_test_cpu(target) == ERROR_OK)
+        {
+            printf("Success: CPU test Passed\n");
+        }
+        else
+        {
+            printf("Error: CPU test failed!\n");
+            return ERROR_FAIL;
+        }
+    }
+
+
+    printf("Succesfully passed given tests\n");
+
+    return ERROR_OK;
+}
+
+static const struct command_registration rv12_hw_ip_command_handlers[] = {
+       {
+               .name = "rl_tap_select",
+               .handler = rl_tap_select_command_handler,
+               .mode = COMMAND_ANY,
+               .usage = "name",
+               .help = "Select the TAP core to use",
+       },
+       {
+               .name = "rl_tap_list",
+               .handler = rl_tap_list_command_handler,
+               .mode = COMMAND_ANY,
+               .usage = "",
+               .help = "Display available TAP core",
+       },
+       {
+               .name = "rl_du_select",
+               .handler = rl_du_select_command_handler,
+               .mode = COMMAND_ANY,
+               .usage = "name",
+               .help = "Select the Debug Unit core to use",
+       },
+       {
+               .name = "rl_du_list",
+               .handler = rl_du_list_command_handler,
+               .mode = COMMAND_ANY,
+               .usage = "select_tap name",
+               .help = "Display available Debug Unit core",
+       },
+    {
+        .name = "rv12_test",
+        .handler = rv12_test_handler,
+        .mode = COMMAND_ANY,
+        .usage = "Test the rv12 SoC",
+        .help = "Test the rv12 SoC implementation",
+    },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration rv12_reg_command_handlers[] = {
+       {
+               .name = "addreg",
+               .handler = rv12_addreg_command_handler,
+               .mode = COMMAND_ANY,
+               .usage = "name addr feature group",
+               .help = "Add a register to the register list",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration rv12_command_handlers[] = {
+       {
+               .chain = rv12_reg_command_handlers,
+       },
+       {
+               .chain = rv12_hw_ip_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
+
+struct target_type rv12_target = {
+       .name = "rv12",
+
+       .poll = rv12_poll,
+       .arch_state = rv12_arch_state,
+
+       .target_request_data = NULL,
+
+       .halt = rv12_halt,
+       .resume = rv12_resume,
+       .step = rv12_step,
+
+       .assert_reset = rv12_assert_reset,
+       .deassert_reset = rv12_deassert_reset,
+       .soft_reset_halt = rv12_soft_reset_halt,
+
+       .get_gdb_reg_list = rv12_get_gdb_reg_list,
+
+       .read_memory = rv12_read_memory,
+       .write_memory = rv12_write_memory,
+       .checksum_memory = rv12_checksum_memory,
+
+       .commands = rv12_command_handlers,
+       .add_breakpoint = rv12_add_breakpoint,
+       .remove_breakpoint = rv12_remove_breakpoint,
+       .add_watchpoint = rv12_add_watchpoint,
+       .remove_watchpoint = rv12_remove_watchpoint,
+
+       .target_create = rv12_target_create,
+       .init_target = rv12_init_target,
+       .examine = rv12_examine,
+
+       .get_gdb_fileio_info = rv12_get_gdb_fileio_info,
+
+       .profiling = rv12_profiling,
+};
diff --git a/src/target/roalogic/rv12.h b/src/target/roalogic/rv12.h
new file mode 100644
index 0000000000..80c441b06c
--- /dev/null
+++ b/src/target/roalogic/rv12.h
@@ -0,0 +1,266 @@
+/***************************************************************************
+ *   Copyright (C) 2022 by Richard Herveille                               *
+ *   richard.hervei...@roalogic.com                                        *
+ *                                                                         *
+ *   Copyright (C) 2022 by Bjorn Schouteten                                *
+ *   bjorn.schoute...@roalogic.com                                         *
+ *                                                                         * 
+ *   Based on the OR1K version                                             *
+ *                                                                         *
+ *                                                                         *
+ *   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_ROALOGIC_rv12_H
+#define OPENOCD_TARGET_ROALOGIC_rv12_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <target/target.h>
+#include <target/riscv/encoding.h>
+
+/* Debug Register Access Groups Start Addresses 
+ * INTERNAL = Debug Unit internal registers
+ * GPRS = INR_RF, FP_RF, NPC, PPC
+ * CSRS = RISC-V State CSRs
+ * */
+#define GROUP_DBG      (0 << 12)
+#define GROUP_GPRS     (1 << 12)
+#define GROUP_CSR      (2 << 12)
+
+#define CSR_USTATUS 0x0
+#define CSR_UIE 0x4
+#define CSR_UTVEC 0x5
+#define CSR_USCRATCH 0x40
+#define CSR_UEPC 0x41
+#define CSR_UCAUSE 0x42
+#define CSR_UTVAL 0x43
+#define CSR_UIP 0x44
+#define CSR_MNMIVEC 0x70C
+
+/* Integer Register File
+ * Floating Point Register File
+ * NPC
+ * PPC
+ */ 
+#define GROUP_RF       (GROUP_GPRS +        0)
+#define GROUP_FPRF     (GROUP_GPRS + (1 << 8))
+
+
+/* rv12 registers */
+/* gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in
+ * its source tree. We must interpret the numbers the same here. */
+enum gdb_regno {
+       GDB_REGNO_ZERO = 0,        /* Read-only register, always 0.  */
+       GDB_REGNO_RA = 1,          /* Return Address.  */
+       GDB_REGNO_SP = 2,          /* Stack Pointer.  */
+       GDB_REGNO_GP = 3,          /* Global Pointer.  */
+       GDB_REGNO_TP = 4,          /* Thread Pointer.  */
+       GDB_REGNO_T0,
+       GDB_REGNO_T1,
+       GDB_REGNO_T2,
+       GDB_REGNO_S0 = 8,
+       GDB_REGNO_FP = 8,          /* Frame Pointer.  */
+       GDB_REGNO_S1,
+       GDB_REGNO_A0 = 10,         /* First argument.  */
+       GDB_REGNO_A1 = 11,         /* Second argument.  */
+       GDB_REGNO_A2,
+       GDB_REGNO_A3,
+       GDB_REGNO_A4,
+       GDB_REGNO_A5,
+       GDB_REGNO_XPR15 = GDB_REGNO_A5,
+       GDB_REGNO_A6,
+       GDB_REGNO_A7,
+       GDB_REGNO_S2,
+       GDB_REGNO_S3,
+       GDB_REGNO_S4,
+       GDB_REGNO_S5,
+       GDB_REGNO_S6,
+       GDB_REGNO_S7,
+       GDB_REGNO_S8,
+       GDB_REGNO_S9,
+       GDB_REGNO_S10,
+       GDB_REGNO_S11,
+       GDB_REGNO_T3,
+       GDB_REGNO_T4,
+       GDB_REGNO_T5,
+       GDB_REGNO_T6,
+       GDB_REGNO_XPR31 = GDB_REGNO_T6,
+
+       GDB_REGNO_PC = 32,
+       GDB_REGNO_FPR0 = 33,
+       GDB_REGNO_FT0 = GDB_REGNO_FPR0,
+       GDB_REGNO_FT1,
+       GDB_REGNO_FT2,
+       GDB_REGNO_FT3,
+       GDB_REGNO_FT4,
+       GDB_REGNO_FT5,
+       GDB_REGNO_FT6,
+       GDB_REGNO_FT7,
+       GDB_REGNO_FS0,
+       GDB_REGNO_FS1,
+       GDB_REGNO_FA0,
+       GDB_REGNO_FA1,
+       GDB_REGNO_FA2,
+       GDB_REGNO_FA3,
+       GDB_REGNO_FA4,
+       GDB_REGNO_FA5,
+       GDB_REGNO_FA6,
+       GDB_REGNO_FA7,
+       GDB_REGNO_FS2,
+       GDB_REGNO_FS3,
+       GDB_REGNO_FS4,
+       GDB_REGNO_FS5,
+       GDB_REGNO_FS6,
+       GDB_REGNO_FS7,
+       GDB_REGNO_FS8,
+       GDB_REGNO_FS9,
+       GDB_REGNO_FS10,
+       GDB_REGNO_FS11,
+       GDB_REGNO_FT8,
+       GDB_REGNO_FT9,
+       GDB_REGNO_FT10,
+       GDB_REGNO_FT11,
+       GDB_REGNO_FPR31 = GDB_REGNO_FT11,
+       GDB_REGNO_CSR0 = 65,
+       GDB_REGNO_VSTART = CSR_VSTART + GDB_REGNO_CSR0,
+       GDB_REGNO_VXSAT = CSR_VXSAT + GDB_REGNO_CSR0,
+       GDB_REGNO_VXRM = CSR_VXRM + GDB_REGNO_CSR0,
+       GDB_REGNO_VLENB = CSR_VLENB + GDB_REGNO_CSR0,
+       GDB_REGNO_VL = CSR_VL + GDB_REGNO_CSR0,
+       GDB_REGNO_VTYPE = CSR_VTYPE + GDB_REGNO_CSR0,
+       GDB_REGNO_TSELECT = CSR_TSELECT + GDB_REGNO_CSR0,
+       GDB_REGNO_TDATA1 = CSR_TDATA1 + GDB_REGNO_CSR0,
+       GDB_REGNO_TDATA2 = CSR_TDATA2 + GDB_REGNO_CSR0,
+       GDB_REGNO_MISA = CSR_MISA + GDB_REGNO_CSR0,
+       GDB_REGNO_DPC = CSR_DPC + GDB_REGNO_CSR0,
+       GDB_REGNO_DCSR = CSR_DCSR + GDB_REGNO_CSR0,
+       GDB_REGNO_DSCRATCH0 = CSR_DSCRATCH0 + GDB_REGNO_CSR0,
+       GDB_REGNO_MSTATUS = CSR_MSTATUS + GDB_REGNO_CSR0,
+       GDB_REGNO_MEPC = CSR_MEPC + GDB_REGNO_CSR0,
+       GDB_REGNO_MCAUSE = CSR_MCAUSE + GDB_REGNO_CSR0,
+       GDB_REGNO_SATP = CSR_SATP + GDB_REGNO_CSR0,
+       GDB_REGNO_CSR4095 = GDB_REGNO_CSR0 + 4095,
+       GDB_REGNO_PRIV = 4161,
+       /* It's still undecided what register numbers GDB will actually use for
+        * these. See
+        * 
https://groups.google.com/a/groups.riscv.org/d/msg/sw-dev/7lQYiTUN9Ms/gTxGhzaYBQAJ
+        */
+       GDB_REGNO_V0, GDB_REGNO_V1, GDB_REGNO_V2, GDB_REGNO_V3,
+       GDB_REGNO_V4, GDB_REGNO_V5, GDB_REGNO_V6, GDB_REGNO_V7,
+       GDB_REGNO_V8, GDB_REGNO_V9, GDB_REGNO_V10, GDB_REGNO_V11,
+       GDB_REGNO_V12, GDB_REGNO_V13, GDB_REGNO_V14, GDB_REGNO_V15,
+       GDB_REGNO_V16, GDB_REGNO_V17, GDB_REGNO_V18, GDB_REGNO_V19,
+       GDB_REGNO_V20, GDB_REGNO_V21, GDB_REGNO_V22, GDB_REGNO_V23,
+       GDB_REGNO_V24, GDB_REGNO_V25, GDB_REGNO_V26, GDB_REGNO_V27,
+       GDB_REGNO_V28, GDB_REGNO_V29, GDB_REGNO_V30, GDB_REGNO_V31,
+       GDB_REGNO_COUNT
+};
+
+const char *gdb_regno_name(enum gdb_regno regno);
+
+
+struct rl_jtag {
+       struct jtag_tap *tap;
+       int rl_jtag_inited;
+       int rl_jtag_module_selected;
+       int rl_jtag_cpu_selected;
+       int rl_jtag_address_size;
+       uint8_t *current_reg_idx;
+       struct rl_tap_ip *tap_ip;
+       struct rl_du *du_core;
+       struct target *target;
+};
+
+
+struct rv12_common {
+       struct rl_jtag jtag;
+       struct reg_cache *core_cache;
+       uint32_t core_regs[GDB_REGNO_COUNT];
+       int nb_regs;
+       struct rv12_core_reg *arch_info;
+};
+
+static inline struct rv12_common *
+target_to_rv12(struct target *target)
+{
+       return (struct rv12_common *)target->arch_info;
+}
+
+struct rv12_core_reg {
+       const char *name;
+       uint32_t list_num;   /* Index in register cache */
+       uint32_t spr_num;    /* Number in architecture's SPR space */
+       struct target *target;
+       struct rv12_common *rv12_common;
+       const char *feature; /* feature name in XML tdesc file */
+       const char *group;   /* register group in XML tdesc file */
+};
+
+struct rv12_core_reg_init {
+       const char *name;
+       uint32_t spr_num;    /* Number in architecture's SPR space */
+       const char *feature; /* feature name in XML tdesc file */
+       const char *group;   /* register group in XML tdesc file */
+};
+
+/* RISC-V EBREAK instruction */
+#define RV_EBREAK_INSTR  0x00100073
+#define RV_EBREAK16_INSTR 0x9002
+
+enum rv12_debug_reg_nums {
+       rv12_DEBUG_REG_CTRL = 0,
+       rv12_DEBUG_REG_HIT,
+       rv12_DEBUG_REG_IE,
+       rv12_DEBUG_REG_CAUSE,
+       rv12_DEBUG_REG_BPCTRL0 = 0x10,
+       rv12_DEBUG_REG_BPDATA0,
+       rv12_DEBUG_REG_BPCTRL1,
+       rv12_DEBUG_REG_BPDATA1,
+       rv12_DEBUG_REG_BPCTRL2,
+       rv12_DEBUG_REG_BPDATA2
+};
+
+#define rv12_JTAG_DBG_REGS 10
+
+#define NO_SINGLE_STEP         0
+#define SINGLE_STEP            1
+
+
+// DBG CTRL
+//Bit definitions
+#define DBG_CTRL_SINGLE_STEP_TRACE     0x01       /* Enable single-step trace  
                      */
+#define DBG_CTRL_BRANCH_TRACE          0x02       /* Enable branch-trace       
                      */
+
+#define DBG_CSR_MSTASUS_MIE         0x08
+
+#define DBG_IE_INST_MISALIGNED         0x00001
+#define DBG_IE_INST_ACCESS_FAULT       0x00002
+#define DBG_IE_ILLEGAL                 0x00004
+#define DBG_IE_BREAKPOINT              0x00008
+#define DBG_IE_LOAD_MISALIGNED         0x00010
+#define DBG_IE_LOAD_ACCESS_FAULT       0x00020
+#define DBG_IE_AMO_MISALIGNED          0x00040
+#define DBG_IE_STORE_ACCESS_FAULT      0x00080
+#define DBG_IE_UMODE_ECALL             0x00100
+#define DBG_IE_SMODE_ECALL             0x00200
+#define DBG_IE_HMODE_ECALL             0x00400
+#define DBG_IE_MMODE_ECALL             0x00800
+#define DBG_IE_SOFTWARE_INT            0x10000
+#define DBG_IE_TIMER_INT               0x20000
+#define DBG_IE_UART                    0x40000
+
+#endif /* OPENOCD_TARGET_ROALOGIC_rv12_H */
diff --git a/src/target/target.c b/src/target/target.c
index 9b07dbf618..e9ed5b17fc 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -105,6 +105,7 @@ extern struct target_type stm8_target;
 extern struct target_type riscv_target;
 extern struct target_type mem_ap_target;
 extern struct target_type esirisc_target;
+extern struct target_type rv12_target;
 extern struct target_type arcv2_target;
 
 static struct target_type *target_types[] = {
@@ -147,6 +148,7 @@ static struct target_type *target_types[] = {
        &esirisc_target,
        &arcv2_target,
        &aarch64_target,
+       &rv12_target,
        &mips_mips64_target,
        NULL,
 };

-- 

Reply via email to