* 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. *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_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;
"LOAD STORE GLOBAL STOP",
};
-static const int NDS32_LM_SIZE_TABLE[16] = {
+static const int nds32_lm_size_table[16] = {
4 * 1024,
8 * 1024,
16 * 1024,
2 * 1024,
};
-static const int NDS32_LINE_SIZE_TABLE[6] = {
+static const int nds32_line_size_table[6] = {
0,
8,
16,
}
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);
+ uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32);
+ LOG_DEBUG("reading register(cached) %" PRIi32 "(%s), value: 0x%8.8" PRIx32,
+ reg_arch_info->num, reg->name, val);
return ERROR_OK;
}
+ int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num);
+
if (reg_arch_info->enable == false) {
- reg_arch_info->value = NDS32_REGISTER_DISABLE;
+ buf_set_u32(reg_arch_info->value, 0, 32, 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;
+ uint32_t val = 0;
+ if ((nds32->fpu_enable == false)
+ && (nds32_reg_type(mapped_regnum) == NDS32_REG_TYPE_FPU)) {
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;
+ } else if ((nds32->audio_enable == false)
+ && (nds32_reg_type(mapped_regnum) == NDS32_REG_TYPE_AUMR)) {
retval = ERROR_OK;
} else {
- retval = aice_read_register(aice,
- reg_arch_info->num, &(reg_arch_info->value));
+ retval = aice_read_register(aice, mapped_regnum, &val);
}
+ buf_set_u32(reg_arch_info->value, 0, 32, val);
- LOG_DEBUG("reading register %i(%s), value: 0x%8.8" PRIx32,
- reg_arch_info->num, reg->name, reg_arch_info->value);
+ LOG_DEBUG("reading register %" PRIi32 "(%s), value: 0x%8.8" PRIx32,
+ reg_arch_info->num, reg->name, val);
}
if (retval == ERROR_OK) {
return ERROR_OK;
if (reg_arch_info->enable == false) {
- reg_arch_info->value_64 = NDS32_REGISTER_DISABLE;
+ buf_set_u64(reg_arch_info->value, 0, 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;
+ uint64_t val = 0;
+ if ((nds32->fpu_enable == false)
+ && ((reg_arch_info->num >= FD0) && (reg_arch_info->num <= FD31))) {
retval = ERROR_OK;
} else {
- retval = aice_read_reg_64(aice, reg_arch_info->num,
- &(reg_arch_info->value_64));
+ retval = aice_read_reg_64(aice, reg_arch_info->num, &val);
}
+ buf_set_u64(reg_arch_info->value, 0, 64, val);
}
if (retval == ERROR_OK) {
{
uint32_t value;
- if (ERROR_OK == nds32_get_mapped_reg(nds32, MR8, &value)) {
+ if (nds32_get_mapped_reg(nds32, MR8, &value) == ERROR_OK) {
if (value & 0x1)
nds32->memory.icache.enable = true;
else
return ERROR_TARGET_NOT_HALTED;
}
+ int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num);
+
/* ignore values that will generate exception */
- if (nds32_reg_exception(reg_arch_info->num, value))
+ if (nds32_reg_exception(mapped_regnum, value))
return ERROR_OK;
- LOG_DEBUG("writing register %i(%s) with value 0x%8.8" PRIx32,
+ LOG_DEBUG("writing register %" PRIi32 "(%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))) {
+ (nds32_reg_type(mapped_regnum) == NDS32_REG_TYPE_FPU)) {
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))) {
+ (nds32_reg_type(mapped_regnum) == NDS32_REG_TYPE_AUMR)) {
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);
+ uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32);
+ aice_write_register(aice, mapped_regnum, val);
/* 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));
+ aice_read_register(aice, mapped_regnum, &val);
+ buf_set_u32(reg_arch_info->value, 0, 32, val);
}
reg->valid = true;
reg->dirty = false;
/* update registers to take effect right now */
- if (IR0 == reg_arch_info->num) {
+ if (mapped_regnum == IR0) {
nds32_update_psw(nds32);
- } else if (MR0 == reg_arch_info->num) {
+ } else if (mapped_regnum == MR0) {
nds32_update_mmu_info(nds32);
- } else if ((MR6 == reg_arch_info->num) || (MR7 == reg_arch_info->num)) {
+ } else if ((mapped_regnum == MR6) || (mapped_regnum == MR7)) {
/* update lm information */
nds32_update_lm_info(nds32);
- } else if (MR8 == reg_arch_info->num) {
+ } else if (mapped_regnum == MR8) {
nds32_update_cache_info(nds32);
- } else if (FUCPR == reg_arch_info->num) {
+ } else if (mapped_regnum == FUCPR) {
/* update audio/fpu setting */
nds32_check_extension(nds32);
}
}
if ((nds32->fpu_enable == false) &&
- ((FD0 <= reg_arch_info->num) && (reg_arch_info->num <= FD31))) {
+ ((reg_arch_info->num >= FD0) && (reg_arch_info->num <= FD31))) {
buf_set_u32(reg->value, 0, 32, 0);
buf_set_u32(reg->value, 32, 32, 0);
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_cache *cache = calloc(sizeof(struct reg_cache), 1);
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;
reg_arch_info[i].enable = false;
reg_list[i].name = nds32_reg_simple_name(i);
+ reg_list[i].number = reg_arch_info[i].num;
reg_list[i].size = nds32_reg_size(i);
reg_list[i].arch_info = ®_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].reg_data_type = calloc(sizeof(struct reg_data_type), 1);
+
+ if (reg_arch_info[i].num >= FD0 && reg_arch_info[i].num <= FD31) {
+ reg_list[i].value = reg_arch_info[i].value;
reg_list[i].type = &nds32_reg_access_type_64;
+
+ reg_list[i].reg_data_type->type = REG_TYPE_IEEE_DOUBLE;
+ reg_list[i].reg_data_type->id = "ieee_double";
+ reg_list[i].group = "float";
} else {
- reg_list[i].value = &(reg_arch_info[i].value);
+ reg_list[i].value = reg_arch_info[i].value;
reg_list[i].type = &nds32_reg_access_type;
+ reg_list[i].group = "general";
+
+ if ((reg_arch_info[i].num >= FS0) && (reg_arch_info[i].num <= FS31)) {
+ reg_list[i].reg_data_type->type = REG_TYPE_IEEE_SINGLE;
+ reg_list[i].reg_data_type->id = "ieee_single";
+ reg_list[i].group = "float";
+ } else if ((reg_arch_info[i].num == FPCSR) ||
+ (reg_arch_info[i].num == FPCFG)) {
+ reg_list[i].group = "float";
+ } else if ((reg_arch_info[i].num == R28) ||
+ (reg_arch_info[i].num == R29) ||
+ (reg_arch_info[i].num == R31)) {
+ reg_list[i].reg_data_type->type = REG_TYPE_DATA_PTR;
+ reg_list[i].reg_data_type->id = "data_ptr";
+ } else if ((reg_arch_info[i].num == R30) ||
+ (reg_arch_info[i].num == PC)) {
+ reg_list[i].reg_data_type->type = REG_TYPE_CODE_PTR;
+ reg_list[i].reg_data_type->id = "code_ptr";
+ } else {
+ reg_list[i].reg_data_type->type = REG_TYPE_UINT32;
+ reg_list[i].reg_data_type->id = "uint32";
+ }
}
+ if (reg_arch_info[i].num >= R16 && reg_arch_info[i].num <= R25)
+ reg_list[i].caller_save = true;
+ else
+ reg_list[i].caller_save = false;
+
+ reg_list[i].feature = malloc(sizeof(struct reg_feature));
+
+ if (reg_arch_info[i].num >= R0 && reg_arch_info[i].num <= IFC_LP)
+ reg_list[i].feature->name = "org.gnu.gdb.nds32.core";
+ else if (reg_arch_info[i].num >= CR0 && reg_arch_info[i].num <= SECUR0)
+ reg_list[i].feature->name = "org.gnu.gdb.nds32.system";
+ else if (reg_arch_info[i].num >= D0L24 && reg_arch_info[i].num <= CBE3)
+ reg_list[i].feature->name = "org.gnu.gdb.nds32.audio";
+ else if (reg_arch_info[i].num >= FPCSR && reg_arch_info[i].num <= FD31)
+ reg_list[i].feature->name = "org.gnu.gdb.nds32.fpu";
+
cache->num_regs++;
}
{
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;
+ r = nds32->core_cache->reg_list + regnum;
return r;
}
r = nds32_reg_current(nds32, regnum);
- if (ERROR_OK != r->type->get(r))
+ if (r->type->get(r) != ERROR_OK)
return ERROR_FAIL;
*value = buf_get_u32(r->value, 0, 32);
return r->type->set(r, set_value);
}
+/** get general register list */
+static int nds32_get_general_reg_list(struct nds32 *nds32,
+ struct reg **reg_list[], int *reg_list_size)
+{
+ struct reg *reg_current;
+ int i;
+ int current_idx;
+
+ /** freed in gdb_server.c */
+ *reg_list = malloc(sizeof(struct reg *) * (IFC_LP - R0 + 1));
+ current_idx = 0;
+
+ for (i = R0; i < IFC_LP + 1; i++) {
+ reg_current = nds32_reg_current(nds32, i);
+ if (((struct nds32_reg *)reg_current->arch_info)->enable) {
+ (*reg_list)[current_idx] = reg_current;
+ current_idx++;
+ }
+ }
+ *reg_list_size = current_idx;
+
+ return ERROR_OK;
+}
+
/** get all register list */
-int nds32_get_gdb_reg_list(struct target *target,
+static int nds32_get_all_reg_list(struct nds32 *nds32,
struct reg **reg_list[], int *reg_list_size)
{
- struct nds32 *nds32 = target_to_nds32(target);
struct reg_cache *reg_cache = nds32->core_cache;
+ struct reg *reg_current;
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);
+ for (i = 0; i < reg_cache->num_regs; i++) {
+ reg_current = nds32_reg_current(nds32, i);
+ reg_current->exist = ((struct nds32_reg *)
+ reg_current->arch_info)->enable;
+ (*reg_list)[i] = reg_current;
+ }
return ERROR_OK;
}
+/** get all register list */
+int nds32_get_gdb_reg_list(struct target *target,
+ struct reg **reg_list[], int *reg_list_size,
+ enum target_register_class reg_class)
+{
+ struct nds32 *nds32 = target_to_nds32(target);
+
+ switch (reg_class) {
+ case REG_CLASS_ALL:
+ return nds32_get_all_reg_list(nds32, reg_list, reg_list_size);
+ case REG_CLASS_GENERAL:
+ return nds32_get_general_reg_list(nds32, reg_list, reg_list_size);
+ default:
+ return ERROR_FAIL;
+ }
+
+ return ERROR_FAIL;
+}
+
static int nds32_select_memory_mode(struct target *target, uint32_t address,
uint32_t length, uint32_t *end_address)
{
/* init end_address */
*end_address = address_end;
- if (NDS_MEMORY_ACC_CPU == memory->access_channel)
+ if (memory->access_channel == NDS_MEMORY_ACC_CPU)
return ERROR_OK;
if (edm->access_control == false) {
return ERROR_OK;
}
- if (NDS_MEMORY_SELECT_AUTO != memory->mode) {
+ if (memory->mode != NDS_MEMORY_SELECT_AUTO) {
LOG_DEBUG("Memory mode is not AUTO");
return ERROR_OK;
}
struct nds32 *nds32 = target_to_nds32(target);
struct nds32_memory *memory = &(nds32->memory);
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
+ if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
(target->state != TARGET_HALTED)) {
LOG_WARNING("target was not halted");
return ERROR_TARGET_NOT_HALTED;
return aice_read_mem_unit(aice, address, size, count, buffer);
}
-int nds32_read_phys_memory(struct target *target, uint32_t address,
+int nds32_read_phys_memory(struct target *target, target_addr_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);
- if ((NDS_MEMORY_ACC_CPU == memory->access_channel) &&
+ if ((memory->access_channel == NDS_MEMORY_ACC_CPU) &&
(target->state != TARGET_HALTED)) {
LOG_WARNING("target was not halted");
return ERROR_TARGET_NOT_HALTED;
return aice_write_mem_unit(aice, address, size, count, buffer);
}
-int nds32_write_phys_memory(struct target *target, uint32_t address,
+int nds32_write_phys_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, const uint8_t *buffer)
{
struct aice_port_s *aice = target_to_aice(target);
nds32->virtual_hosting ? ", virtual hosting" : "");
/* save pc value to pseudo register pc */
- struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1);
+ struct reg *reg = register_get_by_name(target->reg_cache, "pc", true);
buf_set_u32(reg->value, 0, 32, value_pc);
return ERROR_OK;
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->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;
break_insn = NDS32_BREAK_32;
}
- if (breakpoint->orig_instr != NULL)
- free(breakpoint->orig_instr);
+ free(breakpoint->orig_instr);
breakpoint->orig_instr = malloc(breakpoint->length);
memcpy(breakpoint->orig_instr, &data, breakpoint->length);
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));
+ LOG_DEBUG("writing register %d 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);
+ if (reg_arch_info->num >= FD0 && reg_arch_info->num <= FD31) {
+ uint64_t val = buf_get_u64(reg_arch_info->value, 0, 64);
+ aice_write_reg_64(aice, reg_arch_info->num, val);
+ } else {
+ uint32_t val = buf_get_u32(reg_arch_info->value, 0, 32);
+ aice_write_register(aice, reg_arch_info->num, val);
+ }
+
reg->valid = true;
reg->dirty = false;
}
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);
+ LOG_INFO("EDM version 0x%04x", nds32->edm.version);
nds32->edm.breakpoint_num = (edm_cfg & 0x7) + 1;
- if ((nds32->edm.version & 0x1000) || (0x60 <= nds32->edm.version))
+ if ((nds32->edm.version & 0x1000) || (nds32->edm.version >= 0x60))
nds32->edm.access_control = true;
else
nds32->edm.access_control = false;
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->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];
+ nds32->memory.dlm_size = nds32_lm_size_table[size_index];
return ERROR_OK;
}
nds32->reset_halt_as_examine = false;
nds32->keep_target_edm_ctl = false;
nds32->word_access_mem = false;
- nds32->virtual_hosting = false;
+ nds32->virtual_hosting = true;
+ nds32->hit_syscall = false;
+ nds32->active_syscall_id = NDS32_SYSCALL_UNDEFINED;
+ nds32->virtual_hosting_errno = 0;
+ nds32->virtual_hosting_ctrl_c = false;
+ nds32->attached = false;
+
+ nds32->syscall_break.asid = 0;
+ nds32->syscall_break.length = 4;
+ nds32->syscall_break.set = 0;
+ nds32->syscall_break.orig_instr = NULL;
+ nds32->syscall_break.next = NULL;
+ nds32->syscall_break.unique_id = 0x515CAll + target->target_number;
+ nds32->syscall_break.linked_brp = 0;
nds32_reg_init();
- if (ERROR_FAIL == nds32_reg_cache_init(target, nds32))
+ if (nds32_reg_cache_init(target, nds32) == ERROR_FAIL)
return ERROR_FAIL;
- if (ERROR_OK != nds32_init_register_table(nds32))
+ if (nds32_init_register_table(nds32) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
}
-int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t *physical)
+int nds32_virtual_to_physical(struct target *target, target_addr_t address, target_addr_t *physical)
{
struct nds32 *nds32 = target_to_nds32(target);
return ERROR_OK;
}
- if (ERROR_OK == nds32_probe_tlb(nds32, address, physical))
+ if (nds32_probe_tlb(nds32, address, physical) == ERROR_OK)
return ERROR_OK;
- if (ERROR_OK == nds32_walk_page_table(nds32, address, physical))
+ if (nds32_walk_page_table(nds32, address, physical) == ERROR_OK)
return ERROR_OK;
return ERROR_FAIL;
}
-int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length)
+int nds32_cache_sync(struct target *target, target_addr_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 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;
/* (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 ;
+ 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);
/* (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 ;
+ 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))
+ target_addr_t physical_addr;
+ if (target->type->virt2phys(target, cur_address, &physical_addr) == ERROR_FAIL)
return ERROR_FAIL;
/* I$ invalidate */
}
int nds32_step(struct target *target, int current,
- uint32_t address, int handle_breakpoints)
+ target_addr_t address, int handle_breakpoints)
{
LOG_DEBUG("target->state: %s",
target_state_name(target));
address = nds32_nextpc(nds32, current, address);
- LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : "");
+ LOG_DEBUG("STEP PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : "");
/** set DSSIM */
uint32_t ir14_value;
ir14_value &= ~(0x1 << 31);
nds32_set_mapped_reg(nds32, IR14, ir14_value);
+ /* check hit_syscall before leave_debug_state() because
+ * leave_debug_state() may clear hit_syscall flag */
+ bool no_step = false;
+ if (nds32->hit_syscall)
+ /* step after hit_syscall should be ignored because
+ * leave_debug_state will step implicitly to skip the
+ * syscall */
+ no_step = true;
+
/********* 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;
+ if (no_step == false) {
+ struct aice_port_s *aice = target_to_aice(target);
+ if (aice_step(aice) != ERROR_OK)
+ return ERROR_FAIL;
+ }
/* save state */
CHECK_RETVAL(nds32->enter_debug_state(nds32, true));
struct aice_port_s *aice = target_to_aice(target);
- if (ERROR_OK != aice_step(aice))
+ if (aice_step(aice) != ERROR_OK)
return ERROR_FAIL;
/* save state */
uint32_t reason;
struct target *target = nds32->target;
+ if (nds32->hit_syscall == true) {
+ LOG_DEBUG("Hit syscall breakpoint");
+ target->debug_reason = DBG_REASON_BREAKPOINT;
+ return ERROR_OK;
+ }
+
nds32->get_debug_reason(nds32, &reason);
LOG_DEBUG("nds32 examines debug reason: %s", nds32_debug_type_name[reason]);
nds32_get_mapped_reg(nds32, PC, &value_pc);
- if (ERROR_OK != nds32_read_opcode(nds32, value_pc, &opcode))
+ if (nds32_read_opcode(nds32, value_pc, &opcode) != ERROR_OK)
return ERROR_FAIL;
- if (ERROR_OK != nds32_evaluate_opcode(nds32, opcode, value_pc,
- &instruction))
+ if (nds32_evaluate_opcode(nds32, opcode, value_pc, &instruction) != ERROR_OK)
return ERROR_FAIL;
- target->debug_reason = DBG_REASON_BREAKPOINT;
+ /* hit 'break 0x7FFF' */
+ if ((instruction.info.opc_6 == 0x32) &&
+ (instruction.info.sub_opc == 0xA) &&
+ (instruction.info.imm == 0x7FFF)) {
+ target->debug_reason = DBG_REASON_EXIT;
+ } else
+ target->debug_reason = DBG_REASON_BREAKPOINT;
}
break;
case NDS32_DEBUG_DATA_ADDR_WATCHPOINT_PRECISE:
nds32_step_without_watchpoint(nds32);
/* before single_step, save exception address */
- if (ERROR_OK != result)
+ if (result != ERROR_OK)
return ERROR_FAIL;
target->debug_reason = DBG_REASON_WATCHPOINT;
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))
+ if (nds32->get_watched_address(nds32, &(nds32->watched_address), reason) != ERROR_OK)
return ERROR_FAIL;
target->debug_reason = DBG_REASON_WATCHPOINT;
LOG_DEBUG("nds32_login");
- if (nds32->edm_passcode != NULL) {
+ if (nds32->edm_passcode) {
/* convert EDM passcode to command sequences */
passcode_length = strlen(nds32->edm_passcode);
command_sequence[0] = '\0';
code_str[copy_length] = '\0';
code = strtoul(code_str, NULL, 16);
- sprintf(command_str, "write_misc gen_port0 0x%x;", code);
+ sprintf(command_str, "write_misc gen_port0 0x%" PRIx32 ";", code);
strcat(command_sequence, command_str);
}
- if (ERROR_OK != aice_program_edm(aice, command_sequence))
+ if (aice_program_edm(aice, command_sequence) != ERROR_OK)
return ERROR_FAIL;
/* get current privilege level */
else
return ERROR_FAIL;
- sprintf(command_str, "write_misc %s 0x%x;", reg_name, code);
- if (ERROR_OK != aice_program_edm(aice, command_str))
+ sprintf(command_str, "write_misc %s 0x%" PRIx32 ";", reg_name, code);
+ if (aice_program_edm(aice, command_str) != ERROR_OK)
return ERROR_FAIL;
}
}
if (nds32_target_state(nds32, &state) != ERROR_OK)
return ERROR_FAIL;
- if (TARGET_HALTED != state)
+ if (state != TARGET_HALTED)
/* TODO: if state == TARGET_HALTED, check ETYPE is DBGI or not */
- if (ERROR_OK != aice_halt(aice))
+ if (aice_halt(aice) != ERROR_OK)
return ERROR_FAIL;
CHECK_RETVAL(nds32->enter_debug_state(nds32, true));
if (state == TARGET_HALTED) {
if (target->state != TARGET_HALTED) {
/* if false_hit, continue free_run */
- if (ERROR_OK != nds32->enter_debug_state(nds32, true)) {
+ if (nds32->enter_debug_state(nds32, true) != ERROR_OK) {
struct aice_port_s *aice = target_to_aice(target);
aice_run(aice);
return ERROR_OK;
}
int nds32_resume(struct target *target, int current,
- uint32_t address, int handle_breakpoints, int debug_execution)
+ target_addr_t address, int handle_breakpoints, int debug_execution)
{
- LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d",
+ LOG_DEBUG("current %d address %08" TARGET_PRIxADDR
+ " handle_breakpoints %d"
+ " debug_execution %d",
current, address, handle_breakpoints, debug_execution);
struct nds32 *nds32 = target_to_nds32(target);
address = nds32_nextpc(nds32, current, address);
- LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : "");
+ LOG_DEBUG("RESUME PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : "");
if (!debug_execution)
target_free_all_working_areas(target);
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);
+ if (nds32->virtual_hosting_ctrl_c == false) {
+ struct aice_port_s *aice = target_to_aice(target);
+ aice_run(aice);
+ } else
+ nds32->virtual_hosting_ctrl_c = false;
target->debug_reason = DBG_REASON_NOTHALTED;
if (!debug_execution)
return ERROR_OK;
}
+static int nds32_soft_reset_halt(struct target *target)
+{
+ /* TODO: test it */
+ struct nds32 *nds32 = target_to_nds32(target);
+ struct aice_port_s *aice = target_to_aice(target);
+
+ aice_assert_srst(aice, AICE_SRST);
+
+ /* halt core and set pc to 0x0 */
+ int retval = target_halt(target);
+ if (retval != ERROR_OK)
+ return retval;
+
+ /* start fetching from IVB */
+ uint32_t value_ir3;
+ nds32_get_mapped_reg(nds32, IR3, &value_ir3);
+ nds32_set_mapped_reg(nds32, PC, value_ir3 & 0xFFFF0000);
+
+ 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);
+ struct nds32_cpu_version *cpu_version = &(nds32->cpu_version);
- jtag_poll_set_enabled(true);
+ /* TODO: apply hw reset signal in not examined state */
+ if (!(target_was_examined(target))) {
+ LOG_WARNING("Reset is not asserted because the target is not examined.");
+ LOG_WARNING("Use a reset button or power cycle the target.");
+ return ERROR_TARGET_NOT_EXAMINED;
+ }
if (target->reset_halt) {
- if (nds32->soft_reset_halt)
- target->type->soft_reset_halt(target);
+ if ((nds32->soft_reset_halt)
+ || (nds32->edm.version < 0x51)
+ || ((nds32->edm.version == 0x51)
+ && (cpu_version->revision == 0x1C)
+ && (cpu_version->cpu_id_family == 0xC)
+ && (cpu_version->cpu_id_version == 0x0)))
+ nds32_soft_reset_halt(target);
else
aice_assert_srst(aice, AICE_RESET_HOLD);
} else {
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");
+ LOG_DEBUG("nds32_gdb_attach, target coreid: %" PRId32, nds32->target->coreid);
- if (gdb_attached == false) {
+ if (nds32->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);
+ 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;
+ nds32->attached = true;
}
return ERROR_OK;
LOG_DEBUG("nds32_gdb_detach");
bool backup_virtual_hosting_setting;
- if (gdb_attached) {
+ if (nds32->attached) {
backup_virtual_hosting_setting = nds32->virtual_hosting;
/* turn off virtual hosting before resume as gdb-detach */
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);
+ 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;
+ nds32->attached = false;
}
return ERROR_OK;
enum target_event event, void *priv)
{
int retval = ERROR_OK;
- struct nds32 *nds32 = priv;
+ int target_number = *(int *)priv;
+
+ if (target_number != target->target_number)
+ return ERROR_OK;
+
+ struct nds32 *nds32 = target_to_nds32(target);
switch (event) {
case TARGET_EVENT_GDB_ATTACH:
/* 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);
+ target_register_event_callback(nds32_callback_event_handler,
+ &(nds32->target->target_number));
+
+ return ERROR_OK;
+}
+
+int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
+{
+ /* fill syscall parameters to file-I/O info */
+ if (!fileio_info) {
+ LOG_ERROR("Target has not initial file-I/O data structure");
+ return ERROR_FAIL;
+ }
+
+ struct nds32 *nds32 = target_to_nds32(target);
+ uint32_t value_ir6;
+ uint32_t syscall_id;
+
+ if (nds32->hit_syscall == false)
+ return ERROR_FAIL;
+
+ nds32_get_mapped_reg(nds32, IR6, &value_ir6);
+ syscall_id = (value_ir6 >> 16) & 0x7FFF;
+ nds32->active_syscall_id = syscall_id;
+
+ LOG_DEBUG("hit syscall ID: 0x%" PRIx32, syscall_id);
+
+ /* free previous identifier storage */
+ free(fileio_info->identifier);
+ fileio_info->identifier = NULL;
+
+ uint32_t reg_r0, reg_r1, reg_r2;
+ nds32_get_mapped_reg(nds32, R0, ®_r0);
+ nds32_get_mapped_reg(nds32, R1, ®_r1);
+ nds32_get_mapped_reg(nds32, R2, ®_r2);
+
+ switch (syscall_id) {
+ case NDS32_SYSCALL_EXIT:
+ fileio_info->identifier = malloc(5);
+ sprintf(fileio_info->identifier, "exit");
+ fileio_info->param_1 = reg_r0;
+ break;
+ case NDS32_SYSCALL_OPEN:
+ {
+ uint8_t filename[256];
+ fileio_info->identifier = malloc(5);
+ sprintf(fileio_info->identifier, "open");
+ fileio_info->param_1 = reg_r0;
+ /* reserve fileio_info->param_2 for length of path */
+ fileio_info->param_3 = reg_r1;
+ fileio_info->param_4 = reg_r2;
+
+ target->type->read_buffer(target, reg_r0, 256, filename);
+ fileio_info->param_2 = strlen((char *)filename);
+ }
+ break;
+ case NDS32_SYSCALL_CLOSE:
+ fileio_info->identifier = malloc(6);
+ sprintf(fileio_info->identifier, "close");
+ fileio_info->param_1 = reg_r0;
+ break;
+ case NDS32_SYSCALL_READ:
+ fileio_info->identifier = malloc(5);
+ sprintf(fileio_info->identifier, "read");
+ fileio_info->param_1 = reg_r0;
+ fileio_info->param_2 = reg_r1;
+ fileio_info->param_3 = reg_r2;
+ break;
+ case NDS32_SYSCALL_WRITE:
+ fileio_info->identifier = malloc(6);
+ sprintf(fileio_info->identifier, "write");
+ fileio_info->param_1 = reg_r0;
+ fileio_info->param_2 = reg_r1;
+ fileio_info->param_3 = reg_r2;
+ break;
+ case NDS32_SYSCALL_LSEEK:
+ fileio_info->identifier = malloc(6);
+ sprintf(fileio_info->identifier, "lseek");
+ fileio_info->param_1 = reg_r0;
+ fileio_info->param_2 = reg_r1;
+ fileio_info->param_3 = reg_r2;
+ break;
+ case NDS32_SYSCALL_UNLINK:
+ {
+ uint8_t filename[256];
+ fileio_info->identifier = malloc(7);
+ sprintf(fileio_info->identifier, "unlink");
+ fileio_info->param_1 = reg_r0;
+ /* reserve fileio_info->param_2 for length of path */
+
+ target->type->read_buffer(target, reg_r0, 256, filename);
+ fileio_info->param_2 = strlen((char *)filename);
+ }
+ break;
+ case NDS32_SYSCALL_RENAME:
+ {
+ uint8_t filename[256];
+ fileio_info->identifier = malloc(7);
+ sprintf(fileio_info->identifier, "rename");
+ fileio_info->param_1 = reg_r0;
+ /* reserve fileio_info->param_2 for length of old path */
+ fileio_info->param_3 = reg_r1;
+ /* reserve fileio_info->param_4 for length of new path */
+
+ target->type->read_buffer(target, reg_r0, 256, filename);
+ fileio_info->param_2 = strlen((char *)filename);
+
+ target->type->read_buffer(target, reg_r1, 256, filename);
+ fileio_info->param_4 = strlen((char *)filename);
+ }
+ break;
+ case NDS32_SYSCALL_FSTAT:
+ fileio_info->identifier = malloc(6);
+ sprintf(fileio_info->identifier, "fstat");
+ fileio_info->param_1 = reg_r0;
+ fileio_info->param_2 = reg_r1;
+ break;
+ case NDS32_SYSCALL_STAT:
+ {
+ uint8_t filename[256];
+ fileio_info->identifier = malloc(5);
+ sprintf(fileio_info->identifier, "stat");
+ fileio_info->param_1 = reg_r0;
+ /* reserve fileio_info->param_2 for length of old path */
+ fileio_info->param_3 = reg_r1;
+
+ target->type->read_buffer(target, reg_r0, 256, filename);
+ fileio_info->param_2 = strlen((char *)filename) + 1;
+ }
+ break;
+ case NDS32_SYSCALL_GETTIMEOFDAY:
+ fileio_info->identifier = malloc(13);
+ sprintf(fileio_info->identifier, "gettimeofday");
+ fileio_info->param_1 = reg_r0;
+ fileio_info->param_2 = reg_r1;
+ break;
+ case NDS32_SYSCALL_ISATTY:
+ fileio_info->identifier = malloc(7);
+ sprintf(fileio_info->identifier, "isatty");
+ fileio_info->param_1 = reg_r0;
+ break;
+ case NDS32_SYSCALL_SYSTEM:
+ {
+ uint8_t command[256];
+ fileio_info->identifier = malloc(7);
+ sprintf(fileio_info->identifier, "system");
+ fileio_info->param_1 = reg_r0;
+ /* reserve fileio_info->param_2 for length of old path */
+
+ target->type->read_buffer(target, reg_r0, 256, command);
+ fileio_info->param_2 = strlen((char *)command);
+ }
+ break;
+ case NDS32_SYSCALL_ERRNO:
+ fileio_info->identifier = malloc(6);
+ sprintf(fileio_info->identifier, "errno");
+ nds32_set_mapped_reg(nds32, R0, nds32->virtual_hosting_errno);
+ break;
+ default:
+ fileio_info->identifier = malloc(8);
+ sprintf(fileio_info->identifier, "unknown");
+ break;
+ }
+
+ return ERROR_OK;
+}
+
+int nds32_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
+{
+ LOG_DEBUG("syscall return code: 0x%x, errno: 0x%x , ctrl_c: %s",
+ retcode, fileio_errno, ctrl_c ? "true" : "false");
+
+ struct nds32 *nds32 = target_to_nds32(target);
+
+ nds32_set_mapped_reg(nds32, R0, (uint32_t)retcode);
+
+ nds32->virtual_hosting_errno = fileio_errno;
+ nds32->virtual_hosting_ctrl_c = ctrl_c;
+ nds32->active_syscall_id = NDS32_SYSCALL_UNDEFINED;
+
+ return ERROR_OK;
+}
+
+int nds32_profiling(struct target *target, uint32_t *samples,
+ uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
+{
+ /* sample $PC every 10 milliseconds */
+ uint32_t iteration = seconds * 100;
+ struct aice_port_s *aice = target_to_aice(target);
+ struct nds32 *nds32 = target_to_nds32(target);
+
+ /* REVISIT: can nds32 profile without halting? */
+ if (target->state != TARGET_HALTED) {
+ LOG_WARNING("target %s is not halted (profiling)", target->cmd_name);
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ if (max_num_samples < iteration)
+ iteration = max_num_samples;
+
+ int pc_regnum = nds32->register_map(nds32, PC);
+ aice_profiling(aice, 10, iteration, pc_regnum, samples, num_samples);
+
+ register_cache_invalidate(nds32->core_cache);
return ERROR_OK;
}
+int nds32_gdb_fileio_write_memory(struct nds32 *nds32, uint32_t address,
+ uint32_t size, const uint8_t *buffer)
+{
+ if ((nds32->active_syscall_id == NDS32_SYSCALL_FSTAT) ||
+ (nds32->active_syscall_id == NDS32_SYSCALL_STAT)) {
+ /* If doing GDB file-I/O, target should convert 'struct stat'
+ * from gdb-format to target-format */
+ uint8_t stat_buffer[NDS32_STRUCT_STAT_SIZE];
+ /* st_dev 2 */
+ stat_buffer[0] = buffer[3];
+ stat_buffer[1] = buffer[2];
+ /* st_ino 2 */
+ stat_buffer[2] = buffer[7];
+ stat_buffer[3] = buffer[6];
+ /* st_mode 4 */
+ stat_buffer[4] = buffer[11];
+ stat_buffer[5] = buffer[10];
+ stat_buffer[6] = buffer[9];
+ stat_buffer[7] = buffer[8];
+ /* st_nlink 2 */
+ stat_buffer[8] = buffer[15];
+ stat_buffer[9] = buffer[16];
+ /* st_uid 2 */
+ stat_buffer[10] = buffer[19];
+ stat_buffer[11] = buffer[18];
+ /* st_gid 2 */
+ stat_buffer[12] = buffer[23];
+ stat_buffer[13] = buffer[22];
+ /* st_rdev 2 */
+ stat_buffer[14] = buffer[27];
+ stat_buffer[15] = buffer[26];
+ /* st_size 4 */
+ stat_buffer[16] = buffer[35];
+ stat_buffer[17] = buffer[34];
+ stat_buffer[18] = buffer[33];
+ stat_buffer[19] = buffer[32];
+ /* st_atime 4 */
+ stat_buffer[20] = buffer[55];
+ stat_buffer[21] = buffer[54];
+ stat_buffer[22] = buffer[53];
+ stat_buffer[23] = buffer[52];
+ /* st_spare1 4 */
+ stat_buffer[24] = 0;
+ stat_buffer[25] = 0;
+ stat_buffer[26] = 0;
+ stat_buffer[27] = 0;
+ /* st_mtime 4 */
+ stat_buffer[28] = buffer[59];
+ stat_buffer[29] = buffer[58];
+ stat_buffer[30] = buffer[57];
+ stat_buffer[31] = buffer[56];
+ /* st_spare2 4 */
+ stat_buffer[32] = 0;
+ stat_buffer[33] = 0;
+ stat_buffer[34] = 0;
+ stat_buffer[35] = 0;
+ /* st_ctime 4 */
+ stat_buffer[36] = buffer[63];
+ stat_buffer[37] = buffer[62];
+ stat_buffer[38] = buffer[61];
+ stat_buffer[39] = buffer[60];
+ /* st_spare3 4 */
+ stat_buffer[40] = 0;
+ stat_buffer[41] = 0;
+ stat_buffer[42] = 0;
+ stat_buffer[43] = 0;
+ /* st_blksize 4 */
+ stat_buffer[44] = buffer[43];
+ stat_buffer[45] = buffer[42];
+ stat_buffer[46] = buffer[41];
+ stat_buffer[47] = buffer[40];
+ /* st_blocks 4 */
+ stat_buffer[48] = buffer[51];
+ stat_buffer[49] = buffer[50];
+ stat_buffer[50] = buffer[49];
+ stat_buffer[51] = buffer[48];
+ /* st_spare4 8 */
+ stat_buffer[52] = 0;
+ stat_buffer[53] = 0;
+ stat_buffer[54] = 0;
+ stat_buffer[55] = 0;
+ stat_buffer[56] = 0;
+ stat_buffer[57] = 0;
+ stat_buffer[58] = 0;
+ stat_buffer[59] = 0;
+
+ return nds32_write_buffer(nds32->target, address, NDS32_STRUCT_STAT_SIZE, stat_buffer);
+ } else if (nds32->active_syscall_id == NDS32_SYSCALL_GETTIMEOFDAY) {
+ /* If doing GDB file-I/O, target should convert 'struct timeval'
+ * from gdb-format to target-format */
+ uint8_t timeval_buffer[NDS32_STRUCT_TIMEVAL_SIZE];
+ timeval_buffer[0] = buffer[3];
+ timeval_buffer[1] = buffer[2];
+ timeval_buffer[2] = buffer[1];
+ timeval_buffer[3] = buffer[0];
+ timeval_buffer[4] = buffer[11];
+ timeval_buffer[5] = buffer[10];
+ timeval_buffer[6] = buffer[9];
+ timeval_buffer[7] = buffer[8];
+
+ return nds32_write_buffer(nds32->target, address, NDS32_STRUCT_TIMEVAL_SIZE, timeval_buffer);
+ }
+
+ return nds32_write_buffer(nds32->target, address, size, buffer);
+}
+
int nds32_reset_halt(struct nds32 *nds32)
{
LOG_INFO("reset halt as init");