nds32: add new target type nds32_v2, nds32_v3, nds32_v3m 59/1259/14
authorHsiangkai Wang <hsiangkai@gmail.com>
Tue, 5 Feb 2013 03:55:37 +0000 (11:55 +0800)
committerSpencer Oliver <spen@spen-soft.co.uk>
Wed, 5 Jun 2013 19:27:35 +0000 (19:27 +0000)
Add target code for Andes targets.

Change-Id: Ibf0e1b61b06127ca7d9ed502d98d7e2aeebbbe82
Signed-off-by: Hsiangkai Wang <hsiangkai@gmail.com>
Reviewed-on: http://openocd.zylin.com/1259
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
28 files changed:
src/target/Makefile.am
src/target/nds32.c [new file with mode: 0644]
src/target/nds32.h
src/target/nds32_aice.c [new file with mode: 0644]
src/target/nds32_aice.h [new file with mode: 0644]
src/target/nds32_cmd.c [new file with mode: 0644]
src/target/nds32_cmd.h [new file with mode: 0644]
src/target/nds32_disassembler.c [new file with mode: 0644]
src/target/nds32_disassembler.h [new file with mode: 0644]
src/target/nds32_edm.h
src/target/nds32_insn.h
src/target/nds32_reg.c
src/target/nds32_reg.h
src/target/nds32_tlb.c [new file with mode: 0644]
src/target/nds32_tlb.h [new file with mode: 0644]
src/target/nds32_v2.c [new file with mode: 0644]
src/target/nds32_v2.h [new file with mode: 0644]
src/target/nds32_v3.c [new file with mode: 0644]
src/target/nds32_v3.h [new file with mode: 0644]
src/target/nds32_v3_common.c [new file with mode: 0644]
src/target/nds32_v3_common.h [new file with mode: 0644]
src/target/nds32_v3m.c [new file with mode: 0644]
src/target/nds32_v3m.h [new file with mode: 0644]
src/target/target.c
tcl/board/nds32_xc5.cfg [new file with mode: 0644]
tcl/target/nds32v2.cfg [new file with mode: 0644]
tcl/target/nds32v3.cfg [new file with mode: 0644]
tcl/target/nds32v3m.cfg [new file with mode: 0644]

index 8e9dfb6..027cc8e 100644 (file)
@@ -109,7 +109,16 @@ MIPS32_SRC = \
        mips_ejtag.c
 
 NDS32_SRC = \
-       nds32_reg.c
+       nds32.c \
+       nds32_reg.c \
+       nds32_cmd.c \
+       nds32_disassembler.c \
+       nds32_tlb.c \
+       nds32_v2.c \
+       nds32_v3_common.c \
+       nds32_v3.c \
+       nds32_v3m.c \
+       nds32_aice.c
 
 
 noinst_HEADERS = \
@@ -168,9 +177,17 @@ noinst_HEADERS = \
        avr32_mem.h \
        avr32_regs.h \
        nds32.h \
+       nds32_cmd.h \
+       nds32_disassembler.h \
        nds32_edm.h \
        nds32_insn.h \
-       nds32_reg.h
+       nds32_reg.h \
+       nds32_tlb.h \
+       nds32_v2.h \
+       nds32_v3_common.h \
+       nds32_v3.h \
+       nds32_v3m.h \
+       nds32_aice.h
 
 ocddatadir = $(pkglibdir)
 nobase_dist_ocddata_DATA =
