1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * Copyright (C) 2008 by Oyvind Harboe *
9 * oyvind.harboe@zylin.com *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
32 #include "breakpoints.h"
33 #include "arm_disassembler.h"
34 #include "binarybuffer.h"
35 #include "algorithm.h"
39 char* armv4_5_core_reg_list
[] =
41 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
43 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
53 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
56 static const char *armv4_5_mode_strings_list
[] =
58 "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
61 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
62 const char **armv4_5_mode_strings
= armv4_5_mode_strings_list
+ 1;
64 /** Map PSR mode bits to linear number */
65 int armv4_5_mode_to_number(enum armv4_5_mode mode
)
68 case ARMV4_5_MODE_ANY
:
69 /* map MODE_ANY to user mode */
70 case ARMV4_5_MODE_USR
:
72 case ARMV4_5_MODE_FIQ
:
74 case ARMV4_5_MODE_IRQ
:
76 case ARMV4_5_MODE_SVC
:
78 case ARMV4_5_MODE_ABT
:
80 case ARMV4_5_MODE_UND
:
82 case ARMV4_5_MODE_SYS
:
85 LOG_ERROR("invalid mode value encountered %d", mode
);
90 /** Map linear number to PSR mode bits. */
91 enum armv4_5_mode
armv4_5_number_to_mode(int number
)
95 return ARMV4_5_MODE_USR
;
97 return ARMV4_5_MODE_FIQ
;
99 return ARMV4_5_MODE_IRQ
;
101 return ARMV4_5_MODE_SVC
;
103 return ARMV4_5_MODE_ABT
;
105 return ARMV4_5_MODE_UND
;
107 return ARMV4_5_MODE_SYS
;
109 LOG_ERROR("mode index out of bounds %d", number
);
110 return ARMV4_5_MODE_ANY
;
114 char* armv4_5_state_strings
[] =
116 "ARM", "Thumb", "Jazelle"
119 int armv4_5_core_reg_arch_type
= -1;
121 struct armv4_5_core_reg armv4_5_core_reg_list_arch_info
[] =
123 {0, ARMV4_5_MODE_ANY
, NULL
, NULL
},
124 {1, ARMV4_5_MODE_ANY
, NULL
, NULL
},
125 {2, ARMV4_5_MODE_ANY
, NULL
, NULL
},
126 {3, ARMV4_5_MODE_ANY
, NULL
, NULL
},
127 {4, ARMV4_5_MODE_ANY
, NULL
, NULL
},
128 {5, ARMV4_5_MODE_ANY
, NULL
, NULL
},
129 {6, ARMV4_5_MODE_ANY
, NULL
, NULL
},
130 {7, ARMV4_5_MODE_ANY
, NULL
, NULL
},
131 {8, ARMV4_5_MODE_ANY
, NULL
, NULL
},
132 {9, ARMV4_5_MODE_ANY
, NULL
, NULL
},
133 {10, ARMV4_5_MODE_ANY
, NULL
, NULL
},
134 {11, ARMV4_5_MODE_ANY
, NULL
, NULL
},
135 {12, ARMV4_5_MODE_ANY
, NULL
, NULL
},
136 {13, ARMV4_5_MODE_USR
, NULL
, NULL
},
137 {14, ARMV4_5_MODE_USR
, NULL
, NULL
},
138 {15, ARMV4_5_MODE_ANY
, NULL
, NULL
},
140 {8, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
141 {9, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
142 {10, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
143 {11, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
144 {12, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
145 {13, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
146 {14, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
148 {13, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
149 {14, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
151 {13, ARMV4_5_MODE_SVC
, NULL
, NULL
},
152 {14, ARMV4_5_MODE_SVC
, NULL
, NULL
},
154 {13, ARMV4_5_MODE_ABT
, NULL
, NULL
},
155 {14, ARMV4_5_MODE_ABT
, NULL
, NULL
},
157 {13, ARMV4_5_MODE_UND
, NULL
, NULL
},
158 {14, ARMV4_5_MODE_UND
, NULL
, NULL
},
160 {16, ARMV4_5_MODE_ANY
, NULL
, NULL
},
161 {16, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
162 {16, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
163 {16, ARMV4_5_MODE_SVC
, NULL
, NULL
},
164 {16, ARMV4_5_MODE_ABT
, NULL
, NULL
},
165 {16, ARMV4_5_MODE_UND
, NULL
, NULL
}
168 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
169 int armv4_5_core_reg_map
[7][17] =
172 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
175 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
178 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
181 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
184 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
187 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
190 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
194 uint8_t armv4_5_gdb_dummy_fp_value
[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
196 struct reg armv4_5_gdb_dummy_fp_reg
=
198 .name
= "GDB dummy floating-point register",
199 .value
= armv4_5_gdb_dummy_fp_value
,
207 uint8_t armv4_5_gdb_dummy_fps_value
[] = {0, 0, 0, 0};
209 struct reg armv4_5_gdb_dummy_fps_reg
=
211 .name
= "GDB dummy floating-point status register",
212 .value
= armv4_5_gdb_dummy_fps_value
,
220 int armv4_5_get_core_reg(struct reg
*reg
)
223 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
224 struct target
*target
= armv4_5
->target
;
226 if (target
->state
!= TARGET_HALTED
)
228 LOG_ERROR("Target not halted");
229 return ERROR_TARGET_NOT_HALTED
;
232 /* retval = armv4_5->armv4_5_common->full_context(target); */
233 retval
= armv4_5
->armv4_5_common
->read_core_reg(target
, armv4_5
->num
, armv4_5
->mode
);
238 int armv4_5_set_core_reg(struct reg
*reg
, uint8_t *buf
)
240 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
241 struct target
*target
= armv4_5
->target
;
242 struct armv4_5_common_s
*armv4_5_target
= target_to_armv4_5(target
);
243 uint32_t value
= buf_get_u32(buf
, 0, 32);
245 if (target
->state
!= TARGET_HALTED
)
247 return ERROR_TARGET_NOT_HALTED
;
250 if (reg
== &armv4_5_target
->core_cache
->reg_list
[ARMV4_5_CPSR
])
254 /* T bit should be set */
255 if (armv4_5_target
->core_state
== ARMV4_5_STATE_ARM
)
257 /* change state to Thumb */
258 LOG_DEBUG("changing to Thumb state");
259 armv4_5_target
->core_state
= ARMV4_5_STATE_THUMB
;
264 /* T bit should be cleared */
265 if (armv4_5_target
->core_state
== ARMV4_5_STATE_THUMB
)
267 /* change state to ARM */
268 LOG_DEBUG("changing to ARM state");
269 armv4_5_target
->core_state
= ARMV4_5_STATE_ARM
;
273 if (armv4_5_target
->core_mode
!= (enum armv4_5_mode
)(value
& 0x1f))
275 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings
[armv4_5_mode_to_number(value
& 0x1f)]);
276 armv4_5_target
->core_mode
= value
& 0x1f;
277 armv4_5_target
->write_core_reg(target
, 16, ARMV4_5_MODE_ANY
, value
);
281 buf_set_u32(reg
->value
, 0, 32, value
);
288 int armv4_5_invalidate_core_regs(struct target
*target
)
290 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
293 for (i
= 0; i
< 37; i
++)
295 armv4_5
->core_cache
->reg_list
[i
].valid
= 0;
296 armv4_5
->core_cache
->reg_list
[i
].dirty
= 0;
302 struct reg_cache
* armv4_5_build_reg_cache(struct target
*target
, struct arm
*armv4_5_common
)
305 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
306 struct reg
*reg_list
= malloc(sizeof(struct reg
) * num_regs
);
307 struct armv4_5_core_reg
*arch_info
= malloc(sizeof(struct armv4_5_core_reg
) * num_regs
);
310 cache
->name
= "arm v4/5 registers";
312 cache
->reg_list
= reg_list
;
313 cache
->num_regs
= num_regs
;
315 if (armv4_5_core_reg_arch_type
== -1)
316 armv4_5_core_reg_arch_type
= register_reg_arch_type(armv4_5_get_core_reg
, armv4_5_set_core_reg
);
318 register_init_dummy(&armv4_5_gdb_dummy_fp_reg
);
319 register_init_dummy(&armv4_5_gdb_dummy_fps_reg
);
321 for (i
= 0; i
< 37; i
++)
323 arch_info
[i
] = armv4_5_core_reg_list_arch_info
[i
];
324 arch_info
[i
].target
= target
;
325 arch_info
[i
].armv4_5_common
= armv4_5_common
;
326 reg_list
[i
].name
= armv4_5_core_reg_list
[i
];
327 reg_list
[i
].size
= 32;
328 reg_list
[i
].value
= calloc(1, 4);
329 reg_list
[i
].dirty
= 0;
330 reg_list
[i
].valid
= 0;
331 reg_list
[i
].arch_type
= armv4_5_core_reg_arch_type
;
332 reg_list
[i
].arch_info
= &arch_info
[i
];
338 int armv4_5_arch_state(struct target
*target
)
340 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
342 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
344 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
348 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32
" pc: 0x%8.8" PRIx32
"",
349 armv4_5_state_strings
[armv4_5
->core_state
],
350 Jim_Nvp_value2name_simple(nvp_target_debug_reason
, target
->debug_reason
)->name
,
351 armv4_5_mode_strings
[armv4_5_mode_to_number(armv4_5
->core_mode
)],
352 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
353 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
358 COMMAND_HANDLER(handle_armv4_5_reg_command
)
363 struct target
*target
= get_current_target(cmd_ctx
);
364 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
366 if (!is_arm(armv4_5
))
368 command_print(cmd_ctx
, "current target isn't an ARM");
372 if (target
->state
!= TARGET_HALTED
)
374 command_print(cmd_ctx
, "error: target must be halted for register accesses");
378 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
381 if (!armv4_5
->full_context
) {
382 command_print(cmd_ctx
, "error: target doesn't support %s",
387 for (num
= 0; num
<= 15; num
++)
390 for (mode
= 0; mode
< 6; mode
++)
392 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).valid
)
394 armv4_5
->full_context(target
);
396 output_len
+= snprintf(output
+ output_len
,
398 "%8s: %8.8" PRIx32
" ",
399 ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).name
,
400 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).value
, 0, 32));
402 command_print(cmd_ctx
, "%s", output
);
404 command_print(cmd_ctx
,
405 " cpsr: %8.8" PRIx32
" spsr_fiq: %8.8" PRIx32
" spsr_irq: %8.8" PRIx32
" spsr_svc: %8.8" PRIx32
" spsr_abt: %8.8" PRIx32
" spsr_und: %8.8" PRIx32
"",
406 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
407 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_FIQ
].value
, 0, 32),
408 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_IRQ
].value
, 0, 32),
409 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_SVC
].value
, 0, 32),
410 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_ABT
].value
, 0, 32),
411 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_UND
].value
, 0, 32));
416 COMMAND_HANDLER(handle_armv4_5_core_state_command
)
418 struct target
*target
= get_current_target(cmd_ctx
);
419 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
421 if (!is_arm(armv4_5
))
423 command_print(cmd_ctx
, "current target isn't an ARM");
429 if (strcmp(args
[0], "arm") == 0)
431 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
433 if (strcmp(args
[0], "thumb") == 0)
435 armv4_5
->core_state
= ARMV4_5_STATE_THUMB
;
439 command_print(cmd_ctx
, "core state: %s", armv4_5_state_strings
[armv4_5
->core_state
]);
444 COMMAND_HANDLER(handle_armv4_5_disassemble_command
)
446 int retval
= ERROR_OK
;
447 struct target
*target
= get_current_target(cmd_ctx
);
448 struct arm
*arm
= target
? target_to_arm(target
) : NULL
;
454 command_print(cmd_ctx
, "current target isn't an ARM");
460 if (strcmp(args
[2], "thumb") != 0)
465 COMMAND_PARSE_NUMBER(int, args
[1], count
);
468 COMMAND_PARSE_NUMBER(u32
, args
[0], address
);
469 if (address
& 0x01) {
471 command_print(cmd_ctx
, "Disassemble as Thumb");
479 command_print(cmd_ctx
,
480 "usage: arm disassemble <address> [<count> ['thumb']]");
485 while (count
-- > 0) {
486 struct arm_instruction cur_instruction
;
489 /* Always use Thumb2 disassembly for best handling
490 * of 32-bit BL/BLX, and to work with newer cores
491 * (some ARMv6, all ARMv7) that use Thumb2.
493 retval
= thumb2_opcode(target
, address
,
495 if (retval
!= ERROR_OK
)
500 retval
= target_read_u32(target
, address
, &opcode
);
501 if (retval
!= ERROR_OK
)
503 retval
= arm_evaluate_opcode(opcode
, address
,
504 &cur_instruction
) != ERROR_OK
;
505 if (retval
!= ERROR_OK
)
508 command_print(cmd_ctx
, "%s", cur_instruction
.text
);
509 address
+= cur_instruction
.instruction_size
;
515 int armv4_5_register_commands(struct command_context
*cmd_ctx
)
517 struct command
*armv4_5_cmd
;
519 armv4_5_cmd
= register_command(cmd_ctx
, NULL
, "arm",
521 "generic ARM commands");
523 register_command(cmd_ctx
, armv4_5_cmd
, "reg",
524 handle_armv4_5_reg_command
, COMMAND_EXEC
,
525 "display ARM core registers");
526 register_command(cmd_ctx
, armv4_5_cmd
, "core_state",
527 handle_armv4_5_core_state_command
, COMMAND_EXEC
,
528 "display/change ARM core state <arm | thumb>");
529 register_command(cmd_ctx
, armv4_5_cmd
, "disassemble",
530 handle_armv4_5_disassemble_command
, COMMAND_EXEC
,
531 "disassemble instructions "
532 "<address> [<count> ['thumb']]");
537 int armv4_5_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
539 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
542 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
546 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
548 for (i
= 0; i
< 16; i
++)
550 (*reg_list
)[i
] = &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5
->core_mode
, i
);
553 for (i
= 16; i
< 24; i
++)
555 (*reg_list
)[i
] = &armv4_5_gdb_dummy_fp_reg
;
558 (*reg_list
)[24] = &armv4_5_gdb_dummy_fps_reg
;
559 (*reg_list
)[25] = &armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
];
564 /* wait for execution to complete and check exit point */
565 static int armv4_5_run_algorithm_completion(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
568 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
570 if ((retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
)) != ERROR_OK
)
574 if (target
->state
!= TARGET_HALTED
)
576 if ((retval
= target_halt(target
)) != ERROR_OK
)
578 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
582 return ERROR_TARGET_TIMEOUT
;
585 /* fast exit: ARMv5+ code can use BKPT */
586 if (exit_point
&& buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
,
587 0, 32) != exit_point
)
589 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32
"",
590 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
591 return ERROR_TARGET_TIMEOUT
;
597 int armv4_5_run_algorithm_inner(struct target
*target
, int num_mem_params
, struct mem_param
*mem_params
, int num_reg_params
, struct reg_param
*reg_params
, uint32_t entry_point
, uint32_t exit_point
, int timeout_ms
, void *arch_info
, int (*run_it
)(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
))
599 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
600 struct armv4_5_algorithm
*armv4_5_algorithm_info
= arch_info
;
601 enum armv4_5_state core_state
= armv4_5
->core_state
;
602 enum armv4_5_mode core_mode
= armv4_5
->core_mode
;
603 uint32_t context
[17];
605 int exit_breakpoint_size
= 0;
607 int retval
= ERROR_OK
;
608 LOG_DEBUG("Running algorithm");
610 if (armv4_5_algorithm_info
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
612 LOG_ERROR("current target isn't an ARMV4/5 target");
613 return ERROR_TARGET_INVALID
;
616 if (target
->state
!= TARGET_HALTED
)
618 LOG_WARNING("target not halted");
619 return ERROR_TARGET_NOT_HALTED
;
622 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
625 /* armv5 and later can terminate with BKPT instruction; less overhead */
626 if (!exit_point
&& armv4_5
->is_armv4
)
628 LOG_ERROR("ARMv4 target needs HW breakpoint location");
632 for (i
= 0; i
<= 16; i
++)
634 if (!ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
)
635 armv4_5
->read_core_reg(target
, i
, armv4_5_algorithm_info
->core_mode
);
636 context
[i
] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
638 cpsr
= buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32);
640 for (i
= 0; i
< num_mem_params
; i
++)
642 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
648 for (i
= 0; i
< num_reg_params
; i
++)
650 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
653 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
654 return ERROR_INVALID_ARGUMENTS
;
657 if (reg
->size
!= reg_params
[i
].size
)
659 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
660 return ERROR_INVALID_ARGUMENTS
;
663 if ((retval
= armv4_5_set_core_reg(reg
, reg_params
[i
].value
)) != ERROR_OK
)
669 armv4_5
->core_state
= armv4_5_algorithm_info
->core_state
;
670 if (armv4_5
->core_state
== ARMV4_5_STATE_ARM
)
671 exit_breakpoint_size
= 4;
672 else if (armv4_5
->core_state
== ARMV4_5_STATE_THUMB
)
673 exit_breakpoint_size
= 2;
676 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
677 return ERROR_INVALID_ARGUMENTS
;
680 if (armv4_5_algorithm_info
->core_mode
!= ARMV4_5_MODE_ANY
)
682 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info
->core_mode
);
683 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 5, armv4_5_algorithm_info
->core_mode
);
684 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
685 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
688 /* terminate using a hardware or (ARMv5+) software breakpoint */
689 if (exit_point
&& (retval
= breakpoint_add(target
, exit_point
,
690 exit_breakpoint_size
, BKPT_HARD
)) != ERROR_OK
)
692 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
693 return ERROR_TARGET_FAILURE
;
696 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
701 retval
= run_it(target
, exit_point
, timeout_ms
, arch_info
);
704 breakpoint_remove(target
, exit_point
);
706 if (retval
!= ERROR_OK
)
709 for (i
= 0; i
< num_mem_params
; i
++)
711 if (mem_params
[i
].direction
!= PARAM_OUT
)
712 if ((retvaltemp
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
718 for (i
= 0; i
< num_reg_params
; i
++)
720 if (reg_params
[i
].direction
!= PARAM_OUT
)
723 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
726 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
727 retval
= ERROR_INVALID_ARGUMENTS
;
731 if (reg
->size
!= reg_params
[i
].size
)
733 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
734 retval
= ERROR_INVALID_ARGUMENTS
;
738 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
742 for (i
= 0; i
<= 16; i
++)
745 regvalue
= buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
746 if (regvalue
!= context
[i
])
748 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
"", ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).name
, context
[i
]);
749 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32, context
[i
]);
750 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
= 1;
751 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).dirty
= 1;
754 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32, cpsr
);
755 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
756 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
758 armv4_5
->core_state
= core_state
;
759 armv4_5
->core_mode
= core_mode
;
764 int armv4_5_run_algorithm(struct target
*target
, int num_mem_params
, struct mem_param
*mem_params
, int num_reg_params
, struct reg_param
*reg_params
, uint32_t entry_point
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
766 return armv4_5_run_algorithm_inner(target
, num_mem_params
, mem_params
, num_reg_params
, reg_params
, entry_point
, exit_point
, timeout_ms
, arch_info
, armv4_5_run_algorithm_completion
);
770 * Runs ARM code in the target to calculate a CRC32 checksum.
772 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
774 int arm_checksum_memory(struct target
*target
,
775 uint32_t address
, uint32_t count
, uint32_t *checksum
)
777 struct working_area
*crc_algorithm
;
778 struct armv4_5_algorithm armv4_5_info
;
779 struct reg_param reg_params
[2];
783 static const uint32_t arm_crc_code
[] = {
784 0xE1A02000, /* mov r2, r0 */
785 0xE3E00000, /* mov r0, #0xffffffff */
786 0xE1A03001, /* mov r3, r1 */
787 0xE3A04000, /* mov r4, #0 */
788 0xEA00000B, /* b ncomp */
790 0xE7D21004, /* ldrb r1, [r2, r4] */
791 0xE59F7030, /* ldr r7, CRC32XOR */
792 0xE0200C01, /* eor r0, r0, r1, asl 24 */
793 0xE3A05000, /* mov r5, #0 */
795 0xE3500000, /* cmp r0, #0 */
796 0xE1A06080, /* mov r6, r0, asl #1 */
797 0xE2855001, /* add r5, r5, #1 */
798 0xE1A00006, /* mov r0, r6 */
799 0xB0260007, /* eorlt r0, r6, r7 */
800 0xE3550008, /* cmp r5, #8 */
801 0x1AFFFFF8, /* bne loop */
802 0xE2844001, /* add r4, r4, #1 */
804 0xE1540003, /* cmp r4, r3 */
805 0x1AFFFFF1, /* bne nbyte */
807 0xEAFFFFFE, /* b end */
809 0x04C11DB7 /* .word 0x04C11DB7 */
812 retval
= target_alloc_working_area(target
,
813 sizeof(arm_crc_code
), &crc_algorithm
);
814 if (retval
!= ERROR_OK
)
817 /* convert code into a buffer in target endianness */
818 for (i
= 0; i
< ARRAY_SIZE(arm_crc_code
); i
++) {
819 retval
= target_write_u32(target
,
820 crc_algorithm
->address
+ i
* sizeof(uint32_t),
822 if (retval
!= ERROR_OK
)
826 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
827 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
828 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
830 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
831 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
833 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
834 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
836 /* 20 second timeout/megabyte */
837 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
839 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
840 crc_algorithm
->address
,
841 crc_algorithm
->address
+ sizeof(arm_crc_code
) - 8,
842 timeout
, &armv4_5_info
);
843 if (retval
!= ERROR_OK
) {
844 LOG_ERROR("error executing ARM crc algorithm");
845 destroy_reg_param(®_params
[0]);
846 destroy_reg_param(®_params
[1]);
847 target_free_working_area(target
, crc_algorithm
);
851 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
853 destroy_reg_param(®_params
[0]);
854 destroy_reg_param(®_params
[1]);
856 target_free_working_area(target
, crc_algorithm
);
862 * Runs ARM code in the target to check whether a memory block holds
863 * all ones. NOR flash which has been erased, and thus may be written,
866 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
868 int arm_blank_check_memory(struct target
*target
,
869 uint32_t address
, uint32_t count
, uint32_t *blank
)
871 struct working_area
*check_algorithm
;
872 struct reg_param reg_params
[3];
873 struct armv4_5_algorithm armv4_5_info
;
877 static const uint32_t check_code
[] = {
879 0xe4d03001, /* ldrb r3, [r0], #1 */
880 0xe0022003, /* and r2, r2, r3 */
881 0xe2511001, /* subs r1, r1, #1 */
882 0x1afffffb, /* bne loop */
884 0xeafffffe /* b end */
887 /* make sure we have a working area */
888 retval
= target_alloc_working_area(target
,
889 sizeof(check_code
), &check_algorithm
);
890 if (retval
!= ERROR_OK
)
893 /* convert code into a buffer in target endianness */
894 for (i
= 0; i
< ARRAY_SIZE(check_code
); i
++) {
895 retval
= target_write_u32(target
,
896 check_algorithm
->address
897 + i
* sizeof(uint32_t),
899 if (retval
!= ERROR_OK
)
903 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
904 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
905 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
907 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
908 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
910 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
911 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
913 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
914 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
916 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
917 check_algorithm
->address
,
918 check_algorithm
->address
+ sizeof(check_code
) - 4,
919 10000, &armv4_5_info
);
920 if (retval
!= ERROR_OK
) {
921 destroy_reg_param(®_params
[0]);
922 destroy_reg_param(®_params
[1]);
923 destroy_reg_param(®_params
[2]);
924 target_free_working_area(target
, check_algorithm
);
928 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
930 destroy_reg_param(®_params
[0]);
931 destroy_reg_param(®_params
[1]);
932 destroy_reg_param(®_params
[2]);
934 target_free_working_area(target
, check_algorithm
);
939 int armv4_5_init_arch_info(struct target
*target
, struct arm
*armv4_5
)
941 target
->arch_info
= armv4_5
;
943 armv4_5
->common_magic
= ARMV4_5_COMMON_MAGIC
;
944 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
945 armv4_5
->core_mode
= ARMV4_5_MODE_USR
;