d8285e49c8839ec818e94394ccae0df0eb7818b7
[openocd.git] / src / target / dsp563xx.c
1 /***************************************************************************
2 * Copyright (C) 2009-2011 by Mathias Kuester *
3 * mkdorg@users.sourceforge.net *
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 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <jim.h>
24
25 #include "target.h"
26 #include "breakpoints.h"
27 #include "target_type.h"
28 #include "algorithm.h"
29 #include "register.h"
30 #include "dsp563xx.h"
31 #include "dsp563xx_once.h"
32
33 #define ASM_REG_W_R0 0x60F400
34 #define ASM_REG_W_R1 0x61F400
35 #define ASM_REG_W_R2 0x62F400
36 #define ASM_REG_W_R3 0x63F400
37 #define ASM_REG_W_R4 0x64F400
38 #define ASM_REG_W_R5 0x65F400
39 #define ASM_REG_W_R6 0x66F400
40 #define ASM_REG_W_R7 0x67F400
41
42 #define ASM_REG_W_N0 0x70F400
43 #define ASM_REG_W_N1 0x71F400
44 #define ASM_REG_W_N2 0x72F400
45 #define ASM_REG_W_N3 0x73F400
46 #define ASM_REG_W_N4 0x74F400
47 #define ASM_REG_W_N5 0x75F400
48 #define ASM_REG_W_N6 0x76F400
49 #define ASM_REG_W_N7 0x77F400
50
51 #define ASM_REG_W_M0 0x05F420
52 #define ASM_REG_W_M1 0x05F421
53 #define ASM_REG_W_M2 0x05F422
54 #define ASM_REG_W_M3 0x05F423
55 #define ASM_REG_W_M4 0x05F424
56 #define ASM_REG_W_M5 0x05F425
57 #define ASM_REG_W_M6 0x05F426
58 #define ASM_REG_W_M7 0x05F427
59
60 #define ASM_REG_W_X0 0x44F400
61 #define ASM_REG_W_X1 0x45F400
62
63 #define ASM_REG_W_Y0 0x46F400
64 #define ASM_REG_W_Y1 0x47F400
65
66 #define ASM_REG_W_A0 0x50F400
67 #define ASM_REG_W_A1 0x54F400
68 #define ASM_REG_W_A2 0x52F400
69
70 #define ASM_REG_W_B0 0x51F400
71 #define ASM_REG_W_B1 0x55F400
72 #define ASM_REG_W_B2 0x53F400
73
74 #define ASM_REG_W_VBA 0x05F430
75 #define ASM_REG_W_OMR 0x05F43A
76 #define ASM_REG_W_EP 0x05F42A
77 #define ASM_REG_W_SC 0x05F431
78 #define ASM_REG_W_SZ 0x05F438
79 #define ASM_REG_W_SR 0x05F439
80 #define ASM_REG_W_SP 0x05F43B
81 #define ASM_REG_W_SSH 0x05F43C
82 #define ASM_REG_W_SSL 0x05F43D
83 #define ASM_REG_W_LA 0x05F43E
84 #define ASM_REG_W_LC 0x05F43F
85 #define ASM_REG_W_PC 0x000000
86 #define ASM_REG_W_IPRC 0xFFFFFF
87 #define ASM_REG_W_IPRP 0xFFFFFE
88
89 #define ASM_REG_W_BCR 0xFFFFFB
90 #define ASM_REG_W_DCR 0xFFFFFA
91 #define ASM_REG_W_AAR0 0xFFFFF9
92 #define ASM_REG_W_AAR1 0xFFFFF8
93 #define ASM_REG_W_AAR2 0xFFFFF7
94 #define ASM_REG_W_AAR3 0xFFFFF6
95
96 /*
97 * OBCR Register bit definitions
98 */
99 #define OBCR_b0_and_b1 ((0x0) << 10)
100 #define OBCR_b0_or_b1 ((0x1) << 10)
101 #define OBCR_b1_after_b0 ((0x2) << 10)
102 #define OBCR_b0_after_b1 ((0x3) << 10)
103
104 #define OBCR_BP_DISABLED (0x0)
105 #define OBCR_BP_MEM_P (0x1)
106 #define OBCR_BP_MEM_X (0x2)
107 #define OBCR_BP_MEM_Y (0x3)
108 #define OBCR_BP_ON_READ ((0x2) << 0)
109 #define OBCR_BP_ON_WRITE ((0x1) << 0)
110 #define OBCR_BP_CC_NOT_EQUAL ((0x0) << 2)
111 #define OBCR_BP_CC_EQUAL ((0x1) << 2)
112 #define OBCR_BP_CC_LESS_THAN ((0x2) << 2)
113 #define OBCR_BP_CC_GREATER_THAN ((0x3) << 2)
114
115 #define OBCR_BP_0(x) ((x)<<2)
116 #define OBCR_BP_1(x) ((x)<<6)
117
118
119 enum once_reg_idx {
120 ONCE_REG_IDX_OSCR = 0,
121 ONCE_REG_IDX_OMBC = 1,
122 ONCE_REG_IDX_OBCR = 2,
123 ONCE_REG_IDX_OMLR0 = 3,
124 ONCE_REG_IDX_OMLR1 = 4,
125 ONCE_REG_IDX_OGDBR = 5,
126 ONCE_REG_IDX_OPDBR = 6,
127 ONCE_REG_IDX_OPILR = 7,
128 ONCE_REG_IDX_PDB = 8,
129 ONCE_REG_IDX_OTC = 9,
130 ONCE_REG_IDX_OPABFR = 10,
131 ONCE_REG_IDX_OPABDR = 11,
132 ONCE_REG_IDX_OPABEX = 12,
133 ONCE_REG_IDX_OPABF0 = 13,
134 ONCE_REG_IDX_OPABF1 = 14,
135 ONCE_REG_IDX_OPABF2 = 15,
136 ONCE_REG_IDX_OPABF3 = 16,
137 ONCE_REG_IDX_OPABF4 = 17,
138 ONCE_REG_IDX_OPABF5 = 18,
139 ONCE_REG_IDX_OPABF6 = 19,
140 ONCE_REG_IDX_OPABF7 = 20,
141 ONCE_REG_IDX_OPABF8 = 21,
142 ONCE_REG_IDX_OPABF9 = 22,
143 ONCE_REG_IDX_OPABF10 = 23,
144 ONCE_REG_IDX_OPABF11 = 24,
145 };
146
147 static struct once_reg once_regs[] = {
148 {ONCE_REG_IDX_OSCR, DSP563XX_ONCE_OSCR, 24, "OSCR", 0},
149 {ONCE_REG_IDX_OMBC, DSP563XX_ONCE_OMBC, 24, "OMBC", 0},
150 {ONCE_REG_IDX_OBCR, DSP563XX_ONCE_OBCR, 24, "OBCR", 0},
151 {ONCE_REG_IDX_OMLR0, DSP563XX_ONCE_OMLR0, 24, "OMLR0", 0},
152 {ONCE_REG_IDX_OMLR1, DSP563XX_ONCE_OMLR1, 24, "OMLR1", 0},
153 {ONCE_REG_IDX_OGDBR, DSP563XX_ONCE_OGDBR, 24, "OGDBR", 0},
154 {ONCE_REG_IDX_OPDBR, DSP563XX_ONCE_OPDBR, 24, "OPDBR", 0},
155 {ONCE_REG_IDX_OPILR, DSP563XX_ONCE_OPILR, 24, "OPILR", 0},
156 {ONCE_REG_IDX_PDB, DSP563XX_ONCE_PDBGOTO, 24, "PDB", 0},
157 {ONCE_REG_IDX_OTC, DSP563XX_ONCE_OTC, 24, "OTC", 0},
158 {ONCE_REG_IDX_OPABFR, DSP563XX_ONCE_OPABFR, 24, "OPABFR", 0},
159 {ONCE_REG_IDX_OPABDR, DSP563XX_ONCE_OPABDR, 24, "OPABDR", 0},
160 {ONCE_REG_IDX_OPABEX, DSP563XX_ONCE_OPABEX, 24, "OPABEX", 0},
161 {ONCE_REG_IDX_OPABF0, DSP563XX_ONCE_OPABF11, 25, "OPABF0", 0},
162 {ONCE_REG_IDX_OPABF1, DSP563XX_ONCE_OPABF11, 25, "OPABF1", 0},
163 {ONCE_REG_IDX_OPABF2, DSP563XX_ONCE_OPABF11, 25, "OPABF2", 0},
164 {ONCE_REG_IDX_OPABF3, DSP563XX_ONCE_OPABF11, 25, "OPABF3", 0},
165 {ONCE_REG_IDX_OPABF4, DSP563XX_ONCE_OPABF11, 25, "OPABF4", 0},
166 {ONCE_REG_IDX_OPABF5, DSP563XX_ONCE_OPABF11, 25, "OPABF5", 0},
167 {ONCE_REG_IDX_OPABF6, DSP563XX_ONCE_OPABF11, 25, "OPABF6", 0},
168 {ONCE_REG_IDX_OPABF7, DSP563XX_ONCE_OPABF11, 25, "OPABF7", 0},
169 {ONCE_REG_IDX_OPABF8, DSP563XX_ONCE_OPABF11, 25, "OPABF8", 0},
170 {ONCE_REG_IDX_OPABF9, DSP563XX_ONCE_OPABF11, 25, "OPABF9", 0},
171 {ONCE_REG_IDX_OPABF10, DSP563XX_ONCE_OPABF11, 25, "OPABF10", 0},
172 {ONCE_REG_IDX_OPABF11, DSP563XX_ONCE_OPABF11, 25, "OPABF11", 0},
173 /* {25,0x1f,24,"NRSEL",0}, */
174 };
175
176 enum dsp563xx_reg_idx {
177 DSP563XX_REG_IDX_R0 = 0,
178 DSP563XX_REG_IDX_R1 = 1,
179 DSP563XX_REG_IDX_R2 = 2,
180 DSP563XX_REG_IDX_R3 = 3,
181 DSP563XX_REG_IDX_R4 = 4,
182 DSP563XX_REG_IDX_R5 = 5,
183 DSP563XX_REG_IDX_R6 = 6,
184 DSP563XX_REG_IDX_R7 = 7,
185 DSP563XX_REG_IDX_N0 = 8,
186 DSP563XX_REG_IDX_N1 = 9,
187 DSP563XX_REG_IDX_N2 = 10,
188 DSP563XX_REG_IDX_N3 = 11,
189 DSP563XX_REG_IDX_N4 = 12,
190 DSP563XX_REG_IDX_N5 = 13,
191 DSP563XX_REG_IDX_N6 = 14,
192 DSP563XX_REG_IDX_N7 = 15,
193 DSP563XX_REG_IDX_M0 = 16,
194 DSP563XX_REG_IDX_M1 = 17,
195 DSP563XX_REG_IDX_M2 = 18,
196 DSP563XX_REG_IDX_M3 = 19,
197 DSP563XX_REG_IDX_M4 = 20,
198 DSP563XX_REG_IDX_M5 = 21,
199 DSP563XX_REG_IDX_M6 = 22,
200 DSP563XX_REG_IDX_M7 = 23,
201 DSP563XX_REG_IDX_X0 = 24,
202 DSP563XX_REG_IDX_X1 = 25,
203 DSP563XX_REG_IDX_Y0 = 26,
204 DSP563XX_REG_IDX_Y1 = 27,
205 DSP563XX_REG_IDX_A0 = 28,
206 DSP563XX_REG_IDX_A1 = 29,
207 DSP563XX_REG_IDX_A2 = 30,
208 DSP563XX_REG_IDX_B0 = 31,
209 DSP563XX_REG_IDX_B1 = 32,
210 DSP563XX_REG_IDX_B2 = 33,
211 DSP563XX_REG_IDX_SSH = 34,
212 DSP563XX_REG_IDX_SSL = 35,
213 DSP563XX_REG_IDX_SP = 36,
214 DSP563XX_REG_IDX_EP = 37,
215 DSP563XX_REG_IDX_SZ = 38,
216 DSP563XX_REG_IDX_SC = 39,
217 DSP563XX_REG_IDX_PC = 40,
218 DSP563XX_REG_IDX_SR = 41,
219 DSP563XX_REG_IDX_OMR = 42,
220 DSP563XX_REG_IDX_LA = 43,
221 DSP563XX_REG_IDX_LC = 44,
222 DSP563XX_REG_IDX_VBA = 45,
223 DSP563XX_REG_IDX_IPRC = 46,
224 DSP563XX_REG_IDX_IPRP = 47,
225 DSP563XX_REG_IDX_BCR = 48,
226 DSP563XX_REG_IDX_DCR = 49,
227 DSP563XX_REG_IDX_AAR0 = 50,
228 DSP563XX_REG_IDX_AAR1 = 51,
229 DSP563XX_REG_IDX_AAR2 = 52,
230 DSP563XX_REG_IDX_AAR3 = 53,
231 };
232
233 static const struct {
234 unsigned id;
235 const char *name;
236 unsigned bits;
237 /* effective addressing mode encoding */
238 uint8_t eame;
239 uint32_t instr_mask;
240 } dsp563xx_regs[] = {
241 /* *INDENT-OFF* */
242 /* address registers */
243 {DSP563XX_REG_IDX_R0, "r0", 24, 0x10, ASM_REG_W_R0},
244 {DSP563XX_REG_IDX_R1, "r1", 24, 0x11, ASM_REG_W_R1},
245 {DSP563XX_REG_IDX_R2, "r2", 24, 0x12, ASM_REG_W_R2},
246 {DSP563XX_REG_IDX_R3, "r3", 24, 0x13, ASM_REG_W_R3},
247 {DSP563XX_REG_IDX_R4, "r4", 24, 0x14, ASM_REG_W_R4},
248 {DSP563XX_REG_IDX_R5, "r5", 24, 0x15, ASM_REG_W_R5},
249 {DSP563XX_REG_IDX_R6, "r6", 24, 0x16, ASM_REG_W_R6},
250 {DSP563XX_REG_IDX_R7, "r7", 24, 0x17, ASM_REG_W_R7},
251 /* offset registers */
252 {DSP563XX_REG_IDX_N0, "n0", 24, 0x18, ASM_REG_W_N0},
253 {DSP563XX_REG_IDX_N1, "n1", 24, 0x19, ASM_REG_W_N1},
254 {DSP563XX_REG_IDX_N2, "n2", 24, 0x1a, ASM_REG_W_N2},
255 {DSP563XX_REG_IDX_N3, "n3", 24, 0x1b, ASM_REG_W_N3},
256 {DSP563XX_REG_IDX_N4, "n4", 24, 0x1c, ASM_REG_W_N4},
257 {DSP563XX_REG_IDX_N5, "n5", 24, 0x1d, ASM_REG_W_N5},
258 {DSP563XX_REG_IDX_N6, "n6", 24, 0x1e, ASM_REG_W_N6},
259 {DSP563XX_REG_IDX_N7, "n7", 24, 0x1f, ASM_REG_W_N7},
260 /* modifier registers */
261 {DSP563XX_REG_IDX_M0, "m0", 24, 0x20, ASM_REG_W_M0},
262 {DSP563XX_REG_IDX_M1, "m1", 24, 0x21, ASM_REG_W_M1},
263 {DSP563XX_REG_IDX_M2, "m2", 24, 0x22, ASM_REG_W_M2},
264 {DSP563XX_REG_IDX_M3, "m3", 24, 0x23, ASM_REG_W_M3},
265 {DSP563XX_REG_IDX_M4, "m4", 24, 0x24, ASM_REG_W_M4},
266 {DSP563XX_REG_IDX_M5, "m5", 24, 0x25, ASM_REG_W_M5},
267 {DSP563XX_REG_IDX_M6, "m6", 24, 0x26, ASM_REG_W_M6},
268 {DSP563XX_REG_IDX_M7, "m7", 24, 0x27, ASM_REG_W_M7},
269 /* data alu input register */
270 {DSP563XX_REG_IDX_X0, "x0", 24, 0x04, ASM_REG_W_X0},
271 {DSP563XX_REG_IDX_X1, "x1", 24, 0x05, ASM_REG_W_X1},
272 {DSP563XX_REG_IDX_Y0, "y0", 24, 0x06, ASM_REG_W_Y0},
273 {DSP563XX_REG_IDX_Y1, "y1", 24, 0x07, ASM_REG_W_Y1},
274 /* data alu accumulator register */
275 {DSP563XX_REG_IDX_A0, "a0", 24, 0x08, ASM_REG_W_A0},
276 {DSP563XX_REG_IDX_A1, "a1", 24, 0x0c, ASM_REG_W_A1},
277 {DSP563XX_REG_IDX_A2, "a2", 8, 0x0a, ASM_REG_W_A2},
278 {DSP563XX_REG_IDX_B0, "b0", 24, 0x09, ASM_REG_W_B0},
279 {DSP563XX_REG_IDX_B1, "b1", 24, 0x0d, ASM_REG_W_B1},
280 {DSP563XX_REG_IDX_B2, "b2", 8, 0x0b, ASM_REG_W_B2},
281 /* stack */
282 {DSP563XX_REG_IDX_SSH, "ssh", 24, 0x3c, ASM_REG_W_SSH},
283 {DSP563XX_REG_IDX_SSL, "ssl", 24, 0x3d, ASM_REG_W_SSL},
284 {DSP563XX_REG_IDX_SP, "sp", 24, 0x3b, ASM_REG_W_SP},
285 {DSP563XX_REG_IDX_EP, "ep", 24, 0x2a, ASM_REG_W_EP},
286 {DSP563XX_REG_IDX_SZ, "sz", 24, 0x38, ASM_REG_W_SZ},
287 {DSP563XX_REG_IDX_SC, "sc", 24, 0x31, ASM_REG_W_SC},
288 /* system */
289 {DSP563XX_REG_IDX_PC, "pc", 24, 0x00, ASM_REG_W_PC},
290 {DSP563XX_REG_IDX_SR, "sr", 24, 0x39, ASM_REG_W_SR},
291 {DSP563XX_REG_IDX_OMR, "omr", 24, 0x3a, ASM_REG_W_OMR},
292 {DSP563XX_REG_IDX_LA, "la", 24, 0x3e, ASM_REG_W_LA},
293 {DSP563XX_REG_IDX_LC, "lc", 24, 0x3f, ASM_REG_W_LC},
294 /* interrupt */
295 {DSP563XX_REG_IDX_VBA, "vba", 24, 0x30, ASM_REG_W_VBA},
296 {DSP563XX_REG_IDX_IPRC, "iprc", 24, 0x00, ASM_REG_W_IPRC},
297 {DSP563XX_REG_IDX_IPRP, "iprp", 24, 0x00, ASM_REG_W_IPRP},
298 /* port a */
299 {DSP563XX_REG_IDX_BCR, "bcr", 24, 0x00, ASM_REG_W_BCR},
300 {DSP563XX_REG_IDX_DCR, "dcr", 24, 0x00, ASM_REG_W_DCR},
301 {DSP563XX_REG_IDX_AAR0, "aar0", 24, 0x00, ASM_REG_W_AAR0},
302 {DSP563XX_REG_IDX_AAR1, "aar1", 24, 0x00, ASM_REG_W_AAR1},
303 {DSP563XX_REG_IDX_AAR2, "aar2", 24, 0x00, ASM_REG_W_AAR2},
304 {DSP563XX_REG_IDX_AAR3, "aar3", 24, 0x00, ASM_REG_W_AAR3},
305 /* *INDENT-ON* */
306 };
307
308 enum memory_type {
309 MEM_X = 0,
310 MEM_Y = 1,
311 MEM_P = 2,
312 MEM_L = 3,
313 };
314
315 enum watchpoint_condition {
316 EQUAL,
317 NOT_EQUAL,
318 GREATER,
319 LESS_THAN
320 };
321
322 #define INSTR_JUMP 0x0AF080
323 /* Effective Addressing Mode Encoding */
324 #define EAME_R0 0x10
325 /* instrcution encoder */
326 /* movep
327 * s - peripheral space X/Y (X=0,Y=1)
328 * w - write/read
329 * d - source/destination register
330 * p - IO short address
331 */
332 #define INSTR_MOVEP_REG_HIO(s, w, d, p) (0x084000 | \
333 ((s & 1) << 16) | ((w & 1) << 15) | ((d & 0x3f) << 8) | (p & 0x3f))
334
335 /* the gdb register list is send in this order */
336 static const uint8_t gdb_reg_list_idx[] = {
337 DSP563XX_REG_IDX_X1, DSP563XX_REG_IDX_X0, DSP563XX_REG_IDX_Y1, DSP563XX_REG_IDX_Y0,
338 DSP563XX_REG_IDX_A2, DSP563XX_REG_IDX_A1, DSP563XX_REG_IDX_A0, DSP563XX_REG_IDX_B2,
339 DSP563XX_REG_IDX_B1, DSP563XX_REG_IDX_B0, DSP563XX_REG_IDX_PC, DSP563XX_REG_IDX_SR,
340 DSP563XX_REG_IDX_OMR, DSP563XX_REG_IDX_LA, DSP563XX_REG_IDX_LC, DSP563XX_REG_IDX_SSH,
341 DSP563XX_REG_IDX_SSL, DSP563XX_REG_IDX_SP, DSP563XX_REG_IDX_EP, DSP563XX_REG_IDX_SZ,
342 DSP563XX_REG_IDX_SC, DSP563XX_REG_IDX_VBA, DSP563XX_REG_IDX_IPRC, DSP563XX_REG_IDX_IPRP,
343 DSP563XX_REG_IDX_BCR, DSP563XX_REG_IDX_DCR, DSP563XX_REG_IDX_AAR0, DSP563XX_REG_IDX_AAR1,
344 DSP563XX_REG_IDX_AAR2, DSP563XX_REG_IDX_AAR3, DSP563XX_REG_IDX_R0, DSP563XX_REG_IDX_R1,
345 DSP563XX_REG_IDX_R2, DSP563XX_REG_IDX_R3, DSP563XX_REG_IDX_R4, DSP563XX_REG_IDX_R5,
346 DSP563XX_REG_IDX_R6, DSP563XX_REG_IDX_R7, DSP563XX_REG_IDX_N0, DSP563XX_REG_IDX_N1,
347 DSP563XX_REG_IDX_N2, DSP563XX_REG_IDX_N3, DSP563XX_REG_IDX_N4, DSP563XX_REG_IDX_N5,
348 DSP563XX_REG_IDX_N6, DSP563XX_REG_IDX_N7, DSP563XX_REG_IDX_M0, DSP563XX_REG_IDX_M1,
349 DSP563XX_REG_IDX_M2, DSP563XX_REG_IDX_M3, DSP563XX_REG_IDX_M4, DSP563XX_REG_IDX_M5,
350 DSP563XX_REG_IDX_M6, DSP563XX_REG_IDX_M7,
351 };
352
353 static int dsp563xx_get_gdb_reg_list(struct target *target,
354 struct reg **reg_list[],
355 int *reg_list_size,
356 enum target_register_class reg_class)
357 {
358 int i;
359 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
360
361 if (target->state != TARGET_HALTED)
362 return ERROR_TARGET_NOT_HALTED;
363
364 *reg_list_size = DSP563XX_NUMCOREREGS;
365 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
366
367 if (!*reg_list)
368 return ERROR_COMMAND_SYNTAX_ERROR;
369
370 for (i = 0; i < DSP563XX_NUMCOREREGS; i++)
371 (*reg_list)[i] = &dsp563xx->core_cache->reg_list[gdb_reg_list_idx[i]];
372
373 return ERROR_OK;
374
375 }
376
377 static int dsp563xx_read_core_reg(struct target *target, int num)
378 {
379 uint32_t reg_value;
380 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
381
382 if ((num < 0) || (num >= DSP563XX_NUMCOREREGS))
383 return ERROR_COMMAND_SYNTAX_ERROR;
384
385 reg_value = dsp563xx->core_regs[num];
386 buf_set_u32(dsp563xx->core_cache->reg_list[num].value, 0, 32, reg_value);
387 dsp563xx->core_cache->reg_list[num].valid = true;
388 dsp563xx->core_cache->reg_list[num].dirty = false;
389
390 return ERROR_OK;
391 }
392
393 static int dsp563xx_write_core_reg(struct target *target, int num)
394 {
395 uint32_t reg_value;
396 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
397
398 if ((num < 0) || (num >= DSP563XX_NUMCOREREGS))
399 return ERROR_COMMAND_SYNTAX_ERROR;
400
401 reg_value = buf_get_u32(dsp563xx->core_cache->reg_list[num].value, 0, 32);
402 dsp563xx->core_regs[num] = reg_value;
403 dsp563xx->core_cache->reg_list[num].valid = true;
404 dsp563xx->core_cache->reg_list[num].dirty = false;
405
406 return ERROR_OK;
407 }
408
409 static int dsp563xx_get_core_reg(struct reg *reg)
410 {
411 struct dsp563xx_core_reg *dsp563xx_reg = reg->arch_info;
412 struct target *target = dsp563xx_reg->target;
413 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
414
415 LOG_DEBUG("%s", __func__);
416
417 if (target->state != TARGET_HALTED)
418 return ERROR_TARGET_NOT_HALTED;
419
420 return dsp563xx->read_core_reg(target, dsp563xx_reg->num);
421 }
422
423 static int dsp563xx_set_core_reg(struct reg *reg, uint8_t *buf)
424 {
425 LOG_DEBUG("%s", __func__);
426
427 struct dsp563xx_core_reg *dsp563xx_reg = reg->arch_info;
428 struct target *target = dsp563xx_reg->target;
429 uint32_t value = buf_get_u32(buf, 0, 32);
430
431 if (target->state != TARGET_HALTED)
432 return ERROR_TARGET_NOT_HALTED;
433
434 buf_set_u32(reg->value, 0, reg->size, value);
435 reg->dirty = true;
436 reg->valid = true;
437
438 return ERROR_OK;
439 }
440
441 static const struct reg_arch_type dsp563xx_reg_type = {
442 .get = dsp563xx_get_core_reg,
443 .set = dsp563xx_set_core_reg,
444 };
445
446 static void dsp563xx_build_reg_cache(struct target *target)
447 {
448 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
449
450 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
451 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
452 struct reg *reg_list = calloc(DSP563XX_NUMCOREREGS, sizeof(struct reg));
453 struct dsp563xx_core_reg *arch_info = malloc(
454 sizeof(struct dsp563xx_core_reg) * DSP563XX_NUMCOREREGS);
455 int i;
456
457 /* Build the process context cache */
458 cache->name = "dsp563xx registers";
459 cache->next = NULL;
460 cache->reg_list = reg_list;
461 cache->num_regs = DSP563XX_NUMCOREREGS;
462 (*cache_p) = cache;
463 dsp563xx->core_cache = cache;
464
465 for (i = 0; i < DSP563XX_NUMCOREREGS; i++) {
466 arch_info[i].num = dsp563xx_regs[i].id;
467 arch_info[i].name = dsp563xx_regs[i].name;
468 arch_info[i].size = dsp563xx_regs[i].bits;
469 arch_info[i].eame = dsp563xx_regs[i].eame;
470 arch_info[i].instr_mask = dsp563xx_regs[i].instr_mask;
471 arch_info[i].target = target;
472 arch_info[i].dsp563xx_common = dsp563xx;
473 reg_list[i].name = dsp563xx_regs[i].name;
474 reg_list[i].size = 32; /* dsp563xx_regs[i].bits; */
475 reg_list[i].value = calloc(1, 4);
476 reg_list[i].dirty = false;
477 reg_list[i].valid = false;
478 reg_list[i].type = &dsp563xx_reg_type;
479 reg_list[i].arch_info = &arch_info[i];
480 }
481 }
482
483 static int dsp563xx_read_register(struct target *target, int num, int force);
484 static int dsp563xx_write_register(struct target *target, int num, int force);
485
486 static int dsp563xx_reg_read_high_io(struct target *target, uint32_t instr_mask, uint32_t *data)
487 {
488 int err;
489 uint32_t instr;
490 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
491
492 /* we use r0 to store temporary data */
493 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
494 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
495
496 /* move source memory to r0 */
497 instr = INSTR_MOVEP_REG_HIO(MEM_X, 0, EAME_R0, instr_mask);
498 err = dsp563xx_once_execute_sw_ir(target->tap, 0, instr);
499 if (err != ERROR_OK)
500 return err;
501 /* move r0 to debug register */
502 instr = INSTR_MOVEP_REG_HIO(MEM_X, 1, EAME_R0, 0xfffffc);
503 err = dsp563xx_once_execute_sw_ir(target->tap, 1, instr);
504 if (err != ERROR_OK)
505 return err;
506 /* read debug register */
507 err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OGDBR, data);
508 if (err != ERROR_OK)
509 return err;
510 /* r0 is no longer valid on target */
511 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = true;
512
513 return ERROR_OK;
514 }
515
516 static int dsp563xx_reg_write_high_io(struct target *target, uint32_t instr_mask, uint32_t data)
517 {
518 int err;
519 uint32_t instr;
520 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
521
522 /* we use r0 to store temporary data */
523 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
524 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
525
526 /* move data to r0 */
527 err = dsp563xx_once_execute_dw_ir(target->tap, 0, 0x60F400, data);
528 if (err != ERROR_OK)
529 return err;
530 /* move r0 to destination memory */
531 instr = INSTR_MOVEP_REG_HIO(MEM_X, 1, EAME_R0, instr_mask);
532 err = dsp563xx_once_execute_sw_ir(target->tap, 1, instr);
533 if (err != ERROR_OK)
534 return err;
535
536 /* r0 is no longer valid on target */
537 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = true;
538
539 return ERROR_OK;
540 }
541
542 static int dsp563xx_reg_read(struct target *target, uint32_t eame, uint32_t *data)
543 {
544 int err;
545 uint32_t instr;
546
547 instr = INSTR_MOVEP_REG_HIO(MEM_X, 1, eame, 0xfffffc);
548 err = dsp563xx_once_execute_sw_ir(target->tap, 0, instr);
549 if (err != ERROR_OK)
550 return err;
551 /* nop */
552 err = dsp563xx_once_execute_sw_ir(target->tap, 1, 0x000000);
553 if (err != ERROR_OK)
554 return err;
555 /* read debug register */
556 return dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OGDBR, data);
557 }
558
559 static int dsp563xx_reg_write(struct target *target, uint32_t instr_mask, uint32_t data)
560 {
561 int err;
562
563 err = dsp563xx_once_execute_dw_ir(target->tap, 0, instr_mask, data);
564 if (err != ERROR_OK)
565 return err;
566 /* nop */
567 return dsp563xx_once_execute_sw_ir(target->tap, 1, 0x000000);
568 }
569
570 static int dsp563xx_reg_pc_read(struct target *target)
571 {
572 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
573
574 /* pc was changed, nothing todo */
575 if (dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty)
576 return ERROR_OK;
577
578 /* conditional branch check */
579 if (once_regs[ONCE_REG_IDX_OPABDR].reg == once_regs[ONCE_REG_IDX_OPABEX].reg) {
580 if ((once_regs[ONCE_REG_IDX_OPABF11].reg & 1) == 0) {
581 LOG_DEBUG("%s conditional branch not supported yet (0x%" PRIx32 " 0x%" PRIx32 " 0x%" PRIx32 ")",
582 __func__,
583 (once_regs[ONCE_REG_IDX_OPABF11].reg >> 1),
584 once_regs[ONCE_REG_IDX_OPABDR].reg,
585 once_regs[ONCE_REG_IDX_OPABEX].reg);
586
587 /* TODO: use disassembly to set correct pc offset
588 * read 2 words from OPABF11 and disasm the instruction
589 */
590 dsp563xx->core_regs[DSP563XX_REG_IDX_PC] =
591 (once_regs[ONCE_REG_IDX_OPABF11].reg >> 1) & 0x00FFFFFF;
592 } else {
593 if (once_regs[ONCE_REG_IDX_OPABEX].reg ==
594 once_regs[ONCE_REG_IDX_OPABFR].reg)
595 dsp563xx->core_regs[DSP563XX_REG_IDX_PC] =
596 once_regs[ONCE_REG_IDX_OPABEX].reg;
597 else
598 dsp563xx->core_regs[DSP563XX_REG_IDX_PC] =
599 once_regs[ONCE_REG_IDX_OPABEX].reg - 1;
600 }
601 } else
602 dsp563xx->core_regs[DSP563XX_REG_IDX_PC] = once_regs[ONCE_REG_IDX_OPABEX].reg;
603
604 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_PC);
605
606 return ERROR_OK;
607 }
608
609 static int dsp563xx_reg_ssh_read(struct target *target)
610 {
611 int err;
612 uint32_t sp;
613 struct dsp563xx_core_reg *arch_info;
614 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
615
616 arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSH].arch_info;
617
618 /* get a valid stack pointer */
619 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 0);
620 if (err != ERROR_OK)
621 return err;
622 sp = dsp563xx->core_regs[DSP563XX_REG_IDX_SP];
623 err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SP, 0);
624 if (err != ERROR_OK)
625 return err;
626
627 /* get a valid stack count */
628 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SC, 0);
629 if (err != ERROR_OK)
630 return err;
631
632 err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SC, 0);
633 if (err != ERROR_OK)
634 return err;
635
636 /* get a valid extended pointer */
637 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_EP, 0);
638 if (err != ERROR_OK)
639 return err;
640
641 err = dsp563xx_write_register(target, DSP563XX_REG_IDX_EP, 0);
642 if (err != ERROR_OK)
643 return err;
644
645 if (!sp)
646 sp = 0x00FFFFFF;
647 else {
648 err = dsp563xx_reg_read(target, arch_info->eame, &sp);
649 if (err != ERROR_OK)
650 return err;
651
652 err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SC, 1);
653 if (err != ERROR_OK)
654 return err;
655 err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SP, 1);
656 if (err != ERROR_OK)
657 return err;
658 err = dsp563xx_write_register(target, DSP563XX_REG_IDX_EP, 1);
659 if (err != ERROR_OK)
660 return err;
661 }
662
663 dsp563xx->core_regs[DSP563XX_REG_IDX_SSH] = sp;
664 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_SSH);
665
666 return ERROR_OK;
667 }
668
669 static int dsp563xx_reg_ssh_write(struct target *target)
670 {
671 int err;
672 uint32_t sp;
673 struct dsp563xx_core_reg *arch_info;
674 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
675
676 arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSH].arch_info;
677
678 /* get a valid stack pointer */
679 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 0);
680 if (err != ERROR_OK)
681 return err;
682 sp = dsp563xx->core_regs[DSP563XX_REG_IDX_SP];
683
684 if (sp) {
685 sp--;
686 /* write new stackpointer */
687 dsp563xx->core_regs[DSP563XX_REG_IDX_SP] = sp;
688 err = dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_SP);
689 if (err != ERROR_OK)
690 return err;
691 err = dsp563xx_write_register(target, DSP563XX_REG_IDX_SP, 1);
692 if (err != ERROR_OK)
693 return err;
694
695 err = dsp563xx_reg_write(target, arch_info->instr_mask,
696 dsp563xx->core_regs[DSP563XX_REG_IDX_SSH]);
697 if (err != ERROR_OK)
698 return err;
699
700 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 1);
701 if (err != ERROR_OK)
702 return err;
703 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SSH, 1);
704 if (err != ERROR_OK)
705 return err;
706 }
707
708 return ERROR_OK;
709 }
710
711 static int dsp563xx_reg_ssl_read(struct target *target)
712 {
713 int err;
714 uint32_t sp;
715 struct dsp563xx_core_reg *arch_info;
716 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
717
718 arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSL].arch_info;
719
720 /* get a valid stack pointer */
721 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SP, 0);
722 if (err != ERROR_OK)
723 return err;
724 sp = dsp563xx->core_regs[DSP563XX_REG_IDX_SP];
725
726 if (!sp)
727 sp = 0x00FFFFFF;
728 else {
729 err = dsp563xx_reg_read(target, arch_info->eame, &sp);
730 if (err != ERROR_OK)
731 return err;
732 }
733
734 dsp563xx->core_regs[DSP563XX_REG_IDX_SSL] = sp;
735 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_SSL);
736
737 return ERROR_OK;
738 }
739
740 static int dsp563xx_read_register(struct target *target, int num, int force)
741 {
742 int err = ERROR_OK;
743 uint32_t data = 0;
744 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
745 struct dsp563xx_core_reg *arch_info;
746
747 if (force)
748 dsp563xx->core_cache->reg_list[num].valid = false;
749
750 if (!dsp563xx->core_cache->reg_list[num].valid) {
751 arch_info = dsp563xx->core_cache->reg_list[num].arch_info;
752
753 switch (arch_info->num) {
754 case DSP563XX_REG_IDX_SSH:
755 err = dsp563xx_reg_ssh_read(target);
756 break;
757 case DSP563XX_REG_IDX_SSL:
758 err = dsp563xx_reg_ssl_read(target);
759 break;
760 case DSP563XX_REG_IDX_PC:
761 err = dsp563xx_reg_pc_read(target);
762 break;
763 case DSP563XX_REG_IDX_IPRC:
764 case DSP563XX_REG_IDX_IPRP:
765 case DSP563XX_REG_IDX_BCR:
766 case DSP563XX_REG_IDX_DCR:
767 case DSP563XX_REG_IDX_AAR0:
768 case DSP563XX_REG_IDX_AAR1:
769 case DSP563XX_REG_IDX_AAR2:
770 case DSP563XX_REG_IDX_AAR3:
771 err = dsp563xx_reg_read_high_io(target,
772 arch_info->instr_mask, &data);
773 if (err == ERROR_OK) {
774 dsp563xx->core_regs[num] = data;
775 dsp563xx->read_core_reg(target, num);
776 }
777 break;
778 default:
779 err = dsp563xx_reg_read(target, arch_info->eame, &data);
780 if (err == ERROR_OK) {
781 dsp563xx->core_regs[num] = data;
782 dsp563xx->read_core_reg(target, num);
783 }
784 break;
785 }
786 }
787
788 return err;
789 }
790
791 static int dsp563xx_write_register(struct target *target, int num, int force)
792 {
793 int err = ERROR_OK;
794 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
795 struct dsp563xx_core_reg *arch_info;
796
797 if (force)
798 dsp563xx->core_cache->reg_list[num].dirty = true;
799
800 if (dsp563xx->core_cache->reg_list[num].dirty) {
801 arch_info = dsp563xx->core_cache->reg_list[num].arch_info;
802
803 dsp563xx->write_core_reg(target, num);
804
805 switch (arch_info->num) {
806 case DSP563XX_REG_IDX_SSH:
807 err = dsp563xx_reg_ssh_write(target);
808 break;
809 case DSP563XX_REG_IDX_PC:
810 /* pc is updated on resume, no need to write it here */
811 break;
812 case DSP563XX_REG_IDX_IPRC:
813 case DSP563XX_REG_IDX_IPRP:
814 case DSP563XX_REG_IDX_BCR:
815 case DSP563XX_REG_IDX_DCR:
816 case DSP563XX_REG_IDX_AAR0:
817 case DSP563XX_REG_IDX_AAR1:
818 case DSP563XX_REG_IDX_AAR2:
819 case DSP563XX_REG_IDX_AAR3:
820 err = dsp563xx_reg_write_high_io(target,
821 arch_info->instr_mask,
822 dsp563xx->core_regs[num]);
823 break;
824 default:
825 err = dsp563xx_reg_write(target,
826 arch_info->instr_mask,
827 dsp563xx->core_regs[num]);
828
829 if ((err == ERROR_OK) && (arch_info->num == DSP563XX_REG_IDX_SP)) {
830 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSH].valid =
831 0;
832 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SSL].valid =
833 0;
834 }
835
836 break;
837 }
838 }
839
840 return err;
841 }
842
843 static int dsp563xx_save_context(struct target *target)
844 {
845 int i, err = ERROR_OK;
846
847 for (i = 0; i < DSP563XX_NUMCOREREGS; i++) {
848 err = dsp563xx_read_register(target, i, 0);
849 if (err != ERROR_OK)
850 break;
851 }
852
853 return err;
854 }
855
856 static int dsp563xx_restore_context(struct target *target)
857 {
858 int i, err = ERROR_OK;
859
860 for (i = 0; i < DSP563XX_NUMCOREREGS; i++) {
861 err = dsp563xx_write_register(target, i, 0);
862 if (err != ERROR_OK)
863 break;
864 }
865
866 return err;
867 }
868
869 static void dsp563xx_invalidate_x_context(struct target *target,
870 uint32_t addr_start,
871 uint32_t addr_end)
872 {
873 int i;
874 struct dsp563xx_core_reg *arch_info;
875 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
876
877 if (addr_start > ASM_REG_W_IPRC)
878 return;
879 if (addr_start < ASM_REG_W_AAR3)
880 return;
881
882 for (i = DSP563XX_REG_IDX_IPRC; i < DSP563XX_NUMCOREREGS; i++) {
883 arch_info = dsp563xx->core_cache->reg_list[i].arch_info;
884
885 if ((arch_info->instr_mask >= addr_start) &&
886 (arch_info->instr_mask <= addr_end)) {
887 dsp563xx->core_cache->reg_list[i].valid = false;
888 dsp563xx->core_cache->reg_list[i].dirty = false;
889 }
890 }
891 }
892
893 static int dsp563xx_target_create(struct target *target, Jim_Interp *interp)
894 {
895 struct dsp563xx_common *dsp563xx = calloc(1, sizeof(struct dsp563xx_common));
896
897 if (!dsp563xx)
898 return ERROR_COMMAND_SYNTAX_ERROR;
899
900 dsp563xx->jtag_info.tap = target->tap;
901 target->arch_info = dsp563xx;
902 dsp563xx->read_core_reg = dsp563xx_read_core_reg;
903 dsp563xx->write_core_reg = dsp563xx_write_core_reg;
904
905 return ERROR_OK;
906 }
907
908 static int dsp563xx_init_target(struct command_context *cmd_ctx, struct target *target)
909 {
910 LOG_DEBUG("%s", __func__);
911
912 dsp563xx_build_reg_cache(target);
913 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
914
915 dsp563xx->hardware_breakpoints_cleared = 0;
916 dsp563xx->hardware_breakpoint[0].used = BPU_NONE;
917
918 return ERROR_OK;
919 }
920
921 static int dsp563xx_examine(struct target *target)
922 {
923 uint32_t chip;
924
925 if (target->tap->hasidcode == false) {
926 LOG_ERROR("no IDCODE present on device");
927 return ERROR_COMMAND_SYNTAX_ERROR;
928 }
929
930 if (!target_was_examined(target)) {
931 target_set_examined(target);
932
933 /* examine core and chip derivate number */
934 chip = (target->tap->idcode>>12) & 0x3ff;
935 /* core number 0 means DSP563XX */
936 if (((chip>>5)&0x1f) == 0)
937 chip += 300;
938
939 LOG_INFO("DSP56%03" PRId32 " device found", chip);
940
941 /* Clear all breakpoints */
942 dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0);
943 }
944
945 return ERROR_OK;
946 }
947
948 static int dsp563xx_arch_state(struct target *target)
949 {
950 LOG_DEBUG("%s", __func__);
951 return ERROR_OK;
952 }
953
954 #define DSP563XX_SR_SA (1<<17)
955 #define DSP563XX_SR_SC (1<<13)
956
957 static int dsp563xx_debug_once_init(struct target *target)
958 {
959 return dsp563xx_once_read_register(target->tap, 1, once_regs, DSP563XX_NUMONCEREGS);
960 }
961
962 static int dsp563xx_debug_init(struct target *target)
963 {
964 int err;
965 uint32_t sr;
966 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
967 struct dsp563xx_core_reg *arch_info;
968
969 err = dsp563xx_debug_once_init(target);
970 if (err != ERROR_OK)
971 return err;
972
973 arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SR].arch_info;
974
975 /* check 24bit mode */
976 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_SR, 0);
977 if (err != ERROR_OK)
978 return err;
979
980 sr = dsp563xx->core_regs[DSP563XX_REG_IDX_SR];
981
982 if (sr & (DSP563XX_SR_SA | DSP563XX_SR_SC)) {
983 sr &= ~(DSP563XX_SR_SA | DSP563XX_SR_SC);
984
985 err = dsp563xx_once_execute_dw_ir(target->tap, 1, arch_info->instr_mask, sr);
986 if (err != ERROR_OK)
987 return err;
988 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_SR].dirty = true;
989 }
990
991 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_N0, 0);
992 if (err != ERROR_OK)
993 return err;
994 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_N1, 0);
995 if (err != ERROR_OK)
996 return err;
997 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_M0, 0);
998 if (err != ERROR_OK)
999 return err;
1000 err = dsp563xx_read_register(target, DSP563XX_REG_IDX_M1, 0);
1001 if (err != ERROR_OK)
1002 return err;
1003
1004 if (dsp563xx->core_regs[DSP563XX_REG_IDX_N0] != 0x000000) {
1005 arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N0].arch_info;
1006 err = dsp563xx_reg_write(target, arch_info->instr_mask, 0x000000);
1007 if (err != ERROR_OK)
1008 return err;
1009 }
1010 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N0].dirty = true;
1011
1012 if (dsp563xx->core_regs[DSP563XX_REG_IDX_N1] != 0x000000) {
1013 arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N1].arch_info;
1014 err = dsp563xx_reg_write(target, arch_info->instr_mask, 0x000000);
1015 if (err != ERROR_OK)
1016 return err;
1017 }
1018 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_N1].dirty = true;
1019
1020 if (dsp563xx->core_regs[DSP563XX_REG_IDX_M0] != 0xffffff) {
1021 arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M0].arch_info;
1022 err = dsp563xx_reg_write(target, arch_info->instr_mask, 0xffffff);
1023 if (err != ERROR_OK)
1024 return err;
1025 }
1026 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M0].dirty = true;
1027
1028 if (dsp563xx->core_regs[DSP563XX_REG_IDX_M1] != 0xffffff) {
1029 arch_info = dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M1].arch_info;
1030 err = dsp563xx_reg_write(target, arch_info->instr_mask, 0xffffff);
1031 if (err != ERROR_OK)
1032 return err;
1033 }
1034 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_M1].dirty = true;
1035
1036 err = dsp563xx_save_context(target);
1037 if (err != ERROR_OK)
1038 return err;
1039
1040 return ERROR_OK;
1041 }
1042
1043 static int dsp563xx_jtag_debug_request(struct target *target)
1044 {
1045 return dsp563xx_once_request_debug(target->tap, target->state == TARGET_RESET);
1046 }
1047
1048 static int dsp563xx_poll(struct target *target)
1049 {
1050 int err;
1051 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1052 uint32_t once_status = 0;
1053 int state;
1054
1055 state = dsp563xx_once_target_status(target->tap);
1056
1057 if (state == TARGET_UNKNOWN) {
1058 target->state = state;
1059 LOG_ERROR("jtag status contains invalid mode value - communication failure");
1060 return ERROR_TARGET_FAILURE;
1061 }
1062
1063 err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OSCR, &once_status);
1064 if (err != ERROR_OK)
1065 return err;
1066
1067 if ((once_status & DSP563XX_ONCE_OSCR_DEBUG_M) == DSP563XX_ONCE_OSCR_DEBUG_M) {
1068 if (target->state != TARGET_HALTED) {
1069 target->state = TARGET_HALTED;
1070
1071 err = dsp563xx_debug_init(target);
1072 if (err != ERROR_OK)
1073 return err;
1074
1075 if (once_status & (DSP563XX_ONCE_OSCR_MBO|DSP563XX_ONCE_OSCR_SWO))
1076 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
1077 else
1078 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
1079
1080 LOG_DEBUG("target->state: %s (%" PRIx32 ")", target_state_name(target), once_status);
1081 LOG_INFO("halted: PC: 0x%" PRIx32, dsp563xx->core_regs[DSP563XX_REG_IDX_PC]);
1082 }
1083 }
1084
1085 if (!dsp563xx->hardware_breakpoints_cleared) {
1086 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0);
1087 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR0, 0);
1088 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR1, 0);
1089 dsp563xx->hardware_breakpoints_cleared = 1;
1090 }
1091
1092 return ERROR_OK;
1093 }
1094
1095 static int dsp563xx_halt(struct target *target)
1096 {
1097 int err;
1098
1099 LOG_DEBUG("%s", __func__);
1100
1101 if (target->state == TARGET_HALTED) {
1102 LOG_DEBUG("target was already halted");
1103 return ERROR_OK;
1104 }
1105
1106 if (target->state == TARGET_UNKNOWN)
1107 LOG_WARNING("target was in unknown state when halt was requested");
1108
1109 err = dsp563xx_jtag_debug_request(target);
1110 if (err != ERROR_OK)
1111 return err;
1112
1113 target->debug_reason = DBG_REASON_DBGRQ;
1114
1115 return ERROR_OK;
1116 }
1117
1118 static int dsp563xx_resume(struct target *target,
1119 int current,
1120 target_addr_t address,
1121 int handle_breakpoints,
1122 int debug_execution)
1123 {
1124 int err;
1125 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1126
1127 /* check if pc was changed and resume want to execute the next address
1128 * if pc was changed from gdb or other interface we will
1129 * jump to this address and don't execute the next address
1130 * this will not affect the resume command with an address argument
1131 * because current is set to zero then
1132 */
1133 if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) {
1134 dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC);
1135 address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC];
1136 current = 0;
1137 }
1138
1139 LOG_DEBUG("%s %08X %08X", __func__, current, (unsigned) address);
1140
1141 err = dsp563xx_restore_context(target);
1142 if (err != ERROR_OK)
1143 return err;
1144 register_cache_invalidate(dsp563xx->core_cache);
1145
1146 if (current) {
1147 /* restore pipeline registers and go */
1148 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR,
1149 once_regs[ONCE_REG_IDX_OPILR].reg);
1150 if (err != ERROR_OK)
1151 return err;
1152 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR |
1153 DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO,
1154 once_regs[ONCE_REG_IDX_OPDBR].reg);
1155 if (err != ERROR_OK)
1156 return err;
1157 } else {
1158 /* set to go register and jump */
1159 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR, INSTR_JUMP);
1160 if (err != ERROR_OK)
1161 return err;
1162 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_PDBGOTO |
1163 DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO, address);
1164 if (err != ERROR_OK)
1165 return err;
1166 }
1167
1168 target->state = TARGET_RUNNING;
1169
1170 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
1171
1172 return ERROR_OK;
1173 }
1174
1175 static int dsp563xx_step_ex(struct target *target,
1176 int current,
1177 uint32_t address,
1178 int handle_breakpoints,
1179 int steps)
1180 {
1181 int err;
1182 uint32_t once_status;
1183 uint32_t dr_in, cnt;
1184 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1185
1186 if (target->state != TARGET_HALTED) {
1187 LOG_DEBUG("target was not halted");
1188 return ERROR_OK;
1189 }
1190
1191 /* check if pc was changed and step want to execute the next address
1192 * if pc was changed from gdb or other interface we will
1193 * jump to this address and don't execute the next address
1194 * this will not affect the step command with an address argument
1195 * because current is set to zero then
1196 */
1197 if (current && dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_PC].dirty) {
1198 dsp563xx_write_core_reg(target, DSP563XX_REG_IDX_PC);
1199 address = dsp563xx->core_regs[DSP563XX_REG_IDX_PC];
1200 current = 0;
1201 }
1202
1203 LOG_DEBUG("%s %08X %08X", __func__, current, (unsigned) address);
1204
1205 err = dsp563xx_jtag_debug_request(target);
1206 if (err != ERROR_OK)
1207 return err;
1208 err = dsp563xx_restore_context(target);
1209 if (err != ERROR_OK)
1210 return err;
1211
1212 /* reset trace mode */
1213 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, 0x000000);
1214 if (err != ERROR_OK)
1215 return err;
1216 /* enable trace mode */
1217 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, DSP563XX_ONCE_OSCR_TME);
1218 if (err != ERROR_OK)
1219 return err;
1220
1221 cnt = steps;
1222
1223 /* on JUMP we need one extra cycle */
1224 if (!current)
1225 cnt++;
1226
1227 /* load step counter with N-1 */
1228 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OTC, cnt);
1229 if (err != ERROR_OK)
1230 return err;
1231
1232 if (current) {
1233 /* restore pipeline registers and go */
1234 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR,
1235 once_regs[ONCE_REG_IDX_OPILR].reg);
1236 if (err != ERROR_OK)
1237 return err;
1238 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR |
1239 DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO,
1240 once_regs[ONCE_REG_IDX_OPDBR].reg);
1241 if (err != ERROR_OK)
1242 return err;
1243 } else {
1244 /* set to go register and jump */
1245 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OPDBR, INSTR_JUMP);
1246 if (err != ERROR_OK)
1247 return err;
1248 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_PDBGOTO |
1249 DSP563XX_ONCE_OCR_EX | DSP563XX_ONCE_OCR_GO,
1250 address);
1251 if (err != ERROR_OK)
1252 return err;
1253 }
1254
1255 while (1) {
1256 err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OSCR, &once_status);
1257 if (err != ERROR_OK)
1258 return err;
1259
1260 if (once_status & DSP563XX_ONCE_OSCR_TO) {
1261 err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABFR, &dr_in);
1262 if (err != ERROR_OK)
1263 return err;
1264 LOG_DEBUG("fetch: %08X", (unsigned) dr_in&0x00ffffff);
1265 err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABDR, &dr_in);
1266 if (err != ERROR_OK)
1267 return err;
1268 LOG_DEBUG("decode: %08X", (unsigned) dr_in&0x00ffffff);
1269 err = dsp563xx_once_reg_read(target->tap, 1, DSP563XX_ONCE_OPABEX, &dr_in);
1270 if (err != ERROR_OK)
1271 return err;
1272 LOG_DEBUG("execute: %08X", (unsigned) dr_in&0x00ffffff);
1273
1274 /* reset trace mode */
1275 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OSCR, 0x000000);
1276 if (err != ERROR_OK)
1277 return err;
1278
1279 register_cache_invalidate(dsp563xx->core_cache);
1280 err = dsp563xx_debug_init(target);
1281 if (err != ERROR_OK)
1282 return err;
1283
1284 break;
1285 }
1286 }
1287
1288 return ERROR_OK;
1289 }
1290
1291 static int dsp563xx_step(struct target *target,
1292 int current,
1293 target_addr_t address,
1294 int handle_breakpoints)
1295 {
1296 int err;
1297 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1298
1299 if (target->state != TARGET_HALTED) {
1300 LOG_WARNING("target not halted");
1301 return ERROR_TARGET_NOT_HALTED;
1302 }
1303
1304 err = dsp563xx_step_ex(target, current, address, handle_breakpoints, 0);
1305 if (err != ERROR_OK)
1306 return err;
1307
1308 target->debug_reason = DBG_REASON_SINGLESTEP;
1309 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
1310
1311 LOG_INFO("halted: PC: 0x%" PRIx32, dsp563xx->core_regs[DSP563XX_REG_IDX_PC]);
1312
1313 return err;
1314 }
1315
1316 static int dsp563xx_assert_reset(struct target *target)
1317 {
1318 int retval = 0;
1319 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1320 enum reset_types jtag_reset_config = jtag_get_reset_config();
1321
1322 if (jtag_reset_config & RESET_HAS_SRST) {
1323 /* default to asserting srst */
1324 if (jtag_reset_config & RESET_SRST_PULLS_TRST)
1325 jtag_add_reset(1, 1);
1326 else
1327 jtag_add_reset(0, 1);
1328 }
1329
1330 target->state = TARGET_RESET;
1331 jtag_add_sleep(5000);
1332
1333 /* registers are now invalid */
1334 register_cache_invalidate(dsp563xx->core_cache);
1335
1336 if (target->reset_halt) {
1337 retval = target_halt(target);
1338 if (retval != ERROR_OK)
1339 return retval;
1340 }
1341
1342 LOG_DEBUG("%s", __func__);
1343 return ERROR_OK;
1344 }
1345
1346 static int dsp563xx_deassert_reset(struct target *target)
1347 {
1348 int err;
1349
1350 /* deassert reset lines */
1351 jtag_add_reset(0, 0);
1352
1353 err = dsp563xx_poll(target);
1354 if (err != ERROR_OK)
1355 return err;
1356
1357 if (target->reset_halt) {
1358 if (target->state == TARGET_HALTED) {
1359 /* after a reset the cpu jmp to the
1360 * reset vector and need 2 cycles to fill
1361 * the cache (fetch,decode,excecute)
1362 */
1363 err = dsp563xx_step_ex(target, 1, 0, 1, 1);
1364 if (err != ERROR_OK)
1365 return err;
1366 }
1367 } else
1368 target->state = TARGET_RUNNING;
1369
1370 LOG_DEBUG("%s", __func__);
1371 return ERROR_OK;
1372 }
1373
1374 static int dsp563xx_run_algorithm(struct target *target,
1375 int num_mem_params, struct mem_param *mem_params,
1376 int num_reg_params, struct reg_param *reg_params,
1377 target_addr_t entry_point, target_addr_t exit_point,
1378 int timeout_ms, void *arch_info)
1379 {
1380 int i;
1381 int retval = ERROR_OK;
1382 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1383
1384 if (target->state != TARGET_HALTED) {
1385 LOG_WARNING("target not halted");
1386 return ERROR_TARGET_NOT_HALTED;
1387 }
1388
1389 for (i = 0; i < num_mem_params; i++) {
1390 if (mem_params[i].direction == PARAM_IN)
1391 continue;
1392 retval = target_write_buffer(target, mem_params[i].address,
1393 mem_params[i].size, mem_params[i].value);
1394 if (retval != ERROR_OK)
1395 return retval;
1396 }
1397
1398 for (i = 0; i < num_reg_params; i++) {
1399 if (reg_params[i].direction == PARAM_IN)
1400 continue;
1401
1402 struct reg *reg = register_get_by_name(dsp563xx->core_cache,
1403 reg_params[i].reg_name,
1404 0);
1405
1406 if (!reg) {
1407 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
1408 continue;
1409 }
1410
1411 if (reg->size != reg_params[i].size) {
1412 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
1413 reg_params[i].reg_name);
1414 continue;
1415 }
1416
1417 retval = dsp563xx_set_core_reg(reg, reg_params[i].value);
1418 if (retval != ERROR_OK)
1419 return retval;
1420 }
1421
1422 /* exec */
1423 retval = target_resume(target, 0, entry_point, 1, 1);
1424 if (retval != ERROR_OK)
1425 return retval;
1426
1427 retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
1428 if (retval != ERROR_OK)
1429 return retval;
1430
1431 for (i = 0; i < num_mem_params; i++) {
1432 if (mem_params[i].direction != PARAM_OUT)
1433 retval = target_read_buffer(target,
1434 mem_params[i].address,
1435 mem_params[i].size,
1436 mem_params[i].value);
1437 if (retval != ERROR_OK)
1438 return retval;
1439 }
1440
1441 for (i = 0; i < num_reg_params; i++) {
1442 if (reg_params[i].direction != PARAM_OUT) {
1443
1444 struct reg *reg = register_get_by_name(dsp563xx->core_cache,
1445 reg_params[i].reg_name,
1446 0);
1447 if (!reg) {
1448 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
1449 continue;
1450 }
1451
1452 if (reg->size != reg_params[i].size) {
1453 LOG_ERROR(
1454 "BUG: register '%s' size doesn't match reg_params[i].size",
1455 reg_params[i].reg_name);
1456 continue;
1457 }
1458
1459 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
1460 }
1461 }
1462
1463 return ERROR_OK;
1464 }
1465
1466 /* global command context from openocd.c */
1467 extern struct command_context *global_cmd_ctx;
1468
1469 static int dsp563xx_get_default_memory(void)
1470 {
1471 Jim_Interp *interp;
1472 Jim_Obj *memspace;
1473 char *c;
1474
1475 if (!global_cmd_ctx)
1476 return MEM_P;
1477
1478 interp = global_cmd_ctx->interp;
1479
1480 if (!interp)
1481 return MEM_P;
1482
1483 memspace = Jim_GetGlobalVariableStr(interp, "memspace", JIM_NONE);
1484
1485 if (!memspace)
1486 return MEM_P;
1487
1488 c = (char *)Jim_GetString(memspace, NULL);
1489
1490 if (!c)
1491 return MEM_P;
1492
1493 switch (c[0]) {
1494 case '1':
1495 return MEM_X;
1496 case '2':
1497 return MEM_Y;
1498 case '3':
1499 return MEM_L;
1500 default:
1501 break;
1502 }
1503
1504 return MEM_P;
1505 }
1506
1507 static int dsp563xx_read_memory_core(struct target *target,
1508 int mem_type,
1509 uint32_t address,
1510 uint32_t size,
1511 uint32_t count,
1512 uint8_t *buffer)
1513 {
1514 int err;
1515 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1516 uint32_t i, x;
1517 uint32_t data, move_cmd = 0;
1518 uint8_t *b;
1519
1520 LOG_DEBUG(
1521 "memtype: %d address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
1522 mem_type,
1523 address,
1524 size,
1525 count);
1526
1527 if (target->state != TARGET_HALTED) {
1528 LOG_WARNING("target not halted");
1529 return ERROR_TARGET_NOT_HALTED;
1530 }
1531
1532 switch (mem_type) {
1533 case MEM_X:
1534 /* TODO: mark effected queued registers */
1535 move_cmd = 0x61d800;
1536 break;
1537 case MEM_Y:
1538 move_cmd = 0x69d800;
1539 break;
1540 case MEM_P:
1541 move_cmd = 0x07d891;
1542 break;
1543 default:
1544 return ERROR_COMMAND_SYNTAX_ERROR;
1545 }
1546
1547 /* we use r0 to store temporary data */
1548 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
1549 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
1550 /* we use r1 to store temporary data */
1551 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].valid)
1552 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1);
1553
1554 /* r0 is no longer valid on target */
1555 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = true;
1556 /* r1 is no longer valid on target */
1557 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = true;
1558
1559 x = count;
1560 b = buffer;
1561
1562 err = dsp563xx_once_execute_dw_ir(target->tap, 1, 0x60F400, address);
1563 if (err != ERROR_OK)
1564 return err;
1565
1566 for (i = 0; i < x; i++) {
1567 err = dsp563xx_once_execute_sw_ir(target->tap, 0, move_cmd);
1568 if (err != ERROR_OK)
1569 return err;
1570 err = dsp563xx_once_execute_sw_ir(target->tap, 0, 0x08D13C);
1571 if (err != ERROR_OK)
1572 return err;
1573 err = dsp563xx_once_reg_read(target->tap, 0,
1574 DSP563XX_ONCE_OGDBR, (uint32_t *)(void *)b);
1575 if (err != ERROR_OK)
1576 return err;
1577 b += 4;
1578 }
1579
1580 /* flush the jtag queue */
1581 err = jtag_execute_queue();
1582 if (err != ERROR_OK)
1583 return err;
1584
1585 /* walk over the buffer and fix target endianness */
1586 b = buffer;
1587
1588 for (i = 0; i < x; i++) {
1589 data = buf_get_u32(b, 0, 32) & 0x00FFFFFF;
1590 /* LOG_DEBUG("R: %08X", *((uint32_t*)b)); */
1591 target_buffer_set_u32(target, b, data);
1592 b += 4;
1593 }
1594
1595 return ERROR_OK;
1596 }
1597
1598 static int dsp563xx_read_memory(struct target *target,
1599 int mem_type,
1600 target_addr_t address,
1601 uint32_t size,
1602 uint32_t count,
1603 uint8_t *buffer)
1604 {
1605 int err;
1606 uint32_t i, i1;
1607 uint8_t *buffer_y, *buffer_x;
1608
1609 /* if size equals zero we are called from target read memory
1610 * and have to handle the parameter here */
1611 if ((size == 0) && (count != 0)) {
1612 size = count % 4;
1613
1614 if (size)
1615 LOG_DEBUG("size is not aligned to 4 byte");
1616
1617 count = (count - size) / 4;
1618 size = 4;
1619 }
1620
1621 /* we only support 4 byte aligned data */
1622 if ((size != 4) || (!count))
1623 return ERROR_COMMAND_SYNTAX_ERROR;
1624
1625 if (mem_type != MEM_L)
1626 return dsp563xx_read_memory_core(target, mem_type, address, size, count, buffer);
1627
1628 buffer_y = malloc(size * count);
1629 if (!buffer_y)
1630 return ERROR_COMMAND_SYNTAX_ERROR;
1631
1632 buffer_x = malloc(size * count);
1633 if (!buffer_x) {
1634 free(buffer_y);
1635 return ERROR_COMMAND_SYNTAX_ERROR;
1636 }
1637
1638 err = dsp563xx_read_memory_core(target, MEM_Y, address, size, count / 2, buffer_y);
1639
1640 if (err != ERROR_OK) {
1641 free(buffer_y);
1642 free(buffer_x);
1643 return err;
1644 }
1645
1646 err = dsp563xx_read_memory_core(target, MEM_X, address, size, count / 2, buffer_x);
1647
1648 if (err != ERROR_OK) {
1649 free(buffer_y);
1650 free(buffer_x);
1651 return err;
1652 }
1653
1654 for (i = 0, i1 = 0; i < count; i += 2, i1++) {
1655 buf_set_u32(buffer + i*sizeof(uint32_t), 0, 32,
1656 buf_get_u32(buffer_y + i1 * sizeof(uint32_t), 0, 32));
1657 buf_set_u32(buffer + (i + 1) * sizeof(uint32_t), 0, 32,
1658 buf_get_u32(buffer_x + i1 * sizeof(uint32_t), 0, 32));
1659 }
1660
1661 free(buffer_y);
1662 free(buffer_x);
1663
1664 return ERROR_OK;
1665 }
1666
1667 static int dsp563xx_read_memory_default(struct target *target,
1668 target_addr_t address,
1669 uint32_t size,
1670 uint32_t count,
1671 uint8_t *buffer)
1672 {
1673
1674 return dsp563xx_read_memory(target,
1675 dsp563xx_get_default_memory(), address, size, count, buffer);
1676 }
1677
1678 static int dsp563xx_read_buffer_default(struct target *target,
1679 target_addr_t address,
1680 uint32_t size,
1681 uint8_t *buffer)
1682 {
1683
1684 return dsp563xx_read_memory(target, dsp563xx_get_default_memory(), address, size, 0,
1685 buffer);
1686 }
1687
1688 static int dsp563xx_write_memory_core(struct target *target,
1689 int mem_type,
1690 target_addr_t address,
1691 uint32_t size,
1692 uint32_t count,
1693 const uint8_t *buffer)
1694 {
1695 int err;
1696 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1697 uint32_t i, x;
1698 uint32_t data, move_cmd = 0;
1699 const uint8_t *b;
1700
1701 LOG_DEBUG(
1702 "memtype: %d address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
1703 mem_type,
1704 address,
1705 size,
1706 count);
1707
1708 if (target->state != TARGET_HALTED) {
1709 LOG_WARNING("target not halted");
1710 return ERROR_TARGET_NOT_HALTED;
1711 }
1712
1713 switch (mem_type) {
1714 case MEM_X:
1715 /* invalidate affected x registers */
1716 dsp563xx_invalidate_x_context(target, address, address + count - 1);
1717 move_cmd = 0x615800;
1718 break;
1719 case MEM_Y:
1720 move_cmd = 0x695800;
1721 break;
1722 case MEM_P:
1723 move_cmd = 0x075891;
1724 break;
1725 default:
1726 return ERROR_COMMAND_SYNTAX_ERROR;
1727 }
1728
1729 /* we use r0 to store temporary data */
1730 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
1731 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
1732 /* we use r1 to store temporary data */
1733 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].valid)
1734 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1);
1735
1736 /* r0 is no longer valid on target */
1737 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = true;
1738 /* r1 is no longer valid on target */
1739 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = true;
1740
1741 x = count;
1742 b = buffer;
1743
1744 err = dsp563xx_once_execute_dw_ir(target->tap, 1, 0x60F400, address);
1745 if (err != ERROR_OK)
1746 return err;
1747
1748 for (i = 0; i < x; i++) {
1749 data = target_buffer_get_u32(target, b);
1750
1751 /* LOG_DEBUG("W: %08X", data); */
1752
1753 data &= 0x00ffffff;
1754
1755 err = dsp563xx_once_execute_dw_ir(target->tap, 0, 0x61F400, data);
1756 if (err != ERROR_OK)
1757 return err;
1758 err = dsp563xx_once_execute_sw_ir(target->tap, 0, move_cmd);
1759 if (err != ERROR_OK)
1760 return err;
1761 b += 4;
1762 }
1763
1764 /* flush the jtag queue */
1765 err = jtag_execute_queue();
1766 if (err != ERROR_OK)
1767 return err;
1768
1769 return ERROR_OK;
1770 }
1771
1772 static int dsp563xx_write_memory(struct target *target,
1773 int mem_type,
1774 target_addr_t address,
1775 uint32_t size,
1776 uint32_t count,
1777 const uint8_t *buffer)
1778 {
1779 int err;
1780 uint32_t i, i1;
1781 uint8_t *buffer_y, *buffer_x;
1782
1783 /* if size equals zero we are called from target write memory
1784 * and have to handle the parameter here */
1785 if ((size == 0) && (count != 0)) {
1786 size = count % 4;
1787
1788 if (size)
1789 LOG_DEBUG("size is not aligned to 4 byte");
1790
1791 count = (count - size) / 4;
1792 size = 4;
1793 }
1794
1795 /* we only support 4 byte aligned data */
1796 if ((size != 4) || (!count))
1797 return ERROR_COMMAND_SYNTAX_ERROR;
1798
1799 if (mem_type != MEM_L)
1800 return dsp563xx_write_memory_core(target, mem_type, address, size, count, buffer);
1801
1802 buffer_y = malloc(size * count);
1803 if (!buffer_y)
1804 return ERROR_COMMAND_SYNTAX_ERROR;
1805
1806 buffer_x = malloc(size * count);
1807 if (!buffer_x) {
1808 free(buffer_y);
1809 return ERROR_COMMAND_SYNTAX_ERROR;
1810 }
1811
1812 for (i = 0, i1 = 0; i < count; i += 2, i1++) {
1813 buf_set_u32(buffer_y + i1 * sizeof(uint32_t), 0, 32,
1814 buf_get_u32(buffer + i * sizeof(uint32_t), 0, 32));
1815 buf_set_u32(buffer_x + i1 * sizeof(uint32_t), 0, 32,
1816 buf_get_u32(buffer + (i + 1) * sizeof(uint32_t), 0, 32));
1817 }
1818
1819 err = dsp563xx_write_memory_core(target, MEM_Y, address, size, count / 2, buffer_y);
1820
1821 if (err != ERROR_OK) {
1822 free(buffer_y);
1823 free(buffer_x);
1824 return err;
1825 }
1826
1827 err = dsp563xx_write_memory_core(target, MEM_X, address, size, count / 2, buffer_x);
1828
1829 if (err != ERROR_OK) {
1830 free(buffer_y);
1831 free(buffer_x);
1832 return err;
1833 }
1834
1835 free(buffer_y);
1836 free(buffer_x);
1837
1838 return ERROR_OK;
1839 }
1840
1841 static int dsp563xx_write_memory_default(struct target *target,
1842 target_addr_t address,
1843 uint32_t size,
1844 uint32_t count,
1845 const uint8_t *buffer)
1846 {
1847 return dsp563xx_write_memory(target,
1848 dsp563xx_get_default_memory(), address, size, count, buffer);
1849 }
1850
1851 static int dsp563xx_write_buffer_default(struct target *target,
1852 target_addr_t address,
1853 uint32_t size,
1854 const uint8_t *buffer)
1855 {
1856 return dsp563xx_write_memory(target, dsp563xx_get_default_memory(), address, size, 0,
1857 buffer);
1858 }
1859
1860 /*
1861 * Exit with error here, because we support watchpoints over a custom command.
1862 * This is because the DSP has separate X,Y,P memspace which is not compatible to the
1863 * traditional watchpoint logic.
1864 */
1865 static int dsp563xx_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
1866 {
1867 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1868 }
1869
1870 /*
1871 * @see dsp563xx_add_watchpoint
1872 */
1873 static int dsp563xx_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
1874 {
1875 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1876 }
1877
1878 static void handle_md_output(struct command_invocation *cmd,
1879 struct target *target,
1880 uint32_t address,
1881 unsigned size,
1882 unsigned count,
1883 const uint8_t *buffer)
1884 {
1885 const unsigned line_bytecnt = 32;
1886 unsigned line_modulo = line_bytecnt / size;
1887
1888 char output[line_bytecnt * 4 + 1];
1889 unsigned output_len = 0;
1890
1891 const char *value_fmt;
1892 switch (size) {
1893 case 4:
1894 value_fmt = "%8.8x ";
1895 break;
1896 case 2:
1897 value_fmt = "%4.4x ";
1898 break;
1899 case 1:
1900 value_fmt = "%2.2x ";
1901 break;
1902 default:
1903 /* "can't happen", caller checked */
1904 LOG_ERROR("invalid memory read size: %u", size);
1905 return;
1906 }
1907
1908 for (unsigned i = 0; i < count; i++) {
1909 if (i % line_modulo == 0)
1910 output_len += snprintf(output + output_len,
1911 sizeof(output) - output_len,
1912 "0x%8.8x: ",
1913 (unsigned) (address + i));
1914
1915 uint32_t value = 0;
1916 const uint8_t *value_ptr = buffer + i * size;
1917 switch (size) {
1918 case 4:
1919 value = target_buffer_get_u32(target, value_ptr);
1920 break;
1921 case 2:
1922 value = target_buffer_get_u16(target, value_ptr);
1923 break;
1924 case 1:
1925 value = *value_ptr;
1926 }
1927 output_len += snprintf(output + output_len,
1928 sizeof(output) - output_len,
1929 value_fmt,
1930 value);
1931
1932 if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) {
1933 command_print(cmd, "%s", output);
1934 output_len = 0;
1935 }
1936 }
1937 }
1938
1939 static int dsp563xx_add_custom_watchpoint(struct target *target, uint32_t address, uint32_t memType,
1940 enum watchpoint_rw rw, enum watchpoint_condition cond)
1941 {
1942 int err = ERROR_OK;
1943 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1944
1945 bool wasRunning = false;
1946 /* Only set breakpoint when halted */
1947 if (target->state != TARGET_HALTED) {
1948 dsp563xx_halt(target);
1949 wasRunning = true;
1950 }
1951
1952 if (dsp563xx->hardware_breakpoint[0].used) {
1953 LOG_ERROR("Cannot add watchpoint. Hardware resource already used.");
1954 err = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1955 }
1956
1957 uint32_t obcr_value = 0;
1958 if (err == ERROR_OK) {
1959 obcr_value |= OBCR_b0_or_b1;
1960 switch (memType) {
1961 case MEM_X:
1962 obcr_value |= OBCR_BP_MEM_X;
1963 break;
1964 case MEM_Y:
1965 obcr_value |= OBCR_BP_MEM_Y;
1966 break;
1967 case MEM_P:
1968 obcr_value |= OBCR_BP_MEM_P;
1969 break;
1970 default:
1971 LOG_ERROR("Unknown memType parameter (%" PRIu32 ")", memType);
1972 err = ERROR_TARGET_INVALID;
1973 }
1974 }
1975
1976 if (err == ERROR_OK) {
1977 switch (rw) {
1978 case WPT_READ:
1979 obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ);
1980 break;
1981 case WPT_WRITE:
1982 obcr_value |= OBCR_BP_0(OBCR_BP_ON_WRITE);
1983 break;
1984 case WPT_ACCESS:
1985 obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ|OBCR_BP_ON_WRITE);
1986 break;
1987 default:
1988 LOG_ERROR("Unsupported write mode (%d)", rw);
1989 err = ERROR_TARGET_INVALID;
1990 }
1991 }
1992
1993 if (err == ERROR_OK) {
1994 switch (cond) {
1995 case EQUAL:
1996 obcr_value |= OBCR_BP_0(OBCR_BP_CC_EQUAL);
1997 break;
1998 case NOT_EQUAL:
1999 obcr_value |= OBCR_BP_0(OBCR_BP_CC_NOT_EQUAL);
2000 break;
2001 case LESS_THAN:
2002 obcr_value |= OBCR_BP_0(OBCR_BP_CC_LESS_THAN);
2003 break;
2004 case GREATER:
2005 obcr_value |= OBCR_BP_0(OBCR_BP_CC_GREATER_THAN);
2006 break;
2007 default:
2008 LOG_ERROR("Unsupported condition code (%d)", cond);
2009 err = ERROR_TARGET_INVALID;
2010 }
2011 }
2012
2013 if (err == ERROR_OK)
2014 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR0, address);
2015
2016 if (err == ERROR_OK)
2017 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR1, 0x0);
2018
2019 if (err == ERROR_OK)
2020 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, obcr_value);
2021
2022 if (err == ERROR_OK) {
2023 /* You should write the memory breakpoint counter to 0 */
2024 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMBC, 0);
2025 }
2026
2027 if (err == ERROR_OK) {
2028 /* You should write the memory breakpoint counter to 0 */
2029 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OTC, 0);
2030 }
2031
2032 if (err == ERROR_OK)
2033 dsp563xx->hardware_breakpoint[0].used = BPU_WATCHPOINT;
2034
2035 if (err == ERROR_OK && wasRunning) {
2036 /* Resume from current PC */
2037 err = dsp563xx_resume(target, 1, 0x0, 0, 0);
2038 }
2039
2040 return err;
2041 }
2042
2043 static int dsp563xx_remove_custom_watchpoint(struct target *target)
2044 {
2045 int err = ERROR_OK;
2046 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
2047
2048 if (dsp563xx->hardware_breakpoint[0].used != BPU_WATCHPOINT) {
2049 LOG_ERROR("Cannot remove watchpoint, as no watchpoint is currently configured!");
2050 err = ERROR_TARGET_INVALID;
2051 }
2052
2053 if (err == ERROR_OK) {
2054 /* Clear watchpoint by clearing OBCR. */
2055 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0);
2056 }
2057
2058 if (err == ERROR_OK)
2059 dsp563xx->hardware_breakpoint[0].used = BPU_NONE;
2060
2061 return err;
2062 }
2063
2064 COMMAND_HANDLER(dsp563xx_add_watchpoint_command)
2065 {
2066 int err = ERROR_OK;
2067 struct target *target = get_current_target(CMD_CTX);
2068
2069 uint32_t mem_type = 0;
2070 switch (CMD_NAME[2]) {
2071 case 'x':
2072 mem_type = MEM_X;
2073 break;
2074 case 'y':
2075 mem_type = MEM_Y;
2076 break;
2077 case 'p':
2078 mem_type = MEM_P;
2079 break;
2080 default:
2081 return ERROR_COMMAND_SYNTAX_ERROR;
2082 }
2083
2084 if (CMD_ARGC < 2)
2085 return ERROR_COMMAND_SYNTAX_ERROR;
2086
2087 uint32_t address = 0;
2088 if (CMD_ARGC > 2)
2089 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
2090
2091 enum watchpoint_condition cond;
2092 switch (CMD_ARGV[0][0]) {
2093 case '>':
2094 cond = GREATER;
2095 break;
2096 case '<':
2097 cond = LESS_THAN;
2098 break;
2099 case '=':
2100 cond = EQUAL;
2101 break;
2102 case '!':
2103 cond = NOT_EQUAL;
2104 break;
2105 default:
2106 return ERROR_COMMAND_SYNTAX_ERROR;
2107 }
2108
2109 enum watchpoint_rw rw;
2110 switch (CMD_ARGV[1][0]) {
2111 case 'r':
2112 rw = WPT_READ;
2113 break;
2114 case 'w':
2115 rw = WPT_WRITE;
2116 break;
2117 case 'a':
2118 rw = WPT_ACCESS;
2119 break;
2120 default:
2121 return ERROR_COMMAND_SYNTAX_ERROR;
2122 }
2123
2124 err = dsp563xx_add_custom_watchpoint(target, address, mem_type, rw, cond);
2125
2126 return err;
2127 }
2128
2129 /* Adding a breakpoint using the once breakpoint logic.
2130 * Note that this mechanism is a true hw breakpoint and is share between the watchpoint logic.
2131 * This means, you can only have one breakpoint/watchpoint at any time.
2132 */
2133 static int dsp563xx_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
2134 {
2135 return dsp563xx_add_custom_watchpoint(target, breakpoint->address, MEM_P, WPT_READ, EQUAL);
2136 }
2137
2138 static int dsp563xx_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
2139 {
2140 return dsp563xx_remove_custom_watchpoint(target);
2141 }
2142
2143 COMMAND_HANDLER(dsp563xx_remove_watchpoint_command)
2144 {
2145 struct target *target = get_current_target(CMD_CTX);
2146
2147 return dsp563xx_remove_custom_watchpoint(target);
2148 }
2149
2150 COMMAND_HANDLER(dsp563xx_mem_command)
2151 {
2152 struct target *target = get_current_target(CMD_CTX);
2153 int err = ERROR_OK;
2154 int read_mem;
2155 uint32_t address = 0;
2156 uint32_t count = 1, i;
2157 uint32_t pattern = 0;
2158 uint32_t mem_type;
2159 uint8_t *buffer, *b;
2160
2161 switch (CMD_NAME[1]) {
2162 case 'w':
2163 read_mem = 0;
2164 break;
2165 case 'd':
2166 read_mem = 1;
2167 break;
2168 default:
2169 return ERROR_COMMAND_SYNTAX_ERROR;
2170 }
2171
2172 switch (CMD_NAME[3]) {
2173 case 'x':
2174 mem_type = MEM_X;
2175 break;
2176 case 'y':
2177 mem_type = MEM_Y;
2178 break;
2179 case 'p':
2180 mem_type = MEM_P;
2181 break;
2182 default:
2183 return ERROR_COMMAND_SYNTAX_ERROR;
2184 }
2185
2186 if (CMD_ARGC > 0)
2187 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
2188
2189 if (read_mem == 0) {
2190 if (CMD_ARGC < 2)
2191 return ERROR_COMMAND_SYNTAX_ERROR;
2192 if (CMD_ARGC > 1)
2193 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
2194 if (CMD_ARGC > 2)
2195 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
2196 }
2197
2198 if (read_mem == 1) {
2199 if (CMD_ARGC < 1)
2200 return ERROR_COMMAND_SYNTAX_ERROR;
2201 if (CMD_ARGC > 1)
2202 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], count);
2203 }
2204
2205 buffer = calloc(count, sizeof(uint32_t));
2206
2207 if (read_mem == 1) {
2208 err = dsp563xx_read_memory(target, mem_type, address, sizeof(uint32_t),
2209 count, buffer);
2210 if (err == ERROR_OK)
2211 handle_md_output(CMD, target, address, sizeof(uint32_t), count, buffer);
2212
2213 } else {
2214 b = buffer;
2215
2216 for (i = 0; i < count; i++) {
2217 target_buffer_set_u32(target, b, pattern);
2218 b += 4;
2219 }
2220
2221 err = dsp563xx_write_memory(target,
2222 mem_type,
2223 address,
2224 sizeof(uint32_t),
2225 count,
2226 buffer);
2227 }
2228
2229 free(buffer);
2230
2231 return err;
2232 }
2233
2234 static const struct command_registration dsp563xx_command_handlers[] = {
2235 {
2236 .name = "mwwx",
2237 .handler = dsp563xx_mem_command,
2238 .mode = COMMAND_EXEC,
2239 .help = "write x memory words",
2240 .usage = "address value [count]",
2241 },
2242 {
2243 .name = "mwwy",
2244 .handler = dsp563xx_mem_command,
2245 .mode = COMMAND_EXEC,
2246 .help = "write y memory words",
2247 .usage = "address value [count]",
2248 },
2249 {
2250 .name = "mwwp",
2251 .handler = dsp563xx_mem_command,
2252 .mode = COMMAND_EXEC,
2253 .help = "write p memory words",
2254 .usage = "address value [count]",
2255 },
2256 {
2257 .name = "mdwx",
2258 .handler = dsp563xx_mem_command,
2259 .mode = COMMAND_EXEC,
2260 .help = "display x memory words",
2261 .usage = "address [count]",
2262 },
2263 {
2264 .name = "mdwy",
2265 .handler = dsp563xx_mem_command,
2266 .mode = COMMAND_EXEC,
2267 .help = "display y memory words",
2268 .usage = "address [count]",
2269 },
2270 {
2271 .name = "mdwp",
2272 .handler = dsp563xx_mem_command,
2273 .mode = COMMAND_EXEC,
2274 .help = "display p memory words",
2275 .usage = "address [count]",
2276 },
2277 /*
2278 * Watchpoint commands
2279 */
2280 {
2281 .name = "wpp",
2282 .handler = dsp563xx_add_watchpoint_command,
2283 .mode = COMMAND_EXEC,
2284 .help = "Create p memspace watchpoint",
2285 .usage = "(>|<|=|!) (r|w|a) address",
2286 },
2287 {
2288 .name = "wpx",
2289 .handler = dsp563xx_add_watchpoint_command,
2290 .mode = COMMAND_EXEC,
2291 .help = "Create x memspace watchpoint",
2292 .usage = "(>|<|=|!) (r|w|a) address",
2293 },
2294 {
2295 .name = "wpy",
2296 .handler = dsp563xx_add_watchpoint_command,
2297 .mode = COMMAND_EXEC,
2298 .help = "Create y memspace watchpoint",
2299 .usage = "(>|<|=|!) (r|w|a) address",
2300 },
2301 {
2302 .name = "rwpc",
2303 .handler = dsp563xx_remove_watchpoint_command,
2304 .mode = COMMAND_EXEC,
2305 .help = "remove watchpoint custom",
2306 .usage = " ",
2307 },
2308 COMMAND_REGISTRATION_DONE
2309 };
2310
2311 /** Holds methods for DSP563XX targets. */
2312 struct target_type dsp563xx_target = {
2313 .name = "dsp563xx",
2314
2315 .poll = dsp563xx_poll,
2316 .arch_state = dsp563xx_arch_state,
2317
2318 .get_gdb_reg_list = dsp563xx_get_gdb_reg_list,
2319
2320 .halt = dsp563xx_halt,
2321 .resume = dsp563xx_resume,
2322 .step = dsp563xx_step,
2323
2324 .assert_reset = dsp563xx_assert_reset,
2325 .deassert_reset = dsp563xx_deassert_reset,
2326
2327 .read_memory = dsp563xx_read_memory_default,
2328 .write_memory = dsp563xx_write_memory_default,
2329
2330 .read_buffer = dsp563xx_read_buffer_default,
2331 .write_buffer = dsp563xx_write_buffer_default,
2332
2333 .run_algorithm = dsp563xx_run_algorithm,
2334
2335 .add_breakpoint = dsp563xx_add_breakpoint,
2336 .remove_breakpoint = dsp563xx_remove_breakpoint,
2337 .add_watchpoint = dsp563xx_add_watchpoint,
2338 .remove_watchpoint = dsp563xx_remove_watchpoint,
2339
2340 .commands = dsp563xx_command_handlers,
2341 .target_create = dsp563xx_target_create,
2342 .init_target = dsp563xx_init_target,
2343 .examine = dsp563xx_examine,
2344 };

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)