static int mips_m4k_halt(struct target *target);
static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address,
uint32_t count, const uint8_t *buffer);
+static int mips_m4k_bulk_read_memory(struct target *target, target_addr_t address,
+ uint32_t count, uint8_t *buffer);
static int mips_m4k_examine_debug_reason(struct target *target)
{
/* attempt to find halt reason */
mips_m4k_examine_debug_reason(target);
+ mips32_cpu_probe(target);
+
mips32_read_config_regs(target);
/* default to mips32 isa, it will be changed below if required */
mips32->isa_mode = MIPS32_ISA_MIPS32;
/* other than mips32 only and isa bit set ? */
- if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1))
+ if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1))
mips32->isa_mode = mips32->isa_imp == 2 ? MIPS32_ISA_MIPS16E : MIPS32_ISA_MMIPS32;
LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s",
- buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32),
+ buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32),
target_state_name(target));
return ERROR_OK;
ret = mips_m4k_halt(curr);
if (ret != ERROR_OK) {
- LOG_ERROR("halt failed target->coreid: %" PRId32, curr->coreid);
+ LOG_TARGET_ERROR(curr, "halt failed.");
retval = ret;
}
}
handle_breakpoints, 0);
if (ret != ERROR_OK) {
- LOG_ERROR("target->coreid :%" PRId32 " failed to resume at address :0x%" PRIx32,
- curr->coreid, address);
+ LOG_TARGET_ERROR(curr, "failed to resume at address: 0x%" PRIx32,
+ address);
retval = ret;
}
}
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
mips_m4k_isa_filter(mips32->isa_imp, &address);
- buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
- mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
- mips32->core_cache->reg_list[MIPS32_PC].valid = true;
+ buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
+ mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
+ mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true;
}
if ((mips32->isa_imp > 1) && debug_execution) /* if more than one isa supported */
- buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode);
+ buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1, mips32->isa_mode);
if (!current)
resume_pc = address;
else
- resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
+ resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32);
mips32_restore_context(target);
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
mips_m4k_isa_filter(mips32->isa_imp, &address);
- buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
- mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
- mips32->core_cache->reg_list[MIPS32_PC].valid = true;
+ buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
+ mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
+ mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true;
}
/* the front-end may request us not to handle breakpoints */
if (handle_breakpoints) {
breakpoint = breakpoint_find(target,
- buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
+ buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32));
if (breakpoint)
mips_m4k_unset_breakpoint(target, breakpoint);
}
if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
return ERROR_TARGET_UNALIGNED_ACCESS;
+ if (size == 4 && count > 32) {
+ int retval = mips_m4k_bulk_read_memory(target, address, count, buffer);
+ if (retval == ERROR_OK)
+ return ERROR_OK;
+ LOG_WARNING("Falling back to non-bulk read");
+ }
/* since we don't know if buffer is aligned, we allocate new mem that is always aligned */
void *t = NULL;
return retval;
}
+static int mips_m4k_bulk_read_memory(struct target *target, target_addr_t address,
+ uint32_t count, uint8_t *buffer)
+{
+ struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
+ struct working_area *fast_data_area;
+ int retval;
+ int write_t = 0;
+
+ LOG_DEBUG("address: " TARGET_ADDR_FMT ", count: 0x%8.8" PRIx32 "",
+ address, count);
+
+ /* check alignment */
+ if (address & 0x3u)
+ return ERROR_TARGET_UNALIGNED_ACCESS;
+
+ if (!mips32->fast_data_area) {
+ /* Get memory for block read handler
+ * we preserve this area between calls and gain a speed increase
+ * of about 3kb/sec when reading flash
+ * this will be released/nulled by the system when the target is resumed or reset */
+ retval = target_alloc_working_area(target,
+ MIPS32_FASTDATA_HANDLER_SIZE,
+ &mips32->fast_data_area);
+ if (retval != ERROR_OK) {
+ LOG_ERROR("No working area available");
+ return retval;
+ }
+
+ /* reset fastadata state so the algo get reloaded */
+ ejtag_info->fast_access_save = -1;
+ }
+
+ fast_data_area = mips32->fast_data_area;
+
+ if (address < (fast_data_area->address + fast_data_area->size) &&
+ fast_data_area->address < (address + count)) {
+ LOG_ERROR("fast_data (" TARGET_ADDR_FMT ") is within read area "
+ "(" TARGET_ADDR_FMT "-" TARGET_ADDR_FMT ").",
+ fast_data_area->address, address, address + count);
+ LOG_ERROR("Change work-area-phys or load_image address!");
+ return ERROR_FAIL;
+ }
+
+ /* mips32_pracc_fastdata_xfer requires uint32_t in host endianness, */
+ /* but byte array represents target endianness */
+ uint32_t *t = malloc(count * sizeof(uint32_t));
+ if (!t) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
+
+ retval = mips32_pracc_fastdata_xfer(ejtag_info, mips32->fast_data_area, write_t, address,
+ count, t);
+
+ target_buffer_set_u32_array(target, buffer, count, t);
+
+ free(t);
+
+ if (retval != ERROR_OK)
+ LOG_ERROR("Fastdata access Failed");
+
+ return retval;
+}
+
static int mips_m4k_verify_pointer(struct command_invocation *cmd,
struct mips_m4k_common *mips_m4k)
{