aboutsummaryrefslogtreecommitdiff
path: root/src/target/nds32_cmd.c
diff options
context:
space:
mode:
authorHsiangkai Wang <hsiangkai@gmail.com>2013-02-05 11:55:37 +0800
committerSpencer Oliver <spen@spen-soft.co.uk>2013-06-05 19:27:35 +0000
commitcf8a3c3d7075abad3c88cd604f8add4d06898abc (patch)
tree56f8b5794fd385ba7ba4a6617c214a9516a443b5 /src/target/nds32_cmd.c
parentceb402dc9e903d2f3f6bc8125dfed9d82b83d2d1 (diff)
downloadriscv-openocd-cf8a3c3d7075abad3c88cd604f8add4d06898abc.zip
riscv-openocd-cf8a3c3d7075abad3c88cd604f8add4d06898abc.tar.gz
riscv-openocd-cf8a3c3d7075abad3c88cd604f8add4d06898abc.tar.bz2
nds32: add new target type nds32_v2, nds32_v3, nds32_v3m
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>
Diffstat (limited to 'src/target/nds32_cmd.c')
-rw-r--r--src/target/nds32_cmd.c1106
1 files changed, 1106 insertions, 0 deletions
diff --git a/src/target/nds32_cmd.c b/src/target/nds32_cmd.c
new file mode 100644
index 0000000..a16308e
--- /dev/null
+++ b/src/target/nds32_cmd.c
@@ -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
+};
+