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

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)