b9b9cef768d712d8b1fd9d646722462bd29639a1
[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\n");
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\n");
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\n");
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$\n");
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\n");
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         int nb_idx;
387         uint32_t i = 0;
388         int retval;
389
390         for(i = 0; i < count*size; i++)
391         {
392                 cur_addr = address + i;
393
394                 /* Get cache type */
395                 arm946e_read_cp15(target, 0x01, (uint32_t *) &csize);
396
397                 /* Conclude cache size to find number of lines */
398                 csize = (csize >> 18) & 0x0F;
399
400                 if (csize == 0)
401                         shift = 0;
402                 else
403                         shift = csize - 0x3; /* Now 0 = 4KB, 1 = 8KB, ... */
404
405                 csize = 1 << (12 + shift);
406                 nb_idx = (csize / 32);
407
408                 set = (cur_addr >> 5) & 0xff;   /* set field is 8 bits long */
409
410                 for (way = 0; way < NB_CACHE_WAYS; way++)
411                 {
412                         /**
413                          * Find if the affected address is kept in the cache.
414                          * Because JTAG Scan Chain 15 offers limited approach,
415                          * we have to loop through all cache ways (segments) and
416                          * read cache tags, then compare them with with address.
417                          */
418
419                         /* Form and write cp15 index (segment + line idx) */
420                         cp15_idx = way << 30 | set << 5;
421                         retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
422                         if (retval != ERROR_OK)
423                         {
424                                 LOG_DEBUG("ERROR writing index\n");
425                                 return retval;
426                         }
427
428                         /* Read dtag */
429                         arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
430
431                         /* Check cache line VALID bit */
432                         if ( !(dtag >> 4 & 0x1) )
433                                 continue;
434
435                         /* If line is valid and corresponds to affected address - invalidate it */
436                         if (dtag >> 5 == cur_addr >> 5)
437                         {
438                                 /* Clean data cache line */
439                                 retval = arm946e_write_cp15(target, 0x35, 0x1);
440                                 if (retval != ERROR_OK)
441                                 {
442                                         LOG_DEBUG("ERROR cleaning cache line\n");
443                                         return retval;
444                                 }
445
446                                 /* Flush data cache line */
447                                 retval = arm946e_write_cp15(target, 0x1c, 0x1);
448                                 if (retval != ERROR_OK)
449                                 {
450                                         LOG_DEBUG("ERROR flushing cache line\n");
451                                         return retval;
452                                 }
453
454                                 break;
455                         }
456                 } /* loop through all 4 ways */
457         } /* loop through all addresses */
458
459         return ERROR_OK;
460 }
461
462 uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address,
463                 uint32_t size, uint32_t count)
464 {
465         uint32_t cur_addr = 0x0;
466         uint32_t cp15_idx, set, way, itag;
467         uint32_t i = 0;
468         int retval;
469
470         for(i = 0; i < count*size; i++)
471         {
472                 cur_addr = address + i;
473
474                 set = (cur_addr >> 5) & 0xff;   /* set field is 8 bits long */
475
476                 for (way = 0; way < NB_CACHE_WAYS; way++)
477                 {
478                         /* Form and write cp15 index (segment + line idx) */
479                         cp15_idx = way << 30 | set << 5;
480                         retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
481                         if (retval != ERROR_OK)
482                         {
483                                 LOG_DEBUG("ERROR writing index\n");
484                                 return retval;
485                         }
486
487                         /* Read itag */
488                         arm946e_read_cp15(target, 0x17, (uint32_t *) &itag);
489
490                         /* Check cache line VALID bit */
491                         if ( !(itag >> 4 & 0x1) )
492                                 continue;
493
494                         /* If line is valid and corresponds to affected address - invalidate it */
495                         if (itag >> 5 == cur_addr >> 5)
496                         {
497                                 /* Flush I$ line */
498                                 retval = arm946e_write_cp15(target, 0x1d, 0x0);
499                                 if (retval != ERROR_OK)
500                                 {
501                                         LOG_DEBUG("ERROR flushing cache line\n");
502                                         return retval;
503                                 }
504
505                                 break;
506                         }
507                 } /* way loop */
508         } /* addr loop */
509
510         return ERROR_OK;
511 }
512
513 /** Writes a buffer, in the specified word size, with current MMU settings. */
514 int arm946e_write_memory(struct target *target, uint32_t address,
515                 uint32_t size, uint32_t count, uint8_t *buffer)
516 {
517         int retval;
518
519         LOG_DEBUG("-");
520
521         /* Invalidate D$ if it is ON */
522         if (!arm946e_preserve_cache && dc == 1)
523         {
524                 arm946e_invalidate_dcache(target, address, size, count);
525         }
526
527         /**
528          * Write memory
529          */
530         if ( ( retval = arm7_9_write_memory(target, address,
531                         size, count, buffer) ) != ERROR_OK )
532         {
533                 return retval;
534         }
535
536         /* *
537          * Invalidate I$ if it is ON.
538          *
539          * D$ has been cleaned and flushed before mem write thus forcing it to behave like write-through,
540          * because arm7_9_write_memory() has seen non-valid bit in D$
541          * and wrote data into physical RAM (without touching or allocating the cache line).
542          * From ARM946ES Technical Reference Manual we can see that it uses "allocate on read-miss"
543          * policy for both I$ and D$ (Chapter 3.2 and 3.3)
544          *
545          * Explanation :
546          * "ARM system developer's guide: designing and optimizing system software" by
547          * Andrew N. Sloss, Dominic Symes and Chris Wright,
548          * Chapter 12.3.3 Allocating Policy on a Cache Miss :
549          * A read allocate on cache miss policy allocates a cache line only during a read from main memory.
550          * If the victim cache line contains valid data, then it is written to main memory before the cache line
551          * is filled with new data.
552          * Under this strategy, a write of new data to memory does not update the contents of the cache memory
553          * unless a cache line was allocated on a previous read from main memory.
554          * If the cache line contains valid data, then the write updates the cache and may update the main memory if
555          * the cache write policy is write-through.
556          * If the data is not in the cache, the controller writes to main memory only.
557          */
558         if (!arm946e_preserve_cache && ic == 1)
559         {
560                 arm946e_invalidate_icache(target, address, size, count);
561         }
562
563         return ERROR_OK;
564
565 }
566
567 int arm946e_read_memory(struct target *target, uint32_t address,
568                 uint32_t size, uint32_t count, uint8_t *buffer)
569 {
570         int retval;
571
572         LOG_DEBUG("-");
573
574         if ( ( retval = arm7_9_read_memory(target, address,
575                         size, count, buffer) ) != ERROR_OK )
576         {
577                 return retval;
578         }
579
580         return ERROR_OK;
581 }
582
583
584 COMMAND_HANDLER(arm946e_handle_cp15_command)
585 {
586         int retval;
587         struct target *target = get_current_target(CMD_CTX);
588         struct arm946e_common *arm946e = target_to_arm946(target);
589
590         retval = arm946e_verify_pointer(CMD_CTX, arm946e);
591         if (retval != ERROR_OK)
592                 return retval;
593
594         if (target->state != TARGET_HALTED)
595         {
596                 command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
597                 return ERROR_OK;
598         }
599
600         /* one or more argument, access a single register (write if second argument is given */
601         if (CMD_ARGC >= 1)
602         {
603                 uint32_t address;
604                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
605
606                 if (CMD_ARGC == 1)
607                 {
608                         uint32_t value;
609                         if ((retval = arm946e_read_cp15(target, address, &value)) != ERROR_OK)
610                         {
611                                 command_print(CMD_CTX,
612                                                 "couldn't access reg %" PRIi32,
613                                                 address);
614                                 return ERROR_OK;
615                         }
616                         if ((retval = jtag_execute_queue()) != ERROR_OK)
617                         {
618                                 return retval;
619                         }
620
621                         command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
622                                         address, value);
623                 }
624                 else if (CMD_ARGC == 2)
625                 {
626                         uint32_t value;
627                         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
628                         if ((retval = arm946e_write_cp15(target, address, value)) != ERROR_OK)
629                         {
630                                 command_print(CMD_CTX,
631                                                 "couldn't access reg %" PRIi32,
632                                                 address);
633                                 return ERROR_OK;
634                         }
635                         command_print(CMD_CTX, "%" PRIi32 ": %8.8" PRIx32,
636                                         address, value);
637                 }
638         }
639
640         return ERROR_OK;
641 }
642
643 static const struct command_registration arm946e_exec_command_handlers[] = {
644         {
645                 .name = "cp15",
646                 .handler = arm946e_handle_cp15_command,
647                 .mode = COMMAND_EXEC,
648                 .usage = "regnum [value]",
649                 .help = "display/modify cp15 register",
650         },
651         COMMAND_REGISTRATION_DONE
652 };
653
654 const struct command_registration arm946e_command_handlers[] = {
655         {
656                 .chain = arm9tdmi_command_handlers,
657         },
658         {
659                 .name = "arm946e",
660                 .mode = COMMAND_ANY,
661                 .help = "arm946e command group",
662                 .chain = arm946e_exec_command_handlers,
663         },
664         COMMAND_REGISTRATION_DONE
665 };
666
667 /** Holds methods for ARM946 targets. */
668 struct target_type arm946e_target =
669 {
670         .name = "arm946e",
671
672         .poll = arm7_9_poll,
673         .arch_state = arm_arch_state,
674
675         .target_request_data = arm7_9_target_request_data,
676
677         .halt = arm7_9_halt,
678         .resume = arm7_9_resume,
679         .step = arm7_9_step,
680
681         .assert_reset = arm7_9_assert_reset,
682         .deassert_reset = arm7_9_deassert_reset,
683         .soft_reset_halt = arm7_9_soft_reset_halt,
684
685         .get_gdb_reg_list = arm_get_gdb_reg_list,
686
687         //.read_memory = arm7_9_read_memory,
688         //.write_memory = arm7_9_write_memory,
689         .read_memory = arm946e_read_memory,
690         .write_memory = arm946e_write_memory,
691
692         .bulk_write_memory = arm7_9_bulk_write_memory,
693
694         .checksum_memory = arm_checksum_memory,
695         .blank_check_memory = arm_blank_check_memory,
696
697         .run_algorithm = armv4_5_run_algorithm,
698
699         .add_breakpoint = arm7_9_add_breakpoint,
700         .remove_breakpoint = arm7_9_remove_breakpoint,
701         //.add_breakpoint = arm946e_add_breakpoint,
702         //.remove_breakpoint = arm946e_remove_breakpoint,
703
704         .add_watchpoint = arm7_9_add_watchpoint,
705         .remove_watchpoint = arm7_9_remove_watchpoint,
706
707         .commands = arm946e_command_handlers,
708         .target_create = arm946e_target_create,
709         .init_target = arm9tdmi_init_target,
710         .examine = arm7_9_examine,
711         .check_reset = arm7_9_check_reset,
712 };