cmd: add missing usage vars
[fw/openocd] / src / target / arm946e.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) 2010 by Drasko DRASKOVIC                                *
9  *   drasko.draskovic@gmail.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 "arm946e.h"
31 #include "target_type.h"
32 #include "arm_opcodes.h"
33
34 #include "breakpoints.h"
35
36 #if 0
37 #define _DEBUG_INSTRUCTION_EXECUTION_
38 #endif
39
40 #define NB_CACHE_WAYS 4
41
42 static uint32_t dc = 0x0;
43 static uint32_t ic = 0x0;
44
45 /**
46  * flag to give info about cache manipulation during debug :
47  * "0"  -       cache lines are invalidated "on the fly", for affected addresses.
48  *                      This is prefered from performance point of view.
49  * "1"  -       cache is invalidated and switched off on debug_entry, and switched back on on restore.
50  *                      It is kept off during debugging.
51  */
52 static uint8_t arm946e_preserve_cache;
53
54 int arm946e_post_debug_entry(struct target *target);
55 void arm946e_pre_restore_context(struct target *target);
56 static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value);
57
58
59 int arm946e_init_arch_info(struct target *target, struct arm946e_common *arm946e, struct jtag_tap *tap)
60 {
61         struct arm7_9_common *arm7_9 = &arm946e->arm7_9_common;
62
63         /* initialize arm7/arm9 specific info (including armv4_5) */
64         arm9tdmi_init_arch_info(target, arm7_9, tap);
65
66         arm946e->common_magic = ARM946E_COMMON_MAGIC;
67
68         /**
69          * The ARM946E-S implements the ARMv5TE architecture which
70          * has the BKPT instruction, so we don't have to use a watchpoint comparator
71          */
72         arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
73         arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
74
75
76         arm7_9->post_debug_entry = arm946e_post_debug_entry;
77         arm7_9->pre_restore_context = arm946e_pre_restore_context;
78
79         /**
80          * disabling linefills leads to lockups, so keep them enabled for now
81          * this doesn't affect correctness, but might affect timing issues, if
82          * important data is evicted from the cache during the debug session
83          */
84         arm946e_preserve_cache = 0;
85
86         /* override hw single-step capability from ARM9TDMI */
87         //arm7_9->has_single_step = 1;
88
89         return ERROR_OK;
90 }
91
92 static int arm946e_target_create(struct target *target, Jim_Interp *interp)
93 {
94         struct arm946e_common *arm946e = calloc(1,sizeof(struct arm946e_common));
95
96         arm946e_init_arch_info(target, arm946e, target->tap);
97
98         return ERROR_OK;
99 }
100
101 static int arm946e_verify_pointer(struct command_context *cmd_ctx,
102                 struct arm946e_common *arm946e)
103 {
104         if (arm946e->common_magic != ARM946E_COMMON_MAGIC) {
105                 command_print(cmd_ctx, "target is not an ARM946");
106                 return ERROR_TARGET_INVALID;
107         }
108         return ERROR_OK;
109 }
110
111 /*
112  * REVISIT:  The "read_cp15" and "write_cp15" commands could hook up
113  * to eventual mrc() and mcr() routines ... the reg_addr values being
114  * constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values.
115  * See section 7.3 of the ARM946E-S TRM.
116  */
117 static int arm946e_read_cp15(struct target *target, int reg_addr, uint32_t *value)
118 {
119         int retval = ERROR_OK;
120         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
121         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
122         struct scan_field fields[3];
123         uint8_t reg_addr_buf = reg_addr & 0x3f;
124         uint8_t nr_w_buf = 0;
125
126         if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE)) != ERROR_OK)
127         {
128                 return retval;
129         }
130         retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
131         if (retval != ERROR_OK)
132                 return retval;
133
134         fields[0].num_bits = 32;
135         /* REVISIT: table 7-2 shows that bits 31-31 need to be
136          * specified for accessing BIST registers ...
137          */
138         fields[0].out_value = NULL;
139         fields[0].in_value = NULL;
140
141         fields[1].num_bits = 6;
142         fields[1].out_value = &reg_addr_buf;
143         fields[1].in_value = NULL;
144
145         fields[2].num_bits = 1;
146         fields[2].out_value = &nr_w_buf;
147         fields[2].in_value = NULL;
148
149         jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
150
151         fields[0].in_value = (uint8_t *)value;
152         jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
153
154         jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)value);
155
156 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
157         LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
158 #endif
159
160         if ((retval = jtag_execute_queue()) != ERROR_OK)
161         {
162                 return retval;
163         }
164
165         return ERROR_OK;
166 }
167
168 int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value)
169 {
170         int retval = ERROR_OK;
171         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
172         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
173         struct scan_field fields[3];
174         uint8_t reg_addr_buf = reg_addr & 0x3f;
175         uint8_t nr_w_buf = 1;
176         uint8_t value_buf[4];
177
178         buf_set_u32(value_buf, 0, 32, value);
179
180         if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_IDLE)) != ERROR_OK)
181         {
182                 return retval;
183         }
184         retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_IDLE);
185         if (retval != ERROR_OK)
186                 return retval;
187
188         fields[0].num_bits = 32;
189         fields[0].out_value = value_buf;
190         fields[0].in_value = NULL;
191
192         fields[1].num_bits = 6;
193         fields[1].out_value = &reg_addr_buf;
194         fields[1].in_value = NULL;
195
196         fields[2].num_bits = 1;
197         fields[2].out_value = &nr_w_buf;
198         fields[2].in_value = NULL;
199
200         jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_IDLE);
201
202 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
203         LOG_DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
204 #endif
205
206         if ((retval = jtag_execute_queue()) != ERROR_OK)
207         {
208                 return retval;
209         }
210
211         return ERROR_OK;
212 }
213
214 uint32_t arm946e_invalidate_whole_dcache(struct target *target)
215 {
216
217    uint32_t csize = 0;
218    uint32_t shift = 0;
219    uint32_t cp15_idx, seg, dtag;
220    int nb_idx, idx = 0;
221    int retval;
222
223    /* Get cache type */
224    arm946e_read_cp15(target, 0x01, (uint32_t *) &csize);
225
226    csize = (csize >> 18) & 0x0F;
227
228         if (csize == 0)
229                 shift = 0;
230         else
231                 shift = csize - 0x3; /* Now 0 = 4KB, 1 = 8KB, ... */
232
233         /* Cache size, given in bytes */
234         csize = 1 << (12 + shift);
235         /* One line (index) is 32 bytes (8 words) long */
236         nb_idx = (csize / 32);  /* gives nb of lines (indexes) in the cache */
237
238         /* Loop for all segmentde (i.e. ways) */
239         for( seg=0; seg < NB_CACHE_WAYS; seg++)
240         {
241                 /* Loop for all indexes */
242                 for(idx=0; idx < nb_idx; idx++)
243                 {
244                         /* Form and write cp15 index (segment + line idx) */
245                         cp15_idx = seg << 30 | idx << 5;
246                         retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
247                         if (retval != ERROR_OK)
248                         {
249                                 LOG_DEBUG("ERROR writing index");
250                                 return retval;
251                         }
252
253                         /* Read dtag */
254                         arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
255
256                         /* Check cache line VALID bit */
257                         if ( !(dtag >> 4 & 0x1) )
258                                 continue;
259
260                         /* Clean data cache line */
261                         retval = arm946e_write_cp15(target, 0x35, 0x1);
262                         if (retval != ERROR_OK)
263                         {
264                                 LOG_DEBUG("ERROR cleaning cache line");
265                                 return retval;
266                         }
267
268                         /* Flush data cache line */
269                         retval = arm946e_write_cp15(target, 0x1a, 0x1);
270                         if (retval != ERROR_OK)
271                         {
272                                 LOG_DEBUG("ERROR flushing cache line");
273                                 return retval;
274                         }
275                 }
276         }
277
278         return ERROR_OK;
279 }
280
281 uint32_t arm946e_invalidate_whole_icache(struct target *target)
282 {
283         int retval;
284
285         LOG_DEBUG("FLUSHING I$");
286
287         /**
288          *  Invalidate (flush) I$
289          *  mcr 15, 0, r0, cr7, cr5, {0}
290          */
291         retval = arm946e_write_cp15(target, 0x0f, 0x1);
292         if (retval != ERROR_OK)
293         {
294                 LOG_DEBUG("ERROR flushing I$");
295                 return retval;
296         }
297
298         return ERROR_OK;
299 }
300
301 int arm946e_post_debug_entry(struct target *target)
302 {
303         uint32_t ctr_reg = 0x0;
304         uint32_t retval = ERROR_OK;
305
306         /* See if CACHES are enabled, and save that info
307          * in the global vars, so that arm946e_pre_restore_context() can use them */
308         arm946e_read_cp15(target, 0x02, (uint32_t *) &ctr_reg);
309         dc = (ctr_reg >> 2) & 0x01;
310         ic = (ctr_reg >> 12) & 0x01;
311
312         if (arm946e_preserve_cache)
313         {
314                 if (dc == 1)
315                 {
316                         /* Clean and flush D$ */
317                         arm946e_invalidate_whole_dcache(target);
318
319                         /* Disable D$ */
320                         ctr_reg &= ~(1 << 2);
321                 }
322
323                 if (ic == 1)
324                 {
325                         /* Flush I$ */
326                         arm946e_invalidate_whole_icache(target);
327
328                         /* Disable I$ */
329                         ctr_reg &= ~(1 << 12);
330                 }
331
332                 /* Write the new configuration */
333                 retval = arm946e_write_cp15(target, 0x02, ctr_reg);
334                 if (retval != ERROR_OK)
335                 {
336                         LOG_DEBUG("ERROR disabling cache");
337                         return retval;
338                 }
339         } /* if preserve_cache */
340
341         return ERROR_OK;
342 }
343
344 void arm946e_pre_restore_context(struct target *target)
345 {
346         uint32_t ctr_reg = 0x0;
347         uint32_t retval;
348
349         if (arm946e_preserve_cache)
350         {
351                 /* Get the contents of the CTR reg */
352                 arm946e_read_cp15(target, 0x02, (uint32_t *) &ctr_reg);
353
354                 /**
355                  * Read-modify-write CP15 test state register
356                  * to reenable I/D-cache linefills
357                  */
358                 if (dc == 1)
359                 {
360                         /* Enable D$ */
361                         ctr_reg |= 1 << 2;
362                 }
363
364                 if (ic == 1)
365                 {
366                         /* Enable I$ */
367                         ctr_reg |= 1 << 12;
368                 }
369
370                 /* Write the new configuration */
371                 retval = arm946e_write_cp15(target, 0x02, ctr_reg);
372                 if (retval != ERROR_OK)
373                 {
374                         LOG_DEBUG("ERROR enabling cache");
375                 }
376         } /* if preserve_cache */
377 }
378
379 uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
380                 uint32_t size, uint32_t count)
381 {
382         uint32_t csize = 0x0;
383         uint32_t shift = 0;
384         uint32_t cur_addr = 0x0;
385         uint32_t cp15_idx, set, way, dtag;
386         uint32_t i = 0;
387         int retval;
388
389         for(i = 0; i < count*size; i++)
390         {
391                 cur_addr = address + i;
392
393                 /* Get cache type */
394                 arm946e_read_cp15(target, 0x01, (uint32_t *) &csize);
395
396                 /* Conclude cache size to find number of lines */
397                 csize = (csize >> 18) & 0x0F;
398
399                 if (csize == 0)
400                         shift = 0;
401                 else
402                         shift = csize - 0x3; /* Now 0 = 4KB, 1 = 8KB, ... */
403
404                 csize = 1 << (12 + shift);
405
406                 set = (cur_addr >> 5) & 0xff;   /* set field is 8 bits long */
407
408                 for (way = 0; way < NB_CACHE_WAYS; way++)
409                 {
410                         /**
411                          * Find if the affected address is kept in the cache.
412                          * Because JTAG Scan Chain 15 offers limited approach,
413                          * we have to loop through all cache ways (segments) and
414                          * read cache tags, then compare them with with address.
415                          */
416
417                         /* Form and write cp15 index (segment + line idx) */
418                         cp15_idx = way << 30 | set << 5;
419                         retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
420                         if (retval != ERROR_OK)
421                         {
422                                 LOG_DEBUG("ERROR writing index");
423                                 return retval;
424                         }
425
426                         /* Read dtag */
427                         arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
428
429                         /* Check cache line VALID bit */
430                         if ( !(dtag >> 4 & 0x1) )
431                                 continue;
432
433                         /* If line is valid and corresponds to affected address - invalidate it */
434                         if (dtag >> 5 == cur_addr >> 5)
435                         {
436                                 /* Clean data cache line */
437                                 retval = arm946e_write_cp15(target, 0x35, 0x1);
438                                 if (retval != ERROR_OK)
439                                 {
440                                         LOG_DEBUG("ERROR cleaning cache line");
441                                         return retval;
442                                 }
443
444                                 /* Flush data cache line */
445                                 retval = arm946e_write_cp15(target, 0x1c, 0x1);
446                                 if (retval != ERROR_OK)
447                                 {
448                                         LOG_DEBUG("ERROR flushing cache line");
449                                         return retval;
450                                 }
451
452                                 break;
453                         }
454                 } /* loop through all 4 ways */
455         } /* loop through all addresses */
456
457         return ERROR_OK;
458 }
459
460 uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address,
461                 uint32_t size, uint32_t count)
462 {
463         uint32_t cur_addr = 0x0;
464         uint32_t cp15_idx, set, way, itag;
465         uint32_t i = 0;
466         int retval;
467
468         for(i = 0; i < count*size; i++)
469         {
470                 cur_addr = address + i;
471
472                 set = (cur_addr >> 5) & 0xff;   /* set field is 8 bits long */
473
474                 for (way = 0; way < NB_CACHE_WAYS; way++)
475                 {
476                         /* Form and write cp15 index (segment + line idx) */
477                         cp15_idx = way << 30 | set << 5;
478                         retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
479                         if (retval != ERROR_OK)
480                         {
481                                 LOG_DEBUG("ERROR writing index");
482                                 return retval;
483                         }
484
485                         /* Read itag */
486                         arm946e_read_cp15(target, 0x17, (uint32_t *) &itag);
487
488                         /* Check cache line VALID bit */
489                         if ( !(itag >> 4 & 0x1) )
490                                 continue;
491
492                         /* If line is valid and corresponds to affected address - invalidate it */
493                         if (itag >> 5 == cur_addr >> 5)
494                         {
495                                 /* Flush I$ line */
496                                 retval = arm946e_write_cp15(target, 0x1d, 0x0);
497                                 if (retval != ERROR_OK)
498                                 {
499                                         LOG_DEBUG("ERROR flushing cache line");
500                                         return retval;
501                                 }
502
503                                 break;
504                         }
505                 } /* way loop */
506         } /* addr loop */
507
508         return ERROR_OK;
509 }
510
511 /** Writes a buffer, in the specified word size, with current MMU settings. */
512 int arm946e_write_memory(struct target *target, uint32_t address,
513                 uint32_t size, uint32_t count, const uint8_t *buffer)
514 {
515         int retval;
516
517         LOG_DEBUG("-");
518
519         /* Invalidate D$ if it is ON */
520         if (!arm946e_preserve_cache && dc == 1)
521         {
522                 arm946e_invalidate_dcache(target, address, size, count);
523         }
524
525         /**
526          * Write memory
527          */
528         if ( ( retval = arm7_9_write_memory(target, address,
529                         size, count, buffer) ) != ERROR_OK )
530         {
531                 return retval;
532         }
533
534         /* *
535          * Invalidate I$ if it is ON.
536          *
537          * D$ has been cleaned and flushed before mem write thus forcing it to behave like write-through,
538          * because arm7_9_write_memory() has seen non-valid bit in D$
539          * and wrote data into physical RAM (without touching or allocating the cache line).
540          * From ARM946ES Technical Reference Manual we can see that it uses "allocate on read-miss"
541          * policy for both I$ and D$ (Chapter 3.2 and 3.3)
542          *
543          * Explanation :
544          * "ARM system developer's guide: designing and optimizing system software" by
545          * Andrew N. Sloss, Dominic Symes and Chris Wright,
546          * Chapter 12.3.3 Allocating Policy on a Cache Miss :
547          * A read allocate on cache miss policy allocates a cache line only during a read from main memory.
548          * If the victim cache line contains valid data, then it is written to main memory before the cache line
549          * is filled with new data.
550          * Under this strategy, a write of new data to memory does not update the contents of the cache memory
551          * unless a cache line was allocated on a previous read from main memory.
552          * If the cache line contains valid data, then the write updates the cache and may update the main memory if
553          * the cache write policy is write-through.
554          * If the data is not in the cache, the controller writes to main memory only.
555          */
556         if (!arm946e_preserve_cache && ic == 1)
557         {
558                 arm946e_invalidate_icache(target, address, size, count);
559         }
560
561         return ERROR_OK;
562
563 }
564
565 int arm946e_read_memory(struct target *target, uint32_t address,
566                 uint32_t size, uint32_t count, uint8_t *buffer)
567 {
568         int retval;
569
570         LOG_DEBUG("-");
571
572         if ( ( retval = arm7_9_read_memory(target, address,
573                         size, count, buffer) ) != ERROR_OK )
574         {
575                 return retval;
576         }
577
578         return ERROR_OK;
579 }
580
581
582 COMMAND_HANDLER(arm946e_handle_cp15_command)
583 {
584         int retval;
585         struct target *target = get_current_target(CMD_CTX);
586         struct arm946e_common *arm946e = target_to_arm946(target);
587
588         retval = arm946e_verify_pointer(CMD_CTX, arm946e);
589         if (retval != ERROR_OK)
590                 return retval;
591
592         if (target->state != TARGET_HALTED)
593         {
594                 command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
595                 return ERROR_OK;
596         }
597
598         /* one or more argument, access a single register (write if second argument is given */
599         if (CMD_ARGC >= 1)
600         {
601                 uint32_t address;
602                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
603
604                 if (CMD_ARGC == 1)
605                 {
606                         uint32_t value;
607                         if ((retval = arm946e_read_cp15(target, address, &value)) != ERROR_OK)
608                         {
609                                 command_print(CMD_CTX,
610                                                 "couldn't access reg %" PRIi32,
611                                                 address);
612                                 return ERROR_OK;
613                         }
614                         if ((retval = jtag_execute_queue()) != ERROR_OK)
615                         {
616                                 return retval;
617                         }
618
619                         command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
620                                         address, value);
621                 }
622                 else if (CMD_ARGC == 2)
623                 {
624                         uint32_t value;
625                         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
626                         if ((retval = arm946e_write_cp15(target, address, value)) != ERROR_OK)
627                         {
628                                 command_print(CMD_CTX,
629                                                 "couldn't access reg %" PRIi32,
630                                                 address);
631                                 return ERROR_OK;
632                         }
633                         command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
634                                         address, value);
635                 }
636         }
637
638         return ERROR_OK;
639 }
640
641 static const struct command_registration arm946e_exec_command_handlers[] = {
642         {
643                 .name = "cp15",
644                 .handler = arm946e_handle_cp15_command,
645                 .mode = COMMAND_EXEC,
646                 .usage = "regnum [value]",
647                 .help = "display/modify cp15 register",
648         },
649         COMMAND_REGISTRATION_DONE
650 };
651
652 const struct command_registration arm946e_command_handlers[] = {
653         {
654                 .chain = arm9tdmi_command_handlers,
655         },
656         {
657                 .name = "arm946e",
658                 .mode = COMMAND_ANY,
659                 .help = "arm946e command group",
660                 .usage = "",
661                 .chain = arm946e_exec_command_handlers,
662         },
663         COMMAND_REGISTRATION_DONE
664 };
665
666 /** Holds methods for ARM946 targets. */
667 struct target_type arm946e_target =
668 {
669         .name = "arm946e",
670
671         .poll = arm7_9_poll,
672         .arch_state = arm_arch_state,
673
674         .target_request_data = arm7_9_target_request_data,
675
676         .halt = arm7_9_halt,
677         .resume = arm7_9_resume,
678         .step = arm7_9_step,
679
680         .assert_reset = arm7_9_assert_reset,
681         .deassert_reset = arm7_9_deassert_reset,
682         .soft_reset_halt = arm7_9_soft_reset_halt,
683
684         .get_gdb_reg_list = arm_get_gdb_reg_list,
685
686         //.read_memory = arm7_9_read_memory,
687         //.write_memory = arm7_9_write_memory,
688         .read_memory = arm946e_read_memory,
689         .write_memory = arm946e_write_memory,
690
691         .bulk_write_memory = arm7_9_bulk_write_memory,
692
693         .checksum_memory = arm_checksum_memory,
694         .blank_check_memory = arm_blank_check_memory,
695
696         .run_algorithm = armv4_5_run_algorithm,
697
698         .add_breakpoint = arm7_9_add_breakpoint,
699         .remove_breakpoint = arm7_9_remove_breakpoint,
700         //.add_breakpoint = arm946e_add_breakpoint,
701         //.remove_breakpoint = arm946e_remove_breakpoint,
702
703         .add_watchpoint = arm7_9_add_watchpoint,
704         .remove_watchpoint = arm7_9_remove_watchpoint,
705
706         .commands = arm946e_command_handlers,
707         .target_create = arm946e_target_create,
708         .init_target = arm9tdmi_init_target,
709         .examine = arm7_9_examine,
710         .check_reset = arm7_9_check_reset,
711 };