target algo: do not write reg_param if direction is PARAM_IN
[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 = 1;
388 dsp563xx->core_cache->reg_list[num].dirty = 0;
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 = 1;
404 dsp563xx->core_cache->reg_list[num].dirty = 0;
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 = 1;
436 reg->valid = 1;
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 = 0;
477 reg_list[i].valid = 0;
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 = 1;
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 = 1;
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 = 0;
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 = 1;
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 = 0;
888 dsp563xx->core_cache->reg_list[i].dirty = 0;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 = 1;
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 retval = target_write_buffer(target, mem_params[i].address,
1391 mem_params[i].size, mem_params[i].value);
1392 if (retval != ERROR_OK)
1393 return retval;
1394 }
1395
1396 for (i = 0; i < num_reg_params; i++) {
1397 if (reg_params[i].direction == PARAM_IN)
1398 continue;
1399
1400 struct reg *reg = register_get_by_name(dsp563xx->core_cache,
1401 reg_params[i].reg_name,
1402 0);
1403
1404 if (!reg) {
1405 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
1406 continue;
1407 }
1408
1409 if (reg->size != reg_params[i].size) {
1410 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
1411 reg_params[i].reg_name);
1412 continue;
1413 }
1414
1415 retval = dsp563xx_set_core_reg(reg, reg_params[i].value);
1416 if (retval != ERROR_OK)
1417 return retval;
1418 }
1419
1420 /* exec */
1421 retval = target_resume(target, 0, entry_point, 1, 1);
1422 if (retval != ERROR_OK)
1423 return retval;
1424
1425 retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
1426 if (retval != ERROR_OK)
1427 return retval;
1428
1429 for (i = 0; i < num_mem_params; i++) {
1430 if (mem_params[i].direction != PARAM_OUT)
1431 retval = target_read_buffer(target,
1432 mem_params[i].address,
1433 mem_params[i].size,
1434 mem_params[i].value);
1435 if (retval != ERROR_OK)
1436 return retval;
1437 }
1438
1439 for (i = 0; i < num_reg_params; i++) {
1440 if (reg_params[i].direction != PARAM_OUT) {
1441
1442 struct reg *reg = register_get_by_name(dsp563xx->core_cache,
1443 reg_params[i].reg_name,
1444 0);
1445 if (!reg) {
1446 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
1447 continue;
1448 }
1449
1450 if (reg->size != reg_params[i].size) {
1451 LOG_ERROR(
1452 "BUG: register '%s' size doesn't match reg_params[i].size",
1453 reg_params[i].reg_name);
1454 continue;
1455 }
1456
1457 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
1458 }
1459 }
1460
1461 return ERROR_OK;
1462 }
1463
1464 /* global command context from openocd.c */
1465 extern struct command_context *global_cmd_ctx;
1466
1467 static int dsp563xx_get_default_memory(void)
1468 {
1469 Jim_Interp *interp;
1470 Jim_Obj *memspace;
1471 char *c;
1472
1473 if (!global_cmd_ctx)
1474 return MEM_P;
1475
1476 interp = global_cmd_ctx->interp;
1477
1478 if (!interp)
1479 return MEM_P;
1480
1481 memspace = Jim_GetGlobalVariableStr(interp, "memspace", JIM_NONE);
1482
1483 if (!memspace)
1484 return MEM_P;
1485
1486 c = (char *)Jim_GetString(memspace, NULL);
1487
1488 if (!c)
1489 return MEM_P;
1490
1491 switch (c[0]) {
1492 case '1':
1493 return MEM_X;
1494 case '2':
1495 return MEM_Y;
1496 case '3':
1497 return MEM_L;
1498 default:
1499 break;
1500 }
1501
1502 return MEM_P;
1503 }
1504
1505 static int dsp563xx_read_memory_core(struct target *target,
1506 int mem_type,
1507 uint32_t address,
1508 uint32_t size,
1509 uint32_t count,
1510 uint8_t *buffer)
1511 {
1512 int err;
1513 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1514 uint32_t i, x;
1515 uint32_t data, move_cmd = 0;
1516 uint8_t *b;
1517
1518 LOG_DEBUG(
1519 "memtype: %d address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
1520 mem_type,
1521 address,
1522 size,
1523 count);
1524
1525 if (target->state != TARGET_HALTED) {
1526 LOG_WARNING("target not halted");
1527 return ERROR_TARGET_NOT_HALTED;
1528 }
1529
1530 switch (mem_type) {
1531 case MEM_X:
1532 /* TODO: mark effected queued registers */
1533 move_cmd = 0x61d800;
1534 break;
1535 case MEM_Y:
1536 move_cmd = 0x69d800;
1537 break;
1538 case MEM_P:
1539 move_cmd = 0x07d891;
1540 break;
1541 default:
1542 return ERROR_COMMAND_SYNTAX_ERROR;
1543 }
1544
1545 /* we use r0 to store temporary data */
1546 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
1547 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
1548 /* we use r1 to store temporary data */
1549 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].valid)
1550 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1);
1551
1552 /* r0 is no longer valid on target */
1553 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1;
1554 /* r1 is no longer valid on target */
1555 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = 1;
1556
1557 x = count;
1558 b = buffer;
1559
1560 err = dsp563xx_once_execute_dw_ir(target->tap, 1, 0x60F400, address);
1561 if (err != ERROR_OK)
1562 return err;
1563
1564 for (i = 0; i < x; i++) {
1565 err = dsp563xx_once_execute_sw_ir(target->tap, 0, move_cmd);
1566 if (err != ERROR_OK)
1567 return err;
1568 err = dsp563xx_once_execute_sw_ir(target->tap, 0, 0x08D13C);
1569 if (err != ERROR_OK)
1570 return err;
1571 err = dsp563xx_once_reg_read(target->tap, 0,
1572 DSP563XX_ONCE_OGDBR, (uint32_t *)(void *)b);
1573 if (err != ERROR_OK)
1574 return err;
1575 b += 4;
1576 }
1577
1578 /* flush the jtag queue */
1579 err = jtag_execute_queue();
1580 if (err != ERROR_OK)
1581 return err;
1582
1583 /* walk over the buffer and fix target endianness */
1584 b = buffer;
1585
1586 for (i = 0; i < x; i++) {
1587 data = buf_get_u32(b, 0, 32) & 0x00FFFFFF;
1588 /* LOG_DEBUG("R: %08X", *((uint32_t*)b)); */
1589 target_buffer_set_u32(target, b, data);
1590 b += 4;
1591 }
1592
1593 return ERROR_OK;
1594 }
1595
1596 static int dsp563xx_read_memory(struct target *target,
1597 int mem_type,
1598 target_addr_t address,
1599 uint32_t size,
1600 uint32_t count,
1601 uint8_t *buffer)
1602 {
1603 int err;
1604 uint32_t i, i1;
1605 uint8_t *buffer_y, *buffer_x;
1606
1607 /* if size equals zero we are called from target read memory
1608 * and have to handle the parameter here */
1609 if ((size == 0) && (count != 0)) {
1610 size = count % 4;
1611
1612 if (size)
1613 LOG_DEBUG("size is not aligned to 4 byte");
1614
1615 count = (count - size) / 4;
1616 size = 4;
1617 }
1618
1619 /* we only support 4 byte aligned data */
1620 if ((size != 4) || (!count))
1621 return ERROR_COMMAND_SYNTAX_ERROR;
1622
1623 if (mem_type != MEM_L)
1624 return dsp563xx_read_memory_core(target, mem_type, address, size, count, buffer);
1625
1626 buffer_y = malloc(size * count);
1627 if (!buffer_y)
1628 return ERROR_COMMAND_SYNTAX_ERROR;
1629
1630 buffer_x = malloc(size * count);
1631 if (!buffer_x) {
1632 free(buffer_y);
1633 return ERROR_COMMAND_SYNTAX_ERROR;
1634 }
1635
1636 err = dsp563xx_read_memory_core(target, MEM_Y, address, size, count / 2, buffer_y);
1637
1638 if (err != ERROR_OK) {
1639 free(buffer_y);
1640 free(buffer_x);
1641 return err;
1642 }
1643
1644 err = dsp563xx_read_memory_core(target, MEM_X, address, size, count / 2, buffer_x);
1645
1646 if (err != ERROR_OK) {
1647 free(buffer_y);
1648 free(buffer_x);
1649 return err;
1650 }
1651
1652 for (i = 0, i1 = 0; i < count; i += 2, i1++) {
1653 buf_set_u32(buffer + i*sizeof(uint32_t), 0, 32,
1654 buf_get_u32(buffer_y + i1 * sizeof(uint32_t), 0, 32));
1655 buf_set_u32(buffer + (i + 1) * sizeof(uint32_t), 0, 32,
1656 buf_get_u32(buffer_x + i1 * sizeof(uint32_t), 0, 32));
1657 }
1658
1659 free(buffer_y);
1660 free(buffer_x);
1661
1662 return ERROR_OK;
1663 }
1664
1665 static int dsp563xx_read_memory_default(struct target *target,
1666 target_addr_t address,
1667 uint32_t size,
1668 uint32_t count,
1669 uint8_t *buffer)
1670 {
1671
1672 return dsp563xx_read_memory(target,
1673 dsp563xx_get_default_memory(), address, size, count, buffer);
1674 }
1675
1676 static int dsp563xx_read_buffer_default(struct target *target,
1677 target_addr_t address,
1678 uint32_t size,
1679 uint8_t *buffer)
1680 {
1681
1682 return dsp563xx_read_memory(target, dsp563xx_get_default_memory(), address, size, 0,
1683 buffer);
1684 }
1685
1686 static int dsp563xx_write_memory_core(struct target *target,
1687 int mem_type,
1688 target_addr_t address,
1689 uint32_t size,
1690 uint32_t count,
1691 const uint8_t *buffer)
1692 {
1693 int err;
1694 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1695 uint32_t i, x;
1696 uint32_t data, move_cmd = 0;
1697 const uint8_t *b;
1698
1699 LOG_DEBUG(
1700 "memtype: %d address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "",
1701 mem_type,
1702 address,
1703 size,
1704 count);
1705
1706 if (target->state != TARGET_HALTED) {
1707 LOG_WARNING("target not halted");
1708 return ERROR_TARGET_NOT_HALTED;
1709 }
1710
1711 switch (mem_type) {
1712 case MEM_X:
1713 /* invalidate affected x registers */
1714 dsp563xx_invalidate_x_context(target, address, address + count - 1);
1715 move_cmd = 0x615800;
1716 break;
1717 case MEM_Y:
1718 move_cmd = 0x695800;
1719 break;
1720 case MEM_P:
1721 move_cmd = 0x075891;
1722 break;
1723 default:
1724 return ERROR_COMMAND_SYNTAX_ERROR;
1725 }
1726
1727 /* we use r0 to store temporary data */
1728 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].valid)
1729 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R0);
1730 /* we use r1 to store temporary data */
1731 if (!dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].valid)
1732 dsp563xx->read_core_reg(target, DSP563XX_REG_IDX_R1);
1733
1734 /* r0 is no longer valid on target */
1735 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R0].dirty = 1;
1736 /* r1 is no longer valid on target */
1737 dsp563xx->core_cache->reg_list[DSP563XX_REG_IDX_R1].dirty = 1;
1738
1739 x = count;
1740 b = buffer;
1741
1742 err = dsp563xx_once_execute_dw_ir(target->tap, 1, 0x60F400, address);
1743 if (err != ERROR_OK)
1744 return err;
1745
1746 for (i = 0; i < x; i++) {
1747 data = target_buffer_get_u32(target, b);
1748
1749 /* LOG_DEBUG("W: %08X", data); */
1750
1751 data &= 0x00ffffff;
1752
1753 err = dsp563xx_once_execute_dw_ir(target->tap, 0, 0x61F400, data);
1754 if (err != ERROR_OK)
1755 return err;
1756 err = dsp563xx_once_execute_sw_ir(target->tap, 0, move_cmd);
1757 if (err != ERROR_OK)
1758 return err;
1759 b += 4;
1760 }
1761
1762 /* flush the jtag queue */
1763 err = jtag_execute_queue();
1764 if (err != ERROR_OK)
1765 return err;
1766
1767 return ERROR_OK;
1768 }
1769
1770 static int dsp563xx_write_memory(struct target *target,
1771 int mem_type,
1772 target_addr_t address,
1773 uint32_t size,
1774 uint32_t count,
1775 const uint8_t *buffer)
1776 {
1777 int err;
1778 uint32_t i, i1;
1779 uint8_t *buffer_y, *buffer_x;
1780
1781 /* if size equals zero we are called from target write memory
1782 * and have to handle the parameter here */
1783 if ((size == 0) && (count != 0)) {
1784 size = count % 4;
1785
1786 if (size)
1787 LOG_DEBUG("size is not aligned to 4 byte");
1788
1789 count = (count - size) / 4;
1790 size = 4;
1791 }
1792
1793 /* we only support 4 byte aligned data */
1794 if ((size != 4) || (!count))
1795 return ERROR_COMMAND_SYNTAX_ERROR;
1796
1797 if (mem_type != MEM_L)
1798 return dsp563xx_write_memory_core(target, mem_type, address, size, count, buffer);
1799
1800 buffer_y = malloc(size * count);
1801 if (!buffer_y)
1802 return ERROR_COMMAND_SYNTAX_ERROR;
1803
1804 buffer_x = malloc(size * count);
1805 if (!buffer_x) {
1806 free(buffer_y);
1807 return ERROR_COMMAND_SYNTAX_ERROR;
1808 }
1809
1810 for (i = 0, i1 = 0; i < count; i += 2, i1++) {
1811 buf_set_u32(buffer_y + i1 * sizeof(uint32_t), 0, 32,
1812 buf_get_u32(buffer + i * sizeof(uint32_t), 0, 32));
1813 buf_set_u32(buffer_x + i1 * sizeof(uint32_t), 0, 32,
1814 buf_get_u32(buffer + (i + 1) * sizeof(uint32_t), 0, 32));
1815 }
1816
1817 err = dsp563xx_write_memory_core(target, MEM_Y, address, size, count / 2, buffer_y);
1818
1819 if (err != ERROR_OK) {
1820 free(buffer_y);
1821 free(buffer_x);
1822 return err;
1823 }
1824
1825 err = dsp563xx_write_memory_core(target, MEM_X, address, size, count / 2, buffer_x);
1826
1827 if (err != ERROR_OK) {
1828 free(buffer_y);
1829 free(buffer_x);
1830 return err;
1831 }
1832
1833 free(buffer_y);
1834 free(buffer_x);
1835
1836 return ERROR_OK;
1837 }
1838
1839 static int dsp563xx_write_memory_default(struct target *target,
1840 target_addr_t address,
1841 uint32_t size,
1842 uint32_t count,
1843 const uint8_t *buffer)
1844 {
1845 return dsp563xx_write_memory(target,
1846 dsp563xx_get_default_memory(), address, size, count, buffer);
1847 }
1848
1849 static int dsp563xx_write_buffer_default(struct target *target,
1850 target_addr_t address,
1851 uint32_t size,
1852 const uint8_t *buffer)
1853 {
1854 return dsp563xx_write_memory(target, dsp563xx_get_default_memory(), address, size, 0,
1855 buffer);
1856 }
1857
1858 /*
1859 * Exit with error here, because we support watchpoints over a custom command.
1860 * This is because the DSP has separate X,Y,P memspace which is not compatible to the
1861 * traditional watchpoint logic.
1862 */
1863 static int dsp563xx_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
1864 {
1865 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1866 }
1867
1868 /*
1869 * @see dsp563xx_add_watchpoint
1870 */
1871 static int dsp563xx_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
1872 {
1873 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1874 }
1875
1876 static void handle_md_output(struct command_context *cmd_ctx,
1877 struct target *target,
1878 uint32_t address,
1879 unsigned size,
1880 unsigned count,
1881 const uint8_t *buffer)
1882 {
1883 const unsigned line_bytecnt = 32;
1884 unsigned line_modulo = line_bytecnt / size;
1885
1886 char output[line_bytecnt * 4 + 1];
1887 unsigned output_len = 0;
1888
1889 const char *value_fmt;
1890 switch (size) {
1891 case 4:
1892 value_fmt = "%8.8x ";
1893 break;
1894 case 2:
1895 value_fmt = "%4.4x ";
1896 break;
1897 case 1:
1898 value_fmt = "%2.2x ";
1899 break;
1900 default:
1901 /* "can't happen", caller checked */
1902 LOG_ERROR("invalid memory read size: %u", size);
1903 return;
1904 }
1905
1906 for (unsigned i = 0; i < count; i++) {
1907 if (i % line_modulo == 0)
1908 output_len += snprintf(output + output_len,
1909 sizeof(output) - output_len,
1910 "0x%8.8x: ",
1911 (unsigned) (address + i));
1912
1913 uint32_t value = 0;
1914 const uint8_t *value_ptr = buffer + i * size;
1915 switch (size) {
1916 case 4:
1917 value = target_buffer_get_u32(target, value_ptr);
1918 break;
1919 case 2:
1920 value = target_buffer_get_u16(target, value_ptr);
1921 break;
1922 case 1:
1923 value = *value_ptr;
1924 }
1925 output_len += snprintf(output + output_len,
1926 sizeof(output) - output_len,
1927 value_fmt,
1928 value);
1929
1930 if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) {
1931 command_print(cmd_ctx, "%s", output);
1932 output_len = 0;
1933 }
1934 }
1935 }
1936
1937 static int dsp563xx_add_custom_watchpoint(struct target *target, uint32_t address, uint32_t memType,
1938 enum watchpoint_rw rw, enum watchpoint_condition cond)
1939 {
1940 int err = ERROR_OK;
1941 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
1942
1943 bool wasRunning = false;
1944 /* Only set breakpoint when halted */
1945 if (target->state != TARGET_HALTED) {
1946 dsp563xx_halt(target);
1947 wasRunning = true;
1948 }
1949
1950 if (dsp563xx->hardware_breakpoint[0].used) {
1951 LOG_ERROR("Cannot add watchpoint. Hardware resource already used.");
1952 err = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1953 }
1954
1955 uint32_t obcr_value = 0;
1956 if (err == ERROR_OK) {
1957 obcr_value |= OBCR_b0_or_b1;
1958 switch (memType) {
1959 case MEM_X:
1960 obcr_value |= OBCR_BP_MEM_X;
1961 break;
1962 case MEM_Y:
1963 obcr_value |= OBCR_BP_MEM_Y;
1964 break;
1965 case MEM_P:
1966 obcr_value |= OBCR_BP_MEM_P;
1967 break;
1968 default:
1969 LOG_ERROR("Unknown memType parameter (%" PRIu32 ")", memType);
1970 err = ERROR_TARGET_INVALID;
1971 }
1972 }
1973
1974 if (err == ERROR_OK) {
1975 switch (rw) {
1976 case WPT_READ:
1977 obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ);
1978 break;
1979 case WPT_WRITE:
1980 obcr_value |= OBCR_BP_0(OBCR_BP_ON_WRITE);
1981 break;
1982 case WPT_ACCESS:
1983 obcr_value |= OBCR_BP_0(OBCR_BP_ON_READ|OBCR_BP_ON_WRITE);
1984 break;
1985 default:
1986 LOG_ERROR("Unsupported write mode (%d)", rw);
1987 err = ERROR_TARGET_INVALID;
1988 }
1989 }
1990
1991 if (err == ERROR_OK) {
1992 switch (cond) {
1993 case EQUAL:
1994 obcr_value |= OBCR_BP_0(OBCR_BP_CC_EQUAL);
1995 break;
1996 case NOT_EQUAL:
1997 obcr_value |= OBCR_BP_0(OBCR_BP_CC_NOT_EQUAL);
1998 break;
1999 case LESS_THAN:
2000 obcr_value |= OBCR_BP_0(OBCR_BP_CC_LESS_THAN);
2001 break;
2002 case GREATER:
2003 obcr_value |= OBCR_BP_0(OBCR_BP_CC_GREATER_THAN);
2004 break;
2005 default:
2006 LOG_ERROR("Unsupported condition code (%d)", cond);
2007 err = ERROR_TARGET_INVALID;
2008 }
2009 }
2010
2011 if (err == ERROR_OK)
2012 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR0, address);
2013
2014 if (err == ERROR_OK)
2015 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMLR1, 0x0);
2016
2017 if (err == ERROR_OK)
2018 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, obcr_value);
2019
2020 if (err == ERROR_OK) {
2021 /* You should write the memory breakpoint counter to 0 */
2022 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OMBC, 0);
2023 }
2024
2025 if (err == ERROR_OK) {
2026 /* You should write the memory breakpoint counter to 0 */
2027 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OTC, 0);
2028 }
2029
2030 if (err == ERROR_OK)
2031 dsp563xx->hardware_breakpoint[0].used = BPU_WATCHPOINT;
2032
2033 if (err == ERROR_OK && wasRunning) {
2034 /* Resume from current PC */
2035 err = dsp563xx_resume(target, 1, 0x0, 0, 0);
2036 }
2037
2038 return err;
2039 }
2040
2041 static int dsp563xx_remove_custom_watchpoint(struct target *target)
2042 {
2043 int err = ERROR_OK;
2044 struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target);
2045
2046 if (dsp563xx->hardware_breakpoint[0].used != BPU_WATCHPOINT) {
2047 LOG_ERROR("Cannot remove watchpoint, as no watchpoint is currently configured!");
2048 err = ERROR_TARGET_INVALID;
2049 }
2050
2051 if (err == ERROR_OK) {
2052 /* Clear watchpoint by clearing OBCR. */
2053 err = dsp563xx_once_reg_write(target->tap, 1, DSP563XX_ONCE_OBCR, 0);
2054 }
2055
2056 if (err == ERROR_OK)
2057 dsp563xx->hardware_breakpoint[0].used = BPU_NONE;
2058
2059 return err;
2060 }
2061
2062 COMMAND_HANDLER(dsp563xx_add_watchpoint_command)
2063 {
2064 int err = ERROR_OK;
2065 struct target *target = get_current_target(CMD_CTX);
2066
2067 uint32_t mem_type = 0;
2068 switch (CMD_NAME[2]) {
2069 case 'x':
2070 mem_type = MEM_X;
2071 break;
2072 case 'y':
2073 mem_type = MEM_Y;
2074 break;
2075 case 'p':
2076 mem_type = MEM_P;
2077 break;
2078 default:
2079 return ERROR_COMMAND_SYNTAX_ERROR;
2080 }
2081
2082 if (CMD_ARGC < 2)
2083 return ERROR_COMMAND_SYNTAX_ERROR;
2084
2085 uint32_t address = 0;
2086 if (CMD_ARGC > 2)
2087 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], address);
2088
2089 enum watchpoint_condition cond;
2090 switch (CMD_ARGV[0][0]) {
2091 case '>':
2092 cond = GREATER;
2093 break;
2094 case '<':
2095 cond = LESS_THAN;
2096 break;
2097 case '=':
2098 cond = EQUAL;
2099 break;
2100 case '!':
2101 cond = NOT_EQUAL;
2102 break;
2103 default:
2104 return ERROR_COMMAND_SYNTAX_ERROR;
2105 }
2106
2107 enum watchpoint_rw rw;
2108 switch (CMD_ARGV[1][0]) {
2109 case 'r':
2110 rw = WPT_READ;
2111 break;
2112 case 'w':
2113 rw = WPT_WRITE;
2114 break;
2115 case 'a':
2116 rw = WPT_ACCESS;
2117 break;
2118 default:
2119 return ERROR_COMMAND_SYNTAX_ERROR;
2120 }
2121
2122 err = dsp563xx_add_custom_watchpoint(target, address, mem_type, rw, cond);
2123
2124 return err;
2125 }
2126
2127 /* Adding a breakpoint using the once breakpoint logic.
2128 * Note that this mechanism is a true hw breakpoint and is share between the watchpoint logic.
2129 * This means, you can only have one breakpoint/watchpoint at any time.
2130 */
2131 static int dsp563xx_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
2132 {
2133 return dsp563xx_add_custom_watchpoint(target, breakpoint->address, MEM_P, WPT_READ, EQUAL);
2134 }
2135
2136 static int dsp563xx_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
2137 {
2138 return dsp563xx_remove_custom_watchpoint(target);
2139 }
2140
2141 COMMAND_HANDLER(dsp563xx_remove_watchpoint_command)
2142 {
2143 struct target *target = get_current_target(CMD_CTX);
2144
2145 return dsp563xx_remove_custom_watchpoint(target);
2146 }
2147
2148 COMMAND_HANDLER(dsp563xx_mem_command)
2149 {
2150 struct target *target = get_current_target(CMD_CTX);
2151 int err = ERROR_OK;
2152 int read_mem;
2153 uint32_t address = 0;
2154 uint32_t count = 1, i;
2155 uint32_t pattern = 0;
2156 uint32_t mem_type;
2157 uint8_t *buffer, *b;
2158
2159 switch (CMD_NAME[1]) {
2160 case 'w':
2161 read_mem = 0;
2162 break;
2163 case 'd':
2164 read_mem = 1;
2165 break;
2166 default:
2167 return ERROR_COMMAND_SYNTAX_ERROR;
2168 }
2169
2170 switch (CMD_NAME[3]) {
2171 case 'x':
2172 mem_type = MEM_X;
2173 break;
2174 case 'y':
2175 mem_type = MEM_Y;
2176 break;
2177 case 'p':
2178 mem_type = MEM_P;
2179 break;
2180 default:
2181 return ERROR_COMMAND_SYNTAX_ERROR;
2182 }
2183
2184 if (CMD_ARGC > 0)
2185 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
2186
2187 if (read_mem == 0) {
2188 if (CMD_ARGC < 2)
2189 return ERROR_COMMAND_SYNTAX_ERROR;
2190 if (CMD_ARGC > 1)
2191 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
2192 if (CMD_ARGC > 2)
2193 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
2194 }
2195
2196 if (read_mem == 1) {
2197 if (CMD_ARGC < 1)
2198 return ERROR_COMMAND_SYNTAX_ERROR;
2199 if (CMD_ARGC > 1)
2200 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], count);
2201 }
2202
2203 buffer = calloc(count, sizeof(uint32_t));
2204
2205 if (read_mem == 1) {
2206 err = dsp563xx_read_memory(target, mem_type, address, sizeof(uint32_t),
2207 count, buffer);
2208 if (err == ERROR_OK)
2209 handle_md_output(CMD_CTX, target, address, sizeof(uint32_t), count, buffer);
2210
2211 } else {
2212 b = buffer;
2213
2214 for (i = 0; i < count; i++) {
2215 target_buffer_set_u32(target, b, pattern);
2216 b += 4;
2217 }
2218
2219 err = dsp563xx_write_memory(target,
2220 mem_type,
2221 address,
2222 sizeof(uint32_t),
2223 count,
2224 buffer);
2225 }
2226
2227 free(buffer);
2228
2229 return err;
2230 }
2231
2232 static const struct command_registration dsp563xx_command_handlers[] = {
2233 {
2234 .name = "mwwx",
2235 .handler = dsp563xx_mem_command,
2236 .mode = COMMAND_EXEC,
2237 .help = "write x memory words",
2238 .usage = "address value [count]",
2239 },
2240 {
2241 .name = "mwwy",
2242 .handler = dsp563xx_mem_command,
2243 .mode = COMMAND_EXEC,
2244 .help = "write y memory words",
2245 .usage = "address value [count]",
2246 },
2247 {
2248 .name = "mwwp",
2249 .handler = dsp563xx_mem_command,
2250 .mode = COMMAND_EXEC,
2251 .help = "write p memory words",
2252 .usage = "address value [count]",
2253 },
2254 {
2255 .name = "mdwx",
2256 .handler = dsp563xx_mem_command,
2257 .mode = COMMAND_EXEC,
2258 .help = "display x memory words",
2259 .usage = "address [count]",
2260 },
2261 {
2262 .name = "mdwy",
2263 .handler = dsp563xx_mem_command,
2264 .mode = COMMAND_EXEC,
2265 .help = "display y memory words",
2266 .usage = "address [count]",
2267 },
2268 {
2269 .name = "mdwp",
2270 .handler = dsp563xx_mem_command,
2271 .mode = COMMAND_EXEC,
2272 .help = "display p memory words",
2273 .usage = "address [count]",
2274 },
2275 /*
2276 * Watchpoint commands
2277 */
2278 {
2279 .name = "wpp",
2280 .handler = dsp563xx_add_watchpoint_command,
2281 .mode = COMMAND_EXEC,
2282 .help = "Create p memspace watchpoint",
2283 .usage = "(>|<|=|!) (r|w|a) address",
2284 },
2285 {
2286 .name = "wpx",
2287 .handler = dsp563xx_add_watchpoint_command,
2288 .mode = COMMAND_EXEC,
2289 .help = "Create x memspace watchpoint",
2290 .usage = "(>|<|=|!) (r|w|a) address",
2291 },
2292 {
2293 .name = "wpy",
2294 .handler = dsp563xx_add_watchpoint_command,
2295 .mode = COMMAND_EXEC,
2296 .help = "Create y memspace watchpoint",
2297 .usage = "(>|<|=|!) (r|w|a) address",
2298 },
2299 {
2300 .name = "rwpc",
2301 .handler = dsp563xx_remove_watchpoint_command,
2302 .mode = COMMAND_EXEC,
2303 .help = "remove watchpoint custom",
2304 .usage = " ",
2305 },
2306 COMMAND_REGISTRATION_DONE
2307 };
2308
2309 /** Holds methods for DSP563XX targets. */
2310 struct target_type dsp563xx_target = {
2311 .name = "dsp563xx",
2312
2313 .poll = dsp563xx_poll,
2314 .arch_state = dsp563xx_arch_state,
2315
2316 .get_gdb_reg_list = dsp563xx_get_gdb_reg_list,
2317
2318 .halt = dsp563xx_halt,
2319 .resume = dsp563xx_resume,
2320 .step = dsp563xx_step,
2321
2322 .assert_reset = dsp563xx_assert_reset,
2323 .deassert_reset = dsp563xx_deassert_reset,
2324
2325 .read_memory = dsp563xx_read_memory_default,
2326 .write_memory = dsp563xx_write_memory_default,
2327
2328 .read_buffer = dsp563xx_read_buffer_default,
2329 .write_buffer = dsp563xx_write_buffer_default,
2330
2331 .run_algorithm = dsp563xx_run_algorithm,
2332
2333 .add_breakpoint = dsp563xx_add_breakpoint,
2334 .remove_breakpoint = dsp563xx_remove_breakpoint,
2335 .add_watchpoint = dsp563xx_add_watchpoint,
2336 .remove_watchpoint = dsp563xx_remove_watchpoint,
2337
2338 .commands = dsp563xx_command_handlers,
2339 .target_create = dsp563xx_target_create,
2340 .init_target = dsp563xx_init_target,
2341 .examine = dsp563xx_examine,
2342 };

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)