- .name = "arm11",
-
- ARM11_HANDLER(poll),
- ARM11_HANDLER(arch_state),
-
- ARM11_HANDLER(target_request_data),
-
- ARM11_HANDLER(halt),
- ARM11_HANDLER(resume),
- ARM11_HANDLER(step),
-
- ARM11_HANDLER(assert_reset),
- ARM11_HANDLER(deassert_reset),
- ARM11_HANDLER(soft_reset_halt),
- ARM11_HANDLER(prepare_reset_halt),
-
- ARM11_HANDLER(get_gdb_reg_list),
-
- ARM11_HANDLER(read_memory),
- ARM11_HANDLER(write_memory),
-
- ARM11_HANDLER(bulk_write_memory),
-
- ARM11_HANDLER(checksum_memory),
-
- ARM11_HANDLER(add_breakpoint),
- ARM11_HANDLER(remove_breakpoint),
- ARM11_HANDLER(add_watchpoint),
- ARM11_HANDLER(remove_watchpoint),
-
- ARM11_HANDLER(run_algorithm),
-
- ARM11_HANDLER(register_commands),
- ARM11_HANDLER(target_command),
- ARM11_HANDLER(init_target),
- ARM11_HANDLER(quit),
+ .name = "arm11",
+
+ ARM11_HANDLER(poll),
+ ARM11_HANDLER(arch_state),
+
+ ARM11_HANDLER(target_request_data),
+
+ ARM11_HANDLER(halt),
+ ARM11_HANDLER(resume),
+ ARM11_HANDLER(step),
+
+ ARM11_HANDLER(assert_reset),
+ ARM11_HANDLER(deassert_reset),
+ ARM11_HANDLER(soft_reset_halt),
+
+ ARM11_HANDLER(get_gdb_reg_list),
+
+ ARM11_HANDLER(read_memory),
+ ARM11_HANDLER(write_memory),
+
+ ARM11_HANDLER(bulk_write_memory),
+
+ ARM11_HANDLER(checksum_memory),
+
+ ARM11_HANDLER(add_breakpoint),
+ ARM11_HANDLER(remove_breakpoint),
+ ARM11_HANDLER(add_watchpoint),
+ ARM11_HANDLER(remove_watchpoint),
+
+ ARM11_HANDLER(run_algorithm),
+
+ ARM11_HANDLER(register_commands),
+ ARM11_HANDLER(target_create),
+ ARM11_HANDLER(init_target),
+ ARM11_HANDLER(examine),
+ ARM11_HANDLER(quit),
- {"r0", 0, 0, ARM11_REGISTER_CORE},
- {"r1", 1, 1, ARM11_REGISTER_CORE},
- {"r2", 2, 2, ARM11_REGISTER_CORE},
- {"r3", 3, 3, ARM11_REGISTER_CORE},
- {"r4", 4, 4, ARM11_REGISTER_CORE},
- {"r5", 5, 5, ARM11_REGISTER_CORE},
- {"r6", 6, 6, ARM11_REGISTER_CORE},
- {"r7", 7, 7, ARM11_REGISTER_CORE},
- {"r8", 8, 8, ARM11_REGISTER_CORE},
- {"r9", 9, 9, ARM11_REGISTER_CORE},
- {"r10", 10, 10, ARM11_REGISTER_CORE},
- {"r11", 11, 11, ARM11_REGISTER_CORE},
- {"r12", 12, 12, ARM11_REGISTER_CORE},
- {"sp", 13, 13, ARM11_REGISTER_CORE},
- {"lr", 14, 14, ARM11_REGISTER_CORE},
- {"pc", 15, 15, ARM11_REGISTER_CORE},
+ {"r0", 0, 0, ARM11_REGISTER_CORE},
+ {"r1", 1, 1, ARM11_REGISTER_CORE},
+ {"r2", 2, 2, ARM11_REGISTER_CORE},
+ {"r3", 3, 3, ARM11_REGISTER_CORE},
+ {"r4", 4, 4, ARM11_REGISTER_CORE},
+ {"r5", 5, 5, ARM11_REGISTER_CORE},
+ {"r6", 6, 6, ARM11_REGISTER_CORE},
+ {"r7", 7, 7, ARM11_REGISTER_CORE},
+ {"r8", 8, 8, ARM11_REGISTER_CORE},
+ {"r9", 9, 9, ARM11_REGISTER_CORE},
+ {"r10", 10, 10, ARM11_REGISTER_CORE},
+ {"r11", 11, 11, ARM11_REGISTER_CORE},
+ {"r12", 12, 12, ARM11_REGISTER_CORE},
+ {"sp", 13, 13, ARM11_REGISTER_CORE},
+ {"lr", 14, 14, ARM11_REGISTER_CORE},
+ {"pc", 15, 15, ARM11_REGISTER_CORE},
- {"f0", 0, 16, ARM11_REGISTER_FX},
- {"f1", 1, 17, ARM11_REGISTER_FX},
- {"f2", 2, 18, ARM11_REGISTER_FX},
- {"f3", 3, 19, ARM11_REGISTER_FX},
- {"f4", 4, 20, ARM11_REGISTER_FX},
- {"f5", 5, 21, ARM11_REGISTER_FX},
- {"f6", 6, 22, ARM11_REGISTER_FX},
- {"f7", 7, 23, ARM11_REGISTER_FX},
- {"fps", 0, 24, ARM11_REGISTER_FPS},
+ {"f0", 0, 16, ARM11_REGISTER_FX},
+ {"f1", 1, 17, ARM11_REGISTER_FX},
+ {"f2", 2, 18, ARM11_REGISTER_FX},
+ {"f3", 3, 19, ARM11_REGISTER_FX},
+ {"f4", 4, 20, ARM11_REGISTER_FX},
+ {"f5", 5, 21, ARM11_REGISTER_FX},
+ {"f6", 6, 22, ARM11_REGISTER_FX},
+ {"f7", 7, 23, ARM11_REGISTER_FX},
+ {"fps", 0, 24, ARM11_REGISTER_FPS},
- {"r8_fiq", 8, -1, ARM11_REGISTER_FIQ},
- {"r9_fiq", 9, -1, ARM11_REGISTER_FIQ},
- {"r10_fiq", 10, -1, ARM11_REGISTER_FIQ},
- {"r11_fiq", 11, -1, ARM11_REGISTER_FIQ},
- {"r12_fiq", 12, -1, ARM11_REGISTER_FIQ},
- {"r13_fiq", 13, -1, ARM11_REGISTER_FIQ},
- {"r14_fiq", 14, -1, ARM11_REGISTER_FIQ},
- {"spsr_fiq", 0, -1, ARM11_REGISTER_SPSR_FIQ},
-
- {"r13_svc", 13, -1, ARM11_REGISTER_SVC},
- {"r14_svc", 14, -1, ARM11_REGISTER_SVC},
- {"spsr_svc", 0, -1, ARM11_REGISTER_SPSR_SVC},
-
- {"r13_abt", 13, -1, ARM11_REGISTER_ABT},
- {"r14_abt", 14, -1, ARM11_REGISTER_ABT},
- {"spsr_abt", 0, -1, ARM11_REGISTER_SPSR_ABT},
-
- {"r13_irq", 13, -1, ARM11_REGISTER_IRQ},
- {"r14_irq", 14, -1, ARM11_REGISTER_IRQ},
- {"spsr_irq", 0, -1, ARM11_REGISTER_SPSR_IRQ},
-
- {"r13_und", 13, -1, ARM11_REGISTER_UND},
- {"r14_und", 14, -1, ARM11_REGISTER_UND},
- {"spsr_und", 0, -1, ARM11_REGISTER_SPSR_UND},
-
- /* ARM1176 only */
- {"r13_mon", 13, -1, ARM11_REGISTER_MON},
- {"r14_mon", 14, -1, ARM11_REGISTER_MON},
- {"spsr_mon", 0, -1, ARM11_REGISTER_SPSR_MON},
+ {"r8_fiq", 8, -1, ARM11_REGISTER_FIQ},
+ {"r9_fiq", 9, -1, ARM11_REGISTER_FIQ},
+ {"r10_fiq", 10, -1, ARM11_REGISTER_FIQ},
+ {"r11_fiq", 11, -1, ARM11_REGISTER_FIQ},
+ {"r12_fiq", 12, -1, ARM11_REGISTER_FIQ},
+ {"r13_fiq", 13, -1, ARM11_REGISTER_FIQ},
+ {"r14_fiq", 14, -1, ARM11_REGISTER_FIQ},
+ {"spsr_fiq", 0, -1, ARM11_REGISTER_SPSR_FIQ},
+
+ {"r13_svc", 13, -1, ARM11_REGISTER_SVC},
+ {"r14_svc", 14, -1, ARM11_REGISTER_SVC},
+ {"spsr_svc", 0, -1, ARM11_REGISTER_SPSR_SVC},
+
+ {"r13_abt", 13, -1, ARM11_REGISTER_ABT},
+ {"r14_abt", 14, -1, ARM11_REGISTER_ABT},
+ {"spsr_abt", 0, -1, ARM11_REGISTER_SPSR_ABT},
+
+ {"r13_irq", 13, -1, ARM11_REGISTER_IRQ},
+ {"r14_irq", 14, -1, ARM11_REGISTER_IRQ},
+ {"spsr_irq", 0, -1, ARM11_REGISTER_SPSR_IRQ},
+
+ {"r13_und", 13, -1, ARM11_REGISTER_UND},
+ {"r14_und", 14, -1, ARM11_REGISTER_UND},
+ {"spsr_und", 0, -1, ARM11_REGISTER_SPSR_UND},
+
+ /* ARM1176 only */
+ {"r13_mon", 13, -1, ARM11_REGISTER_MON},
+ {"r14_mon", 14, -1, ARM11_REGISTER_MON},
+ {"spsr_mon", 0, -1, ARM11_REGISTER_SPSR_MON},
- /** skip over BKPT */
- if ((next_instruction & 0xFFF00070) == 0xe1200070)
- {
- R(PC) += 4;
- arm11->reg_list[ARM11_RC_PC].valid = 1;
- arm11->reg_list[ARM11_RC_PC].dirty = 0;
- INFO("Skipping BKPT");
- }
- /* ignore B to self */
- else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe)
- {
- INFO("Not stepping jump to self");
- }
- else
- {
- /** \todo TODO: check if break-/watchpoints make any sense at all in combination
- * with this. */
+ /* skip over BKPT */
+ if ((next_instruction & 0xFFF00070) == 0xe1200070)
+ {
+ R(PC) += 4;
+ arm11->reg_list[ARM11_RC_PC].valid = 1;
+ arm11->reg_list[ARM11_RC_PC].dirty = 0;
+ LOG_DEBUG("Skipping BKPT");
+ }
+ /* skip over Wait for interrupt / Standby */
+ /* mcr 15, 0, r?, cr7, cr0, {4} */
+ else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90)
+ {
+ R(PC) += 4;
+ arm11->reg_list[ARM11_RC_PC].valid = 1;
+ arm11->reg_list[ARM11_RC_PC].dirty = 0;
+ LOG_DEBUG("Skipping WFI");
+ }
+ /* ignore B to self */
+ else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe)
+ {
+ LOG_DEBUG("Not stepping jump to self");
+ }
+ else
+ {
+ /** \todo TODO: check if break-/watchpoints make any sense at all in combination
+ * with this. */
- /* STC p14,c5,[R0],#4 */
- arm11_run_instr_data_to_core(arm11, 0xeca05e01, (u32 *)buffer, count);
+ case 1:
+ {
+ arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+ for (size_t i = 0; i < count; i++)
+ {
+ /* MRC p14,0,r1,c0,c5,0 */
+ arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
+
+ /* strb r1, [r0], #1 */
+ /* strb r1, [r0] */
+ arm11_run_instr_no_data1(arm11,
+ !arm11_config_memrw_no_increment ? 0xe4c01001 : 0xe5c01000);
+ }
+
+ break;
+ }
+
+ case 2:
+ {
+ arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+ for (size_t i = 0; i < count; i++)
+ {
+ uint16_t value;
+ memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
+
+ /* MRC p14,0,r1,c0,c5,0 */
+ arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
+
+ /* strh r1, [r0], #2 */
+ /* strh r1, [r0] */
+ arm11_run_instr_no_data1(arm11,
+ !arm11_config_memrw_no_increment ? 0xe0c010b2 : 0xe1c010b0);
+ }
+
+ break;
+ }
+
+ case 4: {
+ uint32_t instr = !arm11_config_memrw_no_increment ? 0xeca05e01 : 0xed805e00;
+
+ /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
+ uint32_t *words = (uint32_t*)buffer;
+
+ if (!arm11_config_memwrite_burst)
+ {
+ /* STC p14,c5,[R0],#4 */
+ /* STC p14,c5,[R0]*/
+ arm11_run_instr_data_to_core(arm11, instr, words, count);
+ }
+ else
+ {
+ /* STC p14,c5,[R0],#4 */
+ /* STC p14,c5,[R0]*/
+ arm11_run_instr_data_to_core_noack(arm11, instr, words, count);
+ }
+
+ break;
- jtag_device_t *device = jtag_get_device(chain_pos);
+/* arm11->core_state = arm11_algorithm_info->core_state;
+ if (arm11->core_state == ARMV4_5_STATE_ARM)
+ exit_breakpoint_size = 4;
+ else if (arm11->core_state == ARMV4_5_STATE_THUMB)
+ exit_breakpoint_size = 2;
+ else
+ {
+ LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
+ exit(-1);
+ }
+*/
+
+
+/* arm11 at this point only supports ARM not THUMB mode
+ however if this test needs to be reactivated the current state can be read back
+ from CPSR */
+#if 0
+ if (arm11_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
+ {
+ LOG_DEBUG("setting core_mode: 0x%2.2x", arm11_algorithm_info->core_mode);
+ buf_set_u32(arm11->reg_list[ARM11_RC_CPSR].value, 0, 5, arm11_algorithm_info->core_mode);
+ arm11->reg_list[ARM11_RC_CPSR].dirty = 1;
+ arm11->reg_list[ARM11_RC_CPSR].valid = 1;
+ }
+#endif
+
+ if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK)
+ {
+ LOG_ERROR("can't add breakpoint to finish algorithm execution");
+ retval = ERROR_TARGET_FAILURE;
+ goto restore;
+ }
+
+ // no debug, otherwise breakpoint is not set
+ CHECK_RETVAL(target_resume(target, 0, entry_point, 1, 0));
+
+ CHECK_RETVAL(target_wait_state(target, TARGET_HALTED, timeout_ms));
+
+ if (target->state != TARGET_HALTED)
+ {
+ CHECK_RETVAL(target_halt(target));
+
+ CHECK_RETVAL(target_wait_state(target, TARGET_HALTED, 500));
+
+ retval = ERROR_TARGET_TIMEOUT;
+
+ goto del_breakpoint;
+ }
+
+ if (buf_get_u32(arm11->reg_list[15].value, 0, 32) != exit_point)
+ {
+ LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "",
+ buf_get_u32(arm11->reg_list[15].value, 0, 32));
+ retval = ERROR_TARGET_TIMEOUT;
+ goto del_breakpoint;
+ }
+
+ for (int i = 0; i < num_mem_params; i++)
+ {
+ if (mem_params[i].direction != PARAM_OUT)
+ target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
+ }
+
+ for (int i = 0; i < num_reg_params; i++)
+ {
+ if (reg_params[i].direction != PARAM_OUT)
+ {
+ reg_t *reg = register_get_by_name(arm11->core_cache, reg_params[i].reg_name, 0);
+ if (!reg)
+ {
+ LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
+ exit(-1);
+ }
+
+ if (reg->size != reg_params[i].size)
+ {
+ LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
+ exit(-1);
+ }
+
+ buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
+ }
+ }
- arm11_common_t *arm11 = target->arch_info;
-
- NEW(reg_cache_t, cache, 1);
- NEW(reg_t, reg_list, ARM11_REGCACHE_COUNT);
- NEW(arm11_reg_state_t, arm11_reg_states, ARM11_REGCACHE_COUNT);
-
- if (arm11_regs_arch_type == -1)
- arm11_regs_arch_type = register_reg_arch_type(arm11_get_reg, arm11_set_reg);
-
- arm11->reg_list = reg_list;
-
- /* Build the process context cache */
- cache->name = "arm11 registers";
- cache->next = NULL;
- cache->reg_list = reg_list;
- cache->num_regs = ARM11_REGCACHE_COUNT;
-
- reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
- (*cache_p) = cache;
-
-// armv7m->core_cache = cache;
-// armv7m->process_context = cache;
-
- size_t i;
-
- /* Not very elegant assertion */
- if (ARM11_REGCACHE_COUNT != asizeof(arm11->reg_values) ||
- ARM11_REGCACHE_COUNT != asizeof(arm11_reg_defs) ||
- ARM11_REGCACHE_COUNT != ARM11_RC_MAX)
- {
- ERROR("arm11->reg_values inconsistent (%d %d %d %d)", ARM11_REGCACHE_COUNT, asizeof(arm11->reg_values), asizeof(arm11_reg_defs), ARM11_RC_MAX);
- exit(-1);
- }
-
- for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
- {
- reg_t * r = reg_list + i;
- const arm11_reg_defs_t * rd = arm11_reg_defs + i;
- arm11_reg_state_t * rs = arm11_reg_states + i;
-
- r->name = rd->name;
- r->size = 32;
- r->value = (u8 *)(arm11->reg_values + i);
- r->dirty = 0;
- r->valid = 0;
- r->bitfield_desc = NULL;
- r->num_bitfields = 0;
- r->arch_type = arm11_regs_arch_type;
- r->arch_info = rs;
-
- rs->def_index = i;
- rs->target = target;
- }
-}
+ arm11_common_t *arm11 = target->arch_info;
+
+ NEW(reg_cache_t, cache, 1);
+ NEW(reg_t, reg_list, ARM11_REGCACHE_COUNT);
+ NEW(arm11_reg_state_t, arm11_reg_states, ARM11_REGCACHE_COUNT);
+
+ if (arm11_regs_arch_type == -1)
+ arm11_regs_arch_type = register_reg_arch_type(arm11_get_reg, arm11_set_reg);
+ register_init_dummy(&arm11_gdb_dummy_fp_reg);
+ register_init_dummy(&arm11_gdb_dummy_fps_reg);
+
+ arm11->reg_list = reg_list;
+
+ /* Build the process context cache */
+ cache->name = "arm11 registers";
+ cache->next = NULL;
+ cache->reg_list = reg_list;
+ cache->num_regs = ARM11_REGCACHE_COUNT;
+
+ reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+ (*cache_p) = cache;
+
+ arm11->core_cache = cache;
+// armv7m->process_context = cache;
+
+ size_t i;
+
+ /* Not very elegant assertion */
+ if (ARM11_REGCACHE_COUNT != asizeof(arm11->reg_values) ||
+ ARM11_REGCACHE_COUNT != asizeof(arm11_reg_defs) ||
+ ARM11_REGCACHE_COUNT != ARM11_RC_MAX)
+ {
+ LOG_ERROR("BUG: arm11->reg_values inconsistent (%d " ZU " " ZU " %d)", ARM11_REGCACHE_COUNT, asizeof(arm11->reg_values), asizeof(arm11_reg_defs), ARM11_RC_MAX);
+ exit(-1);
+ }
+
+ for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
+ {
+ reg_t * r = reg_list + i;
+ const arm11_reg_defs_t * rd = arm11_reg_defs + i;
+ arm11_reg_state_t * rs = arm11_reg_states + i;
+
+ r->name = rd->name;
+ r->size = 32;
+ r->value = (uint8_t *)(arm11->reg_values + i);
+ r->dirty = 0;
+ r->valid = 0;
+ r->bitfield_desc = NULL;
+ r->num_bitfields = 0;
+ r->arch_type = arm11_regs_arch_type;
+ r->arch_info = rs;
+
+ rs->def_index = i;
+ rs->target = target;
+ }
-int arm11_handle_vcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+const uint32_t arm11_coproc_instruction_limits[] =
+{
+ 15, /* coprocessor */
+ 7, /* opcode 1 */
+ 15, /* CRn */
+ 15, /* CRm */
+ 7, /* opcode 2 */
+ 0xFFFFFFFF, /* value */
+};
+
+const char arm11_mrc_syntax[] = "Syntax: mrc <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2>. All parameters are numbers only.";
+const char arm11_mcr_syntax[] = "Syntax: mcr <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2> <32bit value to write>. All parameters are numbers only.";
+
+arm11_common_t * arm11_find_target(const char * arg)
+{
+ jtag_tap_t * tap;
+ target_t * t;
+
+ tap = jtag_tap_by_string(arg);
+
+ if (!tap)
+ return 0;
+
+ for (t = all_targets; t; t = t->next)
+ {
+ if (t->tap != tap)
+ continue;
+
+ /* if (t->type == arm11_target) */
+ if (0 == strcmp(target_get_name(t), "arm11"))
+ return t->arch_info;
+ }
+
+ return 0;
+}
+
+int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, bool read)
+{
+ if (argc != (read ? 6 : 7))
+ {
+ LOG_ERROR("Invalid number of arguments. %s", read ? arm11_mrc_syntax : arm11_mcr_syntax);
+ return -1;
+ }
+
+ arm11_common_t * arm11 = arm11_find_target(args[0]);
+
+ if (!arm11)
+ {
+ LOG_ERROR("Parameter 1 is not a the JTAG chain position of an ARM11 device. %s",
+ read ? arm11_mrc_syntax : arm11_mcr_syntax);
+
+ return -1;
+ }
+
+ if (arm11->target->state != TARGET_HALTED)
+ {
+ LOG_WARNING("target was not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ uint32_t values[6];
+
+ for (size_t i = 0; i < (read ? 5 : 6); i++)
+ {
+ values[i] = strtoul(args[i + 1], NULL, 0);
+
+ if (values[i] > arm11_coproc_instruction_limits[i])
+ {
+ LOG_ERROR("Parameter %ld out of bounds (%" PRId32 " max). %s",
+ (long)(i + 2),
+ arm11_coproc_instruction_limits[i],
+ read ? arm11_mrc_syntax : arm11_mcr_syntax);
+ return -1;
+ }
+ }
+
+ uint32_t instr = 0xEE000010 |
+ (values[0] << 8) |
+ (values[1] << 21) |
+ (values[2] << 16) |
+ (values[3] << 0) |
+ (values[4] << 5);
+
+ if (read)
+ instr |= 0x00100000;
+
+ arm11_run_instr_data_prepare(arm11);
+
+ if (read)
+ {
+ uint32_t result;
+ arm11_run_instr_data_from_core_via_r0(arm11, instr, &result);
+
+ LOG_INFO("MRC p%d, %d, R0, c%d, c%d, %d = 0x%08" PRIx32 " (%" PRId32 ")",
+ (int)(values[0]),
+ (int)(values[1]),
+ (int)(values[2]),
+ (int)(values[3]),
+ (int)(values[4]), result, result);
+ }
+ else
+ {
+ arm11_run_instr_data_to_core_via_r0(arm11, instr, values[5]);
+
+ LOG_INFO("MRC p%d, %d, R0 (#0x%08" PRIx32 "), c%d, c%d, %d",
+ (int)(values[0]), (int)(values[1]),
+ values[5],
+ (int)(values[2]), (int)(values[3]), (int)(values[4]));
+ }
+
+ arm11_run_instr_data_finish(arm11);
+
+
+ return ERROR_OK;
+}
+
+int arm11_handle_mrc(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)