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 struct armv4_5_core_reg armv4_5_core_reg_list_arch_info
[] =
121 {0, ARMV4_5_MODE_ANY
, NULL
, NULL
},
122 {1, ARMV4_5_MODE_ANY
, NULL
, NULL
},
123 {2, ARMV4_5_MODE_ANY
, NULL
, NULL
},
124 {3, ARMV4_5_MODE_ANY
, NULL
, NULL
},
125 {4, ARMV4_5_MODE_ANY
, NULL
, NULL
},
126 {5, ARMV4_5_MODE_ANY
, NULL
, NULL
},
127 {6, ARMV4_5_MODE_ANY
, NULL
, NULL
},
128 {7, ARMV4_5_MODE_ANY
, NULL
, NULL
},
129 {8, ARMV4_5_MODE_ANY
, NULL
, NULL
},
130 {9, ARMV4_5_MODE_ANY
, NULL
, NULL
},
131 {10, ARMV4_5_MODE_ANY
, NULL
, NULL
},
132 {11, ARMV4_5_MODE_ANY
, NULL
, NULL
},
133 {12, ARMV4_5_MODE_ANY
, NULL
, NULL
},
134 {13, ARMV4_5_MODE_USR
, NULL
, NULL
},
135 {14, ARMV4_5_MODE_USR
, NULL
, NULL
},
136 {15, ARMV4_5_MODE_ANY
, NULL
, NULL
},
138 {8, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
139 {9, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
140 {10, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
141 {11, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
142 {12, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
143 {13, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
144 {14, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
146 {13, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
147 {14, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
149 {13, ARMV4_5_MODE_SVC
, NULL
, NULL
},
150 {14, ARMV4_5_MODE_SVC
, NULL
, NULL
},
152 {13, ARMV4_5_MODE_ABT
, NULL
, NULL
},
153 {14, ARMV4_5_MODE_ABT
, NULL
, NULL
},
155 {13, ARMV4_5_MODE_UND
, NULL
, NULL
},
156 {14, ARMV4_5_MODE_UND
, NULL
, NULL
},
158 {16, ARMV4_5_MODE_ANY
, NULL
, NULL
},
159 {16, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
160 {16, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
161 {16, ARMV4_5_MODE_SVC
, NULL
, NULL
},
162 {16, ARMV4_5_MODE_ABT
, NULL
, NULL
},
163 {16, ARMV4_5_MODE_UND
, NULL
, NULL
}
166 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
167 int armv4_5_core_reg_map
[7][17] =
170 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
173 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
176 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
179 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
182 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
185 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
188 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
192 uint8_t armv4_5_gdb_dummy_fp_value
[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
194 struct reg armv4_5_gdb_dummy_fp_reg
=
196 .name
= "GDB dummy floating-point register",
197 .value
= armv4_5_gdb_dummy_fp_value
,
204 uint8_t armv4_5_gdb_dummy_fps_value
[] = {0, 0, 0, 0};
206 struct reg armv4_5_gdb_dummy_fps_reg
=
208 .name
= "GDB dummy floating-point status register",
209 .value
= armv4_5_gdb_dummy_fps_value
,
216 int armv4_5_get_core_reg(struct reg
*reg
)
219 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
220 struct target
*target
= armv4_5
->target
;
222 if (target
->state
!= TARGET_HALTED
)
224 LOG_ERROR("Target not halted");
225 return ERROR_TARGET_NOT_HALTED
;
228 /* retval = armv4_5->armv4_5_common->full_context(target); */
229 retval
= armv4_5
->armv4_5_common
->read_core_reg(target
, armv4_5
->num
, armv4_5
->mode
);
234 int armv4_5_set_core_reg(struct reg
*reg
, uint8_t *buf
)
236 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
237 struct target
*target
= armv4_5
->target
;
238 struct armv4_5_common_s
*armv4_5_target
= target_to_armv4_5(target
);
239 uint32_t value
= buf_get_u32(buf
, 0, 32);
241 if (target
->state
!= TARGET_HALTED
)
243 return ERROR_TARGET_NOT_HALTED
;
246 if (reg
== &armv4_5_target
->core_cache
->reg_list
[ARMV4_5_CPSR
])
250 /* T bit should be set */
251 if (armv4_5_target
->core_state
== ARMV4_5_STATE_ARM
)
253 /* change state to Thumb */
254 LOG_DEBUG("changing to Thumb state");
255 armv4_5_target
->core_state
= ARMV4_5_STATE_THUMB
;
260 /* T bit should be cleared */
261 if (armv4_5_target
->core_state
== ARMV4_5_STATE_THUMB
)
263 /* change state to ARM */
264 LOG_DEBUG("changing to ARM state");
265 armv4_5_target
->core_state
= ARMV4_5_STATE_ARM
;
269 if (armv4_5_target
->core_mode
!= (enum armv4_5_mode
)(value
& 0x1f))
271 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings
[armv4_5_mode_to_number(value
& 0x1f)]);
272 armv4_5_target
->core_mode
= value
& 0x1f;
273 armv4_5_target
->write_core_reg(target
, 16, ARMV4_5_MODE_ANY
, value
);
277 buf_set_u32(reg
->value
, 0, 32, value
);
284 static const struct reg_arch_type arm_reg_type
= {
285 .get
= armv4_5_get_core_reg
,
286 .set
= armv4_5_set_core_reg
,
289 int armv4_5_invalidate_core_regs(struct target
*target
)
291 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
294 for (i
= 0; i
< 37; i
++)
296 armv4_5
->core_cache
->reg_list
[i
].valid
= 0;
297 armv4_5
->core_cache
->reg_list
[i
].dirty
= 0;
303 struct reg_cache
* armv4_5_build_reg_cache(struct target
*target
, struct arm
*armv4_5_common
)
306 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
307 struct reg
*reg_list
= malloc(sizeof(struct reg
) * num_regs
);
308 struct armv4_5_core_reg
*arch_info
= malloc(sizeof(struct armv4_5_core_reg
) * num_regs
);
311 cache
->name
= "arm v4/5 registers";
313 cache
->reg_list
= reg_list
;
314 cache
->num_regs
= num_regs
;
316 register_init_dummy(&armv4_5_gdb_dummy_fp_reg
);
317 register_init_dummy(&armv4_5_gdb_dummy_fps_reg
);
319 for (i
= 0; i
< 37; i
++)
321 arch_info
[i
] = armv4_5_core_reg_list_arch_info
[i
];
322 arch_info
[i
].target
= target
;
323 arch_info
[i
].armv4_5_common
= armv4_5_common
;
324 reg_list
[i
].name
= armv4_5_core_reg_list
[i
];
325 reg_list
[i
].size
= 32;
326 reg_list
[i
].value
= calloc(1, 4);
327 reg_list
[i
].dirty
= 0;
328 reg_list
[i
].valid
= 0;
329 reg_list
[i
].type
= &arm_reg_type
;
330 reg_list
[i
].arch_info
= &arch_info
[i
];
336 int armv4_5_arch_state(struct target
*target
)
338 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
340 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
342 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
346 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32
" pc: 0x%8.8" PRIx32
"",
347 armv4_5_state_strings
[armv4_5
->core_state
],
348 Jim_Nvp_value2name_simple(nvp_target_debug_reason
, target
->debug_reason
)->name
,
349 armv4_5_mode_strings
[armv4_5_mode_to_number(armv4_5
->core_mode
)],
350 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
351 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
356 COMMAND_HANDLER(handle_armv4_5_reg_command
)
361 struct target
*target
= get_current_target(cmd_ctx
);
362 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
364 if (!is_arm(armv4_5
))
366 command_print(cmd_ctx
, "current target isn't an ARM");
370 if (target
->state
!= TARGET_HALTED
)
372 command_print(cmd_ctx
, "error: target must be halted for register accesses");
376 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
379 if (!armv4_5
->full_context
) {
380 command_print(cmd_ctx
, "error: target doesn't support %s",
385 for (num
= 0; num
<= 15; num
++)
388 for (mode
= 0; mode
< 6; mode
++)
390 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).valid
)
392 armv4_5
->full_context(target
);
394 output_len
+= snprintf(output
+ output_len
,
396 "%8s: %8.8" PRIx32
" ",
397 ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).name
,
398 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).value
, 0, 32));
400 command_print(cmd_ctx
, "%s", output
);
402 command_print(cmd_ctx
,
403 " 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
"",
404 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
405 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_FIQ
].value
, 0, 32),
406 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_IRQ
].value
, 0, 32),
407 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_SVC
].value
, 0, 32),
408 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_ABT
].value
, 0, 32),
409 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_UND
].value
, 0, 32));
414 COMMAND_HANDLER(handle_armv4_5_core_state_command
)
416 struct target
*target
= get_current_target(cmd_ctx
);
417 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
419 if (!is_arm(armv4_5
))
421 command_print(cmd_ctx
, "current target isn't an ARM");
427 if (strcmp(args
[0], "arm") == 0)
429 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
431 if (strcmp(args
[0], "thumb") == 0)
433 armv4_5
->core_state
= ARMV4_5_STATE_THUMB
;
437 command_print(cmd_ctx
, "core state: %s", armv4_5_state_strings
[armv4_5
->core_state
]);
442 COMMAND_HANDLER(handle_armv4_5_disassemble_command
)
444 int retval
= ERROR_OK
;
445 struct target
*target
= get_current_target(cmd_ctx
);
446 struct arm
*arm
= target
? target_to_arm(target
) : NULL
;
452 command_print(cmd_ctx
, "current target isn't an ARM");
458 if (strcmp(args
[2], "thumb") != 0)
463 COMMAND_PARSE_NUMBER(int, args
[1], count
);
466 COMMAND_PARSE_NUMBER(u32
, args
[0], address
);
467 if (address
& 0x01) {
469 command_print(cmd_ctx
, "Disassemble as Thumb");
477 command_print(cmd_ctx
,
478 "usage: arm disassemble <address> [<count> ['thumb']]");
483 while (count
-- > 0) {
484 struct arm_instruction cur_instruction
;
487 /* Always use Thumb2 disassembly for best handling
488 * of 32-bit BL/BLX, and to work with newer cores
489 * (some ARMv6, all ARMv7) that use Thumb2.
491 retval
= thumb2_opcode(target
, address
,
493 if (retval
!= ERROR_OK
)
498 retval
= target_read_u32(target
, address
, &opcode
);
499 if (retval
!= ERROR_OK
)
501 retval
= arm_evaluate_opcode(opcode
, address
,
502 &cur_instruction
) != ERROR_OK
;
503 if (retval
!= ERROR_OK
)
506 command_print(cmd_ctx
, "%s", cur_instruction
.text
);
507 address
+= cur_instruction
.instruction_size
;
513 int armv4_5_register_commands(struct command_context
*cmd_ctx
)
515 struct command
*armv4_5_cmd
;
517 armv4_5_cmd
= register_command(cmd_ctx
, NULL
, "arm",
519 "generic ARM commands");
521 register_command(cmd_ctx
, armv4_5_cmd
, "reg",
522 handle_armv4_5_reg_command
, COMMAND_EXEC
,
523 "display ARM core registers");
524 register_command(cmd_ctx
, armv4_5_cmd
, "core_state",
525 handle_armv4_5_core_state_command
, COMMAND_EXEC
,
526 "display/change ARM core state <arm | thumb>");
527 register_command(cmd_ctx
, armv4_5_cmd
, "disassemble",
528 handle_armv4_5_disassemble_command
, COMMAND_EXEC
,
529 "disassemble instructions "
530 "<address> [<count> ['thumb']]");
535 int armv4_5_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
537 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
540 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
544 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
546 for (i
= 0; i
< 16; i
++)
548 (*reg_list
)[i
] = &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5
->core_mode
, i
);
551 for (i
= 16; i
< 24; i
++)
553 (*reg_list
)[i
] = &armv4_5_gdb_dummy_fp_reg
;
556 (*reg_list
)[24] = &armv4_5_gdb_dummy_fps_reg
;
557 (*reg_list
)[25] = &armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
];
562 /* wait for execution to complete and check exit point */
563 static int armv4_5_run_algorithm_completion(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
566 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
568 if ((retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
)) != ERROR_OK
)
572 if (target
->state
!= TARGET_HALTED
)
574 if ((retval
= target_halt(target
)) != ERROR_OK
)
576 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
580 return ERROR_TARGET_TIMEOUT
;
583 /* fast exit: ARMv5+ code can use BKPT */
584 if (exit_point
&& buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
,
585 0, 32) != exit_point
)
587 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32
"",
588 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
589 return ERROR_TARGET_TIMEOUT
;
595 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
))
597 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
598 struct armv4_5_algorithm
*armv4_5_algorithm_info
= arch_info
;
599 enum armv4_5_state core_state
= armv4_5
->core_state
;
600 enum armv4_5_mode core_mode
= armv4_5
->core_mode
;
601 uint32_t context
[17];
603 int exit_breakpoint_size
= 0;
605 int retval
= ERROR_OK
;
606 LOG_DEBUG("Running algorithm");
608 if (armv4_5_algorithm_info
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
610 LOG_ERROR("current target isn't an ARMV4/5 target");
611 return ERROR_TARGET_INVALID
;
614 if (target
->state
!= TARGET_HALTED
)
616 LOG_WARNING("target not halted");
617 return ERROR_TARGET_NOT_HALTED
;
620 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
623 /* armv5 and later can terminate with BKPT instruction; less overhead */
624 if (!exit_point
&& armv4_5
->is_armv4
)
626 LOG_ERROR("ARMv4 target needs HW breakpoint location");
630 for (i
= 0; i
<= 16; i
++)
632 if (!ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
)
633 armv4_5
->read_core_reg(target
, i
, armv4_5_algorithm_info
->core_mode
);
634 context
[i
] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
636 cpsr
= buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32);
638 for (i
= 0; i
< num_mem_params
; i
++)
640 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
646 for (i
= 0; i
< num_reg_params
; i
++)
648 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
651 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
652 return ERROR_INVALID_ARGUMENTS
;
655 if (reg
->size
!= reg_params
[i
].size
)
657 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
658 return ERROR_INVALID_ARGUMENTS
;
661 if ((retval
= armv4_5_set_core_reg(reg
, reg_params
[i
].value
)) != ERROR_OK
)
667 armv4_5
->core_state
= armv4_5_algorithm_info
->core_state
;
668 if (armv4_5
->core_state
== ARMV4_5_STATE_ARM
)
669 exit_breakpoint_size
= 4;
670 else if (armv4_5
->core_state
== ARMV4_5_STATE_THUMB
)
671 exit_breakpoint_size
= 2;
674 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
675 return ERROR_INVALID_ARGUMENTS
;
678 if (armv4_5_algorithm_info
->core_mode
!= ARMV4_5_MODE_ANY
)
680 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info
->core_mode
);
681 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 5, armv4_5_algorithm_info
->core_mode
);
682 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
683 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
686 /* terminate using a hardware or (ARMv5+) software breakpoint */
687 if (exit_point
&& (retval
= breakpoint_add(target
, exit_point
,
688 exit_breakpoint_size
, BKPT_HARD
)) != ERROR_OK
)
690 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
691 return ERROR_TARGET_FAILURE
;
694 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
699 retval
= run_it(target
, exit_point
, timeout_ms
, arch_info
);
702 breakpoint_remove(target
, exit_point
);
704 if (retval
!= ERROR_OK
)
707 for (i
= 0; i
< num_mem_params
; i
++)
709 if (mem_params
[i
].direction
!= PARAM_OUT
)
710 if ((retvaltemp
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
716 for (i
= 0; i
< num_reg_params
; i
++)
718 if (reg_params
[i
].direction
!= PARAM_OUT
)
721 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
724 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
725 retval
= ERROR_INVALID_ARGUMENTS
;
729 if (reg
->size
!= reg_params
[i
].size
)
731 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
732 retval
= ERROR_INVALID_ARGUMENTS
;
736 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
740 for (i
= 0; i
<= 16; i
++)
743 regvalue
= buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
744 if (regvalue
!= context
[i
])
746 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
]);
747 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32, context
[i
]);
748 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
= 1;
749 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).dirty
= 1;
752 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32, cpsr
);
753 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
754 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
756 armv4_5
->core_state
= core_state
;
757 armv4_5
->core_mode
= core_mode
;
762 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
)
764 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
);
768 * Runs ARM code in the target to calculate a CRC32 checksum.
770 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
772 int arm_checksum_memory(struct target
*target
,
773 uint32_t address
, uint32_t count
, uint32_t *checksum
)
775 struct working_area
*crc_algorithm
;
776 struct armv4_5_algorithm armv4_5_info
;
777 struct reg_param reg_params
[2];
781 static const uint32_t arm_crc_code
[] = {
782 0xE1A02000, /* mov r2, r0 */
783 0xE3E00000, /* mov r0, #0xffffffff */
784 0xE1A03001, /* mov r3, r1 */
785 0xE3A04000, /* mov r4, #0 */
786 0xEA00000B, /* b ncomp */
788 0xE7D21004, /* ldrb r1, [r2, r4] */
789 0xE59F7030, /* ldr r7, CRC32XOR */
790 0xE0200C01, /* eor r0, r0, r1, asl 24 */
791 0xE3A05000, /* mov r5, #0 */
793 0xE3500000, /* cmp r0, #0 */
794 0xE1A06080, /* mov r6, r0, asl #1 */
795 0xE2855001, /* add r5, r5, #1 */
796 0xE1A00006, /* mov r0, r6 */
797 0xB0260007, /* eorlt r0, r6, r7 */
798 0xE3550008, /* cmp r5, #8 */
799 0x1AFFFFF8, /* bne loop */
800 0xE2844001, /* add r4, r4, #1 */
802 0xE1540003, /* cmp r4, r3 */
803 0x1AFFFFF1, /* bne nbyte */
805 0xEAFFFFFE, /* b end */
807 0x04C11DB7 /* .word 0x04C11DB7 */
810 retval
= target_alloc_working_area(target
,
811 sizeof(arm_crc_code
), &crc_algorithm
);
812 if (retval
!= ERROR_OK
)
815 /* convert code into a buffer in target endianness */
816 for (i
= 0; i
< ARRAY_SIZE(arm_crc_code
); i
++) {
817 retval
= target_write_u32(target
,
818 crc_algorithm
->address
+ i
* sizeof(uint32_t),
820 if (retval
!= ERROR_OK
)
824 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
825 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
826 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
828 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
829 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
831 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
832 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
834 /* 20 second timeout/megabyte */
835 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
837 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
838 crc_algorithm
->address
,
839 crc_algorithm
->address
+ sizeof(arm_crc_code
) - 8,
840 timeout
, &armv4_5_info
);
841 if (retval
!= ERROR_OK
) {
842 LOG_ERROR("error executing ARM crc algorithm");
843 destroy_reg_param(®_params
[0]);
844 destroy_reg_param(®_params
[1]);
845 target_free_working_area(target
, crc_algorithm
);
849 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
851 destroy_reg_param(®_params
[0]);
852 destroy_reg_param(®_params
[1]);
854 target_free_working_area(target
, crc_algorithm
);
860 * Runs ARM code in the target to check whether a memory block holds
861 * all ones. NOR flash which has been erased, and thus may be written,
864 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
866 int arm_blank_check_memory(struct target
*target
,
867 uint32_t address
, uint32_t count
, uint32_t *blank
)
869 struct working_area
*check_algorithm
;
870 struct reg_param reg_params
[3];
871 struct armv4_5_algorithm armv4_5_info
;
875 static const uint32_t check_code
[] = {
877 0xe4d03001, /* ldrb r3, [r0], #1 */
878 0xe0022003, /* and r2, r2, r3 */
879 0xe2511001, /* subs r1, r1, #1 */
880 0x1afffffb, /* bne loop */
882 0xeafffffe /* b end */
885 /* make sure we have a working area */
886 retval
= target_alloc_working_area(target
,
887 sizeof(check_code
), &check_algorithm
);
888 if (retval
!= ERROR_OK
)
891 /* convert code into a buffer in target endianness */
892 for (i
= 0; i
< ARRAY_SIZE(check_code
); i
++) {
893 retval
= target_write_u32(target
,
894 check_algorithm
->address
895 + i
* sizeof(uint32_t),
897 if (retval
!= ERROR_OK
)
901 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
902 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
903 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
905 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
906 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
908 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
909 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
911 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
912 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
914 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
915 check_algorithm
->address
,
916 check_algorithm
->address
+ sizeof(check_code
) - 4,
917 10000, &armv4_5_info
);
918 if (retval
!= ERROR_OK
) {
919 destroy_reg_param(®_params
[0]);
920 destroy_reg_param(®_params
[1]);
921 destroy_reg_param(®_params
[2]);
922 target_free_working_area(target
, check_algorithm
);
926 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
928 destroy_reg_param(®_params
[0]);
929 destroy_reg_param(®_params
[1]);
930 destroy_reg_param(®_params
[2]);
932 target_free_working_area(target
, check_algorithm
);
937 int armv4_5_init_arch_info(struct target
*target
, struct arm
*armv4_5
)
939 target
->arch_info
= armv4_5
;
941 armv4_5
->common_magic
= ARMV4_5_COMMON_MAGIC
;
942 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
943 armv4_5
->core_mode
= ARMV4_5_MODE_USR
;