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 (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
368 command_print(cmd_ctx
, "current target isn't an ARMV4/5 target");
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 for (num
= 0; num
<= 15; num
++)
384 for (mode
= 0; mode
< 6; mode
++)
386 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).valid
)
388 armv4_5
->full_context(target
);
390 output_len
+= snprintf(output
+ output_len
,
392 "%8s: %8.8" PRIx32
" ",
393 ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).name
,
394 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).value
, 0, 32));
396 command_print(cmd_ctx
, "%s", output
);
398 command_print(cmd_ctx
,
399 " 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
"",
400 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
401 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_FIQ
].value
, 0, 32),
402 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_IRQ
].value
, 0, 32),
403 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_SVC
].value
, 0, 32),
404 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_ABT
].value
, 0, 32),
405 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_UND
].value
, 0, 32));
410 COMMAND_HANDLER(handle_armv4_5_core_state_command
)
412 struct target
*target
= get_current_target(cmd_ctx
);
413 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
415 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
417 command_print(cmd_ctx
, "current target isn't an ARMV4/5 target");
423 if (strcmp(args
[0], "arm") == 0)
425 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
427 if (strcmp(args
[0], "thumb") == 0)
429 armv4_5
->core_state
= ARMV4_5_STATE_THUMB
;
433 command_print(cmd_ctx
, "core state: %s", armv4_5_state_strings
[armv4_5
->core_state
]);
438 COMMAND_HANDLER(handle_armv4_5_disassemble_command
)
440 int retval
= ERROR_OK
;
441 struct target
*target
= get_current_target(cmd_ctx
);
442 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
446 struct arm_instruction cur_instruction
;
448 uint16_t thumb_opcode
;
451 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
453 command_print(cmd_ctx
, "current target isn't an ARMV4/5 target");
459 if (strcmp(args
[2], "thumb") != 0)
464 COMMAND_PARSE_NUMBER(int, args
[1], count
);
467 COMMAND_PARSE_NUMBER(u32
, args
[0], address
);
468 if (address
& 0x01) {
470 command_print(cmd_ctx
, "Disassemble as Thumb");
478 command_print(cmd_ctx
,
479 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
483 for (i
= 0; i
< count
; i
++)
487 if ((retval
= target_read_u16(target
, address
, &thumb_opcode
)) != ERROR_OK
)
491 if ((retval
= thumb_evaluate_opcode(thumb_opcode
, address
, &cur_instruction
)) != ERROR_OK
)
497 if ((retval
= target_read_u32(target
, address
, &opcode
)) != ERROR_OK
)
501 if ((retval
= arm_evaluate_opcode(opcode
, address
, &cur_instruction
)) != ERROR_OK
)
506 command_print(cmd_ctx
, "%s", cur_instruction
.text
);
507 address
+= (thumb
) ? 2 : 4;
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
, "armv4_5",
519 "armv4/5 specific 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 <address> [<count> ['thumb']]");
534 int armv4_5_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
536 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
539 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
543 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
545 for (i
= 0; i
< 16; i
++)
547 (*reg_list
)[i
] = &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5
->core_mode
, i
);
550 for (i
= 16; i
< 24; i
++)
552 (*reg_list
)[i
] = &armv4_5_gdb_dummy_fp_reg
;
555 (*reg_list
)[24] = &armv4_5_gdb_dummy_fps_reg
;
556 (*reg_list
)[25] = &armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
];
561 /* wait for execution to complete and check exit point */
562 static int armv4_5_run_algorithm_completion(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
565 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
567 if ((retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
)) != ERROR_OK
)
571 if (target
->state
!= TARGET_HALTED
)
573 if ((retval
= target_halt(target
)) != ERROR_OK
)
575 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
579 return ERROR_TARGET_TIMEOUT
;
582 /* fast exit: ARMv5+ code can use BKPT */
583 if (exit_point
&& buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
,
584 0, 32) != exit_point
)
586 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32
"",
587 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
588 return ERROR_TARGET_TIMEOUT
;
594 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
))
596 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
597 struct armv4_5_algorithm
*armv4_5_algorithm_info
= arch_info
;
598 enum armv4_5_state core_state
= armv4_5
->core_state
;
599 enum armv4_5_mode core_mode
= armv4_5
->core_mode
;
600 uint32_t context
[17];
602 int exit_breakpoint_size
= 0;
604 int retval
= ERROR_OK
;
605 LOG_DEBUG("Running algorithm");
607 if (armv4_5_algorithm_info
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
609 LOG_ERROR("current target isn't an ARMV4/5 target");
610 return ERROR_TARGET_INVALID
;
613 if (target
->state
!= TARGET_HALTED
)
615 LOG_WARNING("target not halted");
616 return ERROR_TARGET_NOT_HALTED
;
619 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
622 /* armv5 and later can terminate with BKPT instruction; less overhead */
623 if (!exit_point
&& armv4_5
->is_armv4
)
625 LOG_ERROR("ARMv4 target needs HW breakpoint location");
629 for (i
= 0; i
<= 16; i
++)
631 if (!ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
)
632 armv4_5
->read_core_reg(target
, i
, armv4_5_algorithm_info
->core_mode
);
633 context
[i
] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
635 cpsr
= buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32);
637 for (i
= 0; i
< num_mem_params
; i
++)
639 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
645 for (i
= 0; i
< num_reg_params
; i
++)
647 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
650 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
654 if (reg
->size
!= reg_params
[i
].size
)
656 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
660 if ((retval
= armv4_5_set_core_reg(reg
, reg_params
[i
].value
)) != ERROR_OK
)
666 armv4_5
->core_state
= armv4_5_algorithm_info
->core_state
;
667 if (armv4_5
->core_state
== ARMV4_5_STATE_ARM
)
668 exit_breakpoint_size
= 4;
669 else if (armv4_5
->core_state
== ARMV4_5_STATE_THUMB
)
670 exit_breakpoint_size
= 2;
673 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
677 if (armv4_5_algorithm_info
->core_mode
!= ARMV4_5_MODE_ANY
)
679 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info
->core_mode
);
680 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 5, armv4_5_algorithm_info
->core_mode
);
681 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
682 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
685 /* terminate using a hardware or (ARMv5+) software breakpoint */
686 if (exit_point
&& (retval
= breakpoint_add(target
, exit_point
,
687 exit_breakpoint_size
, BKPT_HARD
)) != ERROR_OK
)
689 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
690 return ERROR_TARGET_FAILURE
;
693 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
698 retval
= run_it(target
, exit_point
, timeout_ms
, arch_info
);
701 breakpoint_remove(target
, exit_point
);
703 if (retval
!= ERROR_OK
)
706 for (i
= 0; i
< num_mem_params
; i
++)
708 if (mem_params
[i
].direction
!= PARAM_OUT
)
709 if ((retvaltemp
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
715 for (i
= 0; i
< num_reg_params
; i
++)
717 if (reg_params
[i
].direction
!= PARAM_OUT
)
720 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
723 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
727 if (reg
->size
!= reg_params
[i
].size
)
729 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
733 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
737 for (i
= 0; i
<= 16; i
++)
740 regvalue
= buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
741 if (regvalue
!= context
[i
])
743 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
]);
744 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32, context
[i
]);
745 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
= 1;
746 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).dirty
= 1;
749 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32, cpsr
);
750 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
751 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
753 armv4_5
->core_state
= core_state
;
754 armv4_5
->core_mode
= core_mode
;
759 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
)
761 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
);
765 * Runs ARM code in the target to calculate a CRC32 checksum.
767 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
769 int arm_checksum_memory(struct target
*target
,
770 uint32_t address
, uint32_t count
, uint32_t *checksum
)
772 struct working_area
*crc_algorithm
;
773 struct armv4_5_algorithm armv4_5_info
;
774 struct reg_param reg_params
[2];
778 static const uint32_t arm_crc_code
[] = {
779 0xE1A02000, /* mov r2, r0 */
780 0xE3E00000, /* mov r0, #0xffffffff */
781 0xE1A03001, /* mov r3, r1 */
782 0xE3A04000, /* mov r4, #0 */
783 0xEA00000B, /* b ncomp */
785 0xE7D21004, /* ldrb r1, [r2, r4] */
786 0xE59F7030, /* ldr r7, CRC32XOR */
787 0xE0200C01, /* eor r0, r0, r1, asl 24 */
788 0xE3A05000, /* mov r5, #0 */
790 0xE3500000, /* cmp r0, #0 */
791 0xE1A06080, /* mov r6, r0, asl #1 */
792 0xE2855001, /* add r5, r5, #1 */
793 0xE1A00006, /* mov r0, r6 */
794 0xB0260007, /* eorlt r0, r6, r7 */
795 0xE3550008, /* cmp r5, #8 */
796 0x1AFFFFF8, /* bne loop */
797 0xE2844001, /* add r4, r4, #1 */
799 0xE1540003, /* cmp r4, r3 */
800 0x1AFFFFF1, /* bne nbyte */
802 0xEAFFFFFE, /* b end */
804 0x04C11DB7 /* .word 0x04C11DB7 */
807 retval
= target_alloc_working_area(target
,
808 sizeof(arm_crc_code
), &crc_algorithm
);
809 if (retval
!= ERROR_OK
)
812 /* convert code into a buffer in target endianness */
813 for (i
= 0; i
< ARRAY_SIZE(arm_crc_code
); i
++) {
814 retval
= target_write_u32(target
,
815 crc_algorithm
->address
+ i
* sizeof(uint32_t),
817 if (retval
!= ERROR_OK
)
821 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
822 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
823 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
825 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
826 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
828 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
829 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
831 /* 20 second timeout/megabyte */
832 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
834 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
835 crc_algorithm
->address
,
836 crc_algorithm
->address
+ sizeof(arm_crc_code
) - 8,
837 timeout
, &armv4_5_info
);
838 if (retval
!= ERROR_OK
) {
839 LOG_ERROR("error executing ARM crc algorithm");
840 destroy_reg_param(®_params
[0]);
841 destroy_reg_param(®_params
[1]);
842 target_free_working_area(target
, crc_algorithm
);
846 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
848 destroy_reg_param(®_params
[0]);
849 destroy_reg_param(®_params
[1]);
851 target_free_working_area(target
, crc_algorithm
);
857 * Runs ARM code in the target to check whether a memory block holds
858 * all ones. NOR flash which has been erased, and thus may be written,
861 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
863 int arm_blank_check_memory(struct target
*target
,
864 uint32_t address
, uint32_t count
, uint32_t *blank
)
866 struct working_area
*check_algorithm
;
867 struct reg_param reg_params
[3];
868 struct armv4_5_algorithm armv4_5_info
;
872 static const uint32_t check_code
[] = {
874 0xe4d03001, /* ldrb r3, [r0], #1 */
875 0xe0022003, /* and r2, r2, r3 */
876 0xe2511001, /* subs r1, r1, #1 */
877 0x1afffffb, /* bne loop */
879 0xeafffffe /* b end */
882 /* make sure we have a working area */
883 retval
= target_alloc_working_area(target
,
884 sizeof(check_code
), &check_algorithm
);
885 if (retval
!= ERROR_OK
)
888 /* convert code into a buffer in target endianness */
889 for (i
= 0; i
< ARRAY_SIZE(check_code
); i
++) {
890 retval
= target_write_u32(target
,
891 check_algorithm
->address
892 + i
* sizeof(uint32_t),
894 if (retval
!= ERROR_OK
)
898 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
899 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
900 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
902 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
903 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
905 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
906 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
908 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
909 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
911 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
912 check_algorithm
->address
,
913 check_algorithm
->address
+ sizeof(check_code
) - 4,
914 10000, &armv4_5_info
);
915 if (retval
!= ERROR_OK
) {
916 destroy_reg_param(®_params
[0]);
917 destroy_reg_param(®_params
[1]);
918 destroy_reg_param(®_params
[2]);
919 target_free_working_area(target
, check_algorithm
);
923 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
925 destroy_reg_param(®_params
[0]);
926 destroy_reg_param(®_params
[1]);
927 destroy_reg_param(®_params
[2]);
929 target_free_working_area(target
, check_algorithm
);
934 int armv4_5_init_arch_info(struct target
*target
, struct arm
*armv4_5
)
936 target
->arch_info
= armv4_5
;
938 armv4_5
->common_magic
= ARMV4_5_COMMON_MAGIC
;
939 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
940 armv4_5
->core_mode
= ARMV4_5_MODE_USR
;