8e8f4d63db3ac175f8c0a35e491b82513c38e65f
[openocd.git] / src / target / arm9tdmi.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * Copyright (C) 2008 by Hongtao Zheng *
9 * hontor@126.com *
10 * *
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. *
15 * *
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. *
20 * *
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 ***************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "arm9tdmi.h"
31 #include "target_type.h"
32 #include "register.h"
33
34
35 /*
36 * NOTE: this holds code that's used with multiple ARM9 processors:
37 * - ARM9TDMI (ARMv4T) ... in ARM920, ARM922, and ARM940 cores
38 * - ARM9E-S (ARMv5TE) ... in ARM946, ARM966, and ARM968 cores
39 * - ARM9EJS (ARMv5TEJ) ... in ARM926 core
40 *
41 * In short, the file name is a misnomer ... it is NOT specific to
42 * that first generation ARM9 processor, or cores using it.
43 */
44
45 #if 0
46 #define _DEBUG_INSTRUCTION_EXECUTION_
47 #endif
48
49 static const struct arm9tdmi_vector arm9tdmi_vectors[] =
50 {
51 {"reset", ARM9TDMI_RESET_VECTOR},
52 {"undef", ARM9TDMI_UNDEF_VECTOR},
53 {"swi", ARM9TDMI_SWI_VECTOR},
54 {"pabt", ARM9TDMI_PABT_VECTOR},
55 {"dabt", ARM9TDMI_DABT_VECTOR},
56 {"irq", ARM9TDMI_IRQ_VECTOR},
57 {"fiq", ARM9TDMI_FIQ_VECTOR},
58 {0, 0},
59 };
60
61 int arm9tdmi_examine_debug_reason(struct target *target)
62 {
63 int retval = ERROR_OK;
64 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
65
66 /* only check the debug reason if we don't know it already */
67 if ((target->debug_reason != DBG_REASON_DBGRQ)
68 && (target->debug_reason != DBG_REASON_SINGLESTEP))
69 {
70 struct scan_field fields[3];
71 uint8_t databus[4];
72 uint8_t instructionbus[4];
73 uint8_t debug_reason;
74
75 jtag_set_end_state(TAP_DRPAUSE);
76
77 fields[0].tap = arm7_9->jtag_info.tap;
78 fields[0].num_bits = 32;
79 fields[0].out_value = NULL;
80 fields[0].in_value = databus;
81
82 fields[1].tap = arm7_9->jtag_info.tap;
83 fields[1].num_bits = 3;
84 fields[1].out_value = NULL;
85 fields[1].in_value = &debug_reason;
86
87 fields[2].tap = arm7_9->jtag_info.tap;
88 fields[2].num_bits = 32;
89 fields[2].out_value = NULL;
90 fields[2].in_value = instructionbus;
91
92 if ((retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1)) != ERROR_OK)
93 {
94 return retval;
95 }
96 arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
97
98 jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_DRPAUSE));
99 if ((retval = jtag_execute_queue()) != ERROR_OK)
100 {
101 return retval;
102 }
103
104 fields[0].in_value = NULL;
105 fields[0].out_value = databus;
106 fields[1].in_value = NULL;
107 fields[1].out_value = &debug_reason;
108 fields[2].in_value = NULL;
109 fields[2].out_value = instructionbus;
110
111 jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_DRPAUSE));
112
113 if (debug_reason & 0x4)
114 if (debug_reason & 0x2)
115 target->debug_reason = DBG_REASON_WPTANDBKPT;
116 else
117 target->debug_reason = DBG_REASON_WATCHPOINT;
118 else
119 target->debug_reason = DBG_REASON_BREAKPOINT;
120 }
121
122 return ERROR_OK;
123 }
124
125 /* put an instruction in the ARM9TDMI pipeline or write the data bus,
126 * and optionally read data
127 */
128 int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr,
129 uint32_t out, uint32_t *in, int sysspeed)
130 {
131 int retval = ERROR_OK;
132 struct scan_field fields[3];
133 uint8_t out_buf[4];
134 uint8_t instr_buf[4];
135 uint8_t sysspeed_buf = 0x0;
136
137 /* prepare buffer */
138 buf_set_u32(out_buf, 0, 32, out);
139
140 buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
141
142 if (sysspeed)
143 buf_set_u32(&sysspeed_buf, 2, 1, 1);
144
145 jtag_set_end_state(TAP_DRPAUSE);
146 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
147 {
148 return retval;
149 }
150
151 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
152
153 fields[0].tap = jtag_info->tap;
154 fields[0].num_bits = 32;
155 fields[0].out_value = out_buf;
156 fields[0].in_value = NULL;
157
158 fields[1].tap = jtag_info->tap;
159 fields[1].num_bits = 3;
160 fields[1].out_value = &sysspeed_buf;
161 fields[1].in_value = NULL;
162
163 fields[2].tap = jtag_info->tap;
164 fields[2].num_bits = 32;
165 fields[2].out_value = instr_buf;
166 fields[2].in_value = NULL;
167
168 if (in)
169 {
170 fields[0].in_value = (uint8_t *)in;
171 jtag_add_dr_scan(3, fields, jtag_get_end_state());
172
173 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
174 }
175 else
176 {
177 jtag_add_dr_scan(3, fields, jtag_get_end_state());
178 }
179
180 jtag_add_runtest(0, jtag_get_end_state());
181
182 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
183 {
184 if ((retval = jtag_execute_queue()) != ERROR_OK)
185 {
186 return retval;
187 }
188
189 if (in)
190 {
191 LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
192 }
193 else
194 LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
195 }
196 #endif
197
198 return ERROR_OK;
199 }
200
201 /* just read data (instruction and data-out = don't care) */
202 int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
203 {
204 int retval = ERROR_OK;;
205 struct scan_field fields[3];
206
207 jtag_set_end_state(TAP_DRPAUSE);
208 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
209 {
210 return retval;
211 }
212
213 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
214
215 fields[0].tap = jtag_info->tap;
216 fields[0].num_bits = 32;
217 fields[0].out_value = NULL;
218 fields[0].in_value = (uint8_t *)in;
219
220 fields[1].tap = jtag_info->tap;
221 fields[1].num_bits = 3;
222 fields[1].out_value = NULL;
223 fields[1].in_value = NULL;
224
225 fields[2].tap = jtag_info->tap;
226 fields[2].num_bits = 32;
227 fields[2].out_value = NULL;
228 fields[2].in_value = NULL;
229
230 jtag_add_dr_scan(3, fields, jtag_get_end_state());
231
232 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
233
234 jtag_add_runtest(0, jtag_get_end_state());
235
236 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
237 {
238 if ((retval = jtag_execute_queue()) != ERROR_OK)
239 {
240 return retval;
241 }
242
243 if (in)
244 {
245 LOG_DEBUG("in: 0x%8.8x", *in);
246 }
247 else
248 {
249 LOG_ERROR("BUG: called with in == NULL");
250 }
251 }
252 #endif
253
254 return ERROR_OK;
255 }
256
257 extern void arm_endianness(uint8_t *tmp, void *in, int size, int be, int flip);
258
259 static int arm9endianness(jtag_callback_data_t arg,
260 jtag_callback_data_t size, jtag_callback_data_t be,
261 jtag_callback_data_t captured)
262 {
263 uint8_t *in = (uint8_t *)arg;
264
265 arm_endianness((uint8_t *)captured, in, (int)size, (int)be, 0);
266 return ERROR_OK;
267 }
268
269 /* clock the target, and read the databus
270 * the *in pointer points to a buffer where elements of 'size' bytes
271 * are stored in big (be == 1) or little (be == 0) endianness
272 */
273 int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
274 void *in, int size, int be)
275 {
276 int retval = ERROR_OK;
277 struct scan_field fields[3];
278
279 jtag_set_end_state(TAP_DRPAUSE);
280 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
281 {
282 return retval;
283 }
284
285 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
286
287 fields[0].tap = jtag_info->tap;
288 fields[0].num_bits = 32;
289 fields[0].out_value = NULL;
290 jtag_alloc_in_value32(&fields[0]);
291
292 fields[1].tap = jtag_info->tap;
293 fields[1].num_bits = 3;
294 fields[1].out_value = NULL;
295 fields[1].in_value = NULL;
296
297 fields[2].tap = jtag_info->tap;
298 fields[2].num_bits = 32;
299 fields[2].out_value = NULL;
300 fields[2].in_value = NULL;
301
302 jtag_add_dr_scan(3, fields, jtag_get_end_state());
303
304 jtag_add_callback4(arm9endianness, (jtag_callback_data_t)in, (jtag_callback_data_t)size, (jtag_callback_data_t)be, (jtag_callback_data_t)fields[0].in_value);
305
306 jtag_add_runtest(0, jtag_get_end_state());
307
308 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
309 {
310 if ((retval = jtag_execute_queue()) != ERROR_OK)
311 {
312 return retval;
313 }
314
315 if (in)
316 {
317 LOG_DEBUG("in: 0x%8.8x", *(uint32_t*)in);
318 }
319 else
320 {
321 LOG_ERROR("BUG: called with in == NULL");
322 }
323 }
324 #endif
325
326 return ERROR_OK;
327 }
328
329 static void arm9tdmi_change_to_arm(struct target *target,
330 uint32_t *r0, uint32_t *pc)
331 {
332 int retval = ERROR_OK;
333 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
334 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
335
336 /* save r0 before using it and put system in ARM state
337 * to allow common handling of ARM and THUMB debugging */
338
339 /* fetch STR r0, [r0] */
340 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
341 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
342 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
343 /* STR r0, [r0] in Memory */
344 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
345
346 /* MOV r0, r15 fetched, STR in Decode */
347 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
348 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
349 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
350 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
351 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
352 /* nothing fetched, STR r0, [r0] in Memory */
353 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
354
355 /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
356 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
357 /* LDR in Decode */
358 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
359 /* LDR in Execute */
360 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
361 /* LDR in Memory (to account for interlock) */
362 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
363
364 /* fetch BX */
365 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0);
366 /* NOP fetched, BX in Decode, MOV in Execute */
367 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
368 /* NOP fetched, BX in Execute (1) */
369 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
370
371 if ((retval = jtag_execute_queue()) != ERROR_OK)
372 {
373 return;
374 }
375
376 /* fix program counter:
377 * MOV r0, r15 was the 5th instruction (+8)
378 * reading PC in Thumb state gives address of instruction + 4
379 */
380 *pc -= 0xc;
381 }
382
383 void arm9tdmi_read_core_regs(struct target *target,
384 uint32_t mask, uint32_t* core_regs[16])
385 {
386 int i;
387 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
388 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
389
390 /* STMIA r0-15, [r0] at debug speed
391 * register values will start to appear on 4th DCLK
392 */
393 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
394
395 /* fetch NOP, STM in DECODE stage */
396 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
397 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
398 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
399
400 for (i = 0; i <= 15; i++)
401 {
402 if (mask & (1 << i))
403 /* nothing fetched, STM in MEMORY (i'th cycle) */
404 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
405 }
406 }
407
408 static void arm9tdmi_read_core_regs_target_buffer(struct target *target,
409 uint32_t mask, void* buffer, int size)
410 {
411 int i;
412 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
413 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
414 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
415 uint32_t *buf_u32 = buffer;
416 uint16_t *buf_u16 = buffer;
417 uint8_t *buf_u8 = buffer;
418
419 /* STMIA r0-15, [r0] at debug speed
420 * register values will start to appear on 4th DCLK
421 */
422 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
423
424 /* fetch NOP, STM in DECODE stage */
425 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
426 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
427 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
428
429 for (i = 0; i <= 15; i++)
430 {
431 if (mask & (1 << i))
432 /* nothing fetched, STM in MEMORY (i'th cycle) */
433 switch (size)
434 {
435 case 4:
436 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
437 break;
438 case 2:
439 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
440 break;
441 case 1:
442 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
443 break;
444 }
445 }
446 }
447
448 static void arm9tdmi_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
449 {
450 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
451 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
452
453 /* MRS r0, cpsr */
454 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
455 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
456 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
457 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
458 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
459
460 /* STR r0, [r15] */
461 arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
462 /* fetch NOP, STR in DECODE stage */
463 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
464 /* fetch NOP, STR in EXECUTE stage (1st cycle) */
465 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
466 /* nothing fetched, STR in MEMORY */
467 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
468 }
469
470 static void arm9tdmi_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
471 {
472 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
473 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
474
475 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
476
477 /* MSR1 fetched */
478 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
479 /* MSR2 fetched, MSR1 in DECODE */
480 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
481 /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
482 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
483 /* nothing fetched, MSR1 in EXECUTE (2) */
484 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
485 /* nothing fetched, MSR1 in EXECUTE (3) */
486 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
487 /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
488 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
489 /* nothing fetched, MSR2 in EXECUTE (2) */
490 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
491 /* nothing fetched, MSR2 in EXECUTE (3) */
492 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
493 /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
494 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
495 /* nothing fetched, MSR3 in EXECUTE (2) */
496 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
497 /* nothing fetched, MSR3 in EXECUTE (3) */
498 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
499 /* NOP fetched, MSR4 in EXECUTE (1) */
500 /* last MSR writes flags, which takes only one cycle */
501 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
502 }
503
504 static void arm9tdmi_write_xpsr_im8(struct target *target,
505 uint8_t xpsr_im, int rot, int spsr)
506 {
507 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
508 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
509
510 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
511
512 /* MSR fetched */
513 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
514 /* NOP fetched, MSR in DECODE */
515 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
516 /* NOP fetched, MSR in EXECUTE (1) */
517 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
518
519 /* rot == 4 writes flags, which takes only one cycle */
520 if (rot != 4)
521 {
522 /* nothing fetched, MSR in EXECUTE (2) */
523 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
524 /* nothing fetched, MSR in EXECUTE (3) */
525 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
526 }
527 }
528
529 void arm9tdmi_write_core_regs(struct target *target,
530 uint32_t mask, uint32_t core_regs[16])
531 {
532 int i;
533 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
534 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
535
536 /* LDMIA r0-15, [r0] at debug speed
537 * register values will start to appear on 4th DCLK
538 */
539 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
540
541 /* fetch NOP, LDM in DECODE stage */
542 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
543 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
544 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
545
546 for (i = 0; i <= 15; i++)
547 {
548 if (mask & (1 << i))
549 /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
550 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
551 }
552 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
553 }
554
555 void arm9tdmi_load_word_regs(struct target *target, uint32_t mask)
556 {
557 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
558 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
559
560 /* put system-speed load-multiple into the pipeline */
561 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0);
562 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
563 }
564
565 void arm9tdmi_load_hword_reg(struct target *target, int num)
566 {
567 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
568 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
569
570 /* put system-speed load half-word into the pipeline */
571 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0);
572 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
573 }
574
575 void arm9tdmi_load_byte_reg(struct target *target, int num)
576 {
577 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
578 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
579
580 /* put system-speed load byte into the pipeline */
581 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0);
582 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
583 }
584
585 void arm9tdmi_store_word_regs(struct target *target, uint32_t mask)
586 {
587 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
588 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
589
590 /* put system-speed store-multiple into the pipeline */
591 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0);
592 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
593 }
594
595 void arm9tdmi_store_hword_reg(struct target *target, int num)
596 {
597 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
598 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
599
600 /* put system-speed store half-word into the pipeline */
601 arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0);
602 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
603 }
604
605 void arm9tdmi_store_byte_reg(struct target *target, int num)
606 {
607 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
608 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
609
610 /* put system-speed store byte into the pipeline */
611 arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0);
612 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
613 }
614
615 static void arm9tdmi_write_pc(struct target *target, uint32_t pc)
616 {
617 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
618 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
619
620 /* LDMIA r0-15, [r0] at debug speed
621 * register values will start to appear on 4th DCLK
622 */
623 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
624
625 /* fetch NOP, LDM in DECODE stage */
626 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
627 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
628 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
629 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
630 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
631 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
632 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
633 /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
634 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
635 /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
636 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
637 }
638
639 void arm9tdmi_branch_resume(struct target *target)
640 {
641 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
642 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
643
644 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0);
645 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
646 }
647
648 static void arm9tdmi_branch_resume_thumb(struct target *target)
649 {
650 LOG_DEBUG("-");
651
652 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
653 struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
654 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
655 struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
656
657 /* LDMIA r0-15, [r0] at debug speed
658 * register values will start to appear on 4th DCLK
659 */
660 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0);
661
662 /* fetch NOP, LDM in DECODE stage */
663 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
664 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
665 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
666 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
667 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
668 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
669 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
670
671 /* Branch and eXchange */
672 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
673
674 embeddedice_read_reg(dbg_stat);
675
676 /* fetch NOP, BX in DECODE stage */
677 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
678
679 embeddedice_read_reg(dbg_stat);
680
681 /* fetch NOP, BX in EXECUTE stage (1st cycle) */
682 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
683
684 /* target is now in Thumb state */
685 embeddedice_read_reg(dbg_stat);
686
687 /* load r0 value, MOV_IM in Decode*/
688 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
689 /* fetch NOP, LDR in Decode, MOV_IM in Execute */
690 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
691 /* fetch NOP, LDR in Execute */
692 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
693 /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
694 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
695 /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
696 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
697
698 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
699 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
700
701 embeddedice_read_reg(dbg_stat);
702
703 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1);
704 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
705 }
706
707 void arm9tdmi_enable_single_step(struct target *target, uint32_t next_pc)
708 {
709 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
710
711 if (arm7_9->has_single_step)
712 {
713 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
714 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
715 }
716 else
717 {
718 arm7_9_enable_eice_step(target, next_pc);
719 }
720 }
721
722 void arm9tdmi_disable_single_step(struct target *target)
723 {
724 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
725
726 if (arm7_9->has_single_step)
727 {
728 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
729 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
730 }
731 else
732 {
733 arm7_9_disable_eice_step(target);
734 }
735 }
736
737 static void arm9tdmi_build_reg_cache(struct target *target)
738 {
739 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
740 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
741
742 (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
743 armv4_5->core_cache = (*cache_p);
744 }
745
746 int arm9tdmi_init_target(struct command_context *cmd_ctx,
747 struct target *target)
748 {
749 arm9tdmi_build_reg_cache(target);
750 return ERROR_OK;
751 }
752
753 int arm9tdmi_init_arch_info(struct target *target, struct arm9tdmi_common *arm9tdmi, struct jtag_tap *tap)
754 {
755 struct arm *armv4_5;
756 struct arm7_9_common *arm7_9;
757
758 arm7_9 = &arm9tdmi->arm7_9_common;
759 armv4_5 = &arm7_9->armv4_5_common;
760
761 /* prepare JTAG information for the new target */
762 arm7_9->jtag_info.tap = tap;
763 arm7_9->jtag_info.scann_size = 5;
764
765 /* register arch-specific functions */
766 arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
767 arm7_9->change_to_arm = arm9tdmi_change_to_arm;
768 arm7_9->read_core_regs = arm9tdmi_read_core_regs;
769 arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer;
770 arm7_9->read_xpsr = arm9tdmi_read_xpsr;
771
772 arm7_9->write_xpsr = arm9tdmi_write_xpsr;
773 arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8;
774 arm7_9->write_core_regs = arm9tdmi_write_core_regs;
775
776 arm7_9->load_word_regs = arm9tdmi_load_word_regs;
777 arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
778 arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
779
780 arm7_9->store_word_regs = arm9tdmi_store_word_regs;
781 arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
782 arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
783
784 arm7_9->write_pc = arm9tdmi_write_pc;
785 arm7_9->branch_resume = arm9tdmi_branch_resume;
786 arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb;
787
788 arm7_9->enable_single_step = arm9tdmi_enable_single_step;
789 arm7_9->disable_single_step = arm9tdmi_disable_single_step;
790
791 arm7_9->post_debug_entry = NULL;
792
793 arm7_9->pre_restore_context = NULL;
794 arm7_9->post_restore_context = NULL;
795
796 /* initialize arch-specific breakpoint handling */
797 arm7_9->arm_bkpt = 0xdeeedeee;
798 arm7_9->thumb_bkpt = 0xdeee;
799
800 arm7_9->dbgreq_adjust_pc = 3;
801
802 arm7_9_init_arch_info(target, arm7_9);
803
804 /* override use of DBGRQ, this is safe on ARM9TDMI */
805 arm7_9->use_dbgrq = 1;
806
807 /* all ARM9s have the vector catch register */
808 arm7_9->has_vector_catch = 1;
809
810 return ERROR_OK;
811 }
812
813 static int arm9tdmi_target_create(struct target *target, Jim_Interp *interp)
814 {
815 struct arm9tdmi_common *arm9tdmi = calloc(1,sizeof(struct arm9tdmi_common));
816
817 arm9tdmi_init_arch_info(target, arm9tdmi, target->tap);
818 arm9tdmi->arm7_9_common.armv4_5_common.is_armv4 = true;
819
820 return ERROR_OK;
821 }
822
823 COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command)
824 {
825 struct target *target = get_current_target(cmd_ctx);
826 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
827 struct reg *vector_catch;
828 uint32_t vector_catch_value;
829
830 /* it's uncommon, but some ARM7 chips can support this */
831 if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC
832 || !arm7_9->has_vector_catch) {
833 command_print(cmd_ctx, "target doesn't have EmbeddedICE "
834 "with vector_catch");
835 return ERROR_TARGET_INVALID;
836 }
837
838 vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH];
839
840 /* read the vector catch register if necessary */
841 if (!vector_catch->valid)
842 embeddedice_read_reg(vector_catch);
843
844 /* get the current setting */
845 vector_catch_value = buf_get_u32(vector_catch->value, 0, 8);
846
847 if (argc > 0)
848 {
849 vector_catch_value = 0x0;
850 if (strcmp(args[0], "all") == 0)
851 {
852 vector_catch_value = 0xdf;
853 }
854 else if (strcmp(args[0], "none") == 0)
855 {
856 /* do nothing */
857 }
858 else
859 {
860 for (unsigned i = 0; i < argc; i++)
861 {
862 /* go through list of vectors */
863 unsigned j;
864 for (j = 0; arm9tdmi_vectors[j].name; j++)
865 {
866 if (strcmp(args[i], arm9tdmi_vectors[j].name) == 0)
867 {
868 vector_catch_value |= arm9tdmi_vectors[j].value;
869 break;
870 }
871 }
872
873 /* complain if vector wasn't found */
874 if (!arm9tdmi_vectors[j].name)
875 {
876 command_print(cmd_ctx, "vector '%s' not found, leaving current setting unchanged", args[i]);
877
878 /* reread current setting */
879 vector_catch_value = buf_get_u32(
880 vector_catch->value,
881 0, 8);
882
883 break;
884 }
885 }
886 }
887
888 /* store new settings */
889 buf_set_u32(vector_catch->value, 0, 8, vector_catch_value);
890 embeddedice_store_reg(vector_catch);
891 }
892
893 /* output current settings */
894 for (unsigned i = 0; arm9tdmi_vectors[i].name; i++) {
895 command_print(cmd_ctx, "%s: %s", arm9tdmi_vectors[i].name,
896 (vector_catch_value & arm9tdmi_vectors[i].value)
897 ? "catch" : "don't catch");
898 }
899
900 return ERROR_OK;
901 }
902
903 int arm9tdmi_register_commands(struct command_context *cmd_ctx)
904 {
905 int retval;
906 struct command *arm9tdmi_cmd;
907
908 retval = arm7_9_register_commands(cmd_ctx);
909 arm9tdmi_cmd = register_command(cmd_ctx, NULL, "arm9",
910 NULL, COMMAND_ANY,
911 "arm9 specific commands");
912 register_command(cmd_ctx, arm9tdmi_cmd, "vector_catch",
913 handle_arm9tdmi_catch_vectors_command, COMMAND_EXEC,
914 "arm9 vector_catch [all|none|reset|undef|swi|pabt|dabt|irq|fiq] ...");
915
916 return retval;
917 }
918
919 /** Holds methods for ARM9TDMI targets. */
920 struct target_type arm9tdmi_target =
921 {
922 .name = "arm9tdmi",
923
924 .poll = arm7_9_poll,
925 .arch_state = armv4_5_arch_state,
926
927 .target_request_data = arm7_9_target_request_data,
928
929 .halt = arm7_9_halt,
930 .resume = arm7_9_resume,
931 .step = arm7_9_step,
932
933 .assert_reset = arm7_9_assert_reset,
934 .deassert_reset = arm7_9_deassert_reset,
935 .soft_reset_halt = arm7_9_soft_reset_halt,
936
937 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
938
939 .read_memory = arm7_9_read_memory,
940 .write_memory = arm7_9_write_memory,
941 .bulk_write_memory = arm7_9_bulk_write_memory,
942
943 .checksum_memory = arm_checksum_memory,
944 .blank_check_memory = arm_blank_check_memory,
945
946 .run_algorithm = armv4_5_run_algorithm,
947
948 .add_breakpoint = arm7_9_add_breakpoint,
949 .remove_breakpoint = arm7_9_remove_breakpoint,
950 .add_watchpoint = arm7_9_add_watchpoint,
951 .remove_watchpoint = arm7_9_remove_watchpoint,
952
953 .register_commands = arm9tdmi_register_commands,
954 .target_create = arm9tdmi_target_create,
955 .init_target = arm9tdmi_init_target,
956 .examine = arm7_9_examine,
957 };

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)