]> git.sur5r.net Git - openocd/blob - src/target/arm7tdmi.c
Remove FSF address from GPL notices
[openocd] / src / target / arm7tdmi.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) 2007,2008 Ã˜yvind Harboe                                 *
9  *   oyvind.harboe@zylin.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, see <http://www.gnu.org/licenses/>. *
23  ***************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "arm7tdmi.h"
30 #include "target_type.h"
31 #include "register.h"
32 #include "arm_opcodes.h"
33
34 /*
35  * For information about ARM7TDMI, see ARM DDI 0210C (r4p1)
36  * or ARM DDI 0029G (r3).  "Debug In Depth", Appendix B,
37  * covers JTAG support.
38  */
39
40 #if 0
41 #define _DEBUG_INSTRUCTION_EXECUTION_
42 #endif
43
44 static int arm7tdmi_examine_debug_reason(struct target *target)
45 {
46         int retval = ERROR_OK;
47         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
48
49         /* only check the debug reason if we don't know it already */
50         if ((target->debug_reason != DBG_REASON_DBGRQ)
51                         && (target->debug_reason != DBG_REASON_SINGLESTEP)) {
52                 struct scan_field fields[2];
53                 uint8_t databus[4];
54                 uint8_t breakpoint;
55
56                 fields[0].num_bits = 1;
57                 fields[0].out_value = NULL;
58                 fields[0].in_value = &breakpoint;
59
60                 fields[1].num_bits = 32;
61                 fields[1].out_value = NULL;
62                 fields[1].in_value = databus;
63
64                 retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE);
65                 if (retval != ERROR_OK)
66                         return retval;
67                 retval = arm_jtag_set_instr(arm7_9->jtag_info.tap, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE);
68                 if (retval != ERROR_OK)
69                         return retval;
70
71                 jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE);
72                 retval = jtag_execute_queue();
73                 if (retval != ERROR_OK)
74                         return retval;
75
76                 fields[0].in_value = NULL;
77                 fields[0].out_value = &breakpoint;
78                 fields[1].in_value = NULL;
79                 fields[1].out_value = databus;
80
81                 jtag_add_dr_scan(arm7_9->jtag_info.tap, 2, fields, TAP_DRPAUSE);
82
83                 if (breakpoint & 1)
84                         target->debug_reason = DBG_REASON_WATCHPOINT;
85                 else
86                         target->debug_reason = DBG_REASON_BREAKPOINT;
87         }
88
89         return ERROR_OK;
90 }
91
92 static const int arm7tdmi_num_bits[] = {1, 32};
93
94 static inline int arm7tdmi_clock_out_inner(struct arm_jtag *jtag_info, uint32_t out, int breakpoint)
95 {
96         uint8_t bp = breakpoint ? 1 : 0;
97         uint8_t out_value[4];
98         buf_set_u32(out_value, 0, 32, flip_u32(out, 32));
99
100         struct scan_field fields[2] = {
101                         { .num_bits = arm7tdmi_num_bits[0], .out_value = &bp },
102                         { .num_bits = arm7tdmi_num_bits[1], .out_value = out_value },
103         };
104
105         jtag_add_dr_scan(jtag_info->tap,
106                         2,
107                         fields,
108                         TAP_DRPAUSE);
109
110         jtag_add_runtest(0, TAP_DRPAUSE);
111
112         return ERROR_OK;
113 }
114
115 /* put an instruction in the ARM7TDMI pipeline or write the data bus,
116  * and optionally read data
117  *
118  * FIXME remove the unused "deprecated" parameter
119  */
120 static inline int arm7tdmi_clock_out(struct arm_jtag *jtag_info,
121                 uint32_t out, uint32_t *deprecated, int breakpoint)
122 {
123         int retval;
124         retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
125         if (retval != ERROR_OK)
126                 return retval;
127         retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
128         if (retval != ERROR_OK)
129                 return retval;
130
131         return arm7tdmi_clock_out_inner(jtag_info, out, breakpoint);
132 }
133
134 /* clock the target, reading the databus */
135 static int arm7tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
136 {
137         int retval = ERROR_OK;
138         struct scan_field fields[2];
139
140         retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
141         if (retval != ERROR_OK)
142                 return retval;
143         retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
144         if (retval != ERROR_OK)
145                 return retval;
146
147         fields[0].num_bits = 1;
148         fields[0].out_value = NULL;
149         fields[0].in_value = NULL;
150
151         fields[1].num_bits = 32;
152         fields[1].out_value = NULL;
153         fields[1].in_value = (uint8_t *)in;
154
155         jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
156
157         jtag_add_callback(arm7flip32, (jtag_callback_data_t)in);
158
159         jtag_add_runtest(0, TAP_DRPAUSE);
160
161 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
162         retval = jtag_execute_queue();
163         if (retval != ERROR_OK)
164                 return retval;
165
166         if (in)
167                 LOG_DEBUG("in: 0x%8.8x", *in);
168         else
169                 LOG_ERROR("BUG: called with in == NULL");
170 #endif
171
172         return ERROR_OK;
173 }
174
175 /* clock the target, and read the databus
176  * the *in pointer points to a buffer where elements of 'size' bytes
177  * are stored in big (be == 1) or little (be == 0) endianness
178  */
179 static int arm7tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
180                 void *in, int size, int be)
181 {
182         int retval = ERROR_OK;
183         struct scan_field fields[3];
184
185         retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
186         if (retval != ERROR_OK)
187                 return retval;
188         retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
189         if (retval != ERROR_OK)
190                 return retval;
191
192         fields[0].num_bits = 1;
193         fields[0].out_value = NULL;
194         fields[0].in_value = NULL;
195
196         if (size == 4) {
197                 fields[1].num_bits = 32;
198                 fields[1].out_value = NULL;
199                 fields[1].in_value = in;
200         } else {
201                 /* Discard irrelevant bits of the scan, making sure we don't write more
202                  * than size bytes to in */
203                 fields[1].num_bits = 32 - size * 8;
204                 fields[1].out_value = NULL;
205                 fields[1].in_value = NULL;
206
207                 fields[2].num_bits = size * 8;
208                 fields[2].out_value = NULL;
209                 fields[2].in_value = in;
210         }
211
212         jtag_add_dr_scan(jtag_info->tap, size == 4 ? 2 : 3, fields, TAP_DRPAUSE);
213
214         jtag_add_callback4(arm7_9_endianness_callback,
215                 (jtag_callback_data_t)in,
216                 (jtag_callback_data_t)size,
217                 (jtag_callback_data_t)be,
218                 (jtag_callback_data_t)1);
219
220         jtag_add_runtest(0, TAP_DRPAUSE);
221
222 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
223 {
224                 retval = jtag_execute_queue();
225                 if (retval != ERROR_OK)
226                         return retval;
227
228                 if (in)
229                         LOG_DEBUG("in: 0x%8.8x", *(uint32_t *)in);
230                 else
231                         LOG_ERROR("BUG: called with in == NULL");
232 }
233 #endif
234
235         return ERROR_OK;
236 }
237
238 static void arm7tdmi_change_to_arm(struct target *target,
239                 uint32_t *r0, uint32_t *pc)
240 {
241         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
242         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
243
244         /* save r0 before using it and put system in ARM state
245          * to allow common handling of ARM and THUMB debugging */
246
247         /* fetch STR r0, [r0] */
248         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
249         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
250         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
251         /* nothing fetched, STR r0, [r0] in Execute (2) */
252         arm7tdmi_clock_data_in(jtag_info, r0);
253
254         /* MOV r0, r15 fetched, STR in Decode */
255         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0);
256         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
257         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
258         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
259         /* nothing fetched, STR r0, [r0] in Execute (2) */
260         arm7tdmi_clock_data_in(jtag_info, pc);
261
262         /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
263         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
264         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
265         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
266         /* nothing fetched, data for LDR r0, [PC, #0] */
267         arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0);
268         /* nothing fetched, data from previous cycle is written to register */
269         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
270
271         /* fetch BX */
272         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0);
273         /* NOP fetched, BX in Decode, MOV in Execute */
274         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
275         /* NOP fetched, BX in Execute (1) */
276         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
277
278         jtag_execute_queue();
279
280         /* fix program counter:
281          * MOV r0, r15 was the 4th instruction (+6)
282          * reading PC in Thumb state gives address of instruction + 4
283          */
284         *pc -= 0xa;
285 }
286
287 /* FIX!!! is this a potential performance bottleneck w.r.t. requiring too many
288  * roundtrips when jtag_execute_queue() has a large overhead(e.g. for USB)s?
289  *
290  * The solution is to arrange for a large out/in scan in this loop and
291  * and convert data afterwards.
292  */
293 static void arm7tdmi_read_core_regs(struct target *target,
294                 uint32_t mask, uint32_t *core_regs[16])
295 {
296         int i;
297         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
298         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
299
300         /* STMIA r0-15, [r0] at debug speed
301          * register values will start to appear on 4th DCLK
302          */
303         arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
304
305         /* fetch NOP, STM in DECODE stage */
306         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
307         /* fetch NOP, STM in EXECUTE stage (1st cycle) */
308         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
309
310         for (i = 0; i <= 15; i++) {
311                 if (mask & (1 << i))
312                         /* nothing fetched, STM still in EXECUTE (1 + i cycle) */
313                         arm7tdmi_clock_data_in(jtag_info, core_regs[i]);
314         }
315 }
316
317 static void arm7tdmi_read_core_regs_target_buffer(struct target *target,
318                 uint32_t mask, void *buffer, int size)
319 {
320         int i;
321         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
322         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
323         int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
324         uint32_t *buf_u32 = buffer;
325         uint16_t *buf_u16 = buffer;
326         uint8_t *buf_u8 = buffer;
327
328         /* STMIA r0-15, [r0] at debug speed
329          * register values will start to appear on 4th DCLK
330          */
331         arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
332
333         /* fetch NOP, STM in DECODE stage */
334         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
335         /* fetch NOP, STM in EXECUTE stage (1st cycle) */
336         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
337
338         for (i = 0; i <= 15; i++) {
339                 /* nothing fetched, STM still in EXECUTE (1 + i cycle), read databus */
340                 if (mask & (1 << i)) {
341                         switch (size) {
342                                 case 4:
343                                         arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
344                                         break;
345                                 case 2:
346                                         arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
347                                         break;
348                                 case 1:
349                                         arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
350                                         break;
351                         }
352                 }
353         }
354 }
355
356 static void arm7tdmi_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
357 {
358         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
359         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
360
361         /* MRS r0, cpsr */
362         arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0);
363
364         /* STR r0, [r15] */
365         arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0);
366         /* fetch NOP, STR in DECODE stage */
367         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
368         /* fetch NOP, STR in EXECUTE stage (1st cycle) */
369         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
370         /* nothing fetched, STR still in EXECUTE (2nd cycle) */
371         arm7tdmi_clock_data_in(jtag_info, xpsr);
372 }
373
374 static void arm7tdmi_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
375 {
376         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
377         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
378
379         LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
380
381         /* MSR1 fetched */
382         arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), NULL, 0);
383         /* MSR2 fetched, MSR1 in DECODE */
384         arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), NULL, 0);
385         /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
386         arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), NULL, 0);
387         /* nothing fetched, MSR1 in EXECUTE (2) */
388         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
389         /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
390         arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), NULL, 0);
391         /* nothing fetched, MSR2 in EXECUTE (2) */
392         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
393         /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
394         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
395         /* nothing fetched, MSR3 in EXECUTE (2) */
396         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
397         /* NOP fetched, MSR4 in EXECUTE (1) */
398         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
399         /* nothing fetched, MSR4 in EXECUTE (2) */
400         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
401 }
402
403 static void arm7tdmi_write_xpsr_im8(struct target *target,
404                 uint8_t xpsr_im, int rot, int spsr)
405 {
406         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
407         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
408
409         LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
410
411         /* MSR fetched */
412         arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), NULL, 0);
413         /* NOP fetched, MSR in DECODE */
414         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
415         /* NOP fetched, MSR in EXECUTE (1) */
416         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
417         /* nothing fetched, MSR in EXECUTE (2) */
418         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
419 }
420
421 static void arm7tdmi_write_core_regs(struct target *target,
422                 uint32_t mask, uint32_t core_regs[16])
423 {
424         int i;
425         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
426         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
427
428         /* LDMIA r0-15, [r0] at debug speed
429         * register values will start to appear on 4th DCLK
430         */
431         arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), NULL, 0);
432
433         /* fetch NOP, LDM in DECODE stage */
434         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
435         /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
436         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
437
438         for (i = 0; i <= 15; i++) {
439                 if (mask & (1 << i))
440                         /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
441                         arm7tdmi_clock_out_inner(jtag_info, core_regs[i], 0);
442         }
443         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
444 }
445
446 static void arm7tdmi_load_word_regs(struct target *target, uint32_t mask)
447 {
448         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
449         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
450
451         /* put system-speed load-multiple into the pipeline */
452         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
453         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
454         arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), NULL, 0);
455 }
456
457 static void arm7tdmi_load_hword_reg(struct target *target, int num)
458 {
459         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
460         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
461
462         /* put system-speed load half-word into the pipeline */
463         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
464         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
465         arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), NULL, 0);
466 }
467
468 static void arm7tdmi_load_byte_reg(struct target *target, int num)
469 {
470         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
471         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
472
473         /* put system-speed load byte into the pipeline */
474         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
475         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
476         arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), NULL, 0);
477 }
478
479 static void arm7tdmi_store_word_regs(struct target *target, uint32_t mask)
480 {
481         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
482         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
483
484         /* put system-speed store-multiple into the pipeline */
485         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
486         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
487         arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), NULL, 0);
488 }
489
490 static void arm7tdmi_store_hword_reg(struct target *target, int num)
491 {
492         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
493         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
494
495         /* put system-speed store half-word into the pipeline */
496         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
497         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
498         arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), NULL, 0);
499 }
500
501 static void arm7tdmi_store_byte_reg(struct target *target, int num)
502 {
503         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
504         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
505
506         /* put system-speed store byte into the pipeline */
507         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
508         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
509         arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), NULL, 0);
510 }
511
512 static void arm7tdmi_write_pc(struct target *target, uint32_t pc)
513 {
514         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
515         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
516
517         /* LDMIA r0-15, [r0] at debug speed
518          * register values will start to appear on 4th DCLK
519          */
520         arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), NULL, 0);
521         /* fetch NOP, LDM in DECODE stage */
522         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
523         /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
524         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
525         /* nothing fetched, LDM in EXECUTE stage (1st cycle) load register */
526         arm7tdmi_clock_out_inner(jtag_info, pc, 0);
527         /* nothing fetched, LDM in EXECUTE stage (2nd cycle) load register */
528         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
529         /* nothing fetched, LDM in EXECUTE stage (3rd cycle) load register */
530         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
531         /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
532         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
533         /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
534         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
535 }
536
537 static void arm7tdmi_branch_resume(struct target *target)
538 {
539         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
540         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
541
542         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
543         arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_B(0xfffffa, 0), 0);
544 }
545
546 static void arm7tdmi_branch_resume_thumb(struct target *target)
547 {
548         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
549         struct arm *arm = &arm7_9->arm;
550         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
551         struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
552
553         LOG_DEBUG("-");
554
555         /* LDMIA r0, [r0] at debug speed
556          * register values will start to appear on 4th DCLK
557          */
558         arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), NULL, 0);
559
560         /* fetch NOP, LDM in DECODE stage */
561         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
562         /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
563         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
564         /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
565         arm7tdmi_clock_out(jtag_info,
566                         buf_get_u32(arm->pc->value, 0, 32) | 1, NULL, 0);
567         /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
568         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
569
570         /* Branch and eXchange */
571         arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), NULL, 0);
572
573         embeddedice_read_reg(dbg_stat);
574
575         /* fetch NOP, BX in DECODE stage */
576         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
577
578         /* target is now in Thumb state */
579         embeddedice_read_reg(dbg_stat);
580
581         /* fetch NOP, BX in EXECUTE stage (1st cycle) */
582         arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
583
584         /* target is now in Thumb state */
585         embeddedice_read_reg(dbg_stat);
586
587         /* load r0 value */
588         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
589         /* fetch NOP, LDR in Decode */
590         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
591         /* fetch NOP, LDR in Execute */
592         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
593         /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
594         arm7tdmi_clock_out(jtag_info, buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32), NULL, 0);
595         /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
596         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
597
598         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
599         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
600
601         embeddedice_read_reg(dbg_stat);
602
603         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1);
604         arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0);
605 }
606
607 static void arm7tdmi_build_reg_cache(struct target *target)
608 {
609         struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
610         struct arm *arm = target_to_arm(target);
611
612         (*cache_p) = arm_build_reg_cache(target, arm);
613 }
614
615 int arm7tdmi_init_target(struct command_context *cmd_ctx, struct target *target)
616 {
617         arm7tdmi_build_reg_cache(target);
618
619         return ERROR_OK;
620 }
621
622 int arm7tdmi_init_arch_info(struct target *target,
623                 struct arm7_9_common *arm7_9, struct jtag_tap *tap)
624 {
625         /* prepare JTAG information for the new target */
626         arm7_9->jtag_info.tap = tap;
627         arm7_9->jtag_info.scann_size = 4;
628
629         /* register arch-specific functions */
630         arm7_9->examine_debug_reason = arm7tdmi_examine_debug_reason;
631         arm7_9->change_to_arm = arm7tdmi_change_to_arm;
632         arm7_9->read_core_regs = arm7tdmi_read_core_regs;
633         arm7_9->read_core_regs_target_buffer = arm7tdmi_read_core_regs_target_buffer;
634         arm7_9->read_xpsr = arm7tdmi_read_xpsr;
635
636         arm7_9->write_xpsr = arm7tdmi_write_xpsr;
637         arm7_9->write_xpsr_im8 = arm7tdmi_write_xpsr_im8;
638         arm7_9->write_core_regs = arm7tdmi_write_core_regs;
639
640         arm7_9->load_word_regs = arm7tdmi_load_word_regs;
641         arm7_9->load_hword_reg = arm7tdmi_load_hword_reg;
642         arm7_9->load_byte_reg = arm7tdmi_load_byte_reg;
643
644         arm7_9->store_word_regs = arm7tdmi_store_word_regs;
645         arm7_9->store_hword_reg = arm7tdmi_store_hword_reg;
646         arm7_9->store_byte_reg = arm7tdmi_store_byte_reg;
647
648         arm7_9->write_pc = arm7tdmi_write_pc;
649         arm7_9->branch_resume = arm7tdmi_branch_resume;
650         arm7_9->branch_resume_thumb = arm7tdmi_branch_resume_thumb;
651
652         arm7_9->enable_single_step = arm7_9_enable_eice_step;
653         arm7_9->disable_single_step = arm7_9_disable_eice_step;
654
655         arm7_9->write_memory = arm7_9_write_memory;
656         arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
657
658         arm7_9->post_debug_entry = NULL;
659
660         arm7_9->pre_restore_context = NULL;
661
662         /* initialize arch-specific breakpoint handling */
663         arm7_9->arm_bkpt = 0xdeeedeee;
664         arm7_9->thumb_bkpt = 0xdeee;
665
666         arm7_9->dbgreq_adjust_pc = 2;
667
668         arm7_9_init_arch_info(target, arm7_9);
669
670         return ERROR_OK;
671 }
672
673 static int arm7tdmi_target_create(struct target *target, Jim_Interp *interp)
674 {
675         struct arm7_9_common *arm7_9;
676
677         arm7_9 = calloc(1, sizeof(struct arm7_9_common));
678         arm7tdmi_init_arch_info(target, arm7_9, target->tap);
679         arm7_9->arm.is_armv4 = true;
680
681         return ERROR_OK;
682 }
683
684 /** Holds methods for ARM7TDMI targets. */
685 struct target_type arm7tdmi_target = {
686         .name = "arm7tdmi",
687
688         .poll = arm7_9_poll,
689         .arch_state = arm_arch_state,
690
691         .target_request_data = arm7_9_target_request_data,
692
693         .halt = arm7_9_halt,
694         .resume = arm7_9_resume,
695         .step = arm7_9_step,
696
697         .assert_reset = arm7_9_assert_reset,
698         .deassert_reset = arm7_9_deassert_reset,
699         .soft_reset_halt = arm7_9_soft_reset_halt,
700
701         .get_gdb_reg_list = arm_get_gdb_reg_list,
702
703         .read_memory = arm7_9_read_memory,
704         .write_memory = arm7_9_write_memory_opt,
705
706         .checksum_memory = arm_checksum_memory,
707         .blank_check_memory = arm_blank_check_memory,
708
709         .run_algorithm = armv4_5_run_algorithm,
710
711         .add_breakpoint = arm7_9_add_breakpoint,
712         .remove_breakpoint = arm7_9_remove_breakpoint,
713         .add_watchpoint = arm7_9_add_watchpoint,
714         .remove_watchpoint = arm7_9_remove_watchpoint,
715
716         .commands  = arm7_9_command_handlers,
717         .target_create  = arm7tdmi_target_create,
718         .init_target = arm7tdmi_init_target,
719         .examine = arm7_9_examine,
720         .check_reset = arm7_9_check_reset,
721 };