diff --git a/src/target/nds32.c b/src/target/nds32.c
new file mode 100644 (file)
index 0000000..2d47709
--- /dev/null
@@ -0,0 +1,2156 @@
+/***************************************************************************
+ *   Copyright (C) 2013 Andes Technology                                   *
+ *   Hsiangkai Wang <hkwang@andestech.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, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/log.h>
+#include <helper/binarybuffer.h>
+#include "nds32.h"
+#include "nds32_aice.h"
+#include "nds32_tlb.h"
+#include "nds32_disassembler.h"
+
+const int NDS32_BREAK_16 = 0x00EA;      /* 0xEA00 */
+const int NDS32_BREAK_32 = 0x0A000064;  /* 0x6400000A */
+
+struct nds32_edm_operation nds32_edm_ops[NDS32_EDM_OPERATION_MAX_NUM];
+uint32_t nds32_edm_ops_num;
+
+const char *nds32_debug_type_name[11] = {
+       "SOFTWARE BREAK",
+       "SOFTWARE BREAK_16",
+       "HARDWARE BREAKPOINT",
+       "DATA ADDR WATCHPOINT PRECISE",
+       "DATA VALUE WATCHPOINT PRECISE",
+       "DATA VALUE WATCHPOINT IMPRECISE",
+       "DEBUG INTERRUPT",
+       "HARDWARE SINGLE STEP",
+       "DATA ADDR WATCHPOINT NEXT PRECISE",
+       "DATA VALUE WATCHPOINT NEXT PRECISE",
+       "LOAD STORE GLOBAL STOP",
+};
+
+static const int NDS32_LM_SIZE_TABLE[16] = {
+       4 * 1024,
+       8 * 1024,
+       16 * 1024,
+       32 * 1024,
+       64 * 1024,
+       128 * 1024,
+       256 * 1024,
+       512 * 1024,
+       1024 * 1024,
+       1 * 1024,
+       2 * 1024,
+};
+
+static const int NDS32_LINE_SIZE_TABLE[6] = {
+       0,
+       8,
+       16,
+       32,
+       64,
+       128,
+};
+
+static int nds32_get_core_reg(struct reg *reg)
+{
+       int retval;
+       struct nds32_reg *reg_arch_info = reg->arch_info;
+       struct target *target = reg_arch_info->target;
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (reg->valid) {
+               LOG_DEBUG("reading register(cached) %i(%s), value: 0x%8.8" PRIx32,
+                               reg_arch_info->num, reg->name, reg_arch_info->value);
+               return ERROR_OK;
+       }
+
+       if (reg_arch_info->enable == false) {
+               reg_arch_info->value = NDS32_REGISTER_DISABLE;
+               retval = ERROR_FAIL;
+       } else {
+               if ((nds32->fpu_enable == false) &&
+                       (NDS32_REG_TYPE_FPU == nds32_reg_type(reg_arch_info->num))) {
+                       reg_arch_info->value = 0;
+                       retval = ERROR_OK;
+               } else if ((nds32->audio_enable == false) &&
+                       (NDS32_REG_TYPE_AUMR == nds32_reg_type(reg_arch_info->num))) {
+                       reg_arch_info->value = 0;
+                       retval = ERROR_OK;
+               } else {
+                       retval = aice_read_register(aice,
+                                       reg_arch_info->num, &(reg_arch_info->value));
+               }
+
+               LOG_DEBUG("reading register %i(%s), value: 0x%8.8" PRIx32,
+                               reg_arch_info->num, reg->name, reg_arch_info->value);
+       }
+
+       if (retval == ERROR_OK) {
+               reg->valid = true;
+               reg->dirty = false;
+       }
+
+       return retval;
+}
+
+static int nds32_get_core_reg_64(struct reg *reg)
+{
+       int retval;
+       struct nds32_reg *reg_arch_info = reg->arch_info;
+       struct target *target = reg_arch_info->target;
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (reg->valid)
+               return ERROR_OK;
+
+       if (reg_arch_info->enable == false) {
+               reg_arch_info->value_64 = NDS32_REGISTER_DISABLE;
+               retval = ERROR_FAIL;
+       } else {
+               if ((nds32->fpu_enable == false) &&
+                       ((FD0 <= reg_arch_info->num) && (reg_arch_info->num <= FD31))) {
+                       reg_arch_info->value_64 = 0;
+                       retval = ERROR_OK;
+               } else {
+                       retval = aice_read_reg_64(aice, reg_arch_info->num,
+                                       &(reg_arch_info->value_64));
+               }
+       }
+
+       if (retval == ERROR_OK) {
+               reg->valid = true;
+               reg->dirty = false;
+       }
+
+       return retval;
+}
+
+static int nds32_update_psw(struct nds32 *nds32)
+{
+       uint32_t value_ir0;
+       struct aice_port_s *aice = target_to_aice(nds32->target);
+
+       nds32_get_mapped_reg(nds32, IR0, &value_ir0);
+
+       /* Save data memory endian */
+       if ((value_ir0 >> 5) & 0x1) {
+               nds32->data_endian = TARGET_BIG_ENDIAN;
+               aice_set_data_endian(aice, AICE_BIG_ENDIAN);
+       } else {
+               nds32->data_endian = TARGET_LITTLE_ENDIAN;
+               aice_set_data_endian(aice, AICE_LITTLE_ENDIAN);
+       }
+
+       /* Save translation status */
+       nds32->memory.address_translation = ((value_ir0 >> 7) & 0x1) ? true : false;
+
+       return ERROR_OK;
+}
+
+static int nds32_update_mmu_info(struct nds32 *nds32)
+{
+       uint32_t value;
+
+       /* Update MMU control status */
+       nds32_get_mapped_reg(nds32, MR0, &value);
+       nds32->mmu_config.default_min_page_size = value & 0x1;
+       nds32->mmu_config.multiple_page_size_in_use = (value >> 10) & 0x1;
+
+       return ERROR_OK;
+}
+
+static int nds32_update_cache_info(struct nds32 *nds32)
+{
+       uint32_t value;
+
+       if (ERROR_OK == nds32_get_mapped_reg(nds32, MR8, &value)) {
+               if (value & 0x1)
+                       nds32->memory.icache.enable = true;
+               else
+                       nds32->memory.icache.enable = false;
+
+               if (value & 0x2)
+                       nds32->memory.dcache.enable = true;
+               else
+                       nds32->memory.dcache.enable = false;
+       } else {
+               nds32->memory.icache.enable = false;
+               nds32->memory.dcache.enable = false;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_update_lm_info(struct nds32 *nds32)
+{
+       struct nds32_memory *memory = &(nds32->memory);
+       uint32_t value_mr6;
+       uint32_t value_mr7;
+
+       nds32_get_mapped_reg(nds32, MR6, &value_mr6);
+       if (value_mr6 & 0x1)
+               memory->ilm_enable = true;
+       else
+               memory->ilm_enable = false;
+
+       if (memory->ilm_align_ver == 0) { /* 1MB aligned */
+               memory->ilm_start = value_mr6 & 0xFFF00000;
+               memory->ilm_end = memory->ilm_start + memory->ilm_size;
+       } else if (memory->ilm_align_ver == 1) { /* aligned to local memory size */
+               memory->ilm_start = value_mr6 & 0xFFFFFC00;
+               memory->ilm_end = memory->ilm_start + memory->ilm_size;
+       } else {
+               memory->ilm_start = -1;
+               memory->ilm_end = -1;
+       }
+
+       nds32_get_mapped_reg(nds32, MR7, &value_mr7);
+       if (value_mr7 & 0x1)
+               memory->dlm_enable = true;
+       else
+               memory->dlm_enable = false;
+
+       if (memory->dlm_align_ver == 0) { /* 1MB aligned */
+               memory->dlm_start = value_mr7 & 0xFFF00000;
+               memory->dlm_end = memory->dlm_start + memory->dlm_size;
+       } else if (memory->dlm_align_ver == 1) { /* aligned to local memory size */
+               memory->dlm_start = value_mr7 & 0xFFFFFC00;
+               memory->dlm_end = memory->dlm_start + memory->dlm_size;
+       } else {
+               memory->dlm_start = -1;
+               memory->dlm_end = -1;
+       }
+
+       return ERROR_OK;
+}
+
+/**
+ * If fpu/audio is disabled, to access fpu/audio registers will cause
+ * exceptions. So, we need to check if fpu/audio is enabled or not as
+ * target is halted. If fpu/audio is disabled, as users access fpu/audio
+ * registers, OpenOCD will return fake value 0 instead of accessing
+ * registers through DIM.
+ */
+static int nds32_check_extension(struct nds32 *nds32)
+{
+       uint32_t value;
+
+       nds32_get_mapped_reg(nds32, FUCPR, &value);
+       if (value == NDS32_REGISTER_DISABLE) {
+               nds32->fpu_enable = false;
+               nds32->audio_enable = false;
+               return ERROR_OK;
+       }
+
+       if (value & 0x1)
+               nds32->fpu_enable = true;
+       else
+               nds32->fpu_enable = false;
+
+       if (value & 0x80000000)
+               nds32->audio_enable = true;
+       else
+               nds32->audio_enable = false;
+
+       return ERROR_OK;
+}
+
+static int nds32_set_core_reg(struct reg *reg, uint8_t *buf)
+{
+       struct nds32_reg *reg_arch_info = reg->arch_info;
+       struct target *target = reg_arch_info->target;
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+       uint32_t value = buf_get_u32(buf, 0, 32);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* ignore values that will generate exception */
+       if (nds32_reg_exception(reg_arch_info->num, value))
+               return ERROR_OK;
+
+       LOG_DEBUG("writing register %i(%s) with value 0x%8.8" PRIx32,
+                       reg_arch_info->num, reg->name, value);
+
+       if ((nds32->fpu_enable == false) &&
+               (NDS32_REG_TYPE_FPU == nds32_reg_type(reg_arch_info->num))) {
+
+               buf_set_u32(reg->value, 0, 32, 0);
+       } else if ((nds32->audio_enable == false) &&
+               (NDS32_REG_TYPE_AUMR == nds32_reg_type(reg_arch_info->num))) {
+
+               buf_set_u32(reg->value, 0, 32, 0);
+       } else {
+               buf_set_u32(reg->value, 0, 32, value);
+               aice_write_register(aice, reg_arch_info->num, reg_arch_info->value);
+
+               /* After set value to registers, read the value from target
+                * to avoid W1C inconsistency. */
+               aice_read_register(aice, reg_arch_info->num, &(reg_arch_info->value));
+       }
+
+       reg->valid = true;
+       reg->dirty = false;
+
+       /* update registers to take effect right now */
+       if (IR0 == reg_arch_info->num) {
+               nds32_update_psw(nds32);
+       } else if (MR0 == reg_arch_info->num) {
+               nds32_update_mmu_info(nds32);
+       } else if ((MR6 == reg_arch_info->num) || (MR7 == reg_arch_info->num)) {
+               /* update lm information */
+               nds32_update_lm_info(nds32);
+       } else if (MR8 == reg_arch_info->num) {
+               nds32_update_cache_info(nds32);
+       } else if (FUCPR == reg_arch_info->num) {
+               /* update audio/fpu setting */
+               nds32_check_extension(nds32);
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_set_core_reg_64(struct reg *reg, uint8_t *buf)
+{
+       struct nds32_reg *reg_arch_info = reg->arch_info;
+       struct target *target = reg_arch_info->target;
+       struct nds32 *nds32 = target_to_nds32(target);
+       uint32_t low_part = buf_get_u32(buf, 0, 32);
+       uint32_t high_part = buf_get_u32(buf, 32, 32);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if ((nds32->fpu_enable == false) &&
+               ((FD0 <= reg_arch_info->num) && (reg_arch_info->num <= FD31))) {
+
+               buf_set_u32(reg->value, 0, 32, 0);
+               buf_set_u32(reg->value, 32, 32, 0);
+
+               reg->valid = true;
+               reg->dirty = false;
+       } else {
+               buf_set_u32(reg->value, 0, 32, low_part);
+               buf_set_u32(reg->value, 32, 32, high_part);
+
+               reg->valid = true;
+               reg->dirty = true;
+       }
+
+       return ERROR_OK;
+}
+
+static const struct reg_arch_type nds32_reg_access_type = {
+       .get = nds32_get_core_reg,
+       .set = nds32_set_core_reg,
+};
+
+static const struct reg_arch_type nds32_reg_access_type_64 = {
+       .get = nds32_get_core_reg_64,
+       .set = nds32_set_core_reg_64,
+};
+
+static struct reg_cache *nds32_build_reg_cache(struct target *target,
+               struct nds32 *nds32)
+{
+       struct reg_cache *cache = malloc(sizeof(struct reg_cache));
+       struct reg *reg_list = calloc(TOTAL_REG_NUM, sizeof(struct reg));
+       struct nds32_reg *reg_arch_info = calloc(TOTAL_REG_NUM, sizeof(struct nds32_reg));
+       int i;
+
+       if (!cache || !reg_list || !reg_arch_info) {
+               free(cache);
+               free(reg_list);
+               free(reg_arch_info);
+               return NULL;
+       }
+
+       cache->name = "Andes registers";
+       cache->next = NULL;
+       cache->reg_list = reg_list;
+       cache->num_regs = 0;
+
+       for (i = 0; i < TOTAL_REG_NUM; i++) {
+               reg_arch_info[i].num = i;
+               reg_arch_info[i].target = target;
+               reg_arch_info[i].nds32 = nds32;
+               reg_arch_info[i].enable = false;
+
+               reg_list[i].name = nds32_reg_simple_name(i);
+               reg_list[i].size = nds32_reg_size(i);
+               reg_list[i].arch_info = &reg_arch_info[i];
+
+               if (FD0 <= reg_arch_info[i].num && reg_arch_info[i].num <= FD31) {
+                       reg_list[i].value = &(reg_arch_info[i].value_64);
+                       reg_list[i].type = &nds32_reg_access_type_64;
+               } else {
+                       reg_list[i].value = &(reg_arch_info[i].value);
+                       reg_list[i].type = &nds32_reg_access_type;
+               }
+
+               cache->num_regs++;
+       }
+
+       nds32->core_cache = cache;
+
+       return cache;
+}
+
+static int nds32_reg_cache_init(struct target *target, struct nds32 *nds32)
+{
+       struct reg_cache *cache;
+
+       cache = nds32_build_reg_cache(target, nds32);
+       if (!cache)
+               return ERROR_FAIL;
+
+       *register_get_last_cache_p(&target->reg_cache) = cache;
+
+       return ERROR_OK;
+}
+
+static struct reg *nds32_reg_current(struct nds32 *nds32, unsigned regnum)
+{
+       struct reg *r;
+
+       /* Register mapping, pass user-view registers to gdb */
+       int mapped_regnum = nds32->register_map(nds32, regnum);
+       r = nds32->core_cache->reg_list + mapped_regnum;
+
+       return r;
+}
+
+int nds32_full_context(struct nds32 *nds32)
+{
+       uint32_t value, value_ir0;
+
+       /* save $pc & $psw */
+       nds32_get_mapped_reg(nds32, PC, &value);
+       nds32_get_mapped_reg(nds32, IR0, &value_ir0);
+
+       nds32_update_psw(nds32);
+       nds32_update_mmu_info(nds32);
+       nds32_update_cache_info(nds32);
+       nds32_update_lm_info(nds32);
+
+       nds32_check_extension(nds32);
+
+       return ERROR_OK;
+}
+
+/* get register value internally */
+int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t *value)
+{
+       struct reg_cache *reg_cache = nds32->core_cache;
+       struct reg *r;
+
+       if (regnum > reg_cache->num_regs)
+               return ERROR_FAIL;
+
+       r = nds32_reg_current(nds32, regnum);
+
+       if (ERROR_OK != r->type->get(r))
+               return ERROR_FAIL;
+
+       *value = buf_get_u32(r->value, 0, 32);
+
+       return ERROR_OK;
+}
+
+/** set register internally */
+int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value)
+{
+       struct reg_cache *reg_cache = nds32->core_cache;
+       struct reg *r;
+       uint8_t set_value[4];
+
+       if (regnum > reg_cache->num_regs)
+               return ERROR_FAIL;
+
+       r = nds32_reg_current(nds32, regnum);
+
+       buf_set_u32(set_value, 0, 32, value);
+
+       return r->type->set(r, set_value);
+}
+
+/** get all register list */
+int nds32_get_gdb_reg_list(struct target *target,
+               struct reg **reg_list[], int *reg_list_size)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct reg_cache *reg_cache = nds32->core_cache;
+       unsigned int i;
+
+       *reg_list_size = reg_cache->num_regs;
+
+       /** freed in gdb_server.c */
+       *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+
+       for (i = 0; i < reg_cache->num_regs; i++)
+               (*reg_list)[i] = nds32_reg_current(nds32, i);
+
+       return ERROR_OK;
+}
+
+static int nds32_select_memory_mode(struct target *target, uint32_t address,
+               uint32_t length, uint32_t *end_address)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+       struct nds32_memory *memory = &(nds32->memory);
+       struct nds32_edm *edm = &(nds32->edm);
+       uint32_t dlm_start, dlm_end;
+       uint32_t ilm_start, ilm_end;
+       uint32_t address_end = address + length;
+
+       /* init end_address */
+       *end_address = address_end;
+
+       if (NDS_MEMORY_ACC_CPU == memory->access_channel)
+               return ERROR_OK;
+
+       if (edm->access_control == false) {
+               LOG_DEBUG("EDM does not support ACC_CTL");
+               return ERROR_OK;
+       }
+
+       if (edm->direct_access_local_memory == false) {
+               LOG_DEBUG("EDM does not support DALM");
+               aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+               return ERROR_OK;
+       }
+
+       if (NDS_MEMORY_SELECT_AUTO != memory->mode) {
+               LOG_DEBUG("Memory mode is not AUTO");
+               return ERROR_OK;
+       }
+
+       /* set default mode */
+       aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+
+       if ((memory->ilm_base != 0) && (memory->ilm_enable == true)) {
+               ilm_start = memory->ilm_start;
+               ilm_end = memory->ilm_end;
+
+               /* case 1, address < ilm_start */
+               if (address < ilm_start) {
+                       if (ilm_start < address_end) {
+                               /* update end_address to split non-ILM from ILM */
+                               *end_address = ilm_start;
+                       }
+                       /* MEM mode */
+                       aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+               } else if ((ilm_start <= address) && (address < ilm_end)) {
+                       /* case 2, ilm_start <= address < ilm_end */
+                       if (ilm_end < address_end) {
+                               /* update end_address to split non-ILM from ILM */
+                               *end_address = ilm_end;
+                       }
+                       /* ILM mode */
+                       aice_memory_mode(aice, NDS_MEMORY_SELECT_ILM);
+               } else { /* case 3, ilm_end <= address */
+                       /* MEM mode */
+                       aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+               }
+
+               return ERROR_OK;
+       } else {
+               LOG_DEBUG("ILM is not enabled");
+       }
+
+       if ((memory->dlm_base != 0) && (memory->dlm_enable == true)) {
+               dlm_start = memory->dlm_start;
+               dlm_end = memory->dlm_end;
+
+               /* case 1, address < dlm_start */
+               if (address < dlm_start) {
+                       if (dlm_start < address_end) {
+                               /* update end_address to split non-DLM from DLM */
+                               *end_address = dlm_start;
+                       }
+                       /* MEM mode */
+                       aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+               } else if ((dlm_start <= address) && (address < dlm_end)) {
+                       /* case 2, dlm_start <= address < dlm_end */
+                       if (dlm_end < address_end) {
+                               /* update end_address to split non-DLM from DLM */
+                               *end_address = dlm_end;
+                       }
+                       /* DLM mode */
+                       aice_memory_mode(aice, NDS_MEMORY_SELECT_DLM);
+               } else { /* case 3, dlm_end <= address */
+                       /* MEM mode */
+                       aice_memory_mode(aice, NDS_MEMORY_SELECT_MEM);
+               }
+
+               return ERROR_OK;
+       } else {
+               LOG_DEBUG("DLM is not enabled");
+       }
+
+       return ERROR_OK;
+}
+
+int nds32_read_buffer(struct target *target, uint32_t address,
+               uint32_t size, uint8_t *buffer)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct nds32_memory *memory = &(nds32->memory);
+
+       if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
+                       (target->state != TARGET_HALTED)) {
+               LOG_WARNING("target was not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       LOG_DEBUG("READ BUFFER: ADDR %08" PRIx32 "  SIZE %08" PRIx32,
+                       address,
+                       size);
+
+       int retval = ERROR_OK;
+       struct aice_port_s *aice = target_to_aice(target);
+       uint32_t end_address;
+
+       if (((address % 2) == 0) && (size == 2)) {
+               nds32_select_memory_mode(target, address, 2, &end_address);
+               return aice_read_mem_unit(aice, address, 2, 1, buffer);
+       }
+
+       /* handle unaligned head bytes */
+       if (address % 4) {
+               uint32_t unaligned = 4 - (address % 4);
+
+               if (unaligned > size)
+                       unaligned = size;
+
+               nds32_select_memory_mode(target, address, unaligned, &end_address);
+               retval = aice_read_mem_unit(aice, address, 1, unaligned, buffer);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               buffer += unaligned;
+               address += unaligned;
+               size -= unaligned;
+       }
+
+       /* handle aligned words */
+       if (size >= 4) {
+               int aligned = size - (size % 4);
+               int read_len;
+
+               do {
+                       nds32_select_memory_mode(target, address, aligned, &end_address);
+
+                       read_len = end_address - address;
+
+                       if (read_len > 8)
+                               retval = aice_read_mem_bulk(aice, address, read_len, buffer);
+                       else
+                               retval = aice_read_mem_unit(aice, address, 4, read_len / 4, buffer);
+
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       buffer += read_len;
+                       address += read_len;
+                       size -= read_len;
+                       aligned -= read_len;
+
+               } while (aligned != 0);
+       }
+
+       /*prevent byte access when possible (avoid AHB access limitations in some cases)*/
+       if (size >= 2) {
+               int aligned = size - (size % 2);
+               nds32_select_memory_mode(target, address, aligned, &end_address);
+               retval = aice_read_mem_unit(aice, address, 2, aligned / 2, buffer);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               buffer += aligned;
+               address += aligned;
+               size -= aligned;
+       }
+       /* handle tail writes of less than 4 bytes */
+       if (size > 0) {
+               nds32_select_memory_mode(target, address, size, &end_address);
+               retval = aice_read_mem_unit(aice, address, 1, size, buffer);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return ERROR_OK;
+}
+
+int nds32_read_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       struct aice_port_s *aice = target_to_aice(target);
+
+       return aice_read_mem_unit(aice, address, size, count, buffer);
+}
+
+int nds32_read_phys_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       struct aice_port_s *aice = target_to_aice(target);
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct nds32_memory *memory = &(nds32->memory);
+       enum nds_memory_access orig_channel;
+       int result;
+
+       /* switch to BUS access mode to skip MMU */
+       orig_channel = memory->access_channel;
+       memory->access_channel = NDS_MEMORY_ACC_BUS;
+       aice_memory_access(aice, memory->access_channel);
+
+       /* The input address is physical address.  No need to do address translation. */
+       result = aice_read_mem_unit(aice, address, size, count, buffer);
+
+       /* restore to origin access mode */
+       memory->access_channel = orig_channel;
+       aice_memory_access(aice, memory->access_channel);
+
+       return result;
+}
+
+int nds32_write_buffer(struct target *target, uint32_t address,
+               uint32_t size, const uint8_t *buffer)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct nds32_memory *memory = &(nds32->memory);
+
+       if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
+                       (target->state != TARGET_HALTED)) {
+               LOG_WARNING("target was not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       LOG_DEBUG("WRITE BUFFER: ADDR %08" PRIx32 "  SIZE %08" PRIx32,
+                       address,
+                       size);
+
+       struct aice_port_s *aice = target_to_aice(target);
+       int retval = ERROR_OK;
+       uint32_t end_address;
+
+       if (((address % 2) == 0) && (size == 2)) {
+               nds32_select_memory_mode(target, address, 2, &end_address);
+               return aice_write_mem_unit(aice, address, 2, 1, buffer);
+       }
+
+       /* handle unaligned head bytes */
+       if (address % 4) {
+               uint32_t unaligned = 4 - (address % 4);
+
+               if (unaligned > size)
+                       unaligned = size;
+
+               nds32_select_memory_mode(target, address, unaligned, &end_address);
+               retval = aice_write_mem_unit(aice, address, 1, unaligned, buffer);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               buffer += unaligned;
+               address += unaligned;
+               size -= unaligned;
+       }
+
+       /* handle aligned words */
+       if (size >= 4) {
+               int aligned = size - (size % 4);
+               int write_len;
+
+               do {
+                       nds32_select_memory_mode(target, address, aligned, &end_address);
+
+                       write_len = end_address - address;
+                       if (write_len > 8)
+                               retval = aice_write_mem_bulk(aice, address, write_len, buffer);
+                       else
+                               retval = aice_write_mem_unit(aice, address, 4, write_len / 4, buffer);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       buffer += write_len;
+                       address += write_len;
+                       size -= write_len;
+                       aligned -= write_len;
+
+               } while (aligned != 0);
+       }
+
+       /* handle tail writes of less than 4 bytes */
+       if (size > 0) {
+               nds32_select_memory_mode(target, address, size, &end_address);
+               retval = aice_write_mem_unit(aice, address, 1, size, buffer);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       return retval;
+}
+
+int nds32_write_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, const uint8_t *buffer)
+{
+       struct aice_port_s *aice = target_to_aice(target);
+
+       return aice_write_mem_unit(aice, address, size, count, buffer);
+}
+
+int nds32_write_phys_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, const uint8_t *buffer)
+{
+       struct aice_port_s *aice = target_to_aice(target);
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct nds32_memory *memory = &(nds32->memory);
+       enum nds_memory_access orig_channel;
+       int result;
+
+       /* switch to BUS access mode to skip MMU */
+       orig_channel = memory->access_channel;
+       memory->access_channel = NDS_MEMORY_ACC_BUS;
+       aice_memory_access(aice, memory->access_channel);
+
+       /* The input address is physical address.  No need to do address translation. */
+       result = aice_write_mem_unit(aice, address, size, count, buffer);
+
+       /* restore to origin access mode */
+       memory->access_channel = orig_channel;
+       aice_memory_access(aice, memory->access_channel);
+
+       return result;
+}
+
+int nds32_mmu(struct target *target, int *enabled)
+{
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("%s: target not halted", __func__);
+               return ERROR_TARGET_INVALID;
+       }
+
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct nds32_memory *memory = &(nds32->memory);
+       struct nds32_mmu_config *mmu_config = &(nds32->mmu_config);
+
+       if ((mmu_config->memory_protection == 2) && (memory->address_translation == true))
+               *enabled = 1;
+       else
+               *enabled = 0;
+
+       return ERROR_OK;
+}
+
+int nds32_arch_state(struct target *target)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (nds32->common_magic != NDS32_COMMON_MAGIC) {
+               LOG_ERROR("BUG: called for a non-Andes target");
+               return ERROR_FAIL;
+       }
+
+       uint32_t value_pc, value_psw;
+
+       nds32_get_mapped_reg(nds32, PC, &value_pc);
+       nds32_get_mapped_reg(nds32, IR0, &value_psw);
+
+       LOG_USER("target halted due to %s\n"
+                       "psw: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s",
+                       debug_reason_name(target),
+                       value_psw,
+                       value_pc,
+                       nds32->virtual_hosting ? ", virtual hosting" : "");
+
+       /* save pc value to pseudo register pc */
+       struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1);
+       buf_set_u32(reg->value, 0, 32, value_pc);
+
+       return ERROR_OK;
+}
+
+static void nds32_init_must_have_registers(struct nds32 *nds32)
+{
+       struct reg_cache *reg_cache = nds32->core_cache;
+
+       /** MUST have general registers */
+       ((struct nds32_reg *)reg_cache->reg_list[R0].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R1].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R2].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R3].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R4].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R5].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R6].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R7].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R8].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R9].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R10].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R15].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R28].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R29].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R30].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[R31].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[PC].arch_info)->enable = true;
+
+       /** MUST have configuration system registers */
+       ((struct nds32_reg *)reg_cache->reg_list[CR0].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[CR1].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[CR2].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[CR3].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[CR4].arch_info)->enable = true;
+
+       /** MUST have interrupt system registers */
+       ((struct nds32_reg *)reg_cache->reg_list[IR0].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[IR1].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[IR3].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[IR4].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[IR6].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[IR9].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[IR11].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[IR14].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[IR15].arch_info)->enable = true;
+
+       /** MUST have MMU system registers */
+       ((struct nds32_reg *)reg_cache->reg_list[MR0].arch_info)->enable = true;
+
+       /** MUST have EDM system registers */
+       ((struct nds32_reg *)reg_cache->reg_list[DR40].arch_info)->enable = true;
+       ((struct nds32_reg *)reg_cache->reg_list[DR42].arch_info)->enable = true;
+}
+
+static int nds32_init_memory_config(struct nds32 *nds32)
+{
+       uint32_t value_cr1; /* ICM_CFG */
+       uint32_t value_cr2; /* DCM_CFG */
+       struct nds32_memory *memory = &(nds32->memory);
+
+       /* read $cr1 to init instruction memory information */
+       nds32_get_mapped_reg(nds32, CR1, &value_cr1);
+       memory->icache.set = value_cr1 & 0x7;
+       memory->icache.way = (value_cr1 >> 3) & 0x7;
+       memory->icache.line_size = (value_cr1 >> 6) & 0x7;
+       memory->icache.lock_support = (value_cr1 >> 9) & 0x1;
+
+       memory->ilm_base = (value_cr1 >> 10) & 0x7;
+       memory->ilm_align_ver = (value_cr1 >> 13) & 0x3;
+
+       /* read $cr2 to init data memory information */
+       nds32_get_mapped_reg(nds32, CR2, &value_cr2);
+       memory->dcache.set = value_cr2 & 0x7;
+       memory->dcache.way = (value_cr2 >> 3) & 0x7;
+       memory->dcache.line_size = (value_cr2 >> 6) & 0x7;
+       memory->dcache.lock_support = (value_cr2 >> 9) & 0x1;
+
+       memory->dlm_base = (value_cr2 >> 10) & 0x7;
+       memory->dlm_align_ver = (value_cr2 >> 13) & 0x3;
+
+       return ERROR_OK;
+}
+
+static void nds32_init_config(struct nds32 *nds32)
+{
+       uint32_t value_cr0;
+       uint32_t value_cr3;
+       uint32_t value_cr4;
+       struct nds32_cpu_version *cpu_version = &(nds32->cpu_version);
+       struct nds32_mmu_config *mmu_config = &(nds32->mmu_config);
+       struct nds32_misc_config *misc_config = &(nds32->misc_config);
+
+       nds32_get_mapped_reg(nds32, CR0, &value_cr0);
+       nds32_get_mapped_reg(nds32, CR3, &value_cr3);
+       nds32_get_mapped_reg(nds32, CR4, &value_cr4);
+
+       /* config cpu version */
+       cpu_version->performance_extension = value_cr0 & 0x1;
+       cpu_version->_16bit_extension = (value_cr0 >> 1) & 0x1;
+       cpu_version->performance_extension_2 = (value_cr0 >> 2) & 0x1;
+       cpu_version->cop_fpu_extension = (value_cr0 >> 3) & 0x1;
+       cpu_version->string_extension = (value_cr0 >> 4) & 0x1;
+       cpu_version->revision = (value_cr0 >> 16) & 0xFF;
+       cpu_version->cpu_id_family = (value_cr0 >> 24) & 0xF;
+       cpu_version->cpu_id_version = (value_cr0 >> 28) & 0xF;
+
+       /* config MMU */
+       mmu_config->memory_protection = value_cr3 & 0x3;
+       mmu_config->memory_protection_version = (value_cr3 >> 2) & 0x1F;
+       mmu_config->fully_associative_tlb = (value_cr3 >> 7) & 0x1;
+       if (mmu_config->fully_associative_tlb) {
+               mmu_config->tlb_size = (value_cr3 >> 8) & 0x7F;
+       } else {
+               mmu_config->tlb_ways = (value_cr3 >> 8) & 0x7;
+               mmu_config->tlb_sets = (value_cr3 >> 11) & 0x7;
+       }
+       mmu_config->_8k_page_support = (value_cr3 >> 15) & 0x1;
+       mmu_config->extra_page_size_support = (value_cr3 >> 16) & 0xFF;
+       mmu_config->tlb_lock = (value_cr3 >> 24) & 0x1;
+       mmu_config->hardware_page_table_walker = (value_cr3 >> 25) & 0x1;
+       mmu_config->default_endian = (value_cr3 >> 26) & 0x1;
+       mmu_config->partition_num = (value_cr3 >> 27) & 0x1;
+       mmu_config->invisible_tlb = (value_cr3 >> 28) & 0x1;
+       mmu_config->vlpt = (value_cr3 >> 29) & 0x1;
+       mmu_config->ntme = (value_cr3 >> 30) & 0x1;
+       mmu_config->drde = (value_cr3 >> 31) & 0x1;
+
+       /* config misc */
+       misc_config->edm = value_cr4 & 0x1;
+       misc_config->local_memory_dma = (value_cr4 >> 1) & 0x1;
+       misc_config->performance_monitor = (value_cr4 >> 2) & 0x1;
+       misc_config->high_speed_memory_port = (value_cr4 >> 3) & 0x1;
+       misc_config->debug_tracer = (value_cr4 >> 4) & 0x1;
+       misc_config->div_instruction = (value_cr4 >> 5) & 0x1;
+       misc_config->mac_instruction = (value_cr4 >> 6) & 0x1;
+       misc_config->audio_isa = (value_cr4 >> 7) & 0x3;
+       misc_config->L2_cache = (value_cr4 >> 9) & 0x1;
+       misc_config->reduce_register = (value_cr4 >> 10) & 0x1;
+       misc_config->addr_24 = (value_cr4 >> 11) & 0x1;
+       misc_config->interruption_level = (value_cr4 >> 12) & 0x1;
+       misc_config->baseline_instruction = (value_cr4 >> 13) & 0x7;
+       misc_config->no_dx_register = (value_cr4 >> 16) & 0x1;
+       misc_config->implement_dependant_register = (value_cr4 >> 17) & 0x1;
+       misc_config->implement_dependant_sr_encoding = (value_cr4 >> 18) & 0x1;
+       misc_config->ifc = (value_cr4 >> 19) & 0x1;
+       misc_config->mcu = (value_cr4 >> 20) & 0x1;
+       misc_config->shadow = (value_cr4 >> 21) & 0x7;
+       misc_config->ex9 = (value_cr4 >> 24) & 0x1;
+
+       nds32_init_memory_config(nds32);
+}
+
+static int nds32_init_option_registers(struct nds32 *nds32)
+{
+       struct reg_cache *reg_cache = nds32->core_cache;
+       struct nds32_cpu_version *cpu_version = &(nds32->cpu_version);
+       struct nds32_mmu_config *mmu_config = &(nds32->mmu_config);
+       struct nds32_misc_config *misc_config = &(nds32->misc_config);
+       struct nds32_memory *memory_config = &(nds32->memory);
+
+       bool no_cr5;
+       bool mr10_exist;
+       bool no_racr0;
+
+       if (((cpu_version->cpu_id_family == 0xC) || (cpu_version->cpu_id_family == 0xD)) &&
+                       ((cpu_version->revision & 0xFC) == 0)) {
+               no_cr5 = true;
+               mr10_exist = true;
+               no_racr0 = true;
+       } else {
+               no_cr5 = false;
+               mr10_exist = false;
+               no_racr0 = false;
+       }
+
+       if (misc_config->reduce_register == false) {
+               ((struct nds32_reg *)reg_cache->reg_list[R11].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R12].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R13].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R14].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R16].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R17].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R18].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R19].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R20].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R21].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R22].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R23].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R24].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R25].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R26].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[R27].arch_info)->enable = true;
+       }
+
+       if (misc_config->no_dx_register == false) {
+               ((struct nds32_reg *)reg_cache->reg_list[D0LO].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[D0HI].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[D1LO].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[D1HI].arch_info)->enable = true;
+       }
+
+       if (misc_config->ex9)
+               ((struct nds32_reg *)reg_cache->reg_list[ITB].arch_info)->enable = true;
+
+       if (no_cr5 == false)
+               ((struct nds32_reg *)reg_cache->reg_list[CR5].arch_info)->enable = true;
+
+       if (cpu_version->cop_fpu_extension) {
+               ((struct nds32_reg *)reg_cache->reg_list[CR6].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[FPCSR].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[FPCFG].arch_info)->enable = true;
+       }
+
+       if (mmu_config->memory_protection == 1) {
+               /* Secure MPU has no IPC, IPSW, P_ITYPE */
+               ((struct nds32_reg *)reg_cache->reg_list[IR1].arch_info)->enable = false;
+               ((struct nds32_reg *)reg_cache->reg_list[IR9].arch_info)->enable = false;
+       }
+
+       if (nds32->privilege_level != 0)
+               ((struct nds32_reg *)reg_cache->reg_list[IR3].arch_info)->enable = false;
+
+       if (misc_config->mcu == true)
+               ((struct nds32_reg *)reg_cache->reg_list[IR4].arch_info)->enable = false;
+
+       if (misc_config->interruption_level == false) {
+               ((struct nds32_reg *)reg_cache->reg_list[IR2].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IR5].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IR10].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IR12].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IR13].arch_info)->enable = true;
+
+               /* Secure MPU has no IPC, IPSW, P_ITYPE */
+               if (mmu_config->memory_protection != 1)
+                       ((struct nds32_reg *)reg_cache->reg_list[IR7].arch_info)->enable = true;
+       }
+
+       if ((cpu_version->cpu_id_family == 0x9) ||
+                       (cpu_version->cpu_id_family == 0xA) ||
+                       (cpu_version->cpu_id_family == 0xC) ||
+                       (cpu_version->cpu_id_family == 0xD))
+               ((struct nds32_reg *)reg_cache->reg_list[IR8].arch_info)->enable = true;
+
+       if (misc_config->shadow == 1) {
+               ((struct nds32_reg *)reg_cache->reg_list[IR16].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IR17].arch_info)->enable = true;
+       }
+
+       if (misc_config->ifc)
+               ((struct nds32_reg *)reg_cache->reg_list[IFC_LP].arch_info)->enable = true;
+
+       if (nds32->privilege_level != 0)
+               ((struct nds32_reg *)reg_cache->reg_list[MR0].arch_info)->enable = false;
+
+       if (mmu_config->memory_protection == 1) {
+               if (mmu_config->memory_protection_version == 24)
+                       ((struct nds32_reg *)reg_cache->reg_list[MR4].arch_info)->enable = true;
+
+               if (nds32->privilege_level == 0) {
+                       if ((mmu_config->memory_protection_version == 16) ||
+                               (mmu_config->memory_protection_version == 24)) {
+                               ((struct nds32_reg *)reg_cache->reg_list[MR11].arch_info)->enable = true;
+                               ((struct nds32_reg *)reg_cache->reg_list[SECUR0].arch_info)->enable = true;
+                               ((struct nds32_reg *)reg_cache->reg_list[IR20].arch_info)->enable = true;
+                               ((struct nds32_reg *)reg_cache->reg_list[IR22].arch_info)->enable = true;
+                               ((struct nds32_reg *)reg_cache->reg_list[IR24].arch_info)->enable = true;
+                               ((struct nds32_reg *)reg_cache->reg_list[IR30].arch_info)->enable = true;
+
+                               if (misc_config->shadow == 1) {
+                                       ((struct nds32_reg *)reg_cache->reg_list[IR21].arch_info)->enable = true;
+                                       ((struct nds32_reg *)reg_cache->reg_list[IR23].arch_info)->enable = true;
+                                       ((struct nds32_reg *)reg_cache->reg_list[IR25].arch_info)->enable = true;
+                               }
+                       }
+               }
+       } else if (mmu_config->memory_protection == 2) {
+               ((struct nds32_reg *)reg_cache->reg_list[MR1].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[MR4].arch_info)->enable = true;
+
+               if ((cpu_version->cpu_id_family != 0xA) && (cpu_version->cpu_id_family != 0xC) &&
+                               (cpu_version->cpu_id_family != 0xD))
+                       ((struct nds32_reg *)reg_cache->reg_list[MR5].arch_info)->enable = true;
+       }
+
+       if (mmu_config->memory_protection > 0) {
+               ((struct nds32_reg *)reg_cache->reg_list[MR2].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[MR3].arch_info)->enable = true;
+       }
+
+       if (memory_config->ilm_base != 0)
+               if (nds32->privilege_level == 0)
+                       ((struct nds32_reg *)reg_cache->reg_list[MR6].arch_info)->enable = true;
+
+       if (memory_config->dlm_base != 0)
+               if (nds32->privilege_level == 0)
+                       ((struct nds32_reg *)reg_cache->reg_list[MR7].arch_info)->enable = true;
+
+       if ((memory_config->icache.line_size != 0) && (memory_config->dcache.line_size != 0))
+               ((struct nds32_reg *)reg_cache->reg_list[MR8].arch_info)->enable = true;
+
+       if (misc_config->high_speed_memory_port)
+               ((struct nds32_reg *)reg_cache->reg_list[MR9].arch_info)->enable = true;
+
+       if (mr10_exist)
+               ((struct nds32_reg *)reg_cache->reg_list[MR10].arch_info)->enable = true;
+
+       if (misc_config->edm) {
+               int dr_reg_n = nds32->edm.breakpoint_num * 5;
+
+               for (int i = 0 ; i < dr_reg_n ; i++)
+                       ((struct nds32_reg *)reg_cache->reg_list[DR0 + i].arch_info)->enable = true;
+
+               ((struct nds32_reg *)reg_cache->reg_list[DR41].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DR43].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DR44].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DR45].arch_info)->enable = true;
+       }
+
+       if (misc_config->debug_tracer) {
+               ((struct nds32_reg *)reg_cache->reg_list[DR46].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DR47].arch_info)->enable = true;
+       }
+
+       if (misc_config->performance_monitor) {
+               ((struct nds32_reg *)reg_cache->reg_list[PFR0].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[PFR1].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[PFR2].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[PFR3].arch_info)->enable = true;
+       }
+
+       if (misc_config->local_memory_dma) {
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR0].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR1].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR2].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR3].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR4].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR5].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR6].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR7].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR8].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR9].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[DMAR10].arch_info)->enable = true;
+       }
+
+       if ((misc_config->local_memory_dma || misc_config->performance_monitor) &&
+                       (no_racr0 == false))
+               ((struct nds32_reg *)reg_cache->reg_list[RACR].arch_info)->enable = true;
+
+       if (cpu_version->cop_fpu_extension || (misc_config->audio_isa != 0))
+               ((struct nds32_reg *)reg_cache->reg_list[FUCPR].arch_info)->enable = true;
+
+       if (misc_config->audio_isa != 0) {
+               if (misc_config->audio_isa > 1) {
+                       ((struct nds32_reg *)reg_cache->reg_list[D0L24].arch_info)->enable = true;
+                       ((struct nds32_reg *)reg_cache->reg_list[D1L24].arch_info)->enable = true;
+               }
+
+               ((struct nds32_reg *)reg_cache->reg_list[I0].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[I1].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[I2].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[I3].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[I4].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[I5].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[I6].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[I7].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[M1].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[M2].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[M3].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[M5].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[M6].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[M7].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[MOD].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[LBE].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[LE].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[LC].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[ADM_VBASE].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[SHFT_CTL0].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[SHFT_CTL1].arch_info)->enable = true;
+
+               uint32_t value_mod;
+               uint32_t fucpr_backup;
+               /* enable fpu and get configuration */
+               nds32_get_mapped_reg(nds32, FUCPR, &fucpr_backup);
+               if ((fucpr_backup & 0x80000000) == 0)
+                       nds32_set_mapped_reg(nds32, FUCPR, fucpr_backup | 0x80000000);
+               nds32_get_mapped_reg(nds32, MOD, &value_mod);
+               /* restore origin fucpr value */
+               if ((fucpr_backup & 0x80000000) == 0)
+                       nds32_set_mapped_reg(nds32, FUCPR, fucpr_backup);
+
+               if ((value_mod >> 6) & 0x1) {
+                       ((struct nds32_reg *)reg_cache->reg_list[CB_CTL].arch_info)->enable = true;
+                       ((struct nds32_reg *)reg_cache->reg_list[CBB0].arch_info)->enable = true;
+                       ((struct nds32_reg *)reg_cache->reg_list[CBB1].arch_info)->enable = true;
+                       ((struct nds32_reg *)reg_cache->reg_list[CBB2].arch_info)->enable = true;
+                       ((struct nds32_reg *)reg_cache->reg_list[CBB3].arch_info)->enable = true;
+                       ((struct nds32_reg *)reg_cache->reg_list[CBE0].arch_info)->enable = true;
+                       ((struct nds32_reg *)reg_cache->reg_list[CBE1].arch_info)->enable = true;
+                       ((struct nds32_reg *)reg_cache->reg_list[CBE2].arch_info)->enable = true;
+                       ((struct nds32_reg *)reg_cache->reg_list[CBE3].arch_info)->enable = true;
+               }
+       }
+
+       if ((cpu_version->cpu_id_family == 0x9) ||
+                       (cpu_version->cpu_id_family == 0xA) ||
+                       (cpu_version->cpu_id_family == 0xC)) {
+
+               ((struct nds32_reg *)reg_cache->reg_list[IDR0].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IDR1].arch_info)->enable = true;
+
+               if ((cpu_version->cpu_id_family == 0xC) && (cpu_version->revision == 0x0C))
+                       ((struct nds32_reg *)reg_cache->reg_list[IDR0].arch_info)->enable = false;
+       }
+
+       uint32_t ir3_value;
+       uint32_t ivb_prog_pri_lvl;
+       uint32_t ivb_ivic_ver;
+
+       nds32_get_mapped_reg(nds32, IR3, &ir3_value);
+       ivb_prog_pri_lvl = ir3_value & 0x1;
+       ivb_ivic_ver = (ir3_value >> 11) & 0x3;
+
+       if ((ivb_prog_pri_lvl == 1) || (ivb_ivic_ver >= 1)) {
+               ((struct nds32_reg *)reg_cache->reg_list[IR18].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IR19].arch_info)->enable = true;
+       }
+
+       if (ivb_ivic_ver >= 1) {
+               ((struct nds32_reg *)reg_cache->reg_list[IR26].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IR27].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IR28].arch_info)->enable = true;
+               ((struct nds32_reg *)reg_cache->reg_list[IR29].arch_info)->enable = true;
+       }
+
+       return ERROR_OK;
+}
+
+int nds32_init_register_table(struct nds32 *nds32)
+{
+       nds32_init_must_have_registers(nds32);
+
+       return ERROR_OK;
+}
+
+int nds32_add_software_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
+{
+       uint32_t data;
+       uint32_t check_data;
+       uint32_t break_insn;
+
+       /* check the breakpoint size */
+       target->type->read_buffer(target, breakpoint->address, 4, (uint8_t *)&data);
+
+       /* backup origin instruction
+        * instruction is big-endian */
+       if (*(char *)&data & 0x80) { /* 16-bits instruction */
+               breakpoint->length = 2;
+               break_insn = NDS32_BREAK_16;
+       } else { /* 32-bits instruction */
+               breakpoint->length = 4;
+               break_insn = NDS32_BREAK_32;
+       }
+
+       if (breakpoint->orig_instr != NULL)
+               free(breakpoint->orig_instr);
+
+       breakpoint->orig_instr = malloc(breakpoint->length);
+       memcpy(breakpoint->orig_instr, &data, breakpoint->length);
+
+       /* self-modified code */
+       target->type->write_buffer(target, breakpoint->address, breakpoint->length, (const uint8_t *)&break_insn);
+       /* write_back & invalidate dcache & invalidate icache */
+       nds32_cache_sync(target, breakpoint->address, breakpoint->length);
+
+       /* read back to check */
+       target->type->read_buffer(target, breakpoint->address, breakpoint->length, (uint8_t *)&check_data);
+       if (memcmp(&check_data, &break_insn, breakpoint->length) == 0)
+               return ERROR_OK;
+
+       return ERROR_FAIL;
+}
+
+int nds32_remove_software_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
+{
+       uint32_t check_data;
+       uint32_t break_insn;
+
+       if (breakpoint->length == 2)
+               break_insn = NDS32_BREAK_16;
+       else if (breakpoint->length == 4)
+               break_insn = NDS32_BREAK_32;
+       else
+               return ERROR_FAIL;
+
+       target->type->read_buffer(target, breakpoint->address, breakpoint->length,
+                       (uint8_t *)&check_data);
+
+       /* break instruction is modified */
+       if (memcmp(&check_data, &break_insn, breakpoint->length) != 0)
+               return ERROR_FAIL;
+
+       /* self-modified code */
+       target->type->write_buffer(target, breakpoint->address, breakpoint->length,
+                       breakpoint->orig_instr);
+
+       /* write_back & invalidate dcache & invalidate icache */
+       nds32_cache_sync(target, breakpoint->address, breakpoint->length);
+
+       return ERROR_OK;
+}
+
+/**
+ * Restore the processor context on an Andes target.  The full processor
+ * context is analyzed to see if any of the registers are dirty on this end, but
+ * have a valid new value.  If this is the case, the processor is changed to the
+ * appropriate mode and the new register values are written out to the
+ * processor.  If there happens to be a dirty register with an invalid value, an
+ * error will be logged.
+ *
+ * @param target Pointer to the Andes target to have its context restored
+ * @return Error status if the target is not halted.
+ */
+int nds32_restore_context(struct target *target)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+       struct reg_cache *reg_cache = nds32->core_cache;
+       struct reg *reg;
+       struct nds32_reg *reg_arch_info;
+       unsigned int i;
+
+       LOG_DEBUG("-");
+
+       if (target->state != TARGET_HALTED) {
+               LOG_WARNING("target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /* check if there are dirty registers */
+       for (i = 0; i < reg_cache->num_regs; i++) {
+               reg = &(reg_cache->reg_list[i]);
+               if (reg->dirty == true) {
+                       if (reg->valid == true) {
+
+                               LOG_DEBUG("examining dirty reg: %s", reg->name);
+                               LOG_DEBUG("writing register %i "
+                                               "with value 0x%8.8" PRIx32, i, buf_get_u32(reg->value, 0, 32));
+
+                               reg_arch_info = reg->arch_info;
+                               if (FD0 <= reg_arch_info->num && reg_arch_info->num <= FD31)
+                                       aice_write_reg_64(aice, reg_arch_info->num, reg_arch_info->value_64);
+                               else
+                                       aice_write_register(aice, reg_arch_info->num, reg_arch_info->value);
+                               reg->valid = true;
+                               reg->dirty = false;
+                       }
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int nds32_edm_config(struct nds32 *nds32)
+{
+       struct target *target = nds32->target;
+       struct aice_port_s *aice = target_to_aice(target);
+       uint32_t edm_cfg;
+       uint32_t edm_ctl;
+
+       aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CFG, &edm_cfg);
+
+       nds32->edm.version = (edm_cfg >> 16) & 0xFFFF;
+       LOG_INFO("EDM version 0x%04" PRIx32, nds32->edm.version);
+
+       nds32->edm.breakpoint_num = (edm_cfg & 0x7) + 1;
+
+       if ((nds32->edm.version & 0x1000) || (0x60 <= nds32->edm.version))
+               nds32->edm.access_control = true;
+       else
+               nds32->edm.access_control = false;
+
+       if ((edm_cfg >> 4) & 0x1)
+               nds32->edm.direct_access_local_memory = true;
+       else
+               nds32->edm.direct_access_local_memory = false;
+
+       if (nds32->edm.version <= 0x20)
+               nds32->edm.direct_access_local_memory = false;
+
+       aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &edm_ctl);
+       if (edm_ctl & (0x1 << 29))
+               nds32->edm.support_max_stop = true;
+       else
+               nds32->edm.support_max_stop = false;
+
+       /* set passcode for secure MCU */
+       nds32_login(nds32);
+
+       return ERROR_OK;
+}
+
+int nds32_config(struct nds32 *nds32)
+{
+       nds32_init_config(nds32);
+
+       /* init optional system registers according to config registers */
+       nds32_init_option_registers(nds32);
+
+       /* get max interrupt level */
+       if (nds32->misc_config.interruption_level)
+               nds32->max_interrupt_level = 2;
+       else
+               nds32->max_interrupt_level = 3;
+
+       /* get ILM/DLM size from MR6/MR7 */
+       uint32_t value_mr6, value_mr7;
+       uint32_t size_index;
+       nds32_get_mapped_reg(nds32, MR6, &value_mr6);
+       size_index = (value_mr6 >> 1) & 0xF;
+       nds32->memory.ilm_size = NDS32_LM_SIZE_TABLE[size_index];
+
+       nds32_get_mapped_reg(nds32, MR7, &value_mr7);
+       size_index = (value_mr7 >> 1) & 0xF;
+       nds32->memory.dlm_size = NDS32_LM_SIZE_TABLE[size_index];
+
+       return ERROR_OK;
+}
+
+int nds32_init_arch_info(struct target *target, struct nds32 *nds32)
+{
+       target->arch_info = nds32;
+       nds32->target = target;
+
+       nds32->common_magic = NDS32_COMMON_MAGIC;
+       nds32->init_arch_info_after_halted = false;
+       nds32->auto_convert_hw_bp = true;
+       nds32->global_stop = false;
+       nds32->soft_reset_halt = false;
+       nds32->edm_passcode = NULL;
+       nds32->privilege_level = 0;
+       nds32->boot_time = 1500;
+       nds32->reset_halt_as_examine = false;
+       nds32->keep_target_edm_ctl = false;
+       nds32->word_access_mem = false;
+       nds32->virtual_hosting = false;
+
+       nds32_reg_init();
+
+       if (ERROR_FAIL == nds32_reg_cache_init(target, nds32))
+               return ERROR_FAIL;
+
+       if (ERROR_OK != nds32_init_register_table(nds32))
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
+int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t *physical)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (nds32->memory.address_translation == false) {
+               *physical = address;
+               return ERROR_OK;
+       }
+
+       if (ERROR_OK == nds32_probe_tlb(nds32, address, physical))
+               return ERROR_OK;
+
+       if (ERROR_OK == nds32_walk_page_table(nds32, address, physical))
+               return ERROR_OK;
+
+       return ERROR_FAIL;
+}
+
+int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length)
+{
+       struct aice_port_s *aice = target_to_aice(target);
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct nds32_cache *dcache = &(nds32->memory.dcache);
+       struct nds32_cache *icache = &(nds32->memory.icache);
+       uint32_t dcache_line_size = NDS32_LINE_SIZE_TABLE[dcache->line_size];
+       uint32_t icache_line_size = NDS32_LINE_SIZE_TABLE[icache->line_size];
+       uint32_t cur_address;
+       int result;
+       uint32_t start_line, end_line;
+       uint32_t cur_line;
+
+       if ((dcache->line_size != 0) && (dcache->enable == true)) {
+               /* address / dcache_line_size */
+               start_line = address >> (dcache->line_size + 2);
+               /* (address + length - 1) / dcache_line_size */
+               end_line = (address + length - 1) >> (dcache->line_size + 2);
+
+               for (cur_address = address, cur_line = start_line ;
+                               cur_line <= end_line ;
+                               cur_address += dcache_line_size, cur_line++) {
+                       /* D$ write back */
+                       result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_VA_WB, cur_address);
+                       if (result != ERROR_OK)
+                               return result;
+
+                       /* D$ invalidate */
+                       result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_VA_INVAL, cur_address);
+                       if (result != ERROR_OK)
+                               return result;
+               }
+       }
+
+       if ((icache->line_size != 0) && (icache->enable == true)) {
+               /*  address / icache_line_size */
+               start_line = address >> (icache->line_size + 2);
+               /* (address + length - 1) / icache_line_size */
+               end_line = (address + length - 1) >> (icache->line_size + 2);
+
+               for (cur_address = address, cur_line = start_line ;
+                               cur_line <= end_line ;
+                               cur_address += icache_line_size, cur_line++) {
+                       /* Because PSW.IT is turned off under debug exception, address MUST
+                        * be physical address.  L1I_VA_INVALIDATE uses PSW.IT to decide
+                        * address translation or not. */
+                       uint32_t physical_addr;
+                       if (ERROR_FAIL == target->type->virt2phys(target, cur_address,
+                                               &physical_addr))
+                               return ERROR_FAIL;
+
+                       /* I$ invalidate */
+                       result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_VA_INVAL, physical_addr);
+                       if (result != ERROR_OK)
+                               return result;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address)
+{
+       if (!current)
+               nds32_set_mapped_reg(nds32, PC, address);
+       else
+               nds32_get_mapped_reg(nds32, PC, &address);
+
+       return address;
+}
+
+int nds32_step(struct target *target, int current,
+               uint32_t address, int handle_breakpoints)
+{
+       LOG_DEBUG("target->state: %s",
+                       target_state_name(target));
+
+       if (target->state != TARGET_HALTED) {
+               LOG_WARNING("target was not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       address = nds32_nextpc(nds32, current, address);
+
+       LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : "");
+
+       /** set DSSIM */
+       uint32_t ir14_value;
+       nds32_get_mapped_reg(nds32, IR14, &ir14_value);
+       if (nds32->step_isr_enable)
+               ir14_value |= (0x1 << 31);
+       else
+               ir14_value &= ~(0x1 << 31);
+       nds32_set_mapped_reg(nds32, IR14, ir14_value);
+
+       /********* TODO: maybe create another function to handle this part */
+       CHECK_RETVAL(nds32->leave_debug_state(nds32, true));
+       CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
+
+       struct aice_port_s *aice = target_to_aice(target);
+       if (ERROR_OK != aice_step(aice))
+               return ERROR_FAIL;
+
+       /* save state */
+       CHECK_RETVAL(nds32->enter_debug_state(nds32, true));
+       /********* TODO: maybe create another function to handle this part */
+
+       /* restore DSSIM */
+       if (nds32->step_isr_enable) {
+               nds32_get_mapped_reg(nds32, IR14, &ir14_value);
+               ir14_value &= ~(0x1 << 31);
+               nds32_set_mapped_reg(nds32, IR14, ir14_value);
+       }
+
+       CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
+
+       return ERROR_OK;
+}
+
+static int nds32_step_without_watchpoint(struct nds32 *nds32)
+{
+       struct target *target = nds32->target;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_WARNING("target was not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       /** set DSSIM */
+       uint32_t ir14_value;
+       nds32_get_mapped_reg(nds32, IR14, &ir14_value);
+       if (nds32->step_isr_enable)
+               ir14_value |= (0x1 << 31);
+       else
+               ir14_value &= ~(0x1 << 31);
+       nds32_set_mapped_reg(nds32, IR14, ir14_value);
+
+       /********* TODO: maybe create another function to handle this part */
+       CHECK_RETVAL(nds32->leave_debug_state(nds32, false));
+
+       struct aice_port_s *aice = target_to_aice(target);
+
+       if (ERROR_OK != aice_step(aice))
+               return ERROR_FAIL;
+
+       /* save state */
+       CHECK_RETVAL(nds32->enter_debug_state(nds32, false));
+       /********* TODO: maybe create another function to handle this part */
+
+       /* restore DSSIM */
+       if (nds32->step_isr_enable) {
+               nds32_get_mapped_reg(nds32, IR14, &ir14_value);
+               ir14_value &= ~(0x1 << 31);
+               nds32_set_mapped_reg(nds32, IR14, ir14_value);
+       }
+
+       return ERROR_OK;
+}
+
+int nds32_target_state(struct nds32 *nds32, enum target_state *state)
+{
+       struct aice_port_s *aice = target_to_aice(nds32->target);
+       enum aice_target_state_s nds32_state;
+
+       if (aice_state(aice, &nds32_state) != ERROR_OK)
+               return ERROR_FAIL;
+
+       switch (nds32_state) {
+               case AICE_DISCONNECT:
+                       LOG_INFO("USB is disconnected");
+                       return ERROR_FAIL;
+               case AICE_TARGET_DETACH:
+                       LOG_INFO("Target is disconnected");
+                       return ERROR_FAIL;
+               case AICE_TARGET_UNKNOWN:
+                       *state = TARGET_UNKNOWN;
+                       break;
+               case AICE_TARGET_RUNNING:
+                       *state = TARGET_RUNNING;
+                       break;
+               case AICE_TARGET_HALTED:
+                       *state = TARGET_HALTED;
+                       break;
+               case AICE_TARGET_RESET:
+                       *state = TARGET_RESET;
+                       break;
+               case AICE_TARGET_DEBUG_RUNNING:
+                       *state = TARGET_DEBUG_RUNNING;
+                       break;
+               default:
+                       return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+int nds32_examine_debug_reason(struct nds32 *nds32)
+{
+       uint32_t reason;
+       struct target *target = nds32->target;
+
+       nds32->get_debug_reason(nds32, &reason);
+
+       LOG_DEBUG("nds32 examines debug reason: %s", nds32_debug_type_name[reason]);
+
+       /* Examine debug reason */
+       switch (reason) {
+               case NDS32_DEBUG_BREAK:
+               case NDS32_DEBUG_BREAK_16:
+               case NDS32_DEBUG_INST_BREAK:
+                       {
+                               uint32_t value_pc;
+                               uint32_t opcode;
+                               struct nds32_instruction instruction;
+
+                               nds32_get_mapped_reg(nds32, PC, &value_pc);
+
+                               if (ERROR_OK != nds32_read_opcode(nds32, value_pc, &opcode))
+                                       return ERROR_FAIL;
+                               if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode, value_pc,
+                                                       &instruction))
+                                       return ERROR_FAIL;
+
+                               target->debug_reason = DBG_REASON_BREAKPOINT;
+                       }
+                       break;
+               case NDS32_DEBUG_DATA_ADDR_WATCHPOINT_PRECISE:
+               case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_PRECISE:
+               case NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP: /* GLOBAL_STOP is precise exception */
+                       {
+                               int result;
+
+                               result = nds32->get_watched_address(nds32,
+                                               &(nds32->watched_address), reason);
+                               /* do single step(without watchpoints) to skip the "watched" instruction */
+                               nds32_step_without_watchpoint(nds32);
+
+                               /* before single_step, save exception address */
+                               if (ERROR_OK != result)
+                                       return ERROR_FAIL;
+
+                               target->debug_reason = DBG_REASON_WATCHPOINT;
+                       }
+                       break;
+               case NDS32_DEBUG_DEBUG_INTERRUPT:
+                       target->debug_reason = DBG_REASON_DBGRQ;
+                       break;
+               case NDS32_DEBUG_HARDWARE_SINGLE_STEP:
+                       target->debug_reason = DBG_REASON_SINGLESTEP;
+                       break;
+               case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_IMPRECISE:
+               case NDS32_DEBUG_DATA_ADDR_WATCHPOINT_NEXT_PRECISE:
+               case NDS32_DEBUG_DATA_VALUE_WATCHPOINT_NEXT_PRECISE:
+                       if (ERROR_OK != nds32->get_watched_address(nds32,
+                                               &(nds32->watched_address), reason))
+                               return ERROR_FAIL;
+
+                       target->debug_reason = DBG_REASON_WATCHPOINT;
+                       break;
+               default:
+                       target->debug_reason = DBG_REASON_UNDEFINED;
+                       break;
+       }
+
+       return ERROR_OK;
+}
+
+int nds32_login(struct nds32 *nds32)
+{
+       struct target *target = nds32->target;
+       struct aice_port_s *aice = target_to_aice(target);
+       uint32_t passcode_length;
+       char command_sequence[129];
+       char command_str[33];
+       char code_str[9];
+       uint32_t copy_length;
+       uint32_t code;
+       uint32_t i;
+
+       LOG_DEBUG("nds32_login");
+
+       if (nds32->edm_passcode != NULL) {
+               /* convert EDM passcode to command sequences */
+               passcode_length = strlen(nds32->edm_passcode);
+               command_sequence[0] = '\0';
+               for (i = 0; i < passcode_length; i += 8) {
+                       if (passcode_length - i < 8)
+                               copy_length = passcode_length - i;
+                       else
+                               copy_length = 8;
+
+                       strncpy(code_str, nds32->edm_passcode + i, copy_length);
+                       code_str[copy_length] = '\0';
+                       code = strtoul(code_str, NULL, 16);
+
+                       sprintf(command_str, "write_misc gen_port0 0x%x;", code);
+                       strcat(command_sequence, command_str);
+               }
+
+               if (ERROR_OK != aice_program_edm(aice, command_sequence))
+                       return ERROR_FAIL;
+
+               /* get current privilege level */
+               uint32_t value_edmsw;
+               aice_read_debug_reg(aice, NDS_EDM_SR_EDMSW, &value_edmsw);
+               nds32->privilege_level = (value_edmsw >> 16) & 0x3;
+               LOG_INFO("Current privilege level: %d", nds32->privilege_level);
+       }
+
+       if (nds32_edm_ops_num > 0) {
+               const char *reg_name;
+               for (i = 0 ; i < nds32_edm_ops_num ; i++) {
+                       code = nds32_edm_ops[i].value;
+                       if (nds32_edm_ops[i].reg_no == 6)
+                               reg_name = "gen_port0";
+                       else if (nds32_edm_ops[i].reg_no == 7)
+                               reg_name = "gen_port1";
+                       else
+                               return ERROR_FAIL;
+
+                       sprintf(command_str, "write_misc %s 0x%x;", reg_name, code);
+                       if (ERROR_OK != aice_program_edm(aice, command_str))
+                               return ERROR_FAIL;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int nds32_halt(struct target *target)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+       enum target_state state;
+
+       LOG_DEBUG("target->state: %s",
+                       target_state_name(target));
+
+       if (target->state == TARGET_HALTED) {
+               LOG_DEBUG("target was already halted");
+               return ERROR_OK;
+       }
+
+       if (nds32_target_state(nds32, &state) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (TARGET_HALTED != state)
+               /* TODO: if state == TARGET_HALTED, check ETYPE is DBGI or not */
+               if (ERROR_OK != aice_halt(aice))
+                       return ERROR_FAIL;
+
+       CHECK_RETVAL(nds32->enter_debug_state(nds32, true));
+
+       CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
+
+       return ERROR_OK;
+}
+
+/* poll current target status */
+int nds32_poll(struct target *target)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+       enum target_state state;
+
+       if (nds32_target_state(nds32, &state) != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (state == TARGET_HALTED) {
+               if (target->state != TARGET_HALTED) {
+                       /* if false_hit, continue free_run */
+                       if (ERROR_OK != nds32->enter_debug_state(nds32, true)) {
+                               struct aice_port_s *aice = target_to_aice(target);
+                               aice_run(aice);
+                               return ERROR_OK;
+                       }
+
+                       LOG_DEBUG("Change target state to TARGET_HALTED.");
+
+                       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+               }
+       } else if (state == TARGET_RESET) {
+               if (target->state == TARGET_HALTED) {
+                       /* similar to assert srst */
+                       register_cache_invalidate(nds32->core_cache);
+                       target->state = TARGET_RESET;
+
+                       /* TODO: deassert srst */
+               } else if (target->state == TARGET_RUNNING) {
+                       /* reset as running */
+                       LOG_WARNING("<-- TARGET WARNING! The debug target has been reset. -->");
+               }
+       } else {
+               if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING) {
+                       LOG_DEBUG("Change target state to TARGET_RUNNING.");
+                       target->state = TARGET_RUNNING;
+                       target->debug_reason = DBG_REASON_NOTHALTED;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int nds32_resume(struct target *target, int current,
+               uint32_t address, int handle_breakpoints, int debug_execution)
+{
+       LOG_DEBUG("current %d  address %08x  handle_breakpoints %d  debug_execution %d",
+                       current, address, handle_breakpoints, debug_execution);
+
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (target->state != TARGET_HALTED) {
+               LOG_ERROR("Target not halted");
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       address = nds32_nextpc(nds32, current, address);
+
+       LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : "");
+
+       if (!debug_execution)
+               target_free_all_working_areas(target);
+
+       /* Disable HSS to avoid users misuse HSS */
+       if (nds32_reach_max_interrupt_level(nds32) == false) {
+               uint32_t value_ir0;
+               nds32_get_mapped_reg(nds32, IR0, &value_ir0);
+               value_ir0 &= ~(0x1 << 11);
+               nds32_set_mapped_reg(nds32, IR0, value_ir0);
+       }
+
+       CHECK_RETVAL(nds32->leave_debug_state(nds32, true));
+       CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
+
+       struct aice_port_s *aice = target_to_aice(target);
+       aice_run(aice);
+
+       target->debug_reason = DBG_REASON_NOTHALTED;
+       if (!debug_execution)
+               target->state = TARGET_RUNNING;
+       else
+               target->state = TARGET_DEBUG_RUNNING;
+
+       LOG_DEBUG("target->state: %s",
+                       target_state_name(target));
+
+       return ERROR_OK;
+}
+
+int nds32_assert_reset(struct target *target)
+{
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+
+       jtag_poll_set_enabled(true);
+
+       if (target->reset_halt) {
+               if (nds32->soft_reset_halt)
+                       target->type->soft_reset_halt(target);
+               else
+                       aice_assert_srst(aice, AICE_RESET_HOLD);
+       } else {
+               aice_assert_srst(aice, AICE_SRST);
+               alive_sleep(nds32->boot_time);
+       }
+
+       /* set passcode for secure MCU after core reset */
+       nds32_login(nds32);
+
+       /* registers are now invalid */
+       register_cache_invalidate(nds32->core_cache);
+
+       target->state = TARGET_RESET;
+
+       return ERROR_OK;
+}
+
+static uint32_t nds32_backup_edm_ctl;
+static bool gdb_attached;
+
+static int nds32_gdb_attach(struct nds32 *nds32)
+{
+       LOG_DEBUG("nds32_gdb_attach");
+
+       if (gdb_attached == false) {
+
+               if (nds32->keep_target_edm_ctl) {
+                       /* backup target EDM_CTL */
+                       struct aice_port_s *aice = target_to_aice(nds32->target);
+                       aice_read_debug_reg(aice, NDS_EDM_SR_EDM_CTL, &nds32_backup_edm_ctl);
+               }
+
+               target_halt(nds32->target);
+               target_poll(nds32->target);
+
+               gdb_attached = true;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_gdb_detach(struct nds32 *nds32)
+{
+       LOG_DEBUG("nds32_gdb_detach");
+       bool backup_virtual_hosting_setting;
+
+       if (gdb_attached) {
+
+               backup_virtual_hosting_setting = nds32->virtual_hosting;
+               /* turn off virtual hosting before resume as gdb-detach */
+               nds32->virtual_hosting = false;
+               target_resume(nds32->target, 1, 0, 0, 0);
+               nds32->virtual_hosting = backup_virtual_hosting_setting;
+
+               if (nds32->keep_target_edm_ctl) {
+                       /* restore target EDM_CTL */
+                       struct aice_port_s *aice = target_to_aice(nds32->target);
+                       aice_write_debug_reg(aice, NDS_EDM_SR_EDM_CTL, nds32_backup_edm_ctl);
+               }
+
+               /* turn off polling */
+               jtag_poll_set_enabled(false);
+
+               gdb_attached = false;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_callback_event_handler(struct target *target,
+               enum target_event event, void *priv)
+{
+       int retval = ERROR_OK;
+       struct nds32 *nds32 = priv;
+
+       switch (event) {
+               case TARGET_EVENT_GDB_ATTACH:
+                       retval = nds32_gdb_attach(nds32);
+                       break;
+               case TARGET_EVENT_GDB_DETACH:
+                       retval = nds32_gdb_detach(nds32);
+                       break;
+               default:
+                       break;
+       }
+
+       return retval;
+}
+
+int nds32_init(struct nds32 *nds32)
+{
+       /* Initialize anything we can set up without talking to the target */
+       nds32->memory.access_channel = NDS_MEMORY_ACC_CPU;
+
+       /* turn off polling by default */
+       jtag_poll_set_enabled(false);
+
+       /* register event callback */
+       target_register_event_callback(nds32_callback_event_handler, nds32);
+
+       return ERROR_OK;
+}
+
+int nds32_reset_halt(struct nds32 *nds32)
+{
+       LOG_INFO("reset halt as init");
+
+       struct aice_port_s *aice = target_to_aice(nds32->target);
+       aice_assert_srst(aice, AICE_RESET_HOLD);
+
+       return ERROR_OK;
+}
index cec8ae0..f585c2d 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2013 by Andes Technology                                *
+ *   Copyright (C) 2013 Andes Technology                                   *
  *   Hsiangkai Wang <hkwang@andestech.com>                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -22,7 +22,6 @@
 #define __NDS32_H__
 
 #include <jtag/jtag.h>
-#include <jtag/aice/aice_port.h>
 #include "target.h"
 #include "target_type.h"
 #include "register.h"
@@ -31,6 +30,8 @@
 #include "nds32_insn.h"
 #include "nds32_edm.h"
 
+#define NDS32_EDM_OPERATION_MAX_NUM 64
+
 #define CHECK_RETVAL(action)                   \
        do {                                    \
                int __retval = (action);        \
@@ -62,18 +63,11 @@ enum nds32_debug_reason {
        NDS32_DEBUG_LOAD_STORE_GLOBAL_STOP,
 };
 
-enum nds32_tdesc_type {
-       NDS32_CORE_TDESC = 0,
-       NDS32_SYSTEM_TDESC,
-       NDS32_AUDIO_TDESC,
-       NDS32_FPU_TDESC,
-       NDS32_NUM_TDESC,
-};
-
 #define NDS32_STRUCT_STAT_SIZE 60
 #define NDS32_STRUCT_TIMEVAL_SIZE 8
 
 enum nds32_syscall_id {
+       NDS32_SYSCALL_UNDEFINED = 0,
        NDS32_SYSCALL_EXIT = 1,
        NDS32_SYSCALL_OPEN = 2,
        NDS32_SYSCALL_CLOSE = 3,
@@ -100,7 +94,8 @@ struct nds32_edm {
        /** The number of hardware breakpoints */
        int breakpoint_num;
 
-       /** EDM_CFG.DALM, indicate if direct local memory access feature is supported or not */
+       /** EDM_CFG.DALM, indicate if direct local memory access
+        * feature is supported or not */
        bool direct_access_local_memory;
 
        /** Support ACC_CTL register */
@@ -173,10 +168,10 @@ struct nds32_memory {
        int dlm_end;
 
        /** Memory access method */
-       enum aice_memory_access access_channel;
+       enum nds_memory_access access_channel;
 
        /** Memory access mode */
-       enum aice_memory_mode mode;
+       enum nds_memory_select mode;
 
        /** Address translation */
        bool address_translation;
@@ -275,7 +270,7 @@ struct nds32 {
        /** Backup target registers may be modified in debug state */
        int (*enter_debug_state)(struct nds32 *nds32, bool enable_watchpoint);
 
-       /** Get address hitted watchpoint */
+       /** Get address hit watchpoint */
        int (*get_watched_address)(struct nds32 *nds32, uint32_t *address, uint32_t reason);
 
        /** maximum interrupt level */
@@ -289,24 +284,28 @@ struct nds32 {
        /** Flag reporting whether virtual hosting is active. */
        bool virtual_hosting;
 
-       /** Flag reporting whether continue/step hits syscall or not */
-       bool hit_syscall;
-
-       /** Value to be returned by virtual hosting SYS_ERRNO request. */
-       int virtual_hosting_errno;
-
-       /** Flag reporting whether syscall is aborted */
-       bool virtual_hosting_ctrl_c;
-
-       /** Record syscall ID for other operations to do special processing for target */
-       int active_syscall_id;
-
        /** Flag reporting whether global stop is active. */
        bool global_stop;
 
+       /** Flag reporting whether to use soft-reset-halt or not as issuing reset-halt. */
+       bool soft_reset_halt;
+
        /** reset-halt as target examine */
        bool reset_halt_as_examine;
 
+       /** backup/restore target EDM_CTL value. As debugging target debug
+        * handler, it should be true. */
+       bool keep_target_edm_ctl;
+
+       /** always use word-aligned address to access memory */
+       bool word_access_mem;
+
+       /** EDM passcode for debugging secure MCU */
+       char *edm_passcode;
+
+       /** current privilege_level if using secure MCU. value 0 is the highest level.  */
+       int privilege_level;
+
        /** Period to wait after SRST. */
        uint32_t boot_time;
 
@@ -322,12 +321,19 @@ struct nds32 {
        /** Flag to indicate fpu-extension is enabled or not */
        bool fpu_enable;
 
+       /* Andes Core has mixed endian model. Instruction is always big-endian.
+        * Data may be big or little endian. Device registers may have different
+        * endian from data and instruction. */
+       /** Endian of data memory */
+       enum target_endianness data_endian;
+
+       /** Endian of device registers */
+       enum target_endianness device_reg_endian;
+
        /** Flag to indicate if auto convert software breakpoints to
         *  hardware breakpoints or not in ROM */
        bool auto_convert_hw_bp;
 
-       int (*setup_virtual_hosting)(struct target *target, int enable);
-
        /** Backpointer to the target. */
        struct target *target;
 
@@ -343,32 +349,33 @@ struct nds32_reg {
        bool enable;
 };
 
+struct nds32_edm_operation {
+       uint32_t reg_no;
+       uint32_t value;
+};
+
 extern int nds32_config(struct nds32 *nds32);
 extern int nds32_init_arch_info(struct target *target, struct nds32 *nds32);
 extern int nds32_full_context(struct nds32 *nds32);
 extern int nds32_arch_state(struct target *target);
 extern int nds32_add_software_breakpoint(struct target *target,
-                                       struct breakpoint *breakpoint);
+               struct breakpoint *breakpoint);
 extern int nds32_remove_software_breakpoint(struct target *target,
-                                       struct breakpoint *breakpoint);
+               struct breakpoint *breakpoint);
 
-extern int nds32_get_gdb_general_reg_list(struct target *target,
-                                       struct reg **reg_list[], int *reg_list_size);
 extern int nds32_get_gdb_reg_list(struct target *target,
-                               struct reg **reg_list[], int *reg_list_size);
-extern int nds32_get_gdb_target_description(struct target *target, char **xml,
-                                       char *annex, int32_t offset, uint32_t length);
+               struct reg **reg_list[], int *reg_list_size);
 
 extern int nds32_write_buffer(struct target *target, uint32_t address,
-                               uint32_t size, const uint8_t *buffer);
+               uint32_t size, const uint8_t *buffer);
 extern int nds32_read_buffer(struct target *target, uint32_t address,
-                               uint32_t size, uint8_t *buffer);
+               uint32_t size, uint8_t *buffer);
 extern int nds32_bulk_write_memory(struct target *target,
-                                       uint32_t address, uint32_t count, const uint8_t *buffer);
+               uint32_t address, uint32_t count, const uint8_t *buffer);
 extern int nds32_read_memory(struct target *target, uint32_t address,
-                               uint32_t size, uint32_t count, uint8_t *buffer);
+               uint32_t size, uint32_t count, uint8_t *buffer);
 extern int nds32_write_memory(struct target *target, uint32_t address,
-                               uint32_t size, uint32_t count, const uint8_t *buffer);
+               uint32_t size, uint32_t count, const uint8_t *buffer);
 
 extern int nds32_init_register_table(struct nds32 *nds32);
 extern int nds32_init_memory_info(struct nds32 *nds32);
@@ -377,31 +384,27 @@ extern int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t *
 extern int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value);
 
 extern int nds32_edm_config(struct nds32 *nds32);
-extern int nds32_check_extension(struct nds32 *nds32);
 extern int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length);
 extern int nds32_mmu(struct target *target, int *enabled);
-extern int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t *physical);
+extern int nds32_virtual_to_physical(struct target *target, uint32_t address,
+               uint32_t *physical);
 extern int nds32_read_phys_memory(struct target *target, uint32_t address,
-                                       uint32_t size, uint32_t count, uint8_t *buffer);
+               uint32_t size, uint32_t count, uint8_t *buffer);
 extern int nds32_write_phys_memory(struct target *target, uint32_t address,
-                                       uint32_t size, uint32_t count, const uint8_t *buffer);
-extern int nds32_soft_reset_halt(struct target *target);
+               uint32_t size, uint32_t count, const uint8_t *buffer);
 extern uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address);
 extern int nds32_examine_debug_reason(struct nds32 *nds32);
 extern int nds32_step(struct target *target, int current,
-                       uint32_t address, int handle_breakpoints);
+               uint32_t address, int handle_breakpoints);
 extern int nds32_target_state(struct nds32 *nds32, enum target_state *state);
 extern int nds32_halt(struct target *target);
 extern int nds32_poll(struct target *target);
 extern int nds32_resume(struct target *target, int current,
-                       uint32_t address, int handle_breakpoints, int debug_execution);
+               uint32_t address, int handle_breakpoints, int debug_execution);
 extern int nds32_assert_reset(struct target *target);
 extern int nds32_init(struct nds32 *nds32);
-extern int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info);
-extern int nds32_gdb_fileio_write_memory(struct nds32 *nds32, uint32_t address,
-                                               uint32_t size, const uint8_t *buffer);
-extern int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c);
 extern int nds32_reset_halt(struct nds32 *nds32);
+extern int nds32_login(struct nds32 *nds32);
 
 /** Convert target handle to generic Andes target state handle. */
 static inline struct nds32 *target_to_nds32(struct target *target)
diff --git a/src/target/nds32_aice.c b/src/target/nds32_aice.c
new file mode 100644 (file)
index 0000000..78ae8c2
--- /dev/null
@@ -0,0 +1,157 @@
+/***************************************************************************
+ *   Copyright (C) 2013 Andes technology.                                  *
+ *   Hsiangkai Wang <hkwang@andestech.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, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/log.h>
+#include "nds32_aice.h"
+
+int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val)
+{
+       if (aice->port->api->read_reg_64 == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->read_reg_64(num, val);
+}
+
+int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val)
+{
+       if (aice->port->api->write_reg_64 == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->write_reg_64(num, val);
+}
+
+int aice_select_target(struct aice_port_s *aice, uint32_t target_id)
+{
+       if (aice->port->api->select_target == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->select_target(target_id);
+}
+
+int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address,
+               uint32_t *physical_address)
+{
+       if (aice->port->api->read_tlb == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->read_tlb(virtual_address, physical_address);
+}
+
+int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address)
+{
+       if (aice->port->api->cache_ctl == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->cache_ctl(subtype, address);
+}
+
+int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times)
+{
+       if (aice->port->api->set_retry_times == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->set_retry_times(a_retry_times);
+}
+
+int aice_program_edm(struct aice_port_s *aice, char *command_sequence)
+{
+       if (aice->port->api->program_edm == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->program_edm(command_sequence);
+}
+
+int aice_pack_command(struct aice_port_s *aice, bool enable_pack_command)
+{
+       if (aice->port->api->pack_command == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->pack_command(enable_pack_command);
+}
+
+int aice_execute(struct aice_port_s *aice, uint32_t *instructions,
+               uint32_t instruction_num)
+{
+       if (aice->port->api->execute == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->execute(instructions, instruction_num);
+}
+
+int aice_set_custom_srst_script(struct aice_port_s *aice, const char *script)
+{
+       if (aice->port->api->set_custom_srst_script == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->set_custom_srst_script(script);
+}
+
+int aice_set_custom_trst_script(struct aice_port_s *aice, const char *script)
+{
+       if (aice->port->api->set_custom_trst_script == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->set_custom_trst_script(script);
+}
+
+int aice_set_custom_restart_script(struct aice_port_s *aice, const char *script)
+{
+       if (aice->port->api->set_custom_restart_script == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->set_custom_restart_script(script);
+}
+
+int aice_set_count_to_check_dbger(struct aice_port_s *aice, uint32_t count_to_check)
+{
+       if (aice->port->api->set_count_to_check_dbger == NULL) {
+               LOG_WARNING("Not implemented: %s", __func__);
+               return ERROR_FAIL;
+       }
+
+       return aice->port->api->set_count_to_check_dbger(count_to_check);
+}
diff --git a/src/target/nds32_aice.h b/src/target/nds32_aice.h
new file mode 100644 (file)
index 0000000..abea8df
--- /dev/null
@@ -0,0 +1,160 @@
+/***************************************************************************
+ *   Copyright (C) 2013 Andes technology.                                  *
+ *   Hsiangkai Wang <hkwang@andestech.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, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+#ifndef __NDS32_AICE_H__
+#define __NDS32_AICE_H__
+
+#include <jtag/aice/aice_port.h>
+
+int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val);
+int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val);
+int aice_select_target(struct aice_port_s *aice, uint32_t target_id);
+int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address,
+               uint32_t *physical_address);
+int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address);
+int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times);
+int aice_program_edm(struct aice_port_s *aice, char *command_sequence);
+int aice_pack_command(struct aice_port_s *aice, bool enable_pack_command);
+int aice_execute(struct aice_port_s *aice, uint32_t *instructions,
+               uint32_t instruction_num);
+int aice_set_custom_srst_script(struct aice_port_s *aice, const char *script);
+int aice_set_custom_trst_script(struct aice_port_s *aice, const char *script);
+int aice_set_custom_restart_script(struct aice_port_s *aice, const char *script);
+int aice_set_count_to_check_dbger(struct aice_port_s *aice, uint32_t count_to_check);
+
+static inline int aice_open(struct aice_port_s *aice, struct aice_port_param_s *param)
+{
+       return aice->port->api->open(param);
+}
+
+static inline int aice_close(struct aice_port_s *aice)
+{
+       return aice->port->api->close();
+}
+
+static inline int aice_reset(struct aice_port_s *aice)
+{
+       return aice->port->api->reset();
+}
+
+static inline int aice_assert_srst(struct aice_port_s *aice,
+               enum aice_srst_type_s srst)
+{
+       return aice->port->api->assert_srst(srst);
+}
+
+static inline int aice_run(struct aice_port_s *aice)
+{
+       return aice->port->api->run();
+}
+
+static inline int aice_halt(struct aice_port_s *aice)
+{
+       return aice->port->api->halt();
+}
+
+static inline int aice_step(struct aice_port_s *aice)
+{
+       return aice->port->api->step();
+}
+
+static inline int aice_read_register(struct aice_port_s *aice, uint32_t num,
+               uint32_t *val)
+{
+       return aice->port->api->read_reg(num, val);
+}
+
+static inline int aice_write_register(struct aice_port_s *aice, uint32_t num,
+               uint32_t val)
+{
+       return aice->port->api->write_reg(num, val);
+}
+
+static inline int aice_read_debug_reg(struct aice_port_s *aice, uint32_t addr,
+               uint32_t *val)
+{
+       return aice->port->api->read_debug_reg(addr, val);
+}
+
+static inline int aice_write_debug_reg(struct aice_port_s *aice, uint32_t addr,
+               const uint32_t val)
+{
+       return aice->port->api->write_debug_reg(addr, val);
+}
+
+static inline int aice_read_mem_unit(struct aice_port_s *aice, uint32_t addr,
+               uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       return aice->port->api->read_mem_unit(addr, size, count, buffer);
+}
+
+static inline int aice_write_mem_unit(struct aice_port_s *aice, uint32_t addr,
+               uint32_t size, uint32_t count, const uint8_t *buffer)
+{
+       return aice->port->api->write_mem_unit(addr, size, count, buffer);
+}
+
+static inline int aice_read_mem_bulk(struct aice_port_s *aice, uint32_t addr,
+               uint32_t length, uint8_t *buffer)
+{
+       return aice->port->api->read_mem_bulk(addr, length, buffer);
+}
+
+static inline int aice_write_mem_bulk(struct aice_port_s *aice, uint32_t addr,
+               uint32_t length, const uint8_t *buffer)
+{
+       return aice->port->api->write_mem_bulk(addr, length, buffer);
+}
+
+static inline int aice_idcode(struct aice_port_s *aice, uint32_t *idcode,
+               uint8_t *num_of_idcode)
+{
+       return aice->port->api->idcode(idcode, num_of_idcode);
+}
+
+static inline int aice_state(struct aice_port_s *aice,
+               enum aice_target_state_s *state)
+{
+       return aice->port->api->state(state);
+}
+
+static inline int aice_set_jtag_clock(struct aice_port_s *aice, uint32_t a_clock)
+{
+       return aice->port->api->set_jtag_clock(a_clock);
+}
+
+static inline int aice_memory_access(struct aice_port_s *aice,
+               enum nds_memory_access a_access)
+{
+       return aice->port->api->memory_access(a_access);
+}
+
+static inline int aice_memory_mode(struct aice_port_s *aice,
+               enum nds_memory_select mem_select)
+{
+       return aice->port->api->memory_mode(mem_select);
+}
+
+static inline int aice_set_data_endian(struct aice_port_s *aice,
+               enum aice_target_endian target_data_endian)
+{
+       return aice->port->api->set_data_endian(target_data_endian);
+}
+
+#endif
diff --git a/src/target/nds32_cmd.c b/src/target/nds32_cmd.c
new file mode 100644 (file)
index 0000000..a16308e
--- /dev/null
@@ -0,0 +1,1106 @@
+/***************************************************************************
+ *   Copyright (C) 2013 Andes Technology                                   *
+ *   Hsiangkai Wang <hkwang@andestech.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, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/command.h>
+#include "nds32.h"
+#include "nds32_aice.h"
+#include "nds32_disassembler.h"
+
+extern struct nds32_edm_operation nds32_edm_ops[NDS32_EDM_OPERATION_MAX_NUM];
+extern uint32_t nds32_edm_ops_num;
+
+static const char *const NDS_MEMORY_ACCESS_NAME[] = {
+       "BUS",
+       "CPU",
+};
+
+static const char *const NDS_MEMORY_SELECT_NAME[] = {
+       "AUTO",
+       "MEM",
+       "ILM",
+       "DLM",
+};
+
+COMMAND_HANDLER(handle_nds32_dssim_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+               if (strcmp(CMD_ARGV[0], "on") == 0)
+                       nds32->step_isr_enable = true;
+               if (strcmp(CMD_ARGV[0], "off") == 0)
+                       nds32->step_isr_enable = false;
+       }
+
+       command_print(CMD_CTX, "$INT_MASK.DSSIM: %d", nds32->step_isr_enable);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_memory_access_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+
+               /* If target has no cache, always use BUS mode
+                * to access memory. */
+               struct nds32_memory *memory = &(nds32->memory);
+
+               if (memory->dcache.line_size == 0) {
+                       /* There is no Dcache. */
+                       nds32->memory.access_channel = NDS_MEMORY_ACC_BUS;
+               } else if (memory->dcache.enable == false) {
+                       /* Dcache is disabled. */
+                       nds32->memory.access_channel = NDS_MEMORY_ACC_BUS;
+               } else {
+                       /* There is Dcache and Dcache is enabled. */
+                       if (strcmp(CMD_ARGV[0], "bus") == 0)
+                               nds32->memory.access_channel = NDS_MEMORY_ACC_BUS;
+                       else if (strcmp(CMD_ARGV[0], "cpu") == 0)
+                               nds32->memory.access_channel = NDS_MEMORY_ACC_CPU;
+                       else /* default access channel is NDS_MEMORY_ACC_CPU */
+                               nds32->memory.access_channel = NDS_MEMORY_ACC_CPU;
+               }
+
+               aice_memory_access(aice, nds32->memory.access_channel);
+       }
+
+       command_print(CMD_CTX, "memory access channel: %s",
+                       NDS_MEMORY_ACCESS_NAME[nds32->memory.access_channel]);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_memory_mode_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+
+               if (nds32->edm.access_control == false) {
+                       command_print(CMD_CTX, "Target does not support ACC_CTL. "
+                                       "Set memory mode to MEMORY");
+                       nds32->memory.mode = NDS_MEMORY_SELECT_MEM;
+               } else if (nds32->edm.direct_access_local_memory == false) {
+                       command_print(CMD_CTX, "Target does not support direct access "
+                                       "local memory. Set memory mode to MEMORY");
+                       nds32->memory.mode = NDS_MEMORY_SELECT_MEM;
+
+                       /* set to ACC_CTL */
+                       aice_memory_mode(aice, nds32->memory.mode);
+               } else {
+                       if (strcmp(CMD_ARGV[0], "auto") == 0) {
+                               nds32->memory.mode = NDS_MEMORY_SELECT_AUTO;
+                       } else if (strcmp(CMD_ARGV[0], "mem") == 0) {
+                               nds32->memory.mode = NDS_MEMORY_SELECT_MEM;
+                       } else if (strcmp(CMD_ARGV[0], "ilm") == 0) {
+                               if (nds32->memory.ilm_base == 0)
+                                       command_print(CMD_CTX, "Target does not support ILM");
+                               else
+                                       nds32->memory.mode = NDS_MEMORY_SELECT_ILM;
+                       } else if (strcmp(CMD_ARGV[0], "dlm") == 0) {
+                               if (nds32->memory.dlm_base == 0)
+                                       command_print(CMD_CTX, "Target does not support DLM");
+                               else
+                                       nds32->memory.mode = NDS_MEMORY_SELECT_DLM;
+                       }
+
+                       /* set to ACC_CTL */
+                       aice_memory_mode(aice, nds32->memory.mode);
+               }
+       }
+
+       command_print(CMD_CTX, "memory mode: %s",
+                       NDS_MEMORY_SELECT_NAME[nds32->memory.mode]);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_cache_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+       struct nds32_cache *icache = &(nds32->memory.icache);
+       struct nds32_cache *dcache = &(nds32->memory.dcache);
+       int result;
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+
+               if (strcmp(CMD_ARGV[0], "invalidate") == 0) {
+                       if ((dcache->line_size != 0) && (dcache->enable == true)) {
+                               /* D$ write back */
+                               result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_WBALL, 0);
+                               if (result != ERROR_OK) {
+                                       command_print(CMD_CTX, "Write back data cache...failed");
+                                       return result;
+                               }
+
+                               command_print(CMD_CTX, "Write back data cache...done");
+
+                               /* D$ invalidate */
+                               result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_INVALALL, 0);
+                               if (result != ERROR_OK) {
+                                       command_print(CMD_CTX, "Invalidate data cache...failed");
+                                       return result;
+                               }
+
+                               command_print(CMD_CTX, "Invalidate data cache...done");
+                       } else {
+                               if (dcache->line_size == 0)
+                                       command_print(CMD_CTX, "No data cache");
+                               else
+                                       command_print(CMD_CTX, "Data cache disabled");
+                       }
+
+                       if ((icache->line_size != 0) && (icache->enable == true)) {
+                               /* I$ invalidate */
+                               result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_INVALALL, 0);
+                               if (result != ERROR_OK) {
+                                       command_print(CMD_CTX, "Invalidate instruction cache...failed");
+                                       return result;
+                               }
+
+                               command_print(CMD_CTX, "Invalidate instruction cache...done");
+                       } else {
+                               if (icache->line_size == 0)
+                                       command_print(CMD_CTX, "No instruction cache");
+                               else
+                                       command_print(CMD_CTX, "Instruction cache disabled");
+                       }
+               } else
+                       command_print(CMD_CTX, "No valid parameter");
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_icache_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+       struct nds32_cache *icache = &(nds32->memory.icache);
+       int result;
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+
+               if (icache->line_size == 0) {
+                       command_print(CMD_CTX, "No instruction cache");
+                       return ERROR_OK;
+               }
+
+               if (strcmp(CMD_ARGV[0], "invalidate") == 0) {
+                       if (icache->enable == true) {
+                               /* I$ invalidate */
+                               result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1I_INVALALL, 0);
+                               if (result != ERROR_OK) {
+                                       command_print(CMD_CTX, "Invalidate instruction cache...failed");
+                                       return result;
+                               }
+
+                               command_print(CMD_CTX, "Invalidate instruction cache...done");
+                       } else {
+                               command_print(CMD_CTX, "Instruction cache disabled");
+                       }
+               } else if (strcmp(CMD_ARGV[0], "enable") == 0) {
+                       uint32_t value;
+                       nds32_get_mapped_reg(nds32, IR8, &value);
+                       nds32_set_mapped_reg(nds32, IR8, value | 0x1);
+               } else if (strcmp(CMD_ARGV[0], "disable") == 0) {
+                       uint32_t value;
+                       nds32_get_mapped_reg(nds32, IR8, &value);
+                       nds32_set_mapped_reg(nds32, IR8, value & ~0x1);
+               } else if (strcmp(CMD_ARGV[0], "dump") == 0) {
+                       /* TODO: dump cache content */
+               } else {
+                       command_print(CMD_CTX, "No valid parameter");
+               }
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_dcache_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+       struct aice_port_s *aice = target_to_aice(target);
+       struct nds32_cache *dcache = &(nds32->memory.dcache);
+       int result;
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+
+               if (dcache->line_size == 0) {
+                       command_print(CMD_CTX, "No data cache");
+                       return ERROR_OK;
+               }
+
+               if (strcmp(CMD_ARGV[0], "invalidate") == 0) {
+                       if (dcache->enable == true) {
+                               /* D$ write back */
+                               result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_WBALL, 0);
+                               if (result != ERROR_OK) {
+                                       command_print(CMD_CTX, "Write back data cache...failed");
+                                       return result;
+                               }
+
+                               command_print(CMD_CTX, "Write back data cache...done");
+
+                               /* D$ invalidate */
+                               result = aice_cache_ctl(aice, AICE_CACHE_CTL_L1D_INVALALL, 0);
+                               if (result != ERROR_OK) {
+                                       command_print(CMD_CTX, "Invalidate data cache...failed");
+                                       return result;
+                               }
+
+                               command_print(CMD_CTX, "Invalidate data cache...done");
+                       } else {
+                               command_print(CMD_CTX, "Data cache disabled");
+                       }
+               } else if (strcmp(CMD_ARGV[0], "enable") == 0) {
+                       uint32_t value;
+                       nds32_get_mapped_reg(nds32, IR8, &value);
+                       nds32_set_mapped_reg(nds32, IR8, value | 0x2);
+               } else if (strcmp(CMD_ARGV[0], "disable") == 0) {
+                       uint32_t value;
+                       nds32_get_mapped_reg(nds32, IR8, &value);
+                       nds32_set_mapped_reg(nds32, IR8, value & ~0x2);
+               } else if (strcmp(CMD_ARGV[0], "dump") == 0) {
+                       /* TODO: dump cache content */
+               } else {
+                       command_print(CMD_CTX, "No valid parameter");
+               }
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_auto_break_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+               if (strcmp(CMD_ARGV[0], "on") == 0)
+                       nds32->auto_convert_hw_bp = true;
+               if (strcmp(CMD_ARGV[0], "off") == 0)
+                       nds32->auto_convert_hw_bp = false;
+       }
+
+       if (nds32->auto_convert_hw_bp)
+               command_print(CMD_CTX, "convert sw break to hw break on ROM: on");
+       else
+               command_print(CMD_CTX, "convert sw break to hw break on ROM: off");
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_virtual_hosting_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+               if (strcmp(CMD_ARGV[0], "on") == 0)
+                       nds32->virtual_hosting = true;
+               if (strcmp(CMD_ARGV[0], "off") == 0)
+                       nds32->virtual_hosting = false;
+       }
+
+       if (nds32->virtual_hosting)
+               LOG_INFO("virtual hosting: on");
+       else
+               LOG_INFO("virtual hosting: off");
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_global_stop_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+               if (strcmp(CMD_ARGV[0], "on") == 0)
+                       nds32->global_stop = true;
+               if (strcmp(CMD_ARGV[0], "off") == 0)
+                       nds32->global_stop = false;
+       }
+
+       if (nds32->global_stop)
+               LOG_INFO("global stop: on");
+       else
+               LOG_INFO("global stop: off");
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_soft_reset_halt_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+               if (strcmp(CMD_ARGV[0], "on") == 0)
+                       nds32->soft_reset_halt = true;
+               if (strcmp(CMD_ARGV[0], "off") == 0)
+                       nds32->soft_reset_halt = false;
+       }
+
+       if (nds32->soft_reset_halt)
+               LOG_INFO("soft-reset-halt: on");
+       else
+               LOG_INFO("soft-reset-halt: off");
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_boot_time_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0)
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], nds32->boot_time);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_login_edm_passcode_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       nds32->edm_passcode = strdup(CMD_ARGV[0]);
+
+       LOG_INFO("set EDM passcode: %s", nds32->edm_passcode);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_login_edm_operation_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 1) {
+
+               uint32_t misc_reg_no;
+               uint32_t data;
+
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], misc_reg_no);
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], data);
+
+               if (nds32_edm_ops_num >= NDS32_EDM_OPERATION_MAX_NUM)
+                       return ERROR_FAIL;
+
+               /* Just save the operation. Execute it in nds32_login() */
+               nds32_edm_ops[nds32_edm_ops_num].reg_no = misc_reg_no;
+               nds32_edm_ops[nds32_edm_ops_num].value = data;
+               nds32_edm_ops_num++;
+       } else
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_reset_halt_as_init_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+               if (strcmp(CMD_ARGV[0], "on") == 0)
+                       nds32->reset_halt_as_examine = true;
+               if (strcmp(CMD_ARGV[0], "off") == 0)
+                       nds32->reset_halt_as_examine = false;
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_keep_target_edm_ctl_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+               if (strcmp(CMD_ARGV[0], "on") == 0)
+                       nds32->keep_target_edm_ctl = true;
+               if (strcmp(CMD_ARGV[0], "off") == 0)
+                       nds32->keep_target_edm_ctl = false;
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_decode_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 1) {
+
+               uint32_t addr;
+               uint32_t insn_count;
+               uint32_t opcode;
+               uint32_t read_addr;
+               uint32_t i;
+               struct nds32_instruction instruction;
+
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], insn_count);
+
+               read_addr = addr;
+               i = 0;
+               while (i < insn_count) {
+                       if (ERROR_OK != nds32_read_opcode(nds32, read_addr, &opcode))
+                               return ERROR_FAIL;
+                       if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode,
+                                               read_addr, &instruction))
+                               return ERROR_FAIL;
+
+                       command_print(CMD_CTX, "%s", instruction.text);
+
+                       read_addr += instruction.instruction_size;
+                       i++;
+               }
+       } else if (CMD_ARGC == 1) {
+
+               uint32_t addr;
+               uint32_t opcode;
+               struct nds32_instruction instruction;
+
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+
+               if (ERROR_OK != nds32_read_opcode(nds32, addr, &opcode))
+                       return ERROR_FAIL;
+               if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode, addr, &instruction))
+                       return ERROR_FAIL;
+
+               command_print(CMD_CTX, "%s", instruction.text);
+       } else
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_word_access_mem_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0) {
+               if (strcmp(CMD_ARGV[0], "on") == 0)
+                       nds32->word_access_mem = true;
+               if (strcmp(CMD_ARGV[0], "off") == 0)
+                       nds32->word_access_mem = false;
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_query_target_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       command_print(CMD_CTX, "OCD");
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_query_endian_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       uint32_t value_psw;
+       nds32_get_mapped_reg(nds32, IR0, &value_psw);
+
+       if (value_psw & 0x20)
+               command_print(CMD_CTX, "BE");
+       else
+               command_print(CMD_CTX, "LE");
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(handle_nds32_query_cpuid_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       if (!is_nds32(nds32)) {
+               command_print(CMD_CTX, "current target isn't an Andes core");
+               return ERROR_FAIL;
+       }
+
+       command_print(CMD_CTX, "CPUID: %s", target_name(target));
+
+       return ERROR_OK;
+}
+
+static int jim_nds32_bulk_write(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+{
+       const char *cmd_name = Jim_GetString(argv[0], NULL);
+
+       Jim_GetOptInfo goi;
+       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+
+       if (goi.argc < 3) {
+               Jim_SetResultFormatted(goi.interp,
+                               "usage: %s <address> <count> <data>", cmd_name);
+               return JIM_ERR;
+       }
+
+       int e;
+       jim_wide address;
+       e = Jim_GetOpt_Wide(&goi, &address);
+       if (e != JIM_OK)
+               return e;
+
+       jim_wide count;
+       e = Jim_GetOpt_Wide(&goi, &count);
+       if (e != JIM_OK)
+               return e;
+
+       uint32_t *data = malloc(count * sizeof(uint32_t));
+       jim_wide i;
+       for (i = 0; i < count; i++) {
+               jim_wide tmp;
+               e = Jim_GetOpt_Wide(&goi, &tmp);
+               if (e != JIM_OK)
+                       return e;
+               data[i] = (uint32_t)tmp;
+       }
+
+       /* all args must be consumed */
+       if (goi.argc != 0)
+               return JIM_ERR;
+
+       struct target *target = Jim_CmdPrivData(goi.interp);
+       int result;
+
+       result = target_write_buffer(target, address, count * 4, (const uint8_t *)data);
+
+       free(data);
+
+       return result;
+}
+
+static int jim_nds32_multi_write(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+{
+       const char *cmd_name = Jim_GetString(argv[0], NULL);
+
+       Jim_GetOptInfo goi;
+       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+
+       if (goi.argc < 3) {
+               Jim_SetResultFormatted(goi.interp,
+                               "usage: %s # of pairs [<address> <data>]+", cmd_name);
+               return JIM_ERR;
+       }
+
+       int e;
+       jim_wide num_of_pairs;
+       e = Jim_GetOpt_Wide(&goi, &num_of_pairs);
+       if (e != JIM_OK)
+               return e;
+
+       struct target *target = Jim_CmdPrivData(goi.interp);
+       struct aice_port_s *aice = target_to_aice(target);
+       int result;
+       uint32_t address;
+       uint32_t data;
+       jim_wide i;
+
+       aice_pack_command(aice, true);
+       for (i = 0; i < num_of_pairs; i++) {
+               jim_wide tmp;
+               e = Jim_GetOpt_Wide(&goi, &tmp);
+               if (e != JIM_OK)
+                       break;
+               address = (uint32_t)tmp;
+
+               e = Jim_GetOpt_Wide(&goi, &tmp);
+               if (e != JIM_OK)
+                       break;
+               data = (uint32_t)tmp;
+
+               result = target_write_buffer(target, address, 4, (const uint8_t *)&data);
+               if (result != ERROR_OK)
+                       break;
+       }
+       aice_pack_command(aice, false);
+
+       /* all args must be consumed */
+       if (goi.argc != 0)
+               return JIM_ERR;
+
+       return ERROR_OK;
+}
+
+static int jim_nds32_bulk_read(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+{
+       const char *cmd_name = Jim_GetString(argv[0], NULL);
+
+       Jim_GetOptInfo goi;
+       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+
+       if (goi.argc < 2) {
+               Jim_SetResultFormatted(goi.interp,
+                               "usage: %s <address> <count>", cmd_name);
+               return JIM_ERR;
+       }
+
+       int e;
+       jim_wide address;
+       e = Jim_GetOpt_Wide(&goi, &address);
+       if (e != JIM_OK)
+               return e;
+
+       jim_wide count;
+       e = Jim_GetOpt_Wide(&goi, &count);
+       if (e != JIM_OK)
+               return e;
+
+       /* all args must be consumed */
+       if (goi.argc != 0)
+               return JIM_ERR;
+
+       struct target *target = Jim_CmdPrivData(goi.interp);
+       uint32_t *data = malloc(count * sizeof(uint32_t));
+       int result;
+       result = target_read_buffer(target, address, count * 4, (uint8_t *)data);
+       char data_str[11];
+
+       jim_wide i;
+       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+       for (i = 0; i < count; i++) {
+               sprintf(data_str, "0x%08x ", data[i]);
+               Jim_AppendStrings(interp, Jim_GetResult(interp), data_str, NULL);
+       }
+
+       free(data);
+
+       return result;
+}
+
+static int jim_nds32_read_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+{
+       const char *cmd_name = Jim_GetString(argv[0], NULL);
+
+       Jim_GetOptInfo goi;
+       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+
+       if (goi.argc < 1) {
+               Jim_SetResultFormatted(goi.interp,
+                               "usage: %s <edm_sr_name>", cmd_name);
+               return JIM_ERR;
+       }
+
+       int e;
+       char *edm_sr_name;
+       int edm_sr_name_len;
+       e = Jim_GetOpt_String(&goi, &edm_sr_name, &edm_sr_name_len);
+       if (e != JIM_OK)
+               return e;
+
+       /* all args must be consumed */
+       if (goi.argc != 0)
+               return JIM_ERR;
+
+       uint32_t edm_sr_number;
+       uint32_t edm_sr_value;
+       if (strncmp(edm_sr_name, "edm_dtr", edm_sr_name_len) == 0)
+               edm_sr_number = NDS_EDM_SR_EDM_DTR;
+       else if (strncmp(edm_sr_name, "edmsw", edm_sr_name_len) == 0)
+               edm_sr_number = NDS_EDM_SR_EDMSW;
+       else
+               return ERROR_FAIL;
+
+       struct target *target = Jim_CmdPrivData(goi.interp);
+       struct aice_port_s *aice = target_to_aice(target);
+       char data_str[11];
+
+       aice_read_debug_reg(aice, edm_sr_number, &edm_sr_value);
+
+       sprintf(data_str, "0x%08x", edm_sr_value);
+       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+       Jim_AppendStrings(interp, Jim_GetResult(interp), data_str, NULL);
+
+       return ERROR_OK;
+}
+
+static int jim_nds32_write_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+{
+       const char *cmd_name = Jim_GetString(argv[0], NULL);
+
+       Jim_GetOptInfo goi;
+       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+
+       if (goi.argc < 2) {
+               Jim_SetResultFormatted(goi.interp,
+                               "usage: %s <edm_sr_name> <value>", cmd_name);
+               return JIM_ERR;
+       }
+
+       int e;
+       char *edm_sr_name;
+       int edm_sr_name_len;
+       e = Jim_GetOpt_String(&goi, &edm_sr_name, &edm_sr_name_len);
+       if (e != JIM_OK)
+               return e;
+
+       jim_wide value;
+       e = Jim_GetOpt_Wide(&goi, &value);
+       if (e != JIM_OK)
+               return e;
+
+       /* all args must be consumed */
+       if (goi.argc != 0)
+               return JIM_ERR;
+
+       uint32_t edm_sr_number;
+       if (strncmp(edm_sr_name, "edm_dtr", edm_sr_name_len) == 0)
+               edm_sr_number = NDS_EDM_SR_EDM_DTR;
+       else
+               return ERROR_FAIL;
+
+       struct target *target = Jim_CmdPrivData(goi.interp);
+       struct aice_port_s *aice = target_to_aice(target);
+
+       aice_write_debug_reg(aice, edm_sr_number, value);
+
+       return ERROR_OK;
+}
+
+static const struct command_registration nds32_query_command_handlers[] = {
+       {
+               .name = "target",
+               .handler = handle_nds32_query_target_command,
+               .mode = COMMAND_EXEC,
+               .usage = "",
+               .help = "reply 'OCD' for gdb to identify server-side is OpenOCD",
+       },
+       {
+               .name = "endian",
+               .handler = handle_nds32_query_endian_command,
+               .mode = COMMAND_EXEC,
+               .usage = "",
+               .help = "query target endian",
+       },
+       {
+               .name = "cpuid",
+               .handler = handle_nds32_query_cpuid_command,
+               .mode = COMMAND_EXEC,
+               .usage = "",
+               .help = "query CPU ID",
+       },
+
+       COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration nds32_exec_command_handlers[] = {
+       {
+               .name = "dssim",
+               .handler = handle_nds32_dssim_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['on'|'off']",
+               .help = "display/change $INT_MASK.DSSIM status",
+       },
+       {
+               .name = "mem_access",
+               .handler = handle_nds32_memory_access_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['bus'|'cpu']",
+               .help = "display/change memory access channel",
+       },
+       {
+               .name = "mem_mode",
+               .handler = handle_nds32_memory_mode_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['auto'|'mem'|'ilm'|'dlm']",
+               .help = "display/change memory mode",
+       },
+       {
+               .name = "cache",
+               .handler = handle_nds32_cache_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['invalidate']",
+               .help = "cache control",
+       },
+       {
+               .name = "icache",
+               .handler = handle_nds32_icache_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['invalidate'|'enable'|'disable'|'dump']",
+               .help = "icache control",
+       },
+       {
+               .name = "dcache",
+               .handler = handle_nds32_dcache_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['invalidate'|'enable'|'disable'|'dump']",
+               .help = "dcache control",
+       },
+       {
+               .name = "auto_break",
+               .handler = handle_nds32_auto_break_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['on'|'off']",
+               .help = "convert software breakpoints to hardware breakpoints if needed",
+       },
+       {
+               .name = "virtual_hosting",
+               .handler = handle_nds32_virtual_hosting_command,
+               .mode = COMMAND_ANY,
+               .usage = "['on'|'off']",
+               .help = "turn on/off virtual hosting",
+       },
+       {
+               .name = "global_stop",
+               .handler = handle_nds32_global_stop_command,
+               .mode = COMMAND_ANY,
+               .usage = "['on'|'off']",
+               .help = "turn on/off global stop. After turning on, every load/store" \
+                        "instructions will be stopped to check memory access.",
+       },
+       {
+               .name = "soft_reset_halt",
+               .handler = handle_nds32_soft_reset_halt_command,
+               .mode = COMMAND_ANY,
+               .usage = "['on'|'off']",
+               .help = "as issuing rest-halt, to use soft-reset-halt or not." \
+                        "the feature is for backward-compatible.",
+       },
+       {
+               .name = "boot_time",
+               .handler = handle_nds32_boot_time_command,
+               .mode = COMMAND_CONFIG,
+               .usage = "milliseconds",
+               .help = "set the period to wait after srst.",
+       },
+       {
+               .name = "login_edm_passcode",
+               .handler = handle_nds32_login_edm_passcode_command,
+               .mode = COMMAND_CONFIG,
+               .usage = "passcode",
+               .help = "set EDM passcode for secure MCU debugging.",
+       },
+       {
+               .name = "login_edm_operation",
+               .handler = handle_nds32_login_edm_operation_command,
+               .mode = COMMAND_CONFIG,
+               .usage = "login_edm_operation misc_reg_no value",
+               .help = "add EDM operations for secure MCU debugging.",
+       },
+       {
+               .name = "reset_halt_as_init",
+               .handler = handle_nds32_reset_halt_as_init_command,
+               .mode = COMMAND_CONFIG,
+               .usage = "['on'|'off']",
+               .help = "reset halt as openocd init.",
+       },
+       {
+               .name = "keep_target_edm_ctl",
+               .handler = handle_nds32_keep_target_edm_ctl_command,
+               .mode = COMMAND_CONFIG,
+               .usage = "['on'|'off']",
+               .help = "Backup/Restore target EDM_CTL register.",
+       },
+       {
+               .name = "decode",
+               .handler = handle_nds32_decode_command,
+               .mode = COMMAND_EXEC,
+               .usage = "address icount",
+               .help = "decode instruction.",
+       },
+       {
+               .name = "word_access_mem",
+               .handler = handle_nds32_word_access_mem_command,
+               .mode = COMMAND_ANY,
+               .usage = "['on'|'off']",
+               .help = "Always use word-aligned address to access memory.",
+       },
+       {
+               .name = "bulk_write",
+               .jim_handler = jim_nds32_bulk_write,
+               .mode = COMMAND_EXEC,
+               .help = "Write multiple 32-bit words to target memory",
+               .usage = "address count data",
+       },
+       {
+               .name = "multi_write",
+               .jim_handler = jim_nds32_multi_write,
+               .mode = COMMAND_EXEC,
+               .help = "Write multiple addresses/words to target memory",
+               .usage = "num_of_pairs [address data]+",
+       },
+       {
+               .name = "bulk_read",
+               .jim_handler = jim_nds32_bulk_read,
+               .mode = COMMAND_EXEC,
+               .help = "Read multiple 32-bit words from target memory",
+               .usage = "address count",
+       },
+       {
+               .name = "read_edmsr",
+               .jim_handler = jim_nds32_read_edm_sr,
+               .mode = COMMAND_EXEC,
+               .help = "Read EDM system register",
+               .usage = "['edmsw'|'edm_dtr']",
+       },
+       {
+               .name = "write_edmsr",
+               .jim_handler = jim_nds32_write_edm_sr,
+               .mode = COMMAND_EXEC,
+               .help = "Write EDM system register",
+               .usage = "['edm_dtr'] value",
+       },
+       {
+               .name = "query",
+               .mode = COMMAND_EXEC,
+               .help = "Andes query command group",
+               .usage = "",
+               .chain = nds32_query_command_handlers,
+       },
+
+       COMMAND_REGISTRATION_DONE
+};
+
+const struct command_registration nds32_command_handlers[] = {
+       {
+               .name = "nds",
+               .mode = COMMAND_ANY,
+               .help = "Andes command group",
+               .usage = "",
+               .chain = nds32_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
diff --git a/src/target/nds32_cmd.h b/src/target/nds32_cmd.h
new file mode 100644 (file)
index 0000000..44d361e
--- /dev/null
@@ -0,0 +1,27 @@
+/***************************************************************************
+ *   Copyright (C) 2013 Andes Technology                                   *
+ *   Hsiangkai Wang <hkwang@andestech.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, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+#ifndef __NDS32_CMD_H__
+#define __NDS32_CMD_H__
+#include <helper/command.h>
+
+extern const struct command_registration nds32_command_handlers[];
+
+#endif /* __NDS32_CMD_H__ */
diff --git a/src/target/nds32_disassembler.c b/src/target/nds32_disassembler.c
new file mode 100644 (file)
index 0000000..d859e0c
--- /dev/null
@@ -0,0 +1,3637 @@
+/***************************************************************************
+ *   Copyright (C) 2013 Andes Technology                                   *
+ *   Hsiangkai Wang <hkwang@andestech.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, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/log.h>
+#include <target/target.h>
+#include "nds32_disassembler.h"
+
+static const int enable4_bits[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
+
+int nds32_read_opcode(struct nds32 *nds32, uint32_t address, uint32_t *value)
+{
+       struct target *target = nds32->target;
+       uint8_t value_buf[4];
+
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       int retval = target_read_buffer(target, address, 4, value_buf);
+
+       if (retval == ERROR_OK) {
+               /* instructions are always big-endian */
+               *value = be_to_h_u32(value_buf);
+
+               LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "",
+                               address,
+                               *value);
+       } else {
+               *value = 0x0;
+               LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
+                               address);
+       }
+
+       return retval;
+}
+
+static int nds32_parse_type_0(uint32_t opcode, int32_t *imm)
+{
+       *imm = opcode & 0x1FFFFFF;
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_type_1(uint32_t opcode, uint8_t *rt, int32_t *imm)
+{
+       *rt = (opcode >> 20) & 0x1F;
+       *imm = opcode & 0xFFFFF;
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_type_2(uint32_t opcode, uint8_t *rt, uint8_t *ra, int32_t *imm)
+{
+       *rt = (opcode >> 20) & 0x1F;
+       *ra = (opcode >> 15) & 0x1F;
+       *imm = opcode & 0x7FFF;
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_type_3(uint32_t opcode, uint8_t *rt, uint8_t *ra,
+               uint8_t *rb, int32_t *imm)
+{
+       *rt = (opcode >> 20) & 0x1F;
+       *ra = (opcode >> 15) & 0x1F;
+       *rb = (opcode >> 10) & 0x1F;
+       *imm = opcode & 0x3FF;
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_type_4(uint32_t opcode, uint8_t *rt, uint8_t *ra,
+               uint8_t *rb, uint8_t *rd, uint8_t *sub_opc)
+{
+       *rt = (opcode >> 20) & 0x1F;
+       *ra = (opcode >> 15) & 0x1F;
+       *rb = (opcode >> 10) & 0x1F;
+       *rd = (opcode >> 5) & 0x1F;
+       *sub_opc = opcode & 0x1F;
+
+       return ERROR_OK;
+}
+
+/* LBI, LHI, LWI, LBI.bi, LHI.bi, LWI.bi */
+static int nds32_parse_group_0_insn(struct nds32 *nds32, uint32_t opcode,
+               uint32_t address,
+               struct nds32_instruction *instruction)
+{
+       uint8_t opc_6;
+
+       opc_6 = instruction->info.opc_6;
+
+       switch (opc_6 & 0x7) {
+               case 0: /* LBI */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 1;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBI\t$r%d,[$r%d+#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 1: /* LHI */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 2;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHI\t$r%d,[$r%d+#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 2: /* LWI */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 4;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLWI\t$r%d,[$r%d+#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 4: /* LBI.bi */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_end = instruction->access_start + 1;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBI.bi\t$r%d,[$r%d],#%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 5: /* LHI.bi */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_end = instruction->access_start + 2;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHI.bi\t$r%d,[$r%d],#%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 6: /* LWI.bi */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_end = instruction->access_start + 4;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLWI.bi\t$r%d,[$r%d],#%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               default:
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                       address,
+                                       opcode);
+                       return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_group_1_insn(struct nds32 *nds32, uint32_t opcode,
+               uint32_t address, struct nds32_instruction *instruction)
+{
+       uint8_t opc_6;
+
+       opc_6 = instruction->info.opc_6;
+
+       switch (opc_6 & 0x7) {
+               case 0: /* SBI */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 1;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSBI\t$r%d,[$r%d+#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 1: /* SHI */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 2;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSHI\t$r%d,[$r%d+#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 2: /* SWI */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 4;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSWI\t$r%d,[$r%d+#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 4: /* SBI.bi */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_end = instruction->access_start + 1;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSBI.bi\t$r%d,[$r%d],#%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 5: /* SHI.bi */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_end = instruction->access_start + 2;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSHI.bi\t$r%d,[$r%d],#%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 6: /* SWI.bi */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 15; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_end = instruction->access_start + 4;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSWI.bi\t$r%d,[$r%d],#%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               default:
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                       address,
+                                       opcode);
+                       return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_group_2_insn(struct nds32 *nds32, uint32_t opcode,
+               uint32_t address, struct nds32_instruction *instruction)
+{
+       uint8_t opc_6;
+
+       opc_6 = instruction->info.opc_6;
+
+       switch (opc_6 & 0x7) {
+               case 0: /* LBSI */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 1;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBSI\t$r%d,[$r%d+#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 1: /* LHSI */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 2;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHSI\t$r%d,[$r%d+#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 3: { /* DPREFI */
+                               uint8_t sub_type;
+                               nds32_parse_type_2(opcode, &sub_type, &(instruction->info.ra),
+                                               &(instruction->info.imm));
+                               instruction->info.sub_opc = sub_type & 0xF;
+                               instruction->type = NDS32_INSN_MISC;
+                               if (sub_type & 0x10) { /* DPREFI.d */
+                                       /* sign-extend */
+                                       instruction->info.imm = (instruction->info.imm << 17) >> 14;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDPREFI.d\t%d,[$r%d+#%d]",
+                                                       address,
+                                                       opcode, instruction->info.sub_opc,
+                                                       instruction->info.ra, instruction->info.imm);
+                               } else { /* DPREFI.w */
+                                       /* sign-extend */
+                                       instruction->info.imm = (instruction->info.imm << 17) >> 15;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDPREFI.w\t%d,[$r%d+#%d]",
+                                                       address,
+                                                       opcode, instruction->info.sub_opc,
+                                                       instruction->info.ra, instruction->info.imm);
+                               }
+                       }
+                       break;
+               case 4: /* LBSI.bi */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 17; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_end = instruction->access_start + 1;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBSI.bi\t$r%d,[$r%d],#%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 5: /* LHSI.bi */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 17) >> 16; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                       &(instruction->access_start));
+                       instruction->access_end = instruction->access_start + 2;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHSI.bi\t$r%d,[$r%d],#%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.imm);
+                       break;
+               case 6: /* LBGP */
+                       nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       if ((instruction->info.imm >> 19) & 0x1) { /* LBSI.gp */
+                               instruction->info.imm = (instruction->info.imm << 13) >> 13;
+                               nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+                               instruction->access_start += instruction->info.imm;
+                               instruction->access_end = instruction->access_start + 1;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBSI.gp\t$r%d,[#%d]",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.imm);
+                       } else { /* LBI.gp */
+                               instruction->info.imm = (instruction->info.imm << 13) >> 13;
+                               nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+                               instruction->access_start += instruction->info.imm;
+                               instruction->access_end = instruction->access_start + 1;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBI.gp\t$r%d,[#%d]",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.imm);
+                       }
+                       break;
+               default:
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                       address,
+                                       opcode);
+                       return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_mem(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+               struct nds32_instruction *instruction)
+{
+       uint32_t sub_opcode = opcode & 0x3F;
+       uint32_t val_ra, val_rb;
+       switch (sub_opcode >> 3) {
+               case 0:
+                       switch (sub_opcode & 0x7) {
+                               case 0: /* LB */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra), \
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 1;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLB\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 1: /* LH */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 2;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLH\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 2: /* LW */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 4;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLW\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 4: /* LB.bi */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                                       &(instruction->access_start));
+                                       instruction->access_end = instruction->access_start + 1;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLB.bi\t$r%d,[$r%d],($r%d<<%d)",
+                                                       address,
+                                                       opcode, instruction->info.rt,
+                                                       instruction->info.ra, instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 5: /* LH.bi */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                                       &(instruction->access_start));
+                                       instruction->access_end = instruction->access_start + 2;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLH.bi\t$r%d,[$r%d],($r%d<<%d)",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 6: /* LW.bi */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                                       &(instruction->access_start));
+                                       instruction->access_end = instruction->access_start + 4;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLW.bi\t$r%d,[$r%d],($r%d<<%d)",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                       }
+                       break;
+               case 1:
+                       switch (sub_opcode & 0x7) {
+                               case 0: /* SB */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 1;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSB\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt,
+                                                       instruction->info.ra, instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 1: /* SH */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 2;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSH\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 2: /* SW */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 4;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSW\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt,
+                                                       instruction->info.ra, instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 4: /* SB.bi */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                                       &(instruction->access_start));
+                                       instruction->access_end = instruction->access_start + 1;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSB.bi\t$r%d,[$r%d],($r%d<<%d)",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 5: /* SH.bi */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                                       &(instruction->access_start));
+                                       instruction->access_end = instruction->access_start + 2;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSH.bi\t$r%d,[$r%d],($r%d<<%d)",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 6: /* SW.bi */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                                       &(instruction->access_start));
+                                       instruction->access_end = instruction->access_start + 4;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSW.bi\t$r%d,[$r%d],($r%d<<%d)",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                       }
+                       break;
+               case 2:
+                       switch (sub_opcode & 0x7) {
+                               case 0: /* LBS */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 1;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBS\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt,
+                                                       instruction->info.ra, instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 1: /* LHS */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 2;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHS\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 3: /* DPREF */
+                                       nds32_parse_type_3(opcode, &(instruction->info.sub_opc),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_MISC;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDPREF\t#%d,[$r%d+($r%d<<#%d)]",
+                                                       address,
+                                                       opcode, instruction->info.sub_opc,
+                                                       instruction->info.ra, instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 4: /* LBS.bi */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                                       &(instruction->access_start));
+                                       instruction->access_end = instruction->access_start + 1;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBS.bi\t$r%d,[$r%d],($r%d<<%d)",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 5: /* LHS.bi */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra,
+                                                       &(instruction->access_start));
+                                       instruction->access_end = instruction->access_start + 2;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHS.bi\t$r%d,[$r%d],($r%d<<%d)",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                       }
+                       break;
+               case 3:
+                       switch (sub_opcode & 0x7) {
+                               case 0: /* LLW */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 4;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLLW\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 1: /* SCW */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 4;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSCW\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                       }
+                       break;
+               case 4:
+                       switch (sub_opcode & 0x7) {
+                               case 0: /* LBUP */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 1;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLBUP\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 2: /* LWUP */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 4;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLWUP\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                       }
+                       break;
+               case 5:
+                       switch (sub_opcode & 0x7) {
+                               case 0: /* SBUP */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 1;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSBUP\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                               case 2: /* SWUP */
+                                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                       &(instruction->info.ra),
+                                                       &(instruction->info.rb), &(instruction->info.imm));
+                                       instruction->type = NDS32_INSN_LOAD_STORE;
+                                       nds32_get_mapped_reg(nds32, instruction->info.ra, &val_ra);
+                                       nds32_get_mapped_reg(nds32, instruction->info.rb, &val_rb);
+                                       instruction->access_start = val_ra +
+                                               (val_rb << ((instruction->info.imm >> 8) & 0x3));
+                                       instruction->access_end = instruction->access_start + 4;
+                                       snprintf(instruction->text,
+                                                       128,
+                                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSWUP\t$r%d,[$r%d+($r%d<<%d)]",
+                                                       address,
+                                                       opcode, instruction->info.rt, instruction->info.ra,
+                                                       instruction->info.rb,
+                                                       (instruction->info.imm >> 8) & 0x3);
+                                       break;
+                       }
+                       break;
+               default:
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                       address,
+                                       opcode);
+                       return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_calculate_lsmw_access_range(struct nds32 *nds32,
+               struct nds32_instruction *instruction)
+{
+       uint8_t ba;
+       uint8_t id;
+       uint8_t enable4;
+
+       enable4 = (instruction->info.imm >> 6) & 0xF;
+       ba = (instruction->info.imm >> 4) & 0x1;
+       id = (instruction->info.imm >> 3) & 0x1;
+
+       if (ba) {
+               nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start));
+               if (id) { /* decrease */
+                       /* access_end is the (last_element+1), so no need to minus 4 */
+                       /* instruction->access_end -= 4; */
+                       instruction->access_end = instruction->access_start;
+               } else { /* increase */
+                       instruction->access_start += 4;
+               }
+       } else {
+               nds32_get_mapped_reg(nds32, instruction->info.ra, &(instruction->access_start));
+               instruction->access_end = instruction->access_start - 4;
+       }
+
+       if (id) { /* decrease */
+               instruction->access_start = instruction->access_end -
+                       4 * (instruction->info.rd - instruction->info.rb + 1);
+               instruction->access_start -= (4 * enable4_bits[enable4]);
+       } else { /* increase */
+               instruction->access_end = instruction->access_start +
+                       4 * (instruction->info.rd - instruction->info.rb + 1);
+               instruction->access_end += (4 * enable4_bits[enable4]);
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_lsmw(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+               struct nds32_instruction *instruction)
+{
+       if (opcode & 0x20) { /* SMW, SMWA, SMWZB */
+               switch (opcode & 0x3) {
+                       /* TODO */
+                       case 0: /* SMW */
+                               /* use rd as re */
+                               nds32_parse_type_3(opcode, &(instruction->info.rb),
+                                               &(instruction->info.ra),
+                                               &(instruction->info.rd), &(instruction->info.imm));
+                               instruction->type = NDS32_INSN_LOAD_STORE;
+                               nds32_calculate_lsmw_access_range(nds32, instruction);
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMW\t$r%d,[$r%d],$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rb, instruction->info.ra,
+                                               instruction->info.rd,
+                                               (instruction->info.imm >> 6) & 0xF);
+                               break;
+                       case 1: /* SMWA */
+                               nds32_parse_type_3(opcode, &(instruction->info.rb),
+                                               &(instruction->info.ra),
+                                               &(instruction->info.rd), &(instruction->info.imm));
+                               instruction->type = NDS32_INSN_LOAD_STORE;
+                               nds32_calculate_lsmw_access_range(nds32, instruction);
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMWA\t$r%d,[$r%d],$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rb, instruction->info.ra,
+                                               instruction->info.rd,
+                                               (instruction->info.imm >> 6) & 0xF);
+                               break;
+                       case 2: /* SMWZB */
+                               nds32_parse_type_3(opcode, &(instruction->info.rb),
+                                               &(instruction->info.ra),
+                                               &(instruction->info.rd), &(instruction->info.imm));
+                               instruction->type = NDS32_INSN_LOAD_STORE;
+                               /* TODO: calculate access_start/access_end */
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMWZB\t$r%d,[$r%d],$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rb, instruction->info.ra,
+                                               instruction->info.rd,
+                                               (instruction->info.imm >> 6) & 0xF);
+                               break;
+                       default:
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                               address,
+                                               opcode);
+                               return ERROR_FAIL;
+               }
+       } else { /* LMW, LMWA, LMWZB */
+               switch (opcode & 0x3) {
+                       case 0: /* LMW */
+                               nds32_parse_type_3(opcode, &(instruction->info.rb),
+                                               &(instruction->info.ra),
+                                               &(instruction->info.rd), &(instruction->info.imm));
+                               instruction->type = NDS32_INSN_LOAD_STORE;
+                               nds32_calculate_lsmw_access_range(nds32, instruction);
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLMW\t$r%d,[$r%d],$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rb, instruction->info.ra,
+                                               instruction->info.rd,
+                                               (instruction->info.imm >> 6) & 0xF);
+                               break;
+                       case 1: /* LMWA */
+                               nds32_parse_type_3(opcode, &(instruction->info.rb),
+                                               &(instruction->info.ra),
+                                               &(instruction->info.rd), &(instruction->info.imm));
+                               instruction->type = NDS32_INSN_LOAD_STORE;
+                               nds32_calculate_lsmw_access_range(nds32, instruction);
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLMWA\t$r%d,[$r%d],$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rb, instruction->info.ra,
+                                               instruction->info.rd,
+                                               (instruction->info.imm >> 6) & 0xF);
+                               break;
+                       case 2: /* LMWZB */
+                               nds32_parse_type_3(opcode, &(instruction->info.rb),
+                                               &(instruction->info.ra),
+                                               &(instruction->info.rd), &(instruction->info.imm));
+                               instruction->type = NDS32_INSN_LOAD_STORE;
+                               /* TODO: calculate access_start/access_end */
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLMWZB\t$r%d,[$r%d],$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rb, instruction->info.ra,
+                                               instruction->info.rd,
+                                               (instruction->info.imm >> 6) & 0xF);
+                               break;
+                       default:
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                               address,
+                                               opcode);
+                               return ERROR_FAIL;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_hwgp(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+               struct nds32_instruction *instruction)
+{
+       switch ((opcode >> 18) & 0x3) {
+               case 0: /* LHI.gp */
+                       nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 2;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHI.gp\t$r%d,[#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.imm);
+                       break;
+               case 1: /* LHSI.gp */
+                       nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 2;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLHSI.gp\t$r%d,[#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.imm);
+                       break;
+               case 2: /* SHI.gp */
+                       nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 14) >> 13; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 2;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSHI.gp\t$r%d,[#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.imm);
+                       break;
+               case 3:
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       if ((opcode >> 17) & 0x1) { /* SWI.gp */
+                               nds32_parse_type_1(opcode, &(instruction->info.rt),
+                                               &(instruction->info.imm));
+                               /* sign-extend */
+                               instruction->info.imm = (instruction->info.imm << 15) >> 13;
+                               nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+                               instruction->access_start += instruction->info.imm;
+                               instruction->access_end = instruction->access_start + 4;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSWI.gp\t$r%d,[#%d]",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.imm);
+                       } else { /* LWI.gp */
+                               nds32_parse_type_1(opcode, &(instruction->info.rt),
+                                               &(instruction->info.imm));
+                               /* sign-extend */
+                               instruction->info.imm = (instruction->info.imm << 15) >> 13;
+                               nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+                               instruction->access_start += instruction->info.imm;
+                               instruction->access_end = instruction->access_start + 4;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tLWI.gp\t$r%d,[#%d]",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.imm);
+                       }
+
+                       break;
+               default:
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                       address,
+                                       opcode);
+                       return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_sbgp(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+               struct nds32_instruction *instruction)
+{
+       switch ((opcode >> 19) & 0x1) {
+               case 0: /* SBI.gp */
+                       nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 13) >> 13; /* sign-extend */
+                       instruction->type = NDS32_INSN_LOAD_STORE;
+                       nds32_get_mapped_reg(nds32, R29, &(instruction->access_start));
+                       instruction->access_start += instruction->info.imm;
+                       instruction->access_end = instruction->access_start + 1;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSBI.gp\t$r%d,[#%d]",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.imm);
+                       break;
+               case 1: /* ADDI.gp */
+                       nds32_parse_type_1(opcode, &(instruction->info.rt), &(instruction->info.imm));
+                       instruction->info.imm = (instruction->info.imm << 13) >> 13; /* sign-extend */
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADDI.gp\t$r%d,#%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.imm);
+                       break;
+               default:
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                       address,
+                                       opcode);
+                       return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_group_3_insn(struct nds32 *nds32, uint32_t opcode, uint32_t address,
+               struct nds32_instruction *instruction)
+{
+       uint8_t opc_6;
+
+       opc_6 = instruction->info.opc_6;
+
+       switch (opc_6 & 0x7) {
+               case 4: /* MEM */
+                       nds32_parse_mem(nds32, opcode, address, instruction);
+                       break;
+               case 5: /* LSMW */
+                       nds32_parse_lsmw(nds32, opcode, address, instruction);
+                       break;
+               case 6: /* HWGP */
+                       nds32_parse_hwgp(nds32, opcode, address, instruction);
+                       break;
+               case 7: /* SBGP */
+                       nds32_parse_sbgp(nds32, opcode, address, instruction);
+                       break;
+               default:
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                       address,
+                                       opcode);
+                       return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_alu_1(uint32_t opcode, uint32_t address,
+               struct nds32_instruction *instruction)
+{
+       switch (opcode & 0x1F) {
+               case 0: /* ADD */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt), &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADD_SLLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADD\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                       break;
+               case 1: /* SUB */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSUB_SLLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSUB\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                       break;
+               case 2: /* AND */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAND_SLLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAND\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                       break;
+               case 3: /* XOR */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tXOR_SLLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tXOR\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                       break;
+               case 4: /* OR */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tOR_SLLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tOR\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                       break;
+               case 5: /* NOR */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOR\t$r%d,$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.rb);
+                       break;
+               case 6: /* SLT */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLT\t$r%d,$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.rb);
+                       break;
+               case 7: /* SLTS */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLTS\t$r%d,$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.rb);
+                       break;
+               case 8: { /* SLLI */
+                               uint8_t imm;
+                               int32_t sub_op;
+                               nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                               &(instruction->info.ra),
+                                               &imm, &sub_op);
+                               instruction->info.imm = imm;
+                               instruction->type = NDS32_INSN_DATA_PROC;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLLI\t$r%d,$r%d,#%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.imm);
+                       }
+                       break;
+               case 9: { /* SRLI */
+                               uint8_t imm;
+                               int32_t sub_op;
+                               nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                               &(instruction->info.ra),
+                                               &imm, &sub_op);
+                               instruction->info.imm = imm;
+                               instruction->type = NDS32_INSN_DATA_PROC;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSRLI\t$r%d,$r%d,#%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.imm);
+                       }
+                       break;
+               case 10: { /* SRAI */
+                                uint8_t imm;
+                                int32_t sub_op;
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &imm, &sub_op);
+                                instruction->info.imm = imm;
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSRAI\t$r%d,$r%d,#%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.imm);
+                        }
+                        break;
+               case 11: { /* ROTRI */
+                                uint8_t imm;
+                                int32_t sub_op;
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &imm, &sub_op);
+                                instruction->info.imm = imm;
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tROTRI\t$r%d,$r%d,#%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.imm);
+                        }
+                        break;
+               case 12: { /* SLL */
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSLL\t$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb);
+                        }
+                        break;
+               case 13: { /* SRL */
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSRL\t$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb);
+                        }
+                        break;
+               case 14: { /* SRA */
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSRA\t$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb);
+                        }
+                        break;
+               case 15: { /* ROTR */
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tROTR\t$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb);
+                        }
+                        break;
+               case 16: { /* SEB */
+                                nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSEB\t$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra);
+                        }
+                        break;
+               case 17: { /* SEH */
+                                nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSEH\t$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra);
+                        }
+                        break;
+               case 18: /* BITC */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBITC\t$r%d,$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.rb);
+                        break;
+               case 19: { /* ZEH */
+                                nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tZEH\t$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra);
+                        }
+                        break;
+               case 20: { /* WSBH */
+                                nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tWSBH\t$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra);
+                        }
+                        break;
+               case 21: /* OR_SRLI */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tOR_SRLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tOR\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                        break;
+               case 22: { /* DIVSR */
+                                nds32_parse_type_4(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.rd),
+                                                &(instruction->info.sub_opc));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDIVSR\t$r%d,$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb,
+                                                instruction->info.rd);
+                        }
+                        break;
+               case 23: { /* DIVR */
+                                nds32_parse_type_4(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.rd),
+                                                &(instruction->info.sub_opc));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDIVR\t$r%d,$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb,
+                                                instruction->info.rd);
+                        }
+                        break;
+               case 24: { /* SVA */
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVA\t$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb);
+                        }
+                        break;
+               case 25: { /* SVS */
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVS\t$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb);
+                        }
+                        break;
+               case 26: { /* CMOVZ */
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_MISC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCMOVZ\t$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb);
+                        }
+                        break;
+               case 27: { /* CMOVN */
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &(instruction->info.rb), &(instruction->info.imm));
+                                instruction->type = NDS32_INSN_MISC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCMOVN\t$r%d,$r%d,$r%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.rb);
+                        }
+                        break;
+               case 28: /* ADD_SRLI */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADD_SRLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tADD\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                        break;
+               case 29: /* SUB_SRLI */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSUB_SRLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSUB\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                        break;
+               case 30: /* AND_SRLI */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAND_SRLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAND\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                        break;
+               case 31: /* XOR_SRLI */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       instruction->info.imm = (instruction->info.imm >> 5) & 0x1F;
+                       if (instruction->info.imm)
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tXOR_SRLI\t$r%d,$r%d,$r%d,%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb,
+                                               instruction->info.imm);
+                       else
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tXOR\t$r%d,$r%d,$r%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.rb);
+                        break;
+               default:
+                        snprintf(instruction->text,
+                                        128,
+                                        "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
+                                        address,
+                                        opcode);
+                        return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+static int nds32_parse_alu_2(uint32_t opcode, uint32_t address,
+               struct nds32_instruction *instruction)
+{
+       switch (opcode & 0x3F) {
+               case 0: /* MAX */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMAX\t$r%d,$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.rb);
+                       break;
+               case 1: /* MIN */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMIN\t$r%d,$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.rb);
+                       break;
+               case 2: /* AVE */
+                       nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.rb), &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAVE\t$r%d,$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra,
+                                       instruction->info.rb);
+                       break;
+               case 3: /* ABS */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tAVE\t$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra);
+                       break;
+               case 4: { /* CLIPS */
+                               uint8_t imm;
+                               nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                               &(instruction->info.ra),
+                                               &imm, &(instruction->info.imm));
+                               instruction->info.imm = imm;
+                               instruction->type = NDS32_INSN_DATA_PROC;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLIPS\t$r%d,$r%d,#%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.imm);
+                       }
+                       break;
+               case 5: { /* CLIP */
+                               uint8_t imm;
+                               nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                               &(instruction->info.ra),
+                                               &imm, &(instruction->info.imm));
+                               instruction->info.imm = imm;
+                               instruction->type = NDS32_INSN_DATA_PROC;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLIP\t$r%d,$r%d,#%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.imm);
+                       }
+                       break;
+               case 6: /* CLO */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLO\t$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra);
+                       break;
+               case 7: /* CLZ */
+                       nds32_parse_type_2(opcode, &(instruction->info.rt),
+                                       &(instruction->info.ra),
+                                       &(instruction->info.imm));
+                       instruction->type = NDS32_INSN_DATA_PROC;
+                       snprintf(instruction->text,
+                                       128,
+                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ\t$r%d,$r%d",
+                                       address,
+                                       opcode, instruction->info.rt, instruction->info.ra);
+                       break;
+               case 8: { /* BSET */
+                               uint8_t imm;
+                               nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                               &(instruction->info.ra),
+                                               &imm, &(instruction->info.imm));
+                               instruction->info.imm = imm;
+                               instruction->type = NDS32_INSN_DATA_PROC;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBSET\t$r%d,$r%d,#%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.imm);
+                       }
+                       break;
+               case 9: { /* BCLR */
+                               uint8_t imm;
+                               nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                               &(instruction->info.ra),
+                                               &imm, &(instruction->info.imm));
+                               instruction->info.imm = imm;
+                               instruction->type = NDS32_INSN_DATA_PROC;
+                               snprintf(instruction->text,
+                                               128,
+                                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBCLR\t$r%d,$r%d,#%d",
+                                               address,
+                                               opcode, instruction->info.rt, instruction->info.ra,
+                                               instruction->info.imm);
+                       }
+                       break;
+               case 10: { /* BTGL */
+                                uint8_t imm;
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &imm, &(instruction->info.imm));
+                                instruction->info.imm = imm;
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBTGL\t$r%d,$r%d,#%d",
+                                                address,
+                                                opcode, instruction->info.rt, instruction->info.ra,
+                                                instruction->info.imm);
+                        }
+                        break;
+               case 11: { /* BTST */
+                                uint8_t imm;
+                                nds32_parse_type_3(opcode, &(instruction->info.rt),
+                                                &(instruction->info.ra),
+                                                &imm, &(instruction->info.imm));
+                                instruction->info.imm = imm;
+                                instruction->type = NDS32_INSN_DATA_PROC;
+                                snprintf(instruction->text,
+                                                128,
+