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

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)