X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Fnds32.c;h=e4bb17f9df278bd736ded0f78c1086476bc01d24;hb=f18ca510b3430a515f28f19ea6c6731a40022fb6;hp=95a249d0535bf553cf4176260cf461c2cf052c48;hpb=d979d78e97786667d168ba183c9fc60c622d29c1;p=openocd.git diff --git a/src/target/nds32.c b/src/target/nds32.c index 95a249d053..e4bb17f9df 100644 --- a/src/target/nds32.c +++ b/src/target/nds32.c @@ -13,9 +13,7 @@ * 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 . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -86,32 +84,32 @@ static int nds32_get_core_reg(struct reg *reg) } 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(mapped_regnum))) { - reg_arch_info->value = 0; + uint32_t val = 0; + if ((nds32->fpu_enable == false) + && (NDS32_REG_TYPE_FPU == nds32_reg_type(mapped_regnum))) { retval = ERROR_OK; - } else if ((nds32->audio_enable == false) && - (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) { - reg_arch_info->value = 0; + } else if ((nds32->audio_enable == false) + && (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) { retval = ERROR_OK; } else { - retval = aice_read_register(aice, - mapped_regnum, &(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) { @@ -139,17 +137,17 @@ static int nds32_get_core_reg_64(struct reg *reg) 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) + && ((FD0 <= reg_arch_info->num) && (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) { @@ -309,7 +307,7 @@ static int nds32_set_core_reg(struct reg *reg, uint8_t *buf) 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) && @@ -322,11 +320,13 @@ static int nds32_set_core_reg(struct reg *reg, uint8_t *buf) buf_set_u32(reg->value, 0, 32, 0); } else { buf_set_u32(reg->value, 0, 32, value); - aice_write_register(aice, mapped_regnum, 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, mapped_regnum, &(reg_arch_info->value)); + aice_read_register(aice, mapped_regnum, &val); + buf_set_u32(reg_arch_info->value, 0, 32, val); } reg->valid = true; @@ -395,7 +395,7 @@ static const struct reg_arch_type nds32_reg_access_type_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_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; @@ -423,17 +423,17 @@ static struct reg_cache *nds32_build_reg_cache(struct target *target, reg_list[i].size = nds32_reg_size(i); reg_list[i].arch_info = ®_arch_info[i]; - reg_list[i].reg_data_type = malloc(sizeof(struct reg_data_type)); + reg_list[i].reg_data_type = calloc(sizeof(struct reg_data_type), 1); 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].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"; @@ -823,7 +823,7 @@ int nds32_read_memory(struct target *target, uint32_t address, 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); @@ -932,7 +932,7 @@ int nds32_write_memory(struct target *target, uint32_t address, 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); @@ -1545,14 +1545,18 @@ int nds32_restore_context(struct target *target) 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 (FD0 <= reg_arch_info->num && 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; } @@ -1572,7 +1576,7 @@ int nds32_edm_config(struct nds32 *nds32) 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; @@ -1644,7 +1648,20 @@ int nds32_init_arch_info(struct target *target, struct nds32 *nds32) 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(); @@ -1657,7 +1674,7 @@ int nds32_init_arch_info(struct target *target, struct nds32 *nds32) 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); @@ -1675,7 +1692,7 @@ int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t 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); @@ -1721,7 +1738,7 @@ int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length) /* 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; + target_addr_t physical_addr; if (ERROR_FAIL == target->type->virt2phys(target, cur_address, &physical_addr)) return ERROR_FAIL; @@ -1747,7 +1764,7 @@ uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address) } 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)); @@ -1761,7 +1778,7 @@ int nds32_step(struct target *target, int current, 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; @@ -1772,13 +1789,24 @@ int nds32_step(struct target *target, int current, 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 (ERROR_OK != aice_step(aice)) + return ERROR_FAIL; + } /* save state */ CHECK_RETVAL(nds32->enter_debug_state(nds32, true)); @@ -1878,6 +1906,12 @@ int nds32_examine_debug_reason(struct nds32 *nds32) 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]); @@ -1900,7 +1934,13 @@ int nds32_examine_debug_reason(struct nds32 *nds32) &instruction)) 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: @@ -1972,7 +2012,7 @@ int nds32_login(struct nds32 *nds32) 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); } @@ -1997,7 +2037,7 @@ int nds32_login(struct nds32 *nds32) else return ERROR_FAIL; - sprintf(command_str, "write_misc %s 0x%x;", reg_name, code); + sprintf(command_str, "write_misc %s 0x%" PRIx32 ";", reg_name, code); if (ERROR_OK != aice_program_edm(aice, command_str)) return ERROR_FAIL; } @@ -2080,9 +2120,11 @@ int nds32_poll(struct target *target) } 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); @@ -2094,7 +2136,7 @@ int nds32_resume(struct target *target, int current, 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); @@ -2110,8 +2152,11 @@ int nds32_resume(struct target *target, int current, 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) @@ -2125,16 +2170,48 @@ int nds32_resume(struct target *target, int current, 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 { @@ -2153,25 +2230,21 @@ int nds32_assert_reset(struct target *target) 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; @@ -2182,7 +2255,7 @@ static int nds32_gdb_detach(struct nds32 *nds32) 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 */ @@ -2193,13 +2266,10 @@ static int nds32_gdb_detach(struct nds32 *nds32) 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; @@ -2209,7 +2279,12 @@ static int nds32_callback_event_handler(struct target *target, 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: @@ -2230,15 +2305,318 @@ 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); + 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 (NULL == 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 */ + if (NULL != fileio_info->identifier) { + free(fileio_info->identifier); + fileio_info->identifier = NULL; + } + + switch (syscall_id) { + case NDS32_SYSCALL_EXIT: + fileio_info->identifier = malloc(5); + sprintf(fileio_info->identifier, "exit"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + break; + case NDS32_SYSCALL_OPEN: + { + uint8_t filename[256]; + fileio_info->identifier = malloc(5); + sprintf(fileio_info->identifier, "open"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + /* reserve fileio_info->param_2 for length of path */ + nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3)); + nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_4)); + + target->type->read_buffer(target, fileio_info->param_1, + 256, filename); + fileio_info->param_2 = strlen((char *)filename) + 1; + } + break; + case NDS32_SYSCALL_CLOSE: + fileio_info->identifier = malloc(6); + sprintf(fileio_info->identifier, "close"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + break; + case NDS32_SYSCALL_READ: + fileio_info->identifier = malloc(5); + sprintf(fileio_info->identifier, "read"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); + nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); + break; + case NDS32_SYSCALL_WRITE: + fileio_info->identifier = malloc(6); + sprintf(fileio_info->identifier, "write"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); + nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); + break; + case NDS32_SYSCALL_LSEEK: + fileio_info->identifier = malloc(6); + sprintf(fileio_info->identifier, "lseek"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); + nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); + break; + case NDS32_SYSCALL_UNLINK: + { + uint8_t filename[256]; + fileio_info->identifier = malloc(7); + sprintf(fileio_info->identifier, "unlink"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + /* reserve fileio_info->param_2 for length of path */ + + target->type->read_buffer(target, fileio_info->param_1, + 256, filename); + fileio_info->param_2 = strlen((char *)filename) + 1; + } + break; + case NDS32_SYSCALL_RENAME: + { + uint8_t filename[256]; + fileio_info->identifier = malloc(7); + sprintf(fileio_info->identifier, "rename"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + /* reserve fileio_info->param_2 for length of old path */ + nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3)); + /* reserve fileio_info->param_4 for length of new path */ + + target->type->read_buffer(target, fileio_info->param_1, + 256, filename); + fileio_info->param_2 = strlen((char *)filename) + 1; + + target->type->read_buffer(target, fileio_info->param_3, + 256, filename); + fileio_info->param_4 = strlen((char *)filename) + 1; + } + break; + case NDS32_SYSCALL_FSTAT: + fileio_info->identifier = malloc(6); + sprintf(fileio_info->identifier, "fstat"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); + break; + case NDS32_SYSCALL_STAT: + { + uint8_t filename[256]; + fileio_info->identifier = malloc(5); + sprintf(fileio_info->identifier, "stat"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + /* reserve fileio_info->param_2 for length of old path */ + nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3)); + + target->type->read_buffer(target, fileio_info->param_1, + 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"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); + break; + case NDS32_SYSCALL_ISATTY: + fileio_info->identifier = malloc(7); + sprintf(fileio_info->identifier, "isatty"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + break; + case NDS32_SYSCALL_SYSTEM: + { + uint8_t command[256]; + fileio_info->identifier = malloc(7); + sprintf(fileio_info->identifier, "system"); + nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + /* reserve fileio_info->param_2 for length of old path */ + + target->type->read_buffer(target, fileio_info->param_1, + 256, command); + fileio_info->param_2 = strlen((char *)command) + 1; + } + 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); + + 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_SYSCALL_FSTAT == nds32->active_syscall_id) || + (NDS32_SYSCALL_STAT == nds32->active_syscall_id)) { + /* 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_SYSCALL_GETTIMEOFDAY == nds32->active_syscall_id) { + /* 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");