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 ***************************************************************************/
31 #include "arm_disassembler.h"
32 #include "binarybuffer.h"
35 char* armv4_5_core_reg_list
[] =
37 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
39 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
49 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
52 char * armv4_5_mode_strings_list
[] =
54 "Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
57 /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
58 char** armv4_5_mode_strings
= armv4_5_mode_strings_list
+ 1;
60 char* armv4_5_state_strings
[] =
62 "ARM", "Thumb", "Jazelle"
65 int armv4_5_core_reg_arch_type
= -1;
67 struct armv4_5_core_reg armv4_5_core_reg_list_arch_info
[] =
69 {0, ARMV4_5_MODE_ANY
, NULL
, NULL
},
70 {1, ARMV4_5_MODE_ANY
, NULL
, NULL
},
71 {2, ARMV4_5_MODE_ANY
, NULL
, NULL
},
72 {3, ARMV4_5_MODE_ANY
, NULL
, NULL
},
73 {4, ARMV4_5_MODE_ANY
, NULL
, NULL
},
74 {5, ARMV4_5_MODE_ANY
, NULL
, NULL
},
75 {6, ARMV4_5_MODE_ANY
, NULL
, NULL
},
76 {7, ARMV4_5_MODE_ANY
, NULL
, NULL
},
77 {8, ARMV4_5_MODE_ANY
, NULL
, NULL
},
78 {9, ARMV4_5_MODE_ANY
, NULL
, NULL
},
79 {10, ARMV4_5_MODE_ANY
, NULL
, NULL
},
80 {11, ARMV4_5_MODE_ANY
, NULL
, NULL
},
81 {12, ARMV4_5_MODE_ANY
, NULL
, NULL
},
82 {13, ARMV4_5_MODE_USR
, NULL
, NULL
},
83 {14, ARMV4_5_MODE_USR
, NULL
, NULL
},
84 {15, ARMV4_5_MODE_ANY
, NULL
, NULL
},
86 {8, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
87 {9, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
88 {10, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
89 {11, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
90 {12, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
91 {13, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
92 {14, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
94 {13, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
95 {14, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
97 {13, ARMV4_5_MODE_SVC
, NULL
, NULL
},
98 {14, ARMV4_5_MODE_SVC
, NULL
, NULL
},
100 {13, ARMV4_5_MODE_ABT
, NULL
, NULL
},
101 {14, ARMV4_5_MODE_ABT
, NULL
, NULL
},
103 {13, ARMV4_5_MODE_UND
, NULL
, NULL
},
104 {14, ARMV4_5_MODE_UND
, NULL
, NULL
},
106 {16, ARMV4_5_MODE_ANY
, NULL
, NULL
},
107 {16, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
108 {16, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
109 {16, ARMV4_5_MODE_SVC
, NULL
, NULL
},
110 {16, ARMV4_5_MODE_ABT
, NULL
, NULL
},
111 {16, ARMV4_5_MODE_UND
, NULL
, NULL
}
114 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
115 int armv4_5_core_reg_map
[7][17] =
118 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
121 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
124 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
127 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
130 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
133 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
136 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
140 uint8_t armv4_5_gdb_dummy_fp_value
[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
142 struct reg armv4_5_gdb_dummy_fp_reg
=
144 .name
= "GDB dummy floating-point register",
145 .value
= armv4_5_gdb_dummy_fp_value
,
153 uint8_t armv4_5_gdb_dummy_fps_value
[] = {0, 0, 0, 0};
155 struct reg armv4_5_gdb_dummy_fps_reg
=
157 .name
= "GDB dummy floating-point status register",
158 .value
= armv4_5_gdb_dummy_fps_value
,
166 int armv4_5_get_core_reg(struct reg
*reg
)
169 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
170 struct target
*target
= armv4_5
->target
;
172 if (target
->state
!= TARGET_HALTED
)
174 LOG_ERROR("Target not halted");
175 return ERROR_TARGET_NOT_HALTED
;
178 /* retval = armv4_5->armv4_5_common->full_context(target); */
179 retval
= armv4_5
->armv4_5_common
->read_core_reg(target
, armv4_5
->num
, armv4_5
->mode
);
184 int armv4_5_set_core_reg(struct reg
*reg
, uint8_t *buf
)
186 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
187 struct target
*target
= armv4_5
->target
;
188 struct armv4_5_common_s
*armv4_5_target
= target_to_armv4_5(target
);
189 uint32_t value
= buf_get_u32(buf
, 0, 32);
191 if (target
->state
!= TARGET_HALTED
)
193 return ERROR_TARGET_NOT_HALTED
;
196 if (reg
== &armv4_5_target
->core_cache
->reg_list
[ARMV4_5_CPSR
])
200 /* T bit should be set */
201 if (armv4_5_target
->core_state
== ARMV4_5_STATE_ARM
)
203 /* change state to Thumb */
204 LOG_DEBUG("changing to Thumb state");
205 armv4_5_target
->core_state
= ARMV4_5_STATE_THUMB
;
210 /* T bit should be cleared */
211 if (armv4_5_target
->core_state
== ARMV4_5_STATE_THUMB
)
213 /* change state to ARM */
214 LOG_DEBUG("changing to ARM state");
215 armv4_5_target
->core_state
= ARMV4_5_STATE_ARM
;
219 if (armv4_5_target
->core_mode
!= (enum armv4_5_mode
)(value
& 0x1f))
221 LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings
[armv4_5_mode_to_number(value
& 0x1f)]);
222 armv4_5_target
->core_mode
= value
& 0x1f;
223 armv4_5_target
->write_core_reg(target
, 16, ARMV4_5_MODE_ANY
, value
);
227 buf_set_u32(reg
->value
, 0, 32, value
);
234 int armv4_5_invalidate_core_regs(struct target
*target
)
236 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
239 for (i
= 0; i
< 37; i
++)
241 armv4_5
->core_cache
->reg_list
[i
].valid
= 0;
242 armv4_5
->core_cache
->reg_list
[i
].dirty
= 0;
248 struct reg_cache
* armv4_5_build_reg_cache(struct target
*target
, struct arm
*armv4_5_common
)
251 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
252 struct reg
*reg_list
= malloc(sizeof(struct reg
) * num_regs
);
253 struct armv4_5_core_reg
*arch_info
= malloc(sizeof(struct armv4_5_core_reg
) * num_regs
);
256 cache
->name
= "arm v4/5 registers";
258 cache
->reg_list
= reg_list
;
259 cache
->num_regs
= num_regs
;
261 if (armv4_5_core_reg_arch_type
== -1)
262 armv4_5_core_reg_arch_type
= register_reg_arch_type(armv4_5_get_core_reg
, armv4_5_set_core_reg
);
264 register_init_dummy(&armv4_5_gdb_dummy_fp_reg
);
265 register_init_dummy(&armv4_5_gdb_dummy_fps_reg
);
267 for (i
= 0; i
< 37; i
++)
269 arch_info
[i
] = armv4_5_core_reg_list_arch_info
[i
];
270 arch_info
[i
].target
= target
;
271 arch_info
[i
].armv4_5_common
= armv4_5_common
;
272 reg_list
[i
].name
= armv4_5_core_reg_list
[i
];
273 reg_list
[i
].size
= 32;
274 reg_list
[i
].value
= calloc(1, 4);
275 reg_list
[i
].dirty
= 0;
276 reg_list
[i
].valid
= 0;
277 reg_list
[i
].arch_type
= armv4_5_core_reg_arch_type
;
278 reg_list
[i
].arch_info
= &arch_info
[i
];
284 int armv4_5_arch_state(struct target
*target
)
286 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
288 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
290 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
294 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32
" pc: 0x%8.8" PRIx32
"",
295 armv4_5_state_strings
[armv4_5
->core_state
],
296 Jim_Nvp_value2name_simple(nvp_target_debug_reason
, target
->debug_reason
)->name
,
297 armv4_5_mode_strings
[armv4_5_mode_to_number(armv4_5
->core_mode
)],
298 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
299 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
304 COMMAND_HANDLER(handle_armv4_5_reg_command
)
309 struct target
*target
= get_current_target(cmd_ctx
);
310 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
312 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
314 command_print(cmd_ctx
, "current target isn't an ARMV4/5 target");
318 if (target
->state
!= TARGET_HALTED
)
320 command_print(cmd_ctx
, "error: target must be halted for register accesses");
324 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
327 for (num
= 0; num
<= 15; num
++)
330 for (mode
= 0; mode
< 6; mode
++)
332 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).valid
)
334 armv4_5
->full_context(target
);
336 output_len
+= snprintf(output
+ output_len
,
338 "%8s: %8.8" PRIx32
" ",
339 ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).name
,
340 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).value
, 0, 32));
342 command_print(cmd_ctx
, "%s", output
);
344 command_print(cmd_ctx
,
345 " 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
"",
346 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
347 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_FIQ
].value
, 0, 32),
348 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_IRQ
].value
, 0, 32),
349 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_SVC
].value
, 0, 32),
350 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_ABT
].value
, 0, 32),
351 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_UND
].value
, 0, 32));
356 COMMAND_HANDLER(handle_armv4_5_core_state_command
)
358 struct target
*target
= get_current_target(cmd_ctx
);
359 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
361 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
363 command_print(cmd_ctx
, "current target isn't an ARMV4/5 target");
369 if (strcmp(args
[0], "arm") == 0)
371 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
373 if (strcmp(args
[0], "thumb") == 0)
375 armv4_5
->core_state
= ARMV4_5_STATE_THUMB
;
379 command_print(cmd_ctx
, "core state: %s", armv4_5_state_strings
[armv4_5
->core_state
]);
384 COMMAND_HANDLER(handle_armv4_5_disassemble_command
)
386 int retval
= ERROR_OK
;
387 struct target
*target
= get_current_target(cmd_ctx
);
388 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
392 struct arm_instruction cur_instruction
;
394 uint16_t thumb_opcode
;
397 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
399 command_print(cmd_ctx
, "current target isn't an ARMV4/5 target");
405 if (strcmp(args
[2], "thumb") != 0)
410 COMMAND_PARSE_NUMBER(int, args
[1], count
);
413 COMMAND_PARSE_NUMBER(u32
, args
[0], address
);
414 if (address
& 0x01) {
416 command_print(cmd_ctx
, "Disassemble as Thumb");
424 command_print(cmd_ctx
,
425 "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
429 for (i
= 0; i
< count
; i
++)
433 if ((retval
= target_read_u16(target
, address
, &thumb_opcode
)) != ERROR_OK
)
437 if ((retval
= thumb_evaluate_opcode(thumb_opcode
, address
, &cur_instruction
)) != ERROR_OK
)
443 if ((retval
= target_read_u32(target
, address
, &opcode
)) != ERROR_OK
)
447 if ((retval
= arm_evaluate_opcode(opcode
, address
, &cur_instruction
)) != ERROR_OK
)
452 command_print(cmd_ctx
, "%s", cur_instruction
.text
);
453 address
+= (thumb
) ? 2 : 4;
459 int armv4_5_register_commands(struct command_context
*cmd_ctx
)
461 struct command
*armv4_5_cmd
;
463 armv4_5_cmd
= register_command(cmd_ctx
, NULL
, "armv4_5",
465 "armv4/5 specific commands");
467 register_command(cmd_ctx
, armv4_5_cmd
, "reg",
468 handle_armv4_5_reg_command
, COMMAND_EXEC
,
469 "display ARM core registers");
470 register_command(cmd_ctx
, armv4_5_cmd
, "core_state",
471 handle_armv4_5_core_state_command
, COMMAND_EXEC
,
472 "display/change ARM core state <arm | thumb>");
473 register_command(cmd_ctx
, armv4_5_cmd
, "disassemble",
474 handle_armv4_5_disassemble_command
, COMMAND_EXEC
,
475 "disassemble instructions <address> [<count> ['thumb']]");
480 int armv4_5_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
482 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
485 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
489 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
491 for (i
= 0; i
< 16; i
++)
493 (*reg_list
)[i
] = &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5
->core_mode
, i
);
496 for (i
= 16; i
< 24; i
++)
498 (*reg_list
)[i
] = &armv4_5_gdb_dummy_fp_reg
;
501 (*reg_list
)[24] = &armv4_5_gdb_dummy_fps_reg
;
502 (*reg_list
)[25] = &armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
];
507 /* wait for execution to complete and check exit point */
508 static int armv4_5_run_algorithm_completion(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
511 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
513 if ((retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
)) != ERROR_OK
)
517 if (target
->state
!= TARGET_HALTED
)
519 if ((retval
= target_halt(target
)) != ERROR_OK
)
521 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
525 return ERROR_TARGET_TIMEOUT
;
528 /* fast exit: ARMv5+ code can use BKPT */
529 if (exit_point
&& buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
,
530 0, 32) != exit_point
)
532 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32
"",
533 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
534 return ERROR_TARGET_TIMEOUT
;
540 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
))
542 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
543 struct armv4_5_algorithm
*armv4_5_algorithm_info
= arch_info
;
544 enum armv4_5_state core_state
= armv4_5
->core_state
;
545 enum armv4_5_mode core_mode
= armv4_5
->core_mode
;
546 uint32_t context
[17];
548 int exit_breakpoint_size
= 0;
550 int retval
= ERROR_OK
;
551 LOG_DEBUG("Running algorithm");
553 if (armv4_5_algorithm_info
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
555 LOG_ERROR("current target isn't an ARMV4/5 target");
556 return ERROR_TARGET_INVALID
;
559 if (target
->state
!= TARGET_HALTED
)
561 LOG_WARNING("target not halted");
562 return ERROR_TARGET_NOT_HALTED
;
565 if (armv4_5_mode_to_number(armv4_5
->core_mode
)==-1)
568 /* armv5 and later can terminate with BKPT instruction; less overhead */
569 if (!exit_point
&& armv4_5
->is_armv4
)
571 LOG_ERROR("ARMv4 target needs HW breakpoint location");
575 for (i
= 0; i
<= 16; i
++)
577 if (!ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
)
578 armv4_5
->read_core_reg(target
, i
, armv4_5_algorithm_info
->core_mode
);
579 context
[i
] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
581 cpsr
= buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32);
583 for (i
= 0; i
< num_mem_params
; i
++)
585 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
591 for (i
= 0; i
< num_reg_params
; i
++)
593 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
596 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
600 if (reg
->size
!= reg_params
[i
].size
)
602 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
606 if ((retval
= armv4_5_set_core_reg(reg
, reg_params
[i
].value
)) != ERROR_OK
)
612 armv4_5
->core_state
= armv4_5_algorithm_info
->core_state
;
613 if (armv4_5
->core_state
== ARMV4_5_STATE_ARM
)
614 exit_breakpoint_size
= 4;
615 else if (armv4_5
->core_state
== ARMV4_5_STATE_THUMB
)
616 exit_breakpoint_size
= 2;
619 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
623 if (armv4_5_algorithm_info
->core_mode
!= ARMV4_5_MODE_ANY
)
625 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info
->core_mode
);
626 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 5, armv4_5_algorithm_info
->core_mode
);
627 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
628 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
631 /* terminate using a hardware or (ARMv5+) software breakpoint */
632 if (exit_point
&& (retval
= breakpoint_add(target
, exit_point
,
633 exit_breakpoint_size
, BKPT_HARD
)) != ERROR_OK
)
635 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
636 return ERROR_TARGET_FAILURE
;
639 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
644 retval
= run_it(target
, exit_point
, timeout_ms
, arch_info
);
647 breakpoint_remove(target
, exit_point
);
649 if (retval
!= ERROR_OK
)
652 for (i
= 0; i
< num_mem_params
; i
++)
654 if (mem_params
[i
].direction
!= PARAM_OUT
)
655 if ((retvaltemp
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
661 for (i
= 0; i
< num_reg_params
; i
++)
663 if (reg_params
[i
].direction
!= PARAM_OUT
)
666 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
669 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
673 if (reg
->size
!= reg_params
[i
].size
)
675 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
679 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
683 for (i
= 0; i
<= 16; i
++)
686 regvalue
= buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
687 if (regvalue
!= context
[i
])
689 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
]);
690 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32, context
[i
]);
691 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
= 1;
692 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).dirty
= 1;
695 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32, cpsr
);
696 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
697 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
699 armv4_5
->core_state
= core_state
;
700 armv4_5
->core_mode
= core_mode
;
705 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
)
707 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
);
711 * Runs ARM code in the target to calculate a CRC32 checksum.
713 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
715 int arm_checksum_memory(struct target
*target
,
716 uint32_t address
, uint32_t count
, uint32_t *checksum
)
718 struct working_area
*crc_algorithm
;
719 struct armv4_5_algorithm armv4_5_info
;
720 struct reg_param reg_params
[2];
724 static const uint32_t arm_crc_code
[] = {
725 0xE1A02000, /* mov r2, r0 */
726 0xE3E00000, /* mov r0, #0xffffffff */
727 0xE1A03001, /* mov r3, r1 */
728 0xE3A04000, /* mov r4, #0 */
729 0xEA00000B, /* b ncomp */
731 0xE7D21004, /* ldrb r1, [r2, r4] */
732 0xE59F7030, /* ldr r7, CRC32XOR */
733 0xE0200C01, /* eor r0, r0, r1, asl 24 */
734 0xE3A05000, /* mov r5, #0 */
736 0xE3500000, /* cmp r0, #0 */
737 0xE1A06080, /* mov r6, r0, asl #1 */
738 0xE2855001, /* add r5, r5, #1 */
739 0xE1A00006, /* mov r0, r6 */
740 0xB0260007, /* eorlt r0, r6, r7 */
741 0xE3550008, /* cmp r5, #8 */
742 0x1AFFFFF8, /* bne loop */
743 0xE2844001, /* add r4, r4, #1 */
745 0xE1540003, /* cmp r4, r3 */
746 0x1AFFFFF1, /* bne nbyte */
748 0xEAFFFFFE, /* b end */
750 0x04C11DB7 /* .word 0x04C11DB7 */
753 retval
= target_alloc_working_area(target
,
754 sizeof(arm_crc_code
), &crc_algorithm
);
755 if (retval
!= ERROR_OK
)
758 /* convert code into a buffer in target endianness */
759 for (i
= 0; i
< DIM(arm_crc_code
); i
++) {
760 retval
= target_write_u32(target
,
761 crc_algorithm
->address
+ i
* sizeof(uint32_t),
763 if (retval
!= ERROR_OK
)
767 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
768 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
769 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
771 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
772 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
774 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
775 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
777 /* 20 second timeout/megabyte */
778 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
780 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
781 crc_algorithm
->address
,
782 crc_algorithm
->address
+ sizeof(arm_crc_code
) - 8,
783 timeout
, &armv4_5_info
);
784 if (retval
!= ERROR_OK
) {
785 LOG_ERROR("error executing ARM crc algorithm");
786 destroy_reg_param(®_params
[0]);
787 destroy_reg_param(®_params
[1]);
788 target_free_working_area(target
, crc_algorithm
);
792 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
794 destroy_reg_param(®_params
[0]);
795 destroy_reg_param(®_params
[1]);
797 target_free_working_area(target
, crc_algorithm
);
803 * Runs ARM code in the target to check whether a memory block holds
804 * all ones. NOR flash which has been erased, and thus may be written,
807 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
809 int arm_blank_check_memory(struct target
*target
,
810 uint32_t address
, uint32_t count
, uint32_t *blank
)
812 struct working_area
*check_algorithm
;
813 struct reg_param reg_params
[3];
814 struct armv4_5_algorithm armv4_5_info
;
818 static const uint32_t check_code
[] = {
820 0xe4d03001, /* ldrb r3, [r0], #1 */
821 0xe0022003, /* and r2, r2, r3 */
822 0xe2511001, /* subs r1, r1, #1 */
823 0x1afffffb, /* bne loop */
825 0xeafffffe /* b end */
828 /* make sure we have a working area */
829 retval
= target_alloc_working_area(target
,
830 sizeof(check_code
), &check_algorithm
);
831 if (retval
!= ERROR_OK
)
834 /* convert code into a buffer in target endianness */
835 for (i
= 0; i
< DIM(check_code
); i
++) {
836 retval
= target_write_u32(target
,
837 check_algorithm
->address
838 + i
* sizeof(uint32_t),
840 if (retval
!= ERROR_OK
)
844 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
845 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
846 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
848 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
849 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
851 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
852 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
854 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
855 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
857 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
858 check_algorithm
->address
,
859 check_algorithm
->address
+ sizeof(check_code
) - 4,
860 10000, &armv4_5_info
);
861 if (retval
!= ERROR_OK
) {
862 destroy_reg_param(®_params
[0]);
863 destroy_reg_param(®_params
[1]);
864 destroy_reg_param(®_params
[2]);
865 target_free_working_area(target
, check_algorithm
);
869 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
871 destroy_reg_param(®_params
[0]);
872 destroy_reg_param(®_params
[1]);
873 destroy_reg_param(®_params
[2]);
875 target_free_working_area(target
, check_algorithm
);
880 int armv4_5_init_arch_info(struct target
*target
, struct arm
*armv4_5
)
882 target
->arch_info
= armv4_5
;
884 armv4_5
->common_magic
= ARMV4_5_COMMON_MAGIC
;
885 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
886 armv4_5
->core_mode
= ARMV4_5_MODE_USR
;
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)