5b38d3ce7a1f91a5325c82268eecc3dbe9a6eaf0
[fw/openocd] / src / target / fa526.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2009 by Paulius Zaleckas                                *
5  *   paulius.zaleckas@gmail.com                                            *
6  ***************************************************************************/
7
8 /*
9  * FA526 is very similar to ARM920T with following differences:
10  *
11  * - execution pipeline is 6 steps
12  * - Unified TLB
13  * - has Branch Target Buffer
14  * - does not support reading of I/D cache contents
15  */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include "arm920t.h"
22 #include "target_type.h"
23 #include "arm_opcodes.h"
24
25 static void fa526_change_to_arm(struct target *target, uint32_t *r0, uint32_t *pc)
26 {
27         LOG_ERROR("%s: there is no Thumb state on FA526", __func__);
28 }
29
30 static void fa526_read_core_regs(struct target *target,
31                 uint32_t mask, uint32_t *core_regs[16])
32 {
33         int i;
34         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
35         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
36
37         /* STMIA r0-15, [r0] at debug speed
38          * register values will start to appear on 4th DCLK
39          */
40         arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
41
42         /* fetch NOP, STM in DECODE stage */
43         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
44         /* fetch NOP, STM in SHIFT stage */
45         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
46         /* fetch NOP, STM in EXECUTE stage (1st cycle) */
47         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
48
49         for (i = 0; i <= 15; i++) {
50                 if (mask & (1 << i))
51                         /* nothing fetched, STM in MEMORY (i'th cycle) */
52                         arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
53         }
54 }
55
56 static void fa526_read_core_regs_target_buffer(struct target *target,
57                 uint32_t mask, void *buffer, int size)
58 {
59         int i;
60         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
61         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
62         int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
63         uint32_t *buf_u32 = buffer;
64         uint16_t *buf_u16 = buffer;
65         uint8_t *buf_u8 = buffer;
66
67         /* STMIA r0-15, [r0] at debug speed
68          * register values will start to appear on 4th DCLK
69          */
70         arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
71
72         /* fetch NOP, STM in DECODE stage */
73         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
74         /* fetch NOP, STM in SHIFT stage */
75         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
76         /* fetch NOP, STM in EXECUTE stage (1st cycle) */
77         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
78
79         for (i = 0; i <= 15; i++) {
80                 if (mask & (1 << i))
81                         /* nothing fetched, STM in MEMORY (i'th cycle) */
82                         switch (size) {
83                                 case 4:
84                                         arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
85                                         break;
86                                 case 2:
87                                         arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
88                                         break;
89                                 case 1:
90                                         arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
91                                         break;
92                         }
93         }
94 }
95
96 static void fa526_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
97 {
98         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
99         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
100
101         /* MRS r0, cpsr */
102         arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
103         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
104         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
105         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
106         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
107         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
108
109         /* STR r0, [r15] */
110         arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
111         /* fetch NOP, STR in DECODE stage */
112         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
113         /* fetch NOP, STR in SHIFT stage */
114         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
115         /* fetch NOP, STR in EXECUTE stage (1st cycle) */
116         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
117         /* nothing fetched, STR in MEMORY */
118         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
119 }
120
121 static void fa526_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
122 {
123         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
124         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
125
126         LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
127
128         /* MSR1 fetched */
129         arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
130         /* MSR2 fetched, MSR1 in DECODE */
131         arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
132         /* MSR3 fetched, MSR1 in SHIFT, MSR2 in DECODE */
133         arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
134         /* MSR4 fetched, MSR1 in EXECUTE (1), MSR2 in SHIFT, MSR3 in DECODE */
135         arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
136         /* nothing fetched, MSR1 in EXECUTE (2) */
137         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
138         /* nothing fetched, MSR1 in EXECUTE (3) */
139         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
140         /* nothing fetched, MSR2 in EXECUTE (1), MSR3 in SHIFT, MSR4 in DECODE */
141         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
142         /* nothing fetched, MSR2 in EXECUTE (2) */
143         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
144         /* nothing fetched, MSR2 in EXECUTE (3) */
145         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
146         /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in SHIFT */
147         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
148         /* nothing fetched, MSR3 in EXECUTE (2) */
149         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
150         /* nothing fetched, MSR3 in EXECUTE (3) */
151         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
152         /* NOP fetched, MSR4 in EXECUTE (1) */
153         /* last MSR writes flags, which takes only one cycle */
154         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
155 }
156
157 static void fa526_write_xpsr_im8(struct target *target,
158                 uint8_t xpsr_im, int rot, int spsr)
159 {
160         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
161         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
162
163         LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
164
165         /* MSR fetched */
166         arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
167         /* NOP fetched, MSR in DECODE */
168         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
169         /* NOP fetched, MSR in SHIFT */
170         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
171         /* NOP fetched, MSR in EXECUTE (1) */
172         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
173
174         /* rot == 4 writes flags, which takes only one cycle */
175         if (rot != 4) {
176                 /* nothing fetched, MSR in EXECUTE (2) */
177                 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
178                 /* nothing fetched, MSR in EXECUTE (3) */
179                 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
180         }
181 }
182
183 static void fa526_write_core_regs(struct target *target,
184                 uint32_t mask, uint32_t core_regs[16])
185 {
186         int i;
187         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
188         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
189
190         /* LDMIA r0-15, [r0] at debug speed
191         * register values will start to appear on 4th DCLK
192         */
193         arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
194
195         /* fetch NOP, LDM in DECODE stage */
196         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
197         /* fetch NOP, LDM in SHIFT stage */
198         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
199         /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
200         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
201
202         for (i = 0; i <= 15; i++) {
203                 if (mask & (1 << i))
204                         /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
205                         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
206         }
207         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
208 }
209
210 static void fa526_write_pc(struct target *target, uint32_t pc)
211 {
212         struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
213         struct arm_jtag *jtag_info = &arm7_9->jtag_info;
214
215         /* LDMIA r0-15, [r0] at debug speed
216          * register values will start to appear on 4th DCLK
217          */
218         arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
219
220         /* fetch NOP, LDM in DECODE stage */
221         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
222         /* fetch NOP, LDM in SHIFT stage */
223         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
224         /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
225         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
226         /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
227         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
228         /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
229         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
230         /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
231         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
232         /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
233         arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
234 }
235
236 static void fa526_branch_resume_thumb(struct target *target)
237 {
238         LOG_ERROR("%s: there is no Thumb state on FA526", __func__);
239 }
240
241 static int fa526_init_arch_info_2(struct target *target,
242                 struct arm7_9_common *arm7_9, struct jtag_tap *tap)
243 {
244         /* prepare JTAG information for the new target */
245         arm7_9->jtag_info.tap = tap;
246         arm7_9->jtag_info.scann_size = 5;
247
248         /* register arch-specific functions */
249         arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
250         arm7_9->change_to_arm = fa526_change_to_arm;
251         arm7_9->read_core_regs = fa526_read_core_regs;
252         arm7_9->read_core_regs_target_buffer = fa526_read_core_regs_target_buffer;
253         arm7_9->read_xpsr = fa526_read_xpsr;
254
255         arm7_9->write_xpsr = fa526_write_xpsr;
256         arm7_9->write_xpsr_im8 = fa526_write_xpsr_im8;
257         arm7_9->write_core_regs = fa526_write_core_regs;
258
259         arm7_9->load_word_regs = arm9tdmi_load_word_regs;
260         arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
261         arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
262
263         arm7_9->store_word_regs = arm9tdmi_store_word_regs;
264         arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
265         arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
266
267         arm7_9->write_pc = fa526_write_pc;
268         arm7_9->branch_resume = arm9tdmi_branch_resume;
269         arm7_9->branch_resume_thumb = fa526_branch_resume_thumb;
270
271         arm7_9->enable_single_step = arm9tdmi_enable_single_step;
272         arm7_9->disable_single_step = arm9tdmi_disable_single_step;
273
274         arm7_9->write_memory = arm920t_write_memory;
275         arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
276
277         arm7_9->post_debug_entry = NULL;
278
279         arm7_9->pre_restore_context = NULL;
280
281         /* initialize arch-specific breakpoint handling */
282         arm7_9->arm_bkpt = 0xdeeedeee;
283         arm7_9->thumb_bkpt = 0xdeee;
284
285         arm7_9->dbgreq_adjust_pc = 3;
286
287         arm7_9_init_arch_info(target, arm7_9);
288
289         /* override use of DBGRQ, this is safe on ARM9TDMI */
290         arm7_9->use_dbgrq = 1;
291
292         /* all ARM9s have the vector catch register */
293         arm7_9->has_vector_catch = 1;
294
295         return ERROR_OK;
296 }
297
298 static int fa526_init_arch_info(struct target *target,
299                 struct arm920t_common *arm920t, struct jtag_tap *tap)
300 {
301         struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common;
302
303         /* initialize arm7/arm9 specific info (including armv4_5) */
304         fa526_init_arch_info_2(target, arm7_9, tap);
305
306         arm920t->common_magic = ARM920T_COMMON_MAGIC;
307
308         arm7_9->post_debug_entry = arm920t_post_debug_entry;
309         arm7_9->pre_restore_context = arm920t_pre_restore_context;
310
311         arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;
312         arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;
313         arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;
314         arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;
315         arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
316         arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
317         arm920t->armv4_5_mmu.has_tiny_pages = 1;
318         arm920t->armv4_5_mmu.mmu_enabled = 0;
319
320         /* disabling linefills leads to lockups, so keep them enabled for now
321          * this doesn't affect correctness, but might affect timing issues, if
322          * important data is evicted from the cache during the debug session
323          * */
324         arm920t->preserve_cache = 0;
325
326         /* override hw single-step capability from ARM9TDMI */
327         arm7_9->has_single_step = 1;
328
329         return ERROR_OK;
330 }
331
332 static int fa526_target_create(struct target *target, Jim_Interp *interp)
333 {
334         struct arm920t_common *arm920t = calloc(1, sizeof(struct arm920t_common));
335
336         return fa526_init_arch_info(target, arm920t, target->tap);
337 }
338
339 static void fa526_deinit_target(struct target *target)
340 {
341         struct arm *arm = target_to_arm(target);
342         struct arm920t_common *arm920t = target_to_arm920(target);
343
344         arm7_9_deinit(target);
345         arm_free_reg_cache(arm);
346         free(arm920t);
347 }
348
349 /** Holds methods for FA526 targets. */
350 struct target_type fa526_target = {
351         .name = "fa526",
352
353         .poll = arm7_9_poll,
354         .arch_state = arm920t_arch_state,
355
356         .target_request_data = arm7_9_target_request_data,
357
358         .halt = arm7_9_halt,
359         .resume = arm7_9_resume,
360         .step = arm7_9_step,
361
362         .assert_reset = arm7_9_assert_reset,
363         .deassert_reset = arm7_9_deassert_reset,
364         .soft_reset_halt = arm920t_soft_reset_halt,
365
366         .get_gdb_arch = arm_get_gdb_arch,
367         .get_gdb_reg_list = arm_get_gdb_reg_list,
368
369         .read_memory = arm920t_read_memory,
370         .write_memory = arm7_9_write_memory_opt,
371
372         .checksum_memory = arm_checksum_memory,
373         .blank_check_memory = arm_blank_check_memory,
374
375         .run_algorithm = armv4_5_run_algorithm,
376
377         .add_breakpoint = arm7_9_add_breakpoint,
378         .remove_breakpoint = arm7_9_remove_breakpoint,
379         .add_watchpoint = arm7_9_add_watchpoint,
380         .remove_watchpoint = arm7_9_remove_watchpoint,
381
382         .commands = arm920t_command_handlers,
383         .target_create = fa526_target_create,
384         .init_target = arm9tdmi_init_target,
385         .deinit_target = fa526_deinit_target,
386         .examine = arm7_9_examine,
387         .check_reset = arm7_9_check_reset,
388 };