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

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)