1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Generic Xtensa target API for OpenOCD *
5 * Copyright (C) 2016-2019 Espressif Systems Ltd. *
6 * Derived from esp108.c *
7 * Author: Angus Gratton gus@projectgus.com *
8 * Author: Jeroen Domburg <jeroen@espressif.com> *
9 * Author: Alexey Gerenkov <alexey@espressif.com> *
10 * Author: Andrey Gramakov <andrei.gramakov@espressif.com> *
11 ***************************************************************************/
18 #include <helper/time_support.h>
19 #include <helper/align.h>
20 #include <target/register.h>
25 #define _XT_INS_FORMAT_RSR(OPCODE, SR, T) ((OPCODE) \
26 | (((SR) & 0xFF) << 8) \
27 | (((T) & 0x0F) << 4))
29 #define _XT_INS_FORMAT_RRR(OPCODE, ST, R) ((OPCODE) \
30 | (((ST) & 0xFF) << 4) \
31 | (((R) & 0x0F) << 12))
33 #define _XT_INS_FORMAT_RRRN(OPCODE, S, T, IMM4) ((OPCODE) \
34 | (((T) & 0x0F) << 4) \
35 | (((S) & 0x0F) << 8) \
36 | (((IMM4) & 0x0F) << 12))
38 #define _XT_INS_FORMAT_RRI8(OPCODE, R, S, T, IMM8) ((OPCODE) \
39 | (((IMM8) & 0xFF) << 16) \
40 | (((R) & 0x0F) << 12) \
41 | (((S) & 0x0F) << 8) \
42 | (((T) & 0x0F) << 4))
44 #define _XT_INS_FORMAT_RRI4(OPCODE, IMM4, R, S, T) ((OPCODE) \
45 | (((IMM4) & 0x0F) << 20) \
46 | (((R) & 0x0F) << 12) \
47 | (((S) & 0x0F) << 8) \
48 | (((T) & 0x0F) << 4))
50 /* Xtensa processor instruction opcodes
51 * "Return From Debug Operation" to Normal */
52 #define XT_INS_RFDO 0xf1e000
53 /* "Return From Debug and Dispatch" - allow sw debugging stuff to take over */
54 #define XT_INS_RFDD 0xf1e010
56 /* Load to DDR register, increase addr register */
57 #define XT_INS_LDDR32P(S) (0x0070E0 | ((S) << 8))
58 /* Store from DDR register, increase addr register */
59 #define XT_INS_SDDR32P(S) (0x0070F0 | ((S) << 8))
61 /* Load 32-bit Indirect from A(S) + 4 * IMM8 to A(T) */
62 #define XT_INS_L32I(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x002002, 0, S, T, IMM8)
63 /* Load 16-bit Unsigned from A(S) + 2 * IMM8 to A(T) */
64 #define XT_INS_L16UI(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x001002, 0, S, T, IMM8)
65 /* Load 8-bit Unsigned from A(S) + IMM8 to A(T) */
66 #define XT_INS_L8UI(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x000002, 0, S, T, IMM8)
68 /* Store 32-bit Indirect to A(S) + 4 * IMM8 from A(T) */
69 #define XT_INS_S32I(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x006002, 0, S, T, IMM8)
70 /* Store 16-bit to A(S) + 2 * IMM8 from A(T) */
71 #define XT_INS_S16I(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x005002, 0, S, T, IMM8)
72 /* Store 8-bit to A(S) + IMM8 from A(T) */
73 #define XT_INS_S8I(S, T, IMM8) _XT_INS_FORMAT_RRI8(0x004002, 0, S, T, IMM8)
75 /* Read Special Register */
76 #define XT_INS_RSR(SR, T) _XT_INS_FORMAT_RSR(0x030000, SR, T)
77 /* Write Special Register */
78 #define XT_INS_WSR(SR, T) _XT_INS_FORMAT_RSR(0x130000, SR, T)
79 /* Swap Special Register */
80 #define XT_INS_XSR(SR, T) _XT_INS_FORMAT_RSR(0x610000, SR, T)
82 /* Rotate Window by (-8..7) */
83 #define XT_INS_ROTW(N) ((0x408000) | (((N) & 15) << 4))
85 /* Read User Register */
86 #define XT_INS_RUR(UR, T) _XT_INS_FORMAT_RRR(0xE30000, UR, T)
87 /* Write User Register */
88 #define XT_INS_WUR(UR, T) _XT_INS_FORMAT_RSR(0xF30000, UR, T)
90 /* Read Floating-Point Register */
91 #define XT_INS_RFR(FR, T) _XT_INS_FORMAT_RRR(0xFA0000, (((FR) << 4) | 0x4), T)
92 /* Write Floating-Point Register */
93 #define XT_INS_WFR(FR, T) _XT_INS_FORMAT_RRR(0xFA0000, (((FR) << 4) | 0x5), T)
96 #define XT_INS_BREAK(IMM1, IMM2) _XT_INS_FORMAT_RRR(0x000000, \
97 (((IMM1) & 0x0F) << 4) | ((IMM2) & 0x0F), 0x4)
99 #define XT_INS_BREAKN(IMM4) _XT_INS_FORMAT_RRRN(0x00000D, IMM4, 0x2, 0xF)
101 #define XT_INS_L32E(R, S, T) _XT_INS_FORMAT_RRI4(0x90000, 0, R, S, T)
102 #define XT_INS_S32E(R, S, T) _XT_INS_FORMAT_RRI4(0x490000, 0, R, S, T)
103 #define XT_INS_L32E_S32E_MASK 0xFF000F
105 #define XT_INS_RFWO 0x3400
106 #define XT_INS_RFWU 0x3500
107 #define XT_INS_RFWO_RFWU_MASK 0xFFFFFF
109 #define XT_WATCHPOINTS_NUM_MAX 2
111 /* Special register number macro for DDR register.
112 * this gets used a lot so making a shortcut to it is
115 #define XT_SR_DDR (xtensa_regs[XT_REG_IDX_OCD_DDR].reg_num)
117 /*Same thing for A3/A4 */
118 #define XT_REG_A3 (xtensa_regs[XT_REG_IDX_AR3].reg_num)
119 #define XT_REG_A4 (xtensa_regs[XT_REG_IDX_AR4].reg_num)
121 #define XT_PC_REG_NUM_BASE (176)
122 #define XT_SW_BREAKPOINTS_MAX_NUM 32
124 const struct xtensa_reg_desc xtensa_regs[XT_NUM_REGS] = {
125 { "pc", XT_PC_REG_NUM_BASE /*+XT_DEBUGLEVEL*/, XT_REG_SPECIAL, 0 }, /* actually epc[debuglevel] */
126 { "ar0", 0x00, XT_REG_GENERAL, 0 },
127 { "ar1", 0x01, XT_REG_GENERAL, 0 },
128 { "ar2", 0x02, XT_REG_GENERAL, 0 },
129 { "ar3", 0x03, XT_REG_GENERAL, 0 },
130 { "ar4", 0x04, XT_REG_GENERAL, 0 },
131 { "ar5", 0x05, XT_REG_GENERAL, 0 },
132 { "ar6", 0x06, XT_REG_GENERAL, 0 },
133 { "ar7", 0x07, XT_REG_GENERAL, 0 },
134 { "ar8", 0x08, XT_REG_GENERAL, 0 },
135 { "ar9", 0x09, XT_REG_GENERAL, 0 },
136 { "ar10", 0x0A, XT_REG_GENERAL, 0 },
137 { "ar11", 0x0B, XT_REG_GENERAL, 0 },
138 { "ar12", 0x0C, XT_REG_GENERAL, 0 },
139 { "ar13", 0x0D, XT_REG_GENERAL, 0 },
140 { "ar14", 0x0E, XT_REG_GENERAL, 0 },
141 { "ar15", 0x0F, XT_REG_GENERAL, 0 },
142 { "ar16", 0x10, XT_REG_GENERAL, 0 },
143 { "ar17", 0x11, XT_REG_GENERAL, 0 },
144 { "ar18", 0x12, XT_REG_GENERAL, 0 },
145 { "ar19", 0x13, XT_REG_GENERAL, 0 },
146 { "ar20", 0x14, XT_REG_GENERAL, 0 },
147 { "ar21", 0x15, XT_REG_GENERAL, 0 },
148 { "ar22", 0x16, XT_REG_GENERAL, 0 },
149 { "ar23", 0x17, XT_REG_GENERAL, 0 },
150 { "ar24", 0x18, XT_REG_GENERAL, 0 },
151 { "ar25", 0x19, XT_REG_GENERAL, 0 },
152 { "ar26", 0x1A, XT_REG_GENERAL, 0 },
153 { "ar27", 0x1B, XT_REG_GENERAL, 0 },
154 { "ar28", 0x1C, XT_REG_GENERAL, 0 },
155 { "ar29", 0x1D, XT_REG_GENERAL, 0 },
156 { "ar30", 0x1E, XT_REG_GENERAL, 0 },
157 { "ar31", 0x1F, XT_REG_GENERAL, 0 },
158 { "ar32", 0x20, XT_REG_GENERAL, 0 },
159 { "ar33", 0x21, XT_REG_GENERAL, 0 },
160 { "ar34", 0x22, XT_REG_GENERAL, 0 },
161 { "ar35", 0x23, XT_REG_GENERAL, 0 },
162 { "ar36", 0x24, XT_REG_GENERAL, 0 },
163 { "ar37", 0x25, XT_REG_GENERAL, 0 },
164 { "ar38", 0x26, XT_REG_GENERAL, 0 },
165 { "ar39", 0x27, XT_REG_GENERAL, 0 },
166 { "ar40", 0x28, XT_REG_GENERAL, 0 },
167 { "ar41", 0x29, XT_REG_GENERAL, 0 },
168 { "ar42", 0x2A, XT_REG_GENERAL, 0 },
169 { "ar43", 0x2B, XT_REG_GENERAL, 0 },
170 { "ar44", 0x2C, XT_REG_GENERAL, 0 },
171 { "ar45", 0x2D, XT_REG_GENERAL, 0 },
172 { "ar46", 0x2E, XT_REG_GENERAL, 0 },
173 { "ar47", 0x2F, XT_REG_GENERAL, 0 },
174 { "ar48", 0x30, XT_REG_GENERAL, 0 },
175 { "ar49", 0x31, XT_REG_GENERAL, 0 },
176 { "ar50", 0x32, XT_REG_GENERAL, 0 },
177 { "ar51", 0x33, XT_REG_GENERAL, 0 },
178 { "ar52", 0x34, XT_REG_GENERAL, 0 },
179 { "ar53", 0x35, XT_REG_GENERAL, 0 },
180 { "ar54", 0x36, XT_REG_GENERAL, 0 },
181 { "ar55", 0x37, XT_REG_GENERAL, 0 },
182 { "ar56", 0x38, XT_REG_GENERAL, 0 },
183 { "ar57", 0x39, XT_REG_GENERAL, 0 },
184 { "ar58", 0x3A, XT_REG_GENERAL, 0 },
185 { "ar59", 0x3B, XT_REG_GENERAL, 0 },
186 { "ar60", 0x3C, XT_REG_GENERAL, 0 },
187 { "ar61", 0x3D, XT_REG_GENERAL, 0 },
188 { "ar62", 0x3E, XT_REG_GENERAL, 0 },
189 { "ar63", 0x3F, XT_REG_GENERAL, 0 },
190 { "lbeg", 0x00, XT_REG_SPECIAL, 0 },
191 { "lend", 0x01, XT_REG_SPECIAL, 0 },
192 { "lcount", 0x02, XT_REG_SPECIAL, 0 },
193 { "sar", 0x03, XT_REG_SPECIAL, 0 },
194 { "windowbase", 0x48, XT_REG_SPECIAL, 0 },
195 { "windowstart", 0x49, XT_REG_SPECIAL, 0 },
196 { "configid0", 0xB0, XT_REG_SPECIAL, 0 },
197 { "configid1", 0xD0, XT_REG_SPECIAL, 0 },
198 { "ps", 0xC6, XT_REG_SPECIAL, 0 }, /* actually EPS[debuglevel] */
199 { "threadptr", 0xE7, XT_REG_USER, 0 },
200 { "br", 0x04, XT_REG_SPECIAL, 0 },
201 { "scompare1", 0x0C, XT_REG_SPECIAL, 0 },
202 { "acclo", 0x10, XT_REG_SPECIAL, 0 },
203 { "acchi", 0x11, XT_REG_SPECIAL, 0 },
204 { "m0", 0x20, XT_REG_SPECIAL, 0 },
205 { "m1", 0x21, XT_REG_SPECIAL, 0 },
206 { "m2", 0x22, XT_REG_SPECIAL, 0 },
207 { "m3", 0x23, XT_REG_SPECIAL, 0 },
208 { "f0", 0x00, XT_REG_FR, XT_REGF_COPROC0 },
209 { "f1", 0x01, XT_REG_FR, XT_REGF_COPROC0 },
210 { "f2", 0x02, XT_REG_FR, XT_REGF_COPROC0 },
211 { "f3", 0x03, XT_REG_FR, XT_REGF_COPROC0 },
212 { "f4", 0x04, XT_REG_FR, XT_REGF_COPROC0 },
213 { "f5", 0x05, XT_REG_FR, XT_REGF_COPROC0 },
214 { "f6", 0x06, XT_REG_FR, XT_REGF_COPROC0 },
215 { "f7", 0x07, XT_REG_FR, XT_REGF_COPROC0 },
216 { "f8", 0x08, XT_REG_FR, XT_REGF_COPROC0 },
217 { "f9", 0x09, XT_REG_FR, XT_REGF_COPROC0 },
218 { "f10", 0x0A, XT_REG_FR, XT_REGF_COPROC0 },
219 { "f11", 0x0B, XT_REG_FR, XT_REGF_COPROC0 },
220 { "f12", 0x0C, XT_REG_FR, XT_REGF_COPROC0 },
221 { "f13", 0x0D, XT_REG_FR, XT_REGF_COPROC0 },
222 { "f14", 0x0E, XT_REG_FR, XT_REGF_COPROC0 },
223 { "f15", 0x0F, XT_REG_FR, XT_REGF_COPROC0 },
224 { "fcr", 0xE8, XT_REG_USER, XT_REGF_COPROC0 },
225 { "fsr", 0xE9, XT_REG_USER, XT_REGF_COPROC0 },
226 { "mmid", 0x59, XT_REG_SPECIAL, XT_REGF_NOREAD },
227 { "ibreakenable", 0x60, XT_REG_SPECIAL, 0 },
228 { "memctl", 0x61, XT_REG_SPECIAL, 0 },
229 { "atomctl", 0x63, XT_REG_SPECIAL, 0 },
230 { "ibreaka0", 0x80, XT_REG_SPECIAL, 0 },
231 { "ibreaka1", 0x81, XT_REG_SPECIAL, 0 },
232 { "dbreaka0", 0x90, XT_REG_SPECIAL, 0 },
233 { "dbreaka1", 0x91, XT_REG_SPECIAL, 0 },
234 { "dbreakc0", 0xA0, XT_REG_SPECIAL, 0 },
235 { "dbreakc1", 0xA1, XT_REG_SPECIAL, 0 },
236 { "epc1", 0xB1, XT_REG_SPECIAL, 0 },
237 { "epc2", 0xB2, XT_REG_SPECIAL, 0 },
238 { "epc3", 0xB3, XT_REG_SPECIAL, 0 },
239 { "epc4", 0xB4, XT_REG_SPECIAL, 0 },
240 { "epc5", 0xB5, XT_REG_SPECIAL, 0 },
241 { "epc6", 0xB6, XT_REG_SPECIAL, 0 },
242 { "epc7", 0xB7, XT_REG_SPECIAL, 0 },
243 { "depc", 0xC0, XT_REG_SPECIAL, 0 },
244 { "eps2", 0xC2, XT_REG_SPECIAL, 0 },
245 { "eps3", 0xC3, XT_REG_SPECIAL, 0 },
246 { "eps4", 0xC4, XT_REG_SPECIAL, 0 },
247 { "eps5", 0xC5, XT_REG_SPECIAL, 0 },
248 { "eps6", 0xC6, XT_REG_SPECIAL, 0 },
249 { "eps7", 0xC7, XT_REG_SPECIAL, 0 },
250 { "excsave1", 0xD1, XT_REG_SPECIAL, 0 },
251 { "excsave2", 0xD2, XT_REG_SPECIAL, 0 },
252 { "excsave3", 0xD3, XT_REG_SPECIAL, 0 },
253 { "excsave4", 0xD4, XT_REG_SPECIAL, 0 },
254 { "excsave5", 0xD5, XT_REG_SPECIAL, 0 },
255 { "excsave6", 0xD6, XT_REG_SPECIAL, 0 },
256 { "excsave7", 0xD7, XT_REG_SPECIAL, 0 },
257 { "cpenable", 0xE0, XT_REG_SPECIAL, 0 },
258 { "interrupt", 0xE2, XT_REG_SPECIAL, 0 },
259 { "intset", 0xE2, XT_REG_SPECIAL, XT_REGF_NOREAD },
260 { "intclear", 0xE3, XT_REG_SPECIAL, XT_REGF_NOREAD },
261 { "intenable", 0xE4, XT_REG_SPECIAL, 0 },
262 { "vecbase", 0xE7, XT_REG_SPECIAL, 0 },
263 { "exccause", 0xE8, XT_REG_SPECIAL, 0 },
264 { "debugcause", 0xE9, XT_REG_SPECIAL, 0 },
265 { "ccount", 0xEA, XT_REG_SPECIAL, 0 },
266 { "prid", 0xEB, XT_REG_SPECIAL, 0 },
267 { "icount", 0xEC, XT_REG_SPECIAL, 0 },
268 { "icountlevel", 0xED, XT_REG_SPECIAL, 0 },
269 { "excvaddr", 0xEE, XT_REG_SPECIAL, 0 },
270 { "ccompare0", 0xF0, XT_REG_SPECIAL, 0 },
271 { "ccompare1", 0xF1, XT_REG_SPECIAL, 0 },
272 { "ccompare2", 0xF2, XT_REG_SPECIAL, 0 },
273 { "misc0", 0xF4, XT_REG_SPECIAL, 0 },
274 { "misc1", 0xF5, XT_REG_SPECIAL, 0 },
275 { "misc2", 0xF6, XT_REG_SPECIAL, 0 },
276 { "misc3", 0xF7, XT_REG_SPECIAL, 0 },
277 { "litbase", 0x05, XT_REG_SPECIAL, 0 },
278 { "ptevaddr", 0x53, XT_REG_SPECIAL, 0 },
279 { "rasid", 0x5A, XT_REG_SPECIAL, 0 },
280 { "itlbcfg", 0x5B, XT_REG_SPECIAL, 0 },
281 { "dtlbcfg", 0x5C, XT_REG_SPECIAL, 0 },
282 { "mepc", 0x6A, XT_REG_SPECIAL, 0 },
283 { "meps", 0x6B, XT_REG_SPECIAL, 0 },
284 { "mesave", 0x6C, XT_REG_SPECIAL, 0 },
285 { "mesr", 0x6D, XT_REG_SPECIAL, 0 },
286 { "mecr", 0x6E, XT_REG_SPECIAL, 0 },
287 { "mevaddr", 0x6F, XT_REG_SPECIAL, 0 },
288 { "a0", XT_REG_IDX_AR0, XT_REG_RELGEN, 0 }, /* WARNING: For these registers, regnum points to the */
289 { "a1", XT_REG_IDX_AR1, XT_REG_RELGEN, 0 }, /* index of the corresponding ARxregisters, NOT to */
290 { "a2", XT_REG_IDX_AR2, XT_REG_RELGEN, 0 }, /* the processor register number! */
291 { "a3", XT_REG_IDX_AR3, XT_REG_RELGEN, 0 },
292 { "a4", XT_REG_IDX_AR4, XT_REG_RELGEN, 0 },
293 { "a5", XT_REG_IDX_AR5, XT_REG_RELGEN, 0 },
294 { "a6", XT_REG_IDX_AR6, XT_REG_RELGEN, 0 },
295 { "a7", XT_REG_IDX_AR7, XT_REG_RELGEN, 0 },
296 { "a8", XT_REG_IDX_AR8, XT_REG_RELGEN, 0 },
297 { "a9", XT_REG_IDX_AR9, XT_REG_RELGEN, 0 },
298 { "a10", XT_REG_IDX_AR10, XT_REG_RELGEN, 0 },
299 { "a11", XT_REG_IDX_AR11, XT_REG_RELGEN, 0 },
300 { "a12", XT_REG_IDX_AR12, XT_REG_RELGEN, 0 },
301 { "a13", XT_REG_IDX_AR13, XT_REG_RELGEN, 0 },
302 { "a14", XT_REG_IDX_AR14, XT_REG_RELGEN, 0 },
303 { "a15", XT_REG_IDX_AR15, XT_REG_RELGEN, 0 },
305 { "pwrctl", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
306 { "pwrstat", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
307 { "eristat", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
308 { "cs_itctrl", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
309 { "cs_claimset", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
310 { "cs_claimclr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
311 { "cs_lockaccess", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
312 { "cs_lockstatus", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
313 { "cs_authstatus", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
314 { "fault_info", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
315 { "trax_id", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
316 { "trax_ctrl", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
317 { "trax_stat", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
318 { "trax_data", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
319 { "trax_addr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
320 { "trax_pctrigger", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
321 { "trax_pcmatch", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
322 { "trax_delay", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
323 { "trax_memstart", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
324 { "trax_memend", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
325 { "pmg", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
326 { "pmoc", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
327 { "pm0", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
328 { "pm1", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
329 { "pmctrl0", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
330 { "pmctrl1", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
331 { "pmstat0", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
332 { "pmstat1", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
333 { "ocd_id", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
334 { "ocd_dcrclr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
335 { "ocd_dcrset", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
336 { "ocd_dsr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
337 { "ddr", 0x68, XT_REG_DEBUG, XT_REGF_NOREAD },
342 * Types of memory used at xtensa target
344 enum xtensa_mem_region_type {
345 XTENSA_MEM_REG_IROM = 0x0,
355 * Gets a config for the specific mem type
357 static inline const struct xtensa_local_mem_config *xtensa_get_mem_config(
358 struct xtensa *xtensa,
359 enum xtensa_mem_region_type type)
362 case XTENSA_MEM_REG_IROM:
363 return &xtensa->core_config->irom;
364 case XTENSA_MEM_REG_IRAM:
365 return &xtensa->core_config->iram;
366 case XTENSA_MEM_REG_DROM:
367 return &xtensa->core_config->drom;
368 case XTENSA_MEM_REG_DRAM:
369 return &xtensa->core_config->dram;
370 case XTENSA_MEM_REG_URAM:
371 return &xtensa->core_config->uram;
372 case XTENSA_MEM_REG_XLMI:
373 return &xtensa->core_config->xlmi;
380 * Extracts an exact xtensa_local_mem_region_config from xtensa_local_mem_config
381 * for a given address
382 * Returns NULL if nothing found
384 static inline const struct xtensa_local_mem_region_config *xtensa_memory_region_find(
385 const struct xtensa_local_mem_config *mem,
386 target_addr_t address)
388 for (unsigned int i = 0; i < mem->count; i++) {
389 const struct xtensa_local_mem_region_config *region = &mem->regions[i];
390 if (address >= region->base && address < (region->base + region->size))
397 * Returns a corresponding xtensa_local_mem_region_config from the xtensa target
398 * for a given address
399 * Returns NULL if nothing found
401 static inline const struct xtensa_local_mem_region_config *xtensa_target_memory_region_find(
402 struct xtensa *xtensa,
403 target_addr_t address)
405 const struct xtensa_local_mem_region_config *result;
406 const struct xtensa_local_mem_config *mcgf;
407 for (unsigned int mtype = 0; mtype < XTENSA_MEM_REGS_NUM; mtype++) {
408 mcgf = xtensa_get_mem_config(xtensa, mtype);
409 result = xtensa_memory_region_find(mcgf, address);
416 static int xtensa_core_reg_get(struct reg *reg)
418 /*We don't need this because we read all registers on halt anyway. */
419 struct xtensa *xtensa = (struct xtensa *)reg->arch_info;
420 struct target *target = xtensa->target;
422 if (target->state != TARGET_HALTED)
423 return ERROR_TARGET_NOT_HALTED;
427 static int xtensa_core_reg_set(struct reg *reg, uint8_t *buf)
429 struct xtensa *xtensa = (struct xtensa *)reg->arch_info;
430 struct target *target = xtensa->target;
432 assert(reg->size <= 64 && "up to 64-bit regs are supported only!");
433 if (target->state != TARGET_HALTED)
434 return ERROR_TARGET_NOT_HALTED;
436 buf_cpy(buf, reg->value, reg->size);
443 static const struct reg_arch_type xtensa_reg_type = {
444 .get = xtensa_core_reg_get,
445 .set = xtensa_core_reg_set,
448 const struct reg_arch_type xtensa_user_reg_u32_type = {
449 .get = xtensa_core_reg_get,
450 .set = xtensa_core_reg_set,
453 const struct reg_arch_type xtensa_user_reg_u128_type = {
454 .get = xtensa_core_reg_get,
455 .set = xtensa_core_reg_set,
458 static inline size_t xtensa_insn_size_get(uint32_t insn)
460 return insn & BIT(3) ? 2 : XT_ISNS_SZ_MAX;
463 /* Convert a register index that's indexed relative to windowbase, to the real address. */
464 static enum xtensa_reg_id xtensa_windowbase_offset_to_canonical(enum xtensa_reg_id reg_idx, int windowbase)
467 if (reg_idx >= XT_REG_IDX_AR0 && reg_idx <= XT_REG_IDX_AR63) {
468 idx = reg_idx - XT_REG_IDX_AR0;
469 } else if (reg_idx >= XT_REG_IDX_A0 && reg_idx <= XT_REG_IDX_A15) {
470 idx = reg_idx - XT_REG_IDX_A0;
472 LOG_ERROR("Error: can't convert register %d to non-windowbased register!", reg_idx);
475 return ((idx + windowbase * 4) & 63) + XT_REG_IDX_AR0;
478 static enum xtensa_reg_id xtensa_canonical_to_windowbase_offset(enum xtensa_reg_id reg_idx, int windowbase)
480 return xtensa_windowbase_offset_to_canonical(reg_idx, -windowbase);
483 static void xtensa_mark_register_dirty(struct xtensa *xtensa, enum xtensa_reg_id reg_idx)
485 struct reg *reg_list = xtensa->core_cache->reg_list;
486 reg_list[reg_idx].dirty = true;
489 static int xtensa_queue_dbg_reg_read(struct xtensa *xtensa, unsigned int reg, uint8_t *data)
491 struct xtensa_debug_module *dm = &xtensa->dbg_mod;
493 if (!xtensa->core_config->trace.enabled &&
494 (reg <= NARADR_MEMADDREND || (reg >= NARADR_PMG && reg <= NARADR_PMSTAT7))) {
495 LOG_ERROR("Can not access %u reg when Trace Port option disabled!", reg);
498 return dm->dbg_ops->queue_reg_read(dm, reg, data);
501 static int xtensa_queue_dbg_reg_write(struct xtensa *xtensa, unsigned int reg, uint32_t data)
503 struct xtensa_debug_module *dm = &xtensa->dbg_mod;
505 if (!xtensa->core_config->trace.enabled &&
506 (reg <= NARADR_MEMADDREND || (reg >= NARADR_PMG && reg <= NARADR_PMSTAT7))) {
507 LOG_ERROR("Can not access %u reg when Trace Port option disabled!", reg);
510 return dm->dbg_ops->queue_reg_write(dm, reg, data);
513 static void xtensa_queue_exec_ins(struct xtensa *xtensa, uint32_t ins)
515 xtensa_queue_dbg_reg_write(xtensa, NARADR_DIR0EXEC, ins);
518 static bool xtensa_reg_is_readable(enum xtensa_reg_flags flags, xtensa_reg_val_t cpenable)
520 if (flags & XT_REGF_NOREAD)
522 if ((flags & XT_REGF_COPROC0) && (cpenable & BIT(0)) == 0)
527 static int xtensa_queue_pwr_reg_write(struct xtensa *xtensa, unsigned int reg, uint32_t data)
529 struct xtensa_debug_module *dm = &xtensa->dbg_mod;
530 return dm->pwr_ops->queue_reg_write(dm, reg, data);
533 static bool xtensa_special_reg_exists(struct xtensa *xtensa, enum xtensa_reg_id reg_idx)
535 /* TODO: array of size XT_NUM_REGS can be used here to map special register ID to
536 * corresponding config option 'enabled' flag */
537 if (reg_idx >= XT_REG_IDX_LBEG && reg_idx <= XT_REG_IDX_LCOUNT)
538 return xtensa->core_config->loop;
539 else if (reg_idx == XT_REG_IDX_BR)
540 return xtensa->core_config->boolean;
541 else if (reg_idx == XT_REG_IDX_LITBASE)
542 return xtensa->core_config->ext_l32r;
543 else if (reg_idx == XT_REG_IDX_SCOMPARE1 || reg_idx == XT_REG_IDX_ATOMCTL)
544 return xtensa->core_config->cond_store;
545 else if (reg_idx >= XT_REG_IDX_ACCLO && reg_idx <= XT_REG_IDX_M3)
546 return xtensa->core_config->mac16;
547 else if (reg_idx == XT_REG_IDX_WINDOWBASE || reg_idx == XT_REG_IDX_WINDOWSTART)
548 return xtensa->core_config->windowed;
549 else if (reg_idx >= XT_REG_IDX_PTEVADDR && reg_idx <= XT_REG_IDX_DTLBCFG)
550 return xtensa->core_config->mmu.enabled;
551 else if (reg_idx == XT_REG_IDX_MMID)
552 return xtensa->core_config->trace.enabled;
553 else if (reg_idx >= XT_REG_IDX_MEPC && reg_idx <= XT_REG_IDX_MEVADDR)
554 return xtensa->core_config->mem_err_check;
555 else if (reg_idx == XT_REG_IDX_CPENABLE)
556 return xtensa->core_config->coproc;
557 else if (reg_idx == XT_REG_IDX_VECBASE)
558 return xtensa->core_config->reloc_vec;
559 else if (reg_idx == XT_REG_IDX_CCOUNT)
560 return xtensa->core_config->tim_irq.enabled;
561 else if (reg_idx >= XT_REG_IDX_CCOMPARE0 && reg_idx <= XT_REG_IDX_CCOMPARE2)
562 return xtensa->core_config->tim_irq.enabled &&
563 (reg_idx - XT_REG_IDX_CCOMPARE0 < xtensa->core_config->tim_irq.comp_num);
564 else if (reg_idx == XT_REG_IDX_PRID)
565 return xtensa->core_config->proc_id;
566 else if (reg_idx >= XT_REG_IDX_MISC0 && reg_idx <= XT_REG_IDX_MISC3)
567 return reg_idx - XT_REG_IDX_MISC0 < xtensa->core_config->miscregs_num;
571 static bool xtensa_user_reg_exists(struct xtensa *xtensa, enum xtensa_reg_id reg_idx)
573 if (reg_idx == XT_REG_IDX_THREADPTR)
574 return xtensa->core_config->threadptr;
575 if (reg_idx == XT_REG_IDX_FCR || reg_idx == XT_REG_IDX_FSR)
576 return xtensa->core_config->fp_coproc;
580 static inline bool xtensa_fp_reg_exists(struct xtensa *xtensa, enum xtensa_reg_id reg_idx)
582 return xtensa->core_config->fp_coproc;
585 static inline bool xtensa_regular_reg_exists(struct xtensa *xtensa, enum xtensa_reg_id reg_idx)
587 if (reg_idx >= XT_REG_IDX_AR0 && reg_idx <= XT_REG_IDX_AR63)
588 return reg_idx - XT_REG_IDX_AR0 < xtensa->core_config->aregs_num;
592 static int xtensa_write_dirty_registers(struct target *target)
594 struct xtensa *xtensa = target_to_xtensa(target);
596 xtensa_reg_val_t regval, windowbase = 0;
597 bool scratch_reg_dirty = false;
598 struct reg *reg_list = xtensa->core_cache->reg_list;
600 LOG_TARGET_DEBUG(target, "start");
602 /*We need to write the dirty registers in the cache list back to the processor.
603 *Start by writing the SFR/user registers. */
604 for (unsigned int i = 0; i < XT_NUM_REGS; i++) {
605 if (reg_list[i].dirty) {
606 if (xtensa_regs[i].type == XT_REG_SPECIAL ||
607 xtensa_regs[i].type == XT_REG_USER ||
608 xtensa_regs[i].type == XT_REG_FR) {
609 scratch_reg_dirty = true;
610 regval = xtensa_reg_get(target, i);
611 LOG_TARGET_DEBUG(target, "Writing back reg %s val %08" PRIX32,
614 xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, regval);
615 xtensa_queue_exec_ins(xtensa, XT_INS_RSR(XT_SR_DDR, XT_REG_A3));
616 if (xtensa_regs[i].type == XT_REG_USER) {
617 if (reg_list[i].exist)
618 xtensa_queue_exec_ins(xtensa,
619 XT_INS_WUR(xtensa_regs[i].reg_num,
621 } else if (xtensa_regs[i].type == XT_REG_FR) {
622 if (reg_list[i].exist)
623 xtensa_queue_exec_ins(xtensa,
624 XT_INS_WFR(xtensa_regs[i].reg_num,
627 if (reg_list[i].exist) {
628 unsigned int reg_num = xtensa_regs[i].reg_num;
629 if (reg_num == XT_PC_REG_NUM_BASE)
630 /* reg number of PC for debug interrupt
631 * depends on NDEBUGLEVEL */
632 reg_num += xtensa->core_config->debug.irq_level;
634 xtensa_queue_exec_ins(xtensa,
635 XT_INS_WSR(reg_num, XT_REG_A3));
638 reg_list[i].dirty = false;
642 if (scratch_reg_dirty)
643 xtensa_mark_register_dirty(xtensa, XT_REG_IDX_A3);
645 if (xtensa->core_config->user_regs_num > 0 &&
646 xtensa->core_config->queue_write_dirty_user_regs)
647 xtensa->core_config->queue_write_dirty_user_regs(target);
649 if (xtensa->core_config->windowed) {
650 /*Grab the windowbase, we need it. */
651 windowbase = xtensa_reg_get(target, XT_REG_IDX_WINDOWBASE);
652 /*Check if there are problems with both the ARx as well as the corresponding Rx
653 * registers set and dirty. */
654 /*Warn the user if this happens, not much else we can do... */
655 for (unsigned int i = XT_REG_IDX_A0; i <= XT_REG_IDX_A15; i++) {
656 unsigned int j = xtensa_windowbase_offset_to_canonical(i, windowbase);
657 if (reg_list[i].dirty && reg_list[j].dirty) {
658 if (memcmp(reg_list[i].value, reg_list[j].value,
659 sizeof(xtensa_reg_val_t)) != 0)
661 "Warning: Both A%d as well as the physical register it points to (AR%d) are dirty and differs in value. Results are undefined!",
669 for (unsigned int i = 0; i < 16; i++) {
670 if (reg_list[XT_REG_IDX_A0 + i].dirty) {
671 regval = xtensa_reg_get(target, XT_REG_IDX_A0 + i);
672 LOG_TARGET_DEBUG(target, "Writing back reg %s value %08" PRIX32 ", num =%i",
673 xtensa_regs[XT_REG_IDX_A0 + i].name,
675 xtensa_regs[XT_REG_IDX_A0 + i].reg_num);
676 xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, regval);
677 xtensa_queue_exec_ins(xtensa, XT_INS_RSR(XT_SR_DDR, i));
678 reg_list[XT_REG_IDX_A0 + i].dirty = false;
682 if (xtensa->core_config->windowed) {
683 /*Now write AR0-AR63. */
684 for (unsigned int j = 0; j < 64; j += 16) {
685 /*Write the 16 registers we can see */
686 for (unsigned int i = 0; i < 16; i++) {
687 if (i + j < xtensa->core_config->aregs_num) {
688 enum xtensa_reg_id realadr =
689 xtensa_windowbase_offset_to_canonical(XT_REG_IDX_AR0 + i + j,
691 /*Write back any dirty un-windowed registers */
692 if (reg_list[realadr].dirty) {
693 regval = xtensa_reg_get(target, realadr);
696 "Writing back reg %s value %08" PRIX32 ", num =%i",
697 xtensa_regs[realadr].name,
699 xtensa_regs[realadr].reg_num);
700 xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, regval);
701 xtensa_queue_exec_ins(xtensa,
702 XT_INS_RSR(XT_SR_DDR, xtensa_regs[XT_REG_IDX_AR0 + i].reg_num));
703 reg_list[realadr].dirty = false;
707 /*Now rotate the window so we'll see the next 16 registers. The final rotate
708 * will wraparound, */
709 /*leaving us in the state we were. */
710 xtensa_queue_exec_ins(xtensa, XT_INS_ROTW(4));
713 res = jtag_execute_queue();
714 xtensa_core_status_check(target);
719 int xtensa_queue_write_dirty_user_regs_u32(struct target *target)
721 struct xtensa *xtensa = target_to_xtensa(target);
722 struct reg *reg_list = xtensa->core_cache->reg_list;
723 xtensa_reg_val_t reg_val;
724 bool scratch_reg_dirty = false;
726 LOG_TARGET_DEBUG(target, "start");
728 /* We need to write the dirty registers in the cache list back to the processor.
729 * Start by writing the SFR/user registers. */
730 for (unsigned int i = 0; i < xtensa->core_config->user_regs_num; i++) {
731 if (!reg_list[XT_USR_REG_START + i].dirty)
733 scratch_reg_dirty = true;
734 reg_val = xtensa_reg_get(target, XT_USR_REG_START + i);
735 LOG_TARGET_DEBUG(target, "Writing back reg %s val %08" PRIX32,
736 xtensa->core_config->user_regs[i].name,
738 xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, reg_val);
739 xtensa_queue_exec_ins(xtensa, XT_INS_RSR(XT_SR_DDR, XT_REG_A3));
740 xtensa_queue_exec_ins(xtensa,
741 XT_INS_WUR(xtensa->core_config->user_regs[i].reg_num,
743 reg_list[XT_USR_REG_START + i].dirty = false;
745 if (scratch_reg_dirty)
746 xtensa_mark_register_dirty(xtensa, XT_REG_IDX_A3);
751 static inline bool xtensa_is_stopped(struct target *target)
753 struct xtensa *xtensa = target_to_xtensa(target);
754 return xtensa->dbg_mod.core_status.dsr & OCDDSR_STOPPED;
757 int xtensa_examine(struct target *target)
759 struct xtensa *xtensa = target_to_xtensa(target);
760 unsigned int cmd = PWRCTL_DEBUGWAKEUP | PWRCTL_MEMWAKEUP | PWRCTL_COREWAKEUP;
762 LOG_DEBUG("coreid = %d", target->coreid);
763 xtensa_queue_pwr_reg_write(xtensa, DMREG_PWRCTL, cmd);
764 xtensa_queue_pwr_reg_write(xtensa, DMREG_PWRCTL, cmd | PWRCTL_JTAGDEBUGUSE);
765 xtensa_dm_queue_enable(&xtensa->dbg_mod);
766 xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
767 int res = jtag_execute_queue();
770 if (!xtensa_dm_is_online(&xtensa->dbg_mod)) {
771 LOG_ERROR("Unexpected OCD_ID = %08" PRIx32, xtensa->dbg_mod.device_id);
772 return ERROR_TARGET_FAILURE;
774 LOG_DEBUG("OCD_ID = %08" PRIx32, xtensa->dbg_mod.device_id);
775 if (!target_was_examined(target))
776 target_set_examined(target);
777 xtensa_smpbreak_write(xtensa, xtensa->smp_break);
781 int xtensa_wakeup(struct target *target)
783 struct xtensa *xtensa = target_to_xtensa(target);
784 unsigned int cmd = PWRCTL_DEBUGWAKEUP | PWRCTL_MEMWAKEUP | PWRCTL_COREWAKEUP;
786 if (xtensa->reset_asserted)
787 cmd |= PWRCTL_CORERESET;
788 xtensa_queue_pwr_reg_write(xtensa, DMREG_PWRCTL, cmd);
789 /* TODO: can we join this with the write above? */
790 xtensa_queue_pwr_reg_write(xtensa, DMREG_PWRCTL, cmd | PWRCTL_JTAGDEBUGUSE);
791 xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
792 return jtag_execute_queue();
795 int xtensa_smpbreak_write(struct xtensa *xtensa, uint32_t set)
797 uint32_t dsr_data = 0x00110000;
798 uint32_t clear = (set | OCDDCR_ENABLEOCD) ^
799 (OCDDCR_BREAKINEN | OCDDCR_BREAKOUTEN | OCDDCR_RUNSTALLINEN |
800 OCDDCR_DEBUGMODEOUTEN | OCDDCR_ENABLEOCD);
802 LOG_TARGET_DEBUG(xtensa->target, "write smpbreak set=0x%" PRIx32 " clear=0x%" PRIx32, set, clear);
803 xtensa_queue_dbg_reg_write(xtensa, NARADR_DCRSET, set | OCDDCR_ENABLEOCD);
804 xtensa_queue_dbg_reg_write(xtensa, NARADR_DCRCLR, clear);
805 xtensa_queue_dbg_reg_write(xtensa, NARADR_DSR, dsr_data);
806 xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
807 return jtag_execute_queue();
810 int xtensa_smpbreak_set(struct target *target, uint32_t set)
812 struct xtensa *xtensa = target_to_xtensa(target);
815 xtensa->smp_break = set;
816 if (target_was_examined(target))
817 res = xtensa_smpbreak_write(xtensa, xtensa->smp_break);
818 LOG_TARGET_DEBUG(target, "set smpbreak=%" PRIx32 ", state=%i", set, target->state);
822 int xtensa_smpbreak_read(struct xtensa *xtensa, uint32_t *val)
824 uint8_t dcr_buf[sizeof(uint32_t)];
826 xtensa_queue_dbg_reg_read(xtensa, NARADR_DCRSET, dcr_buf);
827 xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
828 int res = jtag_execute_queue();
829 *val = buf_get_u32(dcr_buf, 0, 32);
834 int xtensa_smpbreak_get(struct target *target, uint32_t *val)
836 struct xtensa *xtensa = target_to_xtensa(target);
837 *val = xtensa->smp_break;
841 static inline xtensa_reg_val_t xtensa_reg_get_value(struct reg *reg)
843 return buf_get_u32(reg->value, 0, 32);
846 static inline void xtensa_reg_set_value(struct reg *reg, xtensa_reg_val_t value)
848 buf_set_u32(reg->value, 0, 32, value);
852 int xtensa_core_status_check(struct target *target)
854 struct xtensa *xtensa = target_to_xtensa(target);
855 int res, needclear = 0;
857 xtensa_dm_core_status_read(&xtensa->dbg_mod);
858 xtensa_dsr_t dsr = xtensa_dm_core_status_get(&xtensa->dbg_mod);
859 LOG_TARGET_DEBUG(target, "DSR (%08" PRIX32 ")", dsr);
860 if (dsr & OCDDSR_EXECBUSY) {
861 if (!xtensa->suppress_dsr_errors)
862 LOG_TARGET_ERROR(target, "DSR (%08" PRIX32 ") indicates target still busy!", dsr);
865 if (dsr & OCDDSR_EXECEXCEPTION) {
866 if (!xtensa->suppress_dsr_errors)
867 LOG_TARGET_ERROR(target,
868 "DSR (%08" PRIX32 ") indicates DIR instruction generated an exception!",
872 if (dsr & OCDDSR_EXECOVERRUN) {
873 if (!xtensa->suppress_dsr_errors)
874 LOG_TARGET_ERROR(target,
875 "DSR (%08" PRIX32 ") indicates DIR instruction generated an overrun!",
880 res = xtensa_dm_core_status_clear(&xtensa->dbg_mod,
881 OCDDSR_EXECEXCEPTION | OCDDSR_EXECOVERRUN);
882 if (res != ERROR_OK && !xtensa->suppress_dsr_errors)
883 LOG_TARGET_ERROR(target, "clearing DSR failed!");
884 return xtensa->suppress_dsr_errors ? ERROR_OK : ERROR_FAIL;
889 xtensa_reg_val_t xtensa_reg_get(struct target *target, enum xtensa_reg_id reg_id)
891 struct xtensa *xtensa = target_to_xtensa(target);
892 struct reg *reg = &xtensa->core_cache->reg_list[reg_id];
893 assert(reg_id < xtensa->core_cache->num_regs && "Attempt to access non-existing reg!");
894 return xtensa_reg_get_value(reg);
897 void xtensa_reg_set(struct target *target, enum xtensa_reg_id reg_id, xtensa_reg_val_t value)
899 struct xtensa *xtensa = target_to_xtensa(target);
900 struct reg *reg = &xtensa->core_cache->reg_list[reg_id];
901 assert(reg_id < xtensa->core_cache->num_regs && "Attempt to access non-existing reg!");
902 if (xtensa_reg_get_value(reg) == value)
904 xtensa_reg_set_value(reg, value);
907 int xtensa_assert_reset(struct target *target)
909 struct xtensa *xtensa = target_to_xtensa(target);
911 LOG_TARGET_DEBUG(target, "target_number=%i, begin", target->target_number);
912 target->state = TARGET_RESET;
913 xtensa_queue_pwr_reg_write(xtensa,
915 PWRCTL_JTAGDEBUGUSE | PWRCTL_DEBUGWAKEUP | PWRCTL_MEMWAKEUP | PWRCTL_COREWAKEUP |
917 xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
918 int res = jtag_execute_queue();
921 xtensa->reset_asserted = true;
925 int xtensa_deassert_reset(struct target *target)
927 struct xtensa *xtensa = target_to_xtensa(target);
929 LOG_TARGET_DEBUG(target, "halt=%d", target->reset_halt);
930 if (target->reset_halt)
931 xtensa_queue_dbg_reg_write(xtensa,
933 OCDDCR_ENABLEOCD | OCDDCR_DEBUGINTERRUPT);
934 xtensa_queue_pwr_reg_write(xtensa,
936 PWRCTL_JTAGDEBUGUSE | PWRCTL_DEBUGWAKEUP | PWRCTL_MEMWAKEUP | PWRCTL_COREWAKEUP);
937 xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
938 int res = jtag_execute_queue();
941 target->state = TARGET_RUNNING;
942 xtensa->reset_asserted = false;
946 int xtensa_fetch_all_regs(struct target *target)
948 struct xtensa *xtensa = target_to_xtensa(target);
949 struct reg *reg_list = xtensa->core_cache->reg_list;
950 xtensa_reg_val_t cpenable = 0, windowbase = 0;
951 uint8_t regvals[XT_NUM_REGS][sizeof(xtensa_reg_val_t)];
952 uint8_t dsrs[XT_NUM_REGS][sizeof(xtensa_dsr_t)];
953 bool debug_dsrs = !xtensa->regs_fetched || LOG_LEVEL_IS(LOG_LVL_DEBUG);
955 LOG_TARGET_DEBUG(target, "start");
957 /* Assume the CPU has just halted. We now want to fill the register cache with all the
958 * register contents GDB needs. For speed, we pipeline all the read operations, execute them
959 * in one go, then sort everything out from the regvals variable. */
961 /* Start out with AREGS; we can reach those immediately. Grab them per 16 registers. */
962 for (unsigned int j = 0; j < XT_AREGS_NUM_MAX; j += 16) {
963 /*Grab the 16 registers we can see */
964 for (unsigned int i = 0; i < 16; i++) {
965 if (i + j < xtensa->core_config->aregs_num) {
966 xtensa_queue_exec_ins(xtensa,
967 XT_INS_WSR(XT_SR_DDR, xtensa_regs[XT_REG_IDX_AR0 + i].reg_num));
968 xtensa_queue_dbg_reg_read(xtensa, NARADR_DDR, regvals[XT_REG_IDX_AR0 + i + j]);
970 xtensa_queue_dbg_reg_read(xtensa, NARADR_DSR, dsrs[XT_REG_IDX_AR0 + i + j]);
973 if (xtensa->core_config->windowed) {
974 /* Now rotate the window so we'll see the next 16 registers. The final rotate
975 * will wraparound, */
976 /* leaving us in the state we were. */
977 xtensa_queue_exec_ins(xtensa, XT_INS_ROTW(4));
980 if (xtensa->core_config->coproc) {
981 /* As the very first thing after AREGS, go grab the CPENABLE registers. It indicates
982 * if we can also grab the FP */
983 /* (and theoretically other coprocessor) registers, or if this is a bad thing to do.*/
984 xtensa_queue_exec_ins(xtensa, XT_INS_RSR(xtensa_regs[XT_REG_IDX_CPENABLE].reg_num, XT_REG_A3));
985 xtensa_queue_exec_ins(xtensa, XT_INS_WSR(XT_SR_DDR, XT_REG_A3));
986 xtensa_queue_dbg_reg_read(xtensa, NARADR_DDR, regvals[XT_REG_IDX_CPENABLE]);
988 int res = jtag_execute_queue();
989 if (res != ERROR_OK) {
990 LOG_ERROR("Failed to read ARs (%d)!", res);
993 xtensa_core_status_check(target);
995 if (xtensa->core_config->coproc)
996 cpenable = buf_get_u32(regvals[XT_REG_IDX_CPENABLE], 0, 32);
997 /* We're now free to use any of A0-A15 as scratch registers
998 * Grab the SFRs and user registers first. We use A3 as a scratch register. */
999 for (unsigned int i = 0; i < XT_NUM_REGS; i++) {
1000 if (xtensa_reg_is_readable(xtensa_regs[i].flags, cpenable) && reg_list[i].exist &&
1001 (xtensa_regs[i].type == XT_REG_SPECIAL ||
1002 xtensa_regs[i].type == XT_REG_USER || xtensa_regs[i].type == XT_REG_FR)) {
1003 if (xtensa_regs[i].type == XT_REG_USER) {
1004 xtensa_queue_exec_ins(xtensa, XT_INS_RUR(xtensa_regs[i].reg_num, XT_REG_A3));
1005 } else if (xtensa_regs[i].type == XT_REG_FR) {
1006 xtensa_queue_exec_ins(xtensa, XT_INS_RFR(xtensa_regs[i].reg_num, XT_REG_A3));
1008 unsigned int reg_num = xtensa_regs[i].reg_num;
1009 if (reg_num == XT_PC_REG_NUM_BASE) {
1010 /* reg number of PC for debug interrupt depends on NDEBUGLEVEL */
1011 reg_num += xtensa->core_config->debug.irq_level;
1013 xtensa_queue_exec_ins(xtensa, XT_INS_RSR(reg_num, XT_REG_A3));
1015 xtensa_queue_exec_ins(xtensa, XT_INS_WSR(XT_SR_DDR, XT_REG_A3));
1016 xtensa_queue_dbg_reg_read(xtensa, NARADR_DDR, regvals[i]);
1018 xtensa_queue_dbg_reg_read(xtensa, NARADR_DSR, dsrs[i]);
1021 /* Ok, send the whole mess to the CPU. */
1022 res = jtag_execute_queue();
1023 if (res != ERROR_OK) {
1024 LOG_ERROR("Failed to fetch AR regs!");
1027 xtensa_core_status_check(target);
1030 /* DSR checking: follows order in which registers are requested. */
1031 for (unsigned int i = 0; i < XT_NUM_REGS; i++) {
1032 if (xtensa_reg_is_readable(xtensa_regs[i].flags, cpenable) && reg_list[i].exist &&
1033 (xtensa_regs[i].type == XT_REG_SPECIAL || xtensa_regs[i].type == XT_REG_USER ||
1034 xtensa_regs[i].type == XT_REG_FR)) {
1035 if (buf_get_u32(dsrs[i], 0, 32) & OCDDSR_EXECEXCEPTION) {
1036 LOG_ERROR("Exception reading %s!", xtensa_regs[i].name);
1043 if (xtensa->core_config->user_regs_num > 0 && xtensa->core_config->fetch_user_regs) {
1044 res = xtensa->core_config->fetch_user_regs(target);
1045 if (res != ERROR_OK)
1049 if (xtensa->core_config->windowed) {
1050 /* We need the windowbase to decode the general addresses. */
1051 windowbase = buf_get_u32(regvals[XT_REG_IDX_WINDOWBASE], 0, 32);
1053 /* Decode the result and update the cache. */
1054 for (unsigned int i = 0; i < XT_NUM_REGS; i++) {
1055 if (xtensa_reg_is_readable(xtensa_regs[i].flags, cpenable) && reg_list[i].exist) {
1056 if (xtensa_regs[i].type == XT_REG_GENERAL) {
1057 /* TODO: add support for non-windowed configs */
1059 xtensa->core_config->windowed &&
1060 "Regs fetch is not supported for non-windowed configs!");
1061 /* The 64-value general register set is read from (windowbase) on down.
1062 * We need to get the real register address by subtracting windowbase and
1063 * wrapping around. */
1064 int realadr = xtensa_canonical_to_windowbase_offset(i, windowbase);
1065 buf_cpy(regvals[realadr], reg_list[i].value, reg_list[i].size);
1066 } else if (xtensa_regs[i].type == XT_REG_RELGEN) {
1067 buf_cpy(regvals[xtensa_regs[i].reg_num], reg_list[i].value, reg_list[i].size);
1069 buf_cpy(regvals[i], reg_list[i].value, reg_list[i].size);
1071 reg_list[i].valid = true;
1073 reg_list[i].valid = false;
1076 /* We have used A3 as a scratch register and we will need to write that back. */
1077 xtensa_mark_register_dirty(xtensa, XT_REG_IDX_A3);
1078 xtensa->regs_fetched = true;
1083 int xtensa_fetch_user_regs_u32(struct target *target)
1085 struct xtensa *xtensa = target_to_xtensa(target);
1086 struct reg *reg_list = xtensa->core_cache->reg_list;
1087 xtensa_reg_val_t cpenable = 0;
1088 uint8_t regvals[XT_USER_REGS_NUM_MAX][sizeof(xtensa_reg_val_t)];
1089 uint8_t dsrs[XT_USER_REGS_NUM_MAX][sizeof(xtensa_dsr_t)];
1090 bool debug_dsrs = !xtensa->regs_fetched || LOG_LEVEL_IS(LOG_LVL_DEBUG);
1092 assert(xtensa->core_config->user_regs_num < XT_USER_REGS_NUM_MAX && "Too many user regs configured!");
1093 if (xtensa->core_config->coproc)
1094 cpenable = xtensa_reg_get(target, XT_REG_IDX_CPENABLE);
1096 for (unsigned int i = 0; i < xtensa->core_config->user_regs_num; i++) {
1097 if (!xtensa_reg_is_readable(xtensa->core_config->user_regs[i].flags, cpenable))
1099 xtensa_queue_exec_ins(xtensa, XT_INS_RUR(xtensa->core_config->user_regs[i].reg_num, XT_REG_A3));
1100 xtensa_queue_exec_ins(xtensa, XT_INS_WSR(XT_SR_DDR, XT_REG_A3));
1101 xtensa_queue_dbg_reg_read(xtensa, NARADR_DDR, regvals[i]);
1103 xtensa_queue_dbg_reg_read(xtensa, NARADR_DSR, dsrs[i]);
1105 /* Ok, send the whole mess to the CPU. */
1106 int res = jtag_execute_queue();
1107 if (res != ERROR_OK) {
1108 LOG_ERROR("Failed to fetch AR regs!");
1111 xtensa_core_status_check(target);
1114 /* DSR checking: follows order in which registers are requested. */
1115 for (unsigned int i = 0; i < xtensa->core_config->user_regs_num; i++) {
1116 if (!xtensa_reg_is_readable(xtensa->core_config->user_regs[i].flags, cpenable))
1118 if (buf_get_u32(dsrs[i], 0, 32) & OCDDSR_EXECEXCEPTION) {
1119 LOG_ERROR("Exception reading %s!", xtensa->core_config->user_regs[i].name);
1125 for (unsigned int i = 0; i < xtensa->core_config->user_regs_num; i++) {
1126 if (xtensa_reg_is_readable(xtensa->core_config->user_regs[i].flags, cpenable)) {
1127 buf_cpy(regvals[i], reg_list[XT_USR_REG_START + i].value, reg_list[XT_USR_REG_START + i].size);
1128 reg_list[XT_USR_REG_START + i].valid = true;
1130 reg_list[XT_USR_REG_START + i].valid = false;
1134 /* We have used A3 as a scratch register and we will need to write that back. */
1135 xtensa_mark_register_dirty(xtensa, XT_REG_IDX_A3);
1139 int xtensa_get_gdb_reg_list(struct target *target,
1140 struct reg **reg_list[],
1142 enum target_register_class reg_class)
1144 struct xtensa *xtensa = target_to_xtensa(target);
1145 unsigned int num_regs = xtensa->core_config->gdb_general_regs_num;
1147 if (reg_class == REG_CLASS_ALL)
1148 num_regs = xtensa->regs_num;
1150 LOG_DEBUG("reg_class=%i, num_regs=%d", reg_class, num_regs);
1152 *reg_list = malloc(num_regs * sizeof(struct reg *));
1156 for (unsigned int k = 0; k < num_regs; k++) {
1157 unsigned int reg_id = xtensa->core_config->gdb_regs_mapping[k];
1158 (*reg_list)[k] = &xtensa->core_cache->reg_list[reg_id];
1161 *reg_list_size = num_regs;
1166 int xtensa_mmu_is_enabled(struct target *target, int *enabled)
1168 struct xtensa *xtensa = target_to_xtensa(target);
1169 *enabled = xtensa->core_config->mmu.itlb_entries_count > 0 ||
1170 xtensa->core_config->mmu.dtlb_entries_count > 0;
1174 int xtensa_halt(struct target *target)
1176 struct xtensa *xtensa = target_to_xtensa(target);
1178 LOG_TARGET_DEBUG(target, "start");
1179 if (target->state == TARGET_HALTED) {
1180 LOG_TARGET_DEBUG(target, "target was already halted");
1183 /* First we have to read dsr and check if the target stopped */
1184 int res = xtensa_dm_core_status_read(&xtensa->dbg_mod);
1185 if (res != ERROR_OK) {
1186 LOG_TARGET_ERROR(target, "Failed to read core status!");
1189 LOG_TARGET_DEBUG(target, "Core status 0x%" PRIx32, xtensa_dm_core_status_get(&xtensa->dbg_mod));
1190 if (!xtensa_is_stopped(target)) {
1191 xtensa_queue_dbg_reg_write(xtensa, NARADR_DCRSET, OCDDCR_ENABLEOCD | OCDDCR_DEBUGINTERRUPT);
1192 xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
1193 res = jtag_execute_queue();
1194 if (res != ERROR_OK)
1195 LOG_TARGET_ERROR(target, "Failed to set OCDDCR_DEBUGINTERRUPT. Can't halt.");
1201 int xtensa_prepare_resume(struct target *target,
1203 target_addr_t address,
1204 int handle_breakpoints,
1205 int debug_execution)
1207 struct xtensa *xtensa = target_to_xtensa(target);
1210 LOG_TARGET_DEBUG(target,
1211 "current=%d address=" TARGET_ADDR_FMT ", handle_breakpoints=%i, debug_execution=%i)",
1217 if (target->state != TARGET_HALTED) {
1218 LOG_TARGET_WARNING(target, "target not halted");
1219 return ERROR_TARGET_NOT_HALTED;
1222 if (address && !current) {
1223 xtensa_reg_set(target, XT_REG_IDX_PC, address);
1225 xtensa_reg_val_t cause = xtensa_reg_get(target, XT_REG_IDX_DEBUGCAUSE);
1226 if (cause & DEBUGCAUSE_DB) {
1227 /* We stopped due to a watchpoint. We can't just resume executing the
1228 * instruction again because */
1229 /* that would trigger the watchpoint again. To fix this, we single-step,
1230 * which ignores watchpoints. */
1231 xtensa_do_step(target, current, address, handle_breakpoints);
1233 if (cause & (DEBUGCAUSE_BI | DEBUGCAUSE_BN)) {
1234 /* We stopped due to a break instruction. We can't just resume executing the
1235 * instruction again because */
1236 /* that would trigger the break again. To fix this, we single-step, which
1238 xtensa_do_step(target, current, address, handle_breakpoints);
1242 /* Write back hw breakpoints. Current FreeRTOS SMP code can set a hw breakpoint on an
1243 * exception; we need to clear that and return to the breakpoints gdb has set on resume. */
1244 for (unsigned int slot = 0; slot < xtensa->core_config->debug.ibreaks_num; slot++) {
1245 if (xtensa->hw_brps[slot]) {
1246 /* Write IBREAKA[slot] and set bit #slot in IBREAKENABLE */
1247 xtensa_reg_set(target, XT_REG_IDX_IBREAKA0 + slot, xtensa->hw_brps[slot]->address);
1251 xtensa_reg_set(target, XT_REG_IDX_IBREAKENABLE, bpena);
1253 /* Here we write all registers to the targets */
1254 int res = xtensa_write_dirty_registers(target);
1255 if (res != ERROR_OK)
1256 LOG_TARGET_ERROR(target, "Failed to write back register cache.");
1260 int xtensa_do_resume(struct target *target)
1262 struct xtensa *xtensa = target_to_xtensa(target);
1264 LOG_TARGET_DEBUG(target, "start");
1266 xtensa_queue_exec_ins(xtensa, XT_INS_RFDO);
1267 int res = jtag_execute_queue();
1268 if (res != ERROR_OK) {
1269 LOG_TARGET_ERROR(target, "Failed to exec RFDO %d!", res);
1272 xtensa_core_status_check(target);
1276 int xtensa_resume(struct target *target,
1278 target_addr_t address,
1279 int handle_breakpoints,
1280 int debug_execution)
1282 LOG_TARGET_DEBUG(target, "start");
1283 int res = xtensa_prepare_resume(target, current, address, handle_breakpoints, debug_execution);
1284 if (res != ERROR_OK) {
1285 LOG_TARGET_ERROR(target, "Failed to prepare for resume!");
1288 res = xtensa_do_resume(target);
1289 if (res != ERROR_OK) {
1290 LOG_TARGET_ERROR(target, "Failed to resume!");
1294 target->debug_reason = DBG_REASON_NOTHALTED;
1295 if (!debug_execution)
1296 target->state = TARGET_RUNNING;
1298 target->state = TARGET_DEBUG_RUNNING;
1300 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
1305 static bool xtensa_pc_in_winexc(struct target *target, target_addr_t pc)
1307 uint8_t insn_buf[XT_ISNS_SZ_MAX];
1308 int err = xtensa_read_buffer(target, pc, sizeof(insn_buf), insn_buf);
1309 if (err != ERROR_OK)
1312 xtensa_insn_t insn = buf_get_u32(insn_buf, 0, 24);
1313 xtensa_insn_t masked = insn & XT_INS_L32E_S32E_MASK;
1314 if (masked == XT_INS_L32E(0, 0, 0) || masked == XT_INS_S32E(0, 0, 0))
1317 masked = insn & XT_INS_RFWO_RFWU_MASK;
1318 if (masked == XT_INS_RFWO || masked == XT_INS_RFWU)
1324 int xtensa_do_step(struct target *target, int current, target_addr_t address, int handle_breakpoints)
1326 struct xtensa *xtensa = target_to_xtensa(target);
1328 const uint32_t icount_val = -2; /* ICOUNT value to load for 1 step */
1329 xtensa_reg_val_t dbreakc[XT_WATCHPOINTS_NUM_MAX];
1330 xtensa_reg_val_t icountlvl, cause;
1331 xtensa_reg_val_t oldps, newps, oldpc, cur_pc;
1333 LOG_TARGET_DEBUG(target, "current=%d, address=" TARGET_ADDR_FMT ", handle_breakpoints=%i",
1334 current, address, handle_breakpoints);
1336 if (target->state != TARGET_HALTED) {
1337 LOG_TARGET_WARNING(target, "target not halted");
1338 return ERROR_TARGET_NOT_HALTED;
1341 if (xtensa->core_config->debug.icount_sz != 32) {
1342 LOG_TARGET_WARNING(target, "stepping for ICOUNT less then 32 bits is not implemented!");
1346 /* Save old ps/pc */
1347 oldps = xtensa_reg_get(target, XT_REG_IDX_PS);
1348 oldpc = xtensa_reg_get(target, XT_REG_IDX_PC);
1350 cause = xtensa_reg_get(target, XT_REG_IDX_DEBUGCAUSE);
1351 LOG_TARGET_DEBUG(target, "oldps=%" PRIx32 ", oldpc=%" PRIx32 " dbg_cause=%" PRIx32 " exc_cause=%" PRIx32,
1355 xtensa_reg_get(target, XT_REG_IDX_EXCCAUSE));
1356 if (handle_breakpoints && (cause & (DEBUGCAUSE_BI | DEBUGCAUSE_BN))) {
1357 /* handle hard-coded SW breakpoints (e.g. syscalls) */
1358 LOG_TARGET_DEBUG(target, "Increment PC to pass break instruction...");
1359 xtensa_reg_set(target, XT_REG_IDX_DEBUGCAUSE, 0); /* so we don't recurse into the same routine */
1360 xtensa->core_cache->reg_list[XT_REG_IDX_DEBUGCAUSE].dirty = false;
1361 /* pretend that we have stepped */
1362 if (cause & DEBUGCAUSE_BI)
1363 xtensa_reg_set(target, XT_REG_IDX_PC, oldpc + 3); /* PC = PC+3 */
1365 xtensa_reg_set(target, XT_REG_IDX_PC, oldpc + 2); /* PC = PC+2 */
1369 /* Xtensa has an ICOUNTLEVEL register which sets the maximum interrupt level at which the
1370 * instructions are to be counted while stepping.
1371 * For example, if we need to step by 2 instructions, and an interrupt occurs inbetween,
1372 * the processor will execute the interrupt, return, and halt after the 2nd instruction.
1373 * However, sometimes we don't want the interrupt handlers to be executed at all, while
1374 * stepping through the code. In this case (XT_STEPPING_ISR_OFF), PS.INTLEVEL can be raised
1375 * to only allow Debug and NMI interrupts.
1377 if (xtensa->stepping_isr_mode == XT_STEPPING_ISR_OFF) {
1378 if (!xtensa->core_config->high_irq.enabled) {
1381 "disabling IRQs while stepping is not implemented w/o high prio IRQs option!");
1384 /* Mask all interrupts below Debug, i.e. PS.INTLEVEL = DEBUGLEVEL - 1 */
1385 xtensa_reg_val_t temp_ps = (oldps & ~0xF) | (xtensa->core_config->debug.irq_level - 1);
1386 xtensa_reg_set(target, XT_REG_IDX_PS, temp_ps);
1388 /* Regardless of ISRs masking mode we need to count instructions at any CINTLEVEL during step.
1389 So set `icountlvl` to DEBUGLEVEL.
1390 If ISRs are masked they are disabled in PS (see above), so having `icountlvl` set to DEBUGLEVEL
1391 will allow to step through any type of the code, e.g. 'high int level' ISR.
1392 If ISRs are not masked With `icountlvl` set to DEBUGLEVEL, we can step into any ISR
1393 which can happen (enabled in PS).
1395 icountlvl = xtensa->core_config->debug.irq_level;
1397 if (cause & DEBUGCAUSE_DB) {
1398 /* We stopped due to a watchpoint. We can't just resume executing the instruction again because
1399 * that would trigger the watchpoint again. To fix this, we remove watchpoints,single-step and
1400 * re-enable the watchpoint. */
1403 "Single-stepping to get past instruction that triggered the watchpoint...");
1404 xtensa_reg_set(target, XT_REG_IDX_DEBUGCAUSE, 0); /*so we don't recurse into
1405 * the same routine */
1406 xtensa->core_cache->reg_list[XT_REG_IDX_DEBUGCAUSE].dirty = false;
1407 /*Save all DBREAKCx registers and set to 0 to disable watchpoints */
1408 for (unsigned int slot = 0; slot < xtensa->core_config->debug.dbreaks_num; slot++) {
1409 dbreakc[slot] = xtensa_reg_get(target, XT_REG_IDX_DBREAKC0 + slot);
1410 xtensa_reg_set(target, XT_REG_IDX_DBREAKC0 + slot, 0);
1414 if (!handle_breakpoints && (cause & (DEBUGCAUSE_BI | DEBUGCAUSE_BN))) {
1415 /* handle normal SW breakpoint */
1416 xtensa_reg_set(target, XT_REG_IDX_DEBUGCAUSE, 0); /*so we don't recurse into
1417 * the same routine */
1418 xtensa->core_cache->reg_list[XT_REG_IDX_DEBUGCAUSE].dirty = false;
1421 xtensa_reg_set(target, XT_REG_IDX_ICOUNTLEVEL, icountlvl);
1422 xtensa_reg_set(target, XT_REG_IDX_ICOUNT, icount_val);
1424 /* Now ICOUNT is set, we can resume as if we were going to run */
1425 res = xtensa_prepare_resume(target, current, address, 0, 0);
1426 if (res != ERROR_OK) {
1427 LOG_TARGET_ERROR(target, "Failed to prepare resume for single step");
1430 res = xtensa_do_resume(target);
1431 if (res != ERROR_OK) {
1432 LOG_TARGET_ERROR(target, "Failed to resume after setting up single step");
1436 /* Wait for stepping to complete */
1437 long long start = timeval_ms();
1438 while (timeval_ms() < start + 500) {
1439 /* Do not use target_poll here, it also triggers other things... just manually read the DSR
1440 *until stepping is complete. */
1442 res = xtensa_dm_core_status_read(&xtensa->dbg_mod);
1443 if (res != ERROR_OK) {
1444 LOG_TARGET_ERROR(target, "Failed to read core status!");
1447 if (xtensa_is_stopped(target))
1451 LOG_TARGET_DEBUG(target, "Finish stepping. dsr=0x%08" PRIx32,
1452 xtensa_dm_core_status_get(&xtensa->dbg_mod));
1453 if (!xtensa_is_stopped(target)) {
1456 "Timed out waiting for target to finish stepping. dsr=0x%08" PRIx32,
1457 xtensa_dm_core_status_get(&xtensa->dbg_mod));
1458 target->debug_reason = DBG_REASON_NOTHALTED;
1459 target->state = TARGET_RUNNING;
1462 target->debug_reason = DBG_REASON_SINGLESTEP;
1463 target->state = TARGET_HALTED;
1465 xtensa_fetch_all_regs(target);
1467 cur_pc = xtensa_reg_get(target, XT_REG_IDX_PC);
1469 LOG_TARGET_DEBUG(target,
1470 "cur_ps=%" PRIx32 ", cur_pc=%" PRIx32 " dbg_cause=%" PRIx32 " exc_cause=%" PRIx32,
1471 xtensa_reg_get(target, XT_REG_IDX_PS),
1473 xtensa_reg_get(target, XT_REG_IDX_DEBUGCAUSE),
1474 xtensa_reg_get(target, XT_REG_IDX_EXCCAUSE));
1476 /* Do not step into WindowOverflow if ISRs are masked.
1477 If we stop in WindowOverflow at breakpoint with masked ISRs and
1478 try to do a step it will get us out of that handler */
1479 if (xtensa->core_config->windowed &&
1480 xtensa->stepping_isr_mode == XT_STEPPING_ISR_OFF &&
1481 xtensa_pc_in_winexc(target, cur_pc)) {
1482 /* isrmask = on, need to step out of the window exception handler */
1483 LOG_DEBUG("Stepping out of window exception, PC=%" PRIX32, cur_pc);
1485 address = oldpc + 3;
1489 if (oldpc == cur_pc)
1490 LOG_TARGET_WARNING(target, "Stepping doesn't seem to change PC! dsr=0x%08" PRIx32,
1491 xtensa_dm_core_status_get(&xtensa->dbg_mod));
1493 LOG_DEBUG("Stepped from %" PRIX32 " to %" PRIX32, oldpc, cur_pc);
1496 LOG_DEBUG("Done stepping, PC=%" PRIX32, cur_pc);
1498 if (cause & DEBUGCAUSE_DB) {
1499 LOG_TARGET_DEBUG(target, "...Done, re-installing watchpoints.");
1500 /* Restore the DBREAKCx registers */
1501 for (unsigned int slot = 0; slot < xtensa->core_config->debug.dbreaks_num; slot++)
1502 xtensa_reg_set(target, XT_REG_IDX_DBREAKC0 + slot, dbreakc[slot]);
1505 /* Restore int level */
1506 /* TODO: Theoretically, this can mess up stepping over an instruction that modifies
1507 * ps.intlevel by itself. TODO: Look into this. */
1508 if (xtensa->stepping_isr_mode == XT_STEPPING_ISR_OFF) {
1509 newps = xtensa_reg_get(target, XT_REG_IDX_PS);
1510 newps = (newps & ~0xF) | (oldps & 0xf);
1511 xtensa_reg_set(target, XT_REG_IDX_PS, newps);
1514 /* write ICOUNTLEVEL back to zero */
1515 xtensa_reg_set(target, XT_REG_IDX_ICOUNTLEVEL, 0);
1516 /* TODO: can we skip writing dirty registers and re-fetching them? */
1517 res = xtensa_write_dirty_registers(target);
1518 xtensa_fetch_all_regs(target);
1522 int xtensa_step(struct target *target, int current, target_addr_t address, int handle_breakpoints)
1524 return xtensa_do_step(target, current, address, handle_breakpoints);
1528 * Returns true if two ranges are overlapping
1530 static inline bool xtensa_memory_regions_overlap(target_addr_t r1_start,
1531 target_addr_t r1_end,
1532 target_addr_t r2_start,
1533 target_addr_t r2_end)
1535 if ((r2_start >= r1_start) && (r2_start < r1_end))
1536 return true; /* r2_start is in r1 region */
1537 if ((r2_end > r1_start) && (r2_end <= r1_end))
1538 return true; /* r2_end is in r1 region */
1543 * Returns a size of overlapped region of two ranges.
1545 static inline target_addr_t xtensa_get_overlap_size(target_addr_t r1_start,
1546 target_addr_t r1_end,
1547 target_addr_t r2_start,
1548 target_addr_t r2_end)
1550 if (xtensa_memory_regions_overlap(r1_start, r1_end, r2_start, r2_end)) {
1551 target_addr_t ov_start = r1_start < r2_start ? r2_start : r1_start;
1552 target_addr_t ov_end = r1_end > r2_end ? r2_end : r1_end;
1553 return ov_end - ov_start;
1559 * Check if the address gets to memory regions, and it's access mode
1561 static bool xtensa_memory_op_validate_range(struct xtensa *xtensa, target_addr_t address, size_t size, int access)
1563 target_addr_t adr_pos = address; /* address cursor set to the beginning start */
1564 target_addr_t adr_end = address + size; /* region end */
1565 target_addr_t overlap_size;
1566 const struct xtensa_local_mem_region_config *cm; /* current mem region */
1568 while (adr_pos < adr_end) {
1569 cm = xtensa_target_memory_region_find(xtensa, adr_pos);
1570 if (!cm) /* address is not belong to anything */
1572 if ((cm->access & access) != access) /* access check */
1574 overlap_size = xtensa_get_overlap_size(cm->base, (cm->base + cm->size), adr_pos, adr_end);
1575 assert(overlap_size != 0);
1576 adr_pos += overlap_size;
1581 int xtensa_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
1583 struct xtensa *xtensa = target_to_xtensa(target);
1584 /* We are going to read memory in 32-bit increments. This may not be what the calling
1585 * function expects, so we may need to allocate a temp buffer and read into that first. */
1586 target_addr_t addrstart_al = ALIGN_DOWN(address, 4);
1587 target_addr_t addrend_al = ALIGN_UP(address + size * count, 4);
1588 target_addr_t adr = addrstart_al;
1591 if (target->state != TARGET_HALTED) {
1592 LOG_TARGET_WARNING(target, "target not halted");
1593 return ERROR_TARGET_NOT_HALTED;
1596 if (!xtensa->permissive_mode) {
1597 if (!xtensa_memory_op_validate_range(xtensa, address, (size * count),
1598 XT_MEM_ACCESS_READ)) {
1599 LOG_DEBUG("address " TARGET_ADDR_FMT " not readable", address);
1604 if (addrstart_al == address && addrend_al == address + (size * count)) {
1607 albuff = malloc(addrend_al - addrstart_al);
1609 LOG_TARGET_ERROR(target, "Out of memory allocating %" TARGET_PRIdADDR " bytes!",
1610 addrend_al - addrstart_al);
1611 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1615 /* We're going to use A3 here */
1616 xtensa_mark_register_dirty(xtensa, XT_REG_IDX_A3);
1617 /* Write start address to A3 */
1618 xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, addrstart_al);
1619 xtensa_queue_exec_ins(xtensa, XT_INS_RSR(XT_SR_DDR, XT_REG_A3));
1620 /* Now we can safely read data from addrstart_al up to addrend_al into albuff */
1621 for (unsigned int i = 0; adr != addrend_al; i += sizeof(uint32_t), adr += sizeof(uint32_t)) {
1622 xtensa_queue_exec_ins(xtensa, XT_INS_LDDR32P(XT_REG_A3));
1623 xtensa_queue_dbg_reg_read(xtensa, NARADR_DDR, &albuff[i]);
1625 int res = jtag_execute_queue();
1626 if (res == ERROR_OK)
1627 res = xtensa_core_status_check(target);
1628 if (res != ERROR_OK)
1629 LOG_TARGET_WARNING(target, "Failed reading %d bytes at address " TARGET_ADDR_FMT,
1630 count * size, address);
1632 if (albuff != buffer) {
1633 memcpy(buffer, albuff + (address & 3), (size * count));
1640 int xtensa_read_buffer(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer)
1642 /* xtensa_read_memory can also read unaligned stuff. Just pass through to that routine. */
1643 return xtensa_read_memory(target, address, 1, count, buffer);
1646 int xtensa_write_memory(struct target *target,
1647 target_addr_t address,
1650 const uint8_t *buffer)
1652 /* This memory write function can get thrown nigh everything into it, from
1653 * aligned uint32 writes to unaligned uint8ths. The Xtensa memory doesn't always
1654 * accept anything but aligned uint32 writes, though. That is why we convert
1655 * everything into that. */
1656 struct xtensa *xtensa = target_to_xtensa(target);
1657 target_addr_t addrstart_al = ALIGN_DOWN(address, 4);
1658 target_addr_t addrend_al = ALIGN_UP(address + size * count, 4);
1659 target_addr_t adr = addrstart_al;
1663 if (target->state != TARGET_HALTED) {
1664 LOG_TARGET_WARNING(target, "target not halted");
1665 return ERROR_TARGET_NOT_HALTED;
1668 if (!xtensa->permissive_mode) {
1669 if (!xtensa_memory_op_validate_range(xtensa, address, (size * count), XT_MEM_ACCESS_WRITE)) {
1670 LOG_WARNING("address " TARGET_ADDR_FMT " not writable", address);
1675 if (size == 0 || count == 0 || !buffer)
1676 return ERROR_COMMAND_SYNTAX_ERROR;
1678 /* Allocate a temporary buffer to put the aligned bytes in, if needed. */
1679 if (addrstart_al == address && addrend_al == address + (size * count)) {
1680 /* We discard the const here because albuff can also be non-const */
1681 albuff = (uint8_t *)buffer;
1683 albuff = malloc(addrend_al - addrstart_al);
1685 LOG_TARGET_ERROR(target, "Out of memory allocating %" TARGET_PRIdADDR " bytes!",
1686 addrend_al - addrstart_al);
1687 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1691 /* We're going to use A3 here */
1692 xtensa_mark_register_dirty(xtensa, XT_REG_IDX_A3);
1694 /* If we're using a temp aligned buffer, we need to fill the head and/or tail bit of it. */
1695 if (albuff != buffer) {
1696 /* See if we need to read the first and/or last word. */
1698 xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, addrstart_al);
1699 xtensa_queue_exec_ins(xtensa, XT_INS_RSR(XT_SR_DDR, XT_REG_A3));
1700 xtensa_queue_exec_ins(xtensa, XT_INS_LDDR32P(XT_REG_A3));
1701 xtensa_queue_dbg_reg_read(xtensa, NARADR_DDR, &albuff[0]);
1703 if ((address + (size * count)) & 3) {
1704 xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, addrend_al - 4);
1705 xtensa_queue_exec_ins(xtensa, XT_INS_RSR(XT_SR_DDR, XT_REG_A3));
1706 xtensa_queue_exec_ins(xtensa, XT_INS_LDDR32P(XT_REG_A3));
1707 xtensa_queue_dbg_reg_read(xtensa, NARADR_DDR,
1708 &albuff[addrend_al - addrstart_al - 4]);
1711 res = jtag_execute_queue();
1712 if (res != ERROR_OK) {
1713 LOG_ERROR("Error issuing unaligned memory write context instruction(s): %d", res);
1714 if (albuff != buffer)
1718 xtensa_core_status_check(target);
1719 /* Copy data to be written into the aligned buffer */
1720 memcpy(&albuff[address & 3], buffer, size * count);
1721 /* Now we can write albuff in aligned uint32s. */
1724 /* Write start address to A3 */
1725 xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, addrstart_al);
1726 xtensa_queue_exec_ins(xtensa, XT_INS_RSR(XT_SR_DDR, XT_REG_A3));
1727 /* Write the aligned buffer */
1728 for (unsigned int i = 0; adr != addrend_al; i += sizeof(uint32_t), adr += sizeof(uint32_t)) {
1729 xtensa_queue_dbg_reg_write(xtensa, NARADR_DDR, buf_get_u32(&albuff[i], 0, 32));
1730 xtensa_queue_exec_ins(xtensa, XT_INS_SDDR32P(XT_REG_A3));
1732 res = jtag_execute_queue();
1733 if (res == ERROR_OK)
1734 res = xtensa_core_status_check(target);
1735 if (res != ERROR_OK)
1736 LOG_TARGET_WARNING(target, "Failed writing %d bytes at address " TARGET_ADDR_FMT, count * size, address);
1737 if (albuff != buffer)
1743 int xtensa_write_buffer(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer)
1745 /* xtensa_write_memory can handle everything. Just pass on to that. */
1746 return xtensa_write_memory(target, address, 1, count, buffer);
1749 int xtensa_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum)
1751 LOG_WARNING("not implemented yet");
1755 int xtensa_poll(struct target *target)
1757 struct xtensa *xtensa = target_to_xtensa(target);
1759 int res = xtensa_dm_power_status_read(&xtensa->dbg_mod, PWRSTAT_DEBUGWASRESET | PWRSTAT_COREWASRESET);
1760 if (res != ERROR_OK)
1763 if (xtensa_dm_tap_was_reset(&xtensa->dbg_mod)) {
1764 LOG_TARGET_INFO(target, "Debug controller was reset.");
1765 res = xtensa_smpbreak_write(xtensa, xtensa->smp_break);
1766 if (res != ERROR_OK)
1769 if (xtensa_dm_core_was_reset(&xtensa->dbg_mod))
1770 LOG_TARGET_INFO(target, "Core was reset.");
1771 xtensa_dm_power_status_cache(&xtensa->dbg_mod);
1772 /* Enable JTAG, set reset if needed */
1773 res = xtensa_wakeup(target);
1774 if (res != ERROR_OK)
1777 res = xtensa_dm_core_status_read(&xtensa->dbg_mod);
1778 if (res != ERROR_OK)
1780 if (xtensa->dbg_mod.power_status.stath & PWRSTAT_COREWASRESET) {
1781 /* if RESET state is persitent */
1782 target->state = TARGET_RESET;
1783 } else if (!xtensa_dm_is_powered(&xtensa->dbg_mod)) {
1784 LOG_TARGET_DEBUG(target, "not powered 0x%" PRIX32 "%ld",
1785 xtensa->dbg_mod.core_status.dsr,
1786 xtensa->dbg_mod.core_status.dsr & OCDDSR_STOPPED);
1787 target->state = TARGET_UNKNOWN;
1788 if (xtensa->come_online_probes_num == 0)
1789 target->examined = false;
1791 xtensa->come_online_probes_num--;
1792 } else if (xtensa_is_stopped(target)) {
1793 if (target->state != TARGET_HALTED) {
1794 enum target_state oldstate = target->state;
1795 target->state = TARGET_HALTED;
1796 /* Examine why the target has been halted */
1797 target->debug_reason = DBG_REASON_DBGRQ;
1798 xtensa_fetch_all_regs(target);
1799 /* When setting debug reason DEBUGCAUSE events have the following
1800 * priorities: watchpoint == breakpoint > single step > debug interrupt. */
1801 /* Watchpoint and breakpoint events at the same time results in special
1802 * debug reason: DBG_REASON_WPTANDBKPT. */
1803 xtensa_reg_val_t halt_cause = xtensa_reg_get(target, XT_REG_IDX_DEBUGCAUSE);
1804 /* TODO: Add handling of DBG_REASON_EXC_CATCH */
1805 if (halt_cause & DEBUGCAUSE_IC)
1806 target->debug_reason = DBG_REASON_SINGLESTEP;
1807 if (halt_cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BN | DEBUGCAUSE_BI)) {
1808 if (halt_cause & DEBUGCAUSE_DB)
1809 target->debug_reason = DBG_REASON_WPTANDBKPT;
1811 target->debug_reason = DBG_REASON_BREAKPOINT;
1812 } else if (halt_cause & DEBUGCAUSE_DB) {
1813 target->debug_reason = DBG_REASON_WATCHPOINT;
1815 LOG_TARGET_DEBUG(target, "Target halted, pc=0x%08" PRIX32 ", debug_reason=%08x, oldstate=%08x",
1816 xtensa_reg_get(target, XT_REG_IDX_PC),
1817 target->debug_reason,
1819 LOG_TARGET_DEBUG(target, "Halt reason=0x%08" PRIX32 ", exc_cause=%" PRId32 ", dsr=0x%08" PRIx32,
1821 xtensa_reg_get(target, XT_REG_IDX_EXCCAUSE),
1822 xtensa->dbg_mod.core_status.dsr);
1823 LOG_TARGET_INFO(target, "Target halted, PC=0x%08" PRIX32 ", debug_reason=%08x",
1824 xtensa_reg_get(target, XT_REG_IDX_PC), target->debug_reason);
1825 xtensa_dm_core_status_clear(
1827 OCDDSR_DEBUGPENDBREAK | OCDDSR_DEBUGINTBREAK | OCDDSR_DEBUGPENDTRAX |
1828 OCDDSR_DEBUGINTTRAX |
1829 OCDDSR_DEBUGPENDHOST | OCDDSR_DEBUGINTHOST);
1832 target->debug_reason = DBG_REASON_NOTHALTED;
1833 if (target->state != TARGET_RUNNING && target->state != TARGET_DEBUG_RUNNING) {
1834 target->state = TARGET_RUNNING;
1835 target->debug_reason = DBG_REASON_NOTHALTED;
1838 if (xtensa->trace_active) {
1839 /* Detect if tracing was active but has stopped. */
1840 struct xtensa_trace_status trace_status;
1841 res = xtensa_dm_trace_status_read(&xtensa->dbg_mod, &trace_status);
1842 if (res == ERROR_OK) {
1843 if (!(trace_status.stat & TRAXSTAT_TRACT)) {
1844 LOG_INFO("Detected end of trace.");
1845 if (trace_status.stat & TRAXSTAT_PCMTG)
1846 LOG_TARGET_INFO(target, "Trace stop triggered by PC match");
1847 if (trace_status.stat & TRAXSTAT_PTITG)
1848 LOG_TARGET_INFO(target, "Trace stop triggered by Processor Trigger Input");
1849 if (trace_status.stat & TRAXSTAT_CTITG)
1850 LOG_TARGET_INFO(target, "Trace stop triggered by Cross-trigger Input");
1851 xtensa->trace_active = false;
1858 static int xtensa_sw_breakpoint_add(struct target *target,
1859 struct breakpoint *breakpoint,
1860 struct xtensa_sw_breakpoint *sw_bp)
1862 int ret = target_read_buffer(target, breakpoint->address, XT_ISNS_SZ_MAX, sw_bp->insn);
1863 if (ret != ERROR_OK) {
1864 LOG_TARGET_ERROR(target, "Failed to read original instruction (%d)!", ret);
1868 sw_bp->insn_sz = xtensa_insn_size_get(buf_get_u32(sw_bp->insn, 0, 24));
1869 sw_bp->oocd_bp = breakpoint;
1871 uint32_t break_insn = sw_bp->insn_sz == XT_ISNS_SZ_MAX ? XT_INS_BREAK(0, 0) : XT_INS_BREAKN(0);
1872 /* convert to target endianness */
1873 uint8_t break_insn_buff[4];
1874 target_buffer_set_u32(target, break_insn_buff, break_insn);
1876 ret = target_write_buffer(target, breakpoint->address, sw_bp->insn_sz, break_insn_buff);
1877 if (ret != ERROR_OK) {
1878 LOG_TARGET_ERROR(target, "Failed to write breakpoint instruction (%d)!", ret);
1885 static int xtensa_sw_breakpoint_remove(struct target *target, struct xtensa_sw_breakpoint *sw_bp)
1887 int ret = target_write_buffer(target, sw_bp->oocd_bp->address, sw_bp->insn_sz, sw_bp->insn);
1888 if (ret != ERROR_OK) {
1889 LOG_TARGET_ERROR(target, "Failed to read insn (%d)!", ret);
1892 sw_bp->oocd_bp = NULL;
1896 int xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint)
1898 struct xtensa *xtensa = target_to_xtensa(target);
1901 if (breakpoint->type == BKPT_SOFT) {
1902 for (slot = 0; slot < XT_SW_BREAKPOINTS_MAX_NUM; slot++) {
1903 if (!xtensa->sw_brps[slot].oocd_bp ||
1904 xtensa->sw_brps[slot].oocd_bp == breakpoint)
1907 if (slot == XT_SW_BREAKPOINTS_MAX_NUM) {
1908 LOG_TARGET_WARNING(target, "No free slots to add SW breakpoint!");
1909 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1911 int ret = xtensa_sw_breakpoint_add(target, breakpoint, &xtensa->sw_brps[slot]);
1912 if (ret != ERROR_OK) {
1913 LOG_TARGET_ERROR(target, "Failed to add SW breakpoint!");
1916 LOG_TARGET_DEBUG(target, "placed SW breakpoint %u @ " TARGET_ADDR_FMT,
1918 breakpoint->address);
1922 for (slot = 0; slot < xtensa->core_config->debug.ibreaks_num; slot++) {
1923 if (!xtensa->hw_brps[slot] || xtensa->hw_brps[slot] == breakpoint)
1926 if (slot == xtensa->core_config->debug.ibreaks_num) {
1927 LOG_TARGET_ERROR(target, "No free slots to add HW breakpoint!");
1928 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1931 xtensa->hw_brps[slot] = breakpoint;
1932 /* We will actually write the breakpoints when we resume the target. */
1933 LOG_TARGET_DEBUG(target, "placed HW breakpoint @ " TARGET_ADDR_FMT,
1934 breakpoint->address);
1939 int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint)
1941 struct xtensa *xtensa = target_to_xtensa(target);
1944 if (breakpoint->type == BKPT_SOFT) {
1945 for (slot = 0; slot < XT_SW_BREAKPOINTS_MAX_NUM; slot++) {
1946 if (xtensa->sw_brps[slot].oocd_bp && xtensa->sw_brps[slot].oocd_bp == breakpoint)
1949 if (slot == XT_SW_BREAKPOINTS_MAX_NUM) {
1950 LOG_TARGET_WARNING(target, "Max SW breakpoints slot reached, slot=%u!", slot);
1951 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1953 int ret = xtensa_sw_breakpoint_remove(target, &xtensa->sw_brps[slot]);
1954 if (ret != ERROR_OK) {
1955 LOG_TARGET_ERROR(target, "Failed to remove SW breakpoint (%d)!", ret);
1958 LOG_TARGET_DEBUG(target, "cleared SW breakpoint %u @ " TARGET_ADDR_FMT, slot, breakpoint->address);
1962 for (slot = 0; slot < xtensa->core_config->debug.ibreaks_num; slot++) {
1963 if (xtensa->hw_brps[slot] == breakpoint)
1966 if (slot == xtensa->core_config->debug.ibreaks_num) {
1967 LOG_TARGET_ERROR(target, "HW breakpoint not found!");
1968 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1970 xtensa->hw_brps[slot] = NULL;
1971 LOG_TARGET_DEBUG(target, "cleared HW breakpoint %u @ " TARGET_ADDR_FMT, slot, breakpoint->address);
1975 int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint)
1977 struct xtensa *xtensa = target_to_xtensa(target);
1979 xtensa_reg_val_t dbreakcval;
1981 if (target->state != TARGET_HALTED) {
1982 LOG_TARGET_WARNING(target, "target not halted");
1983 return ERROR_TARGET_NOT_HALTED;
1986 if (watchpoint->mask != ~(uint32_t)0) {
1987 LOG_TARGET_ERROR(target, "watchpoint value masks not supported");
1988 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1991 for (slot = 0; slot < xtensa->core_config->debug.dbreaks_num; slot++) {
1992 if (!xtensa->hw_wps[slot] || xtensa->hw_wps[slot] == watchpoint)
1995 if (slot == xtensa->core_config->debug.dbreaks_num) {
1996 LOG_TARGET_WARNING(target, "No free slots to add HW watchpoint!");
1997 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
2000 /* Figure out value for dbreakc5..0
2001 * It's basically 0x3F with an incremental bit removed from the LSB for each extra length power of 2. */
2002 if (watchpoint->length < 1 || watchpoint->length > 64 ||
2003 !IS_PWR_OF_2(watchpoint->length) ||
2004 !IS_ALIGNED(watchpoint->address, watchpoint->length)) {
2007 "Watchpoint with length %d on address " TARGET_ADDR_FMT
2008 " not supported by hardware.",
2010 watchpoint->address);
2011 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
2013 dbreakcval = ALIGN_DOWN(0x3F, watchpoint->length);
2015 if (watchpoint->rw == WPT_READ)
2016 dbreakcval |= BIT(30);
2017 if (watchpoint->rw == WPT_WRITE)
2018 dbreakcval |= BIT(31);
2019 if (watchpoint->rw == WPT_ACCESS)
2020 dbreakcval |= BIT(30) | BIT(31);
2022 /* Write DBREAKA[slot] and DBCREAKC[slot] */
2023 xtensa_reg_set(target, XT_REG_IDX_DBREAKA0 + slot, watchpoint->address);
2024 xtensa_reg_set(target, XT_REG_IDX_DBREAKC0 + slot, dbreakcval);
2025 xtensa->hw_wps[slot] = watchpoint;
2026 LOG_TARGET_DEBUG(target, "placed HW watchpoint @ " TARGET_ADDR_FMT,
2027 watchpoint->address);
2031 int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoint)
2033 struct xtensa *xtensa = target_to_xtensa(target);
2036 for (slot = 0; slot < xtensa->core_config->debug.dbreaks_num; slot++) {
2037 if (xtensa->hw_wps[slot] == watchpoint)
2040 if (slot == xtensa->core_config->debug.dbreaks_num) {
2041 LOG_TARGET_WARNING(target, "HW watchpoint " TARGET_ADDR_FMT " not found!", watchpoint->address);
2042 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
2044 xtensa_reg_set(target, XT_REG_IDX_DBREAKC0 + slot, 0);
2045 xtensa->hw_wps[slot] = NULL;
2046 LOG_TARGET_DEBUG(target, "cleared HW watchpoint @ " TARGET_ADDR_FMT,
2047 watchpoint->address);
2051 static int xtensa_build_reg_cache(struct target *target)
2053 struct xtensa *xtensa = target_to_xtensa(target);
2054 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
2055 struct reg_cache *reg_cache = calloc(1, sizeof(struct reg_cache));
2058 LOG_ERROR("Failed to alloc reg cache!");
2061 reg_cache->name = "Xtensa registers";
2062 reg_cache->next = NULL;
2063 reg_cache->num_regs = XT_NUM_REGS + xtensa->core_config->user_regs_num;
2065 struct reg *reg_list = calloc(reg_cache->num_regs, sizeof(struct reg));
2067 LOG_ERROR("Failed to alloc reg list!");
2070 xtensa->regs_num = 0;
2072 for (unsigned int i = 0; i < XT_NUM_REGS; i++) {
2073 reg_list[i].exist = false;
2074 if (xtensa_regs[i].type == XT_REG_USER) {
2075 if (xtensa_user_reg_exists(xtensa, i))
2076 reg_list[i].exist = true;
2078 LOG_DEBUG("User reg '%s' (%d) does not exist", xtensa_regs[i].name, i);
2079 } else if (xtensa_regs[i].type == XT_REG_FR) {
2080 if (xtensa_fp_reg_exists(xtensa, i))
2081 reg_list[i].exist = true;
2083 LOG_DEBUG("FP reg '%s' (%d) does not exist", xtensa_regs[i].name, i);
2084 } else if (xtensa_regs[i].type == XT_REG_SPECIAL) {
2085 if (xtensa_special_reg_exists(xtensa, i))
2086 reg_list[i].exist = true;
2088 LOG_DEBUG("Special reg '%s' (%d) does not exist", xtensa_regs[i].name, i);
2090 if (xtensa_regular_reg_exists(xtensa, i))
2091 reg_list[i].exist = true;
2093 LOG_DEBUG("Regular reg '%s' (%d) does not exist", xtensa_regs[i].name, i);
2095 reg_list[i].name = xtensa_regs[i].name;
2096 reg_list[i].size = 32;
2097 reg_list[i].value = calloc(1, 4 /*XT_REG_LEN*/);/* make Clang Static Analyzer happy */
2098 if (!reg_list[i].value) {
2099 LOG_ERROR("Failed to alloc reg list value!");
2102 reg_list[i].dirty = false;
2103 reg_list[i].valid = false;
2104 reg_list[i].type = &xtensa_reg_type;
2105 reg_list[i].arch_info = xtensa;
2106 if (reg_list[i].exist)
2109 for (unsigned int i = 0; i < xtensa->core_config->user_regs_num; i++) {
2110 reg_list[XT_USR_REG_START + i].exist = true;
2111 reg_list[XT_USR_REG_START + i].name = xtensa->core_config->user_regs[i].name;
2112 reg_list[XT_USR_REG_START + i].size = xtensa->core_config->user_regs[i].size;
2113 reg_list[XT_USR_REG_START + i].value = calloc(1, reg_list[XT_USR_REG_START + i].size / 8);
2114 if (!reg_list[XT_USR_REG_START + i].value) {
2115 LOG_ERROR("Failed to alloc user reg list value!");
2118 reg_list[XT_USR_REG_START + i].dirty = false;
2119 reg_list[XT_USR_REG_START + i].valid = false;
2120 reg_list[XT_USR_REG_START + i].type = xtensa->core_config->user_regs[i].type;
2121 reg_list[XT_USR_REG_START + i].arch_info = xtensa;
2124 if (xtensa->core_config->gdb_general_regs_num >= xtensa->regs_num) {
2125 LOG_ERROR("Regs number less then GDB general regs number!");
2129 /* assign GDB reg numbers to registers */
2130 for (unsigned int gdb_reg_id = 0; gdb_reg_id < xtensa->regs_num; gdb_reg_id++) {
2131 unsigned int reg_id = xtensa->core_config->gdb_regs_mapping[gdb_reg_id];
2132 if (reg_id >= reg_cache->num_regs) {
2133 LOG_ERROR("Invalid GDB map!");
2136 if (!reg_list[reg_id].exist) {
2137 LOG_ERROR("Non-existing reg in GDB map!");
2140 reg_list[reg_id].number = gdb_reg_id;
2142 reg_cache->reg_list = reg_list;
2144 xtensa->algo_context_backup = calloc(reg_cache->num_regs, sizeof(void *));
2145 if (!xtensa->algo_context_backup) {
2146 LOG_ERROR("Failed to alloc mem for algorithm context backup!");
2149 for (unsigned int i = 0; i < reg_cache->num_regs; i++) {
2150 struct reg *reg = ®_cache->reg_list[i];
2151 xtensa->algo_context_backup[i] = calloc(1, reg->size / 8);
2152 if (!xtensa->algo_context_backup[i]) {
2153 LOG_ERROR("Failed to alloc mem for algorithm context!");
2158 xtensa->core_cache = reg_cache;
2160 *cache_p = reg_cache;
2165 for (unsigned int i = 0; i < reg_cache->num_regs; i++)
2166 free(reg_list[i].value);
2169 if (xtensa->algo_context_backup) {
2170 for (unsigned int i = 0; i < reg_cache->num_regs; i++)
2171 free(xtensa->algo_context_backup[i]);
2172 free(xtensa->algo_context_backup);
2179 int xtensa_init_arch_info(struct target *target, struct xtensa *xtensa,
2180 const struct xtensa_config *xtensa_config,
2181 const struct xtensa_debug_module_config *dm_cfg)
2183 target->arch_info = xtensa;
2184 xtensa->common_magic = XTENSA_COMMON_MAGIC;
2185 xtensa->target = target;
2186 xtensa->core_config = xtensa_config;
2187 xtensa->stepping_isr_mode = XT_STEPPING_ISR_ON;
2189 if (!xtensa->core_config->exc.enabled || !xtensa->core_config->irq.enabled ||
2190 !xtensa->core_config->high_irq.enabled || !xtensa->core_config->debug.enabled) {
2191 LOG_ERROR("Xtensa configuration does not support debugging!");
2194 return xtensa_dm_init(&xtensa->dbg_mod, dm_cfg);
2197 void xtensa_set_permissive_mode(struct target *target, bool state)
2199 target_to_xtensa(target)->permissive_mode = state;
2202 int xtensa_target_init(struct command_context *cmd_ctx, struct target *target)
2204 struct xtensa *xtensa = target_to_xtensa(target);
2206 xtensa->come_online_probes_num = 3;
2207 xtensa->hw_brps = calloc(xtensa->core_config->debug.ibreaks_num, sizeof(struct breakpoint *));
2208 if (!xtensa->hw_brps) {
2209 LOG_ERROR("Failed to alloc memory for HW breakpoints!");
2212 xtensa->hw_wps = calloc(xtensa->core_config->debug.dbreaks_num, sizeof(struct watchpoint *));
2213 if (!xtensa->hw_wps) {
2214 free(xtensa->hw_brps);
2215 LOG_ERROR("Failed to alloc memory for HW watchpoints!");
2218 xtensa->sw_brps = calloc(XT_SW_BREAKPOINTS_MAX_NUM, sizeof(struct xtensa_sw_breakpoint));
2219 if (!xtensa->sw_brps) {
2220 free(xtensa->hw_brps);
2221 free(xtensa->hw_wps);
2222 LOG_ERROR("Failed to alloc memory for SW breakpoints!");
2226 return xtensa_build_reg_cache(target);
2229 static void xtensa_free_reg_cache(struct target *target)
2231 struct xtensa *xtensa = target_to_xtensa(target);
2232 struct reg_cache *cache = xtensa->core_cache;
2235 register_unlink_cache(&target->reg_cache, cache);
2236 for (unsigned int i = 0; i < cache->num_regs; i++) {
2237 free(xtensa->algo_context_backup[i]);
2238 free(cache->reg_list[i].value);
2240 free(xtensa->algo_context_backup);
2241 free(cache->reg_list);
2244 xtensa->core_cache = NULL;
2245 xtensa->algo_context_backup = NULL;
2248 void xtensa_target_deinit(struct target *target)
2250 struct xtensa *xtensa = target_to_xtensa(target);
2254 if (target_was_examined(target)) {
2255 int ret = xtensa_queue_dbg_reg_write(xtensa, NARADR_DCRCLR, OCDDCR_ENABLEOCD);
2256 if (ret != ERROR_OK) {
2257 LOG_ERROR("Failed to queue OCDDCR_ENABLEOCD clear operation!");
2260 xtensa_dm_queue_tdi_idle(&xtensa->dbg_mod);
2261 ret = jtag_execute_queue();
2262 if (ret != ERROR_OK) {
2263 LOG_ERROR("Failed to clear OCDDCR_ENABLEOCD!");
2267 xtensa_free_reg_cache(target);
2268 free(xtensa->hw_brps);
2269 free(xtensa->hw_wps);
2270 free(xtensa->sw_brps);
2273 const char *xtensa_get_gdb_arch(struct target *target)
2278 COMMAND_HELPER(xtensa_cmd_permissive_mode_do, struct xtensa *xtensa)
2280 return CALL_COMMAND_HANDLER(handle_command_parse_bool,
2281 &xtensa->permissive_mode, "xtensa permissive mode");
2284 COMMAND_HANDLER(xtensa_cmd_permissive_mode)
2286 return CALL_COMMAND_HANDLER(xtensa_cmd_permissive_mode_do,
2287 target_to_xtensa(get_current_target(CMD_CTX)));
2290 /* perfmon_enable <counter_id> <select> [mask] [kernelcnt] [tracelevel] */
2291 COMMAND_HELPER(xtensa_cmd_perfmon_enable_do, struct xtensa *xtensa)
2293 struct xtensa_perfmon_config config = {
2296 .tracelevel = -1 /* use DEBUGLEVEL by default */
2299 if (CMD_ARGC < 2 || CMD_ARGC > 6)
2300 return ERROR_COMMAND_SYNTAX_ERROR;
2302 unsigned int counter_id = strtoul(CMD_ARGV[0], NULL, 0);
2303 if (counter_id >= XTENSA_MAX_PERF_COUNTERS) {
2304 command_print(CMD, "counter_id should be < %d", XTENSA_MAX_PERF_COUNTERS);
2305 return ERROR_COMMAND_ARGUMENT_INVALID;
2308 config.select = strtoul(CMD_ARGV[1], NULL, 0);
2309 if (config.select > XTENSA_MAX_PERF_SELECT) {
2310 command_print(CMD, "select should be < %d", XTENSA_MAX_PERF_SELECT);
2311 return ERROR_COMMAND_ARGUMENT_INVALID;
2314 if (CMD_ARGC >= 3) {
2315 config.mask = strtoul(CMD_ARGV[2], NULL, 0);
2316 if (config.mask > XTENSA_MAX_PERF_MASK) {
2317 command_print(CMD, "mask should be < %d", XTENSA_MAX_PERF_MASK);
2318 return ERROR_COMMAND_ARGUMENT_INVALID;
2322 if (CMD_ARGC >= 4) {
2323 config.kernelcnt = strtoul(CMD_ARGV[3], NULL, 0);
2324 if (config.kernelcnt > 1) {
2325 command_print(CMD, "kernelcnt should be 0 or 1");
2326 return ERROR_COMMAND_ARGUMENT_INVALID;
2330 if (CMD_ARGC >= 5) {
2331 config.tracelevel = strtoul(CMD_ARGV[4], NULL, 0);
2332 if (config.tracelevel > 7) {
2333 command_print(CMD, "tracelevel should be <=7");
2334 return ERROR_COMMAND_ARGUMENT_INVALID;
2338 if (config.tracelevel == -1)
2339 config.tracelevel = xtensa->core_config->debug.irq_level;
2341 return xtensa_dm_perfmon_enable(&xtensa->dbg_mod, counter_id, &config);
2344 COMMAND_HANDLER(xtensa_cmd_perfmon_enable)
2346 return CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_enable_do,
2347 target_to_xtensa(get_current_target(CMD_CTX)));
2350 /* perfmon_dump [counter_id] */
2351 COMMAND_HELPER(xtensa_cmd_perfmon_dump_do, struct xtensa *xtensa)
2354 return ERROR_COMMAND_SYNTAX_ERROR;
2356 int counter_id = -1;
2357 if (CMD_ARGC == 1) {
2358 counter_id = strtol(CMD_ARGV[0], NULL, 0);
2359 if (counter_id > XTENSA_MAX_PERF_COUNTERS) {
2360 command_print(CMD, "counter_id should be < %d", XTENSA_MAX_PERF_COUNTERS);
2361 return ERROR_COMMAND_ARGUMENT_INVALID;
2365 unsigned int counter_start = (counter_id < 0) ? 0 : counter_id;
2366 unsigned int counter_end = (counter_id < 0) ? XTENSA_MAX_PERF_COUNTERS : counter_id + 1;
2367 for (unsigned int counter = counter_start; counter < counter_end; ++counter) {
2368 char result_buf[128] = { 0 };
2369 size_t result_pos = snprintf(result_buf, sizeof(result_buf), "Counter %d: ", counter);
2370 struct xtensa_perfmon_result result;
2371 int res = xtensa_dm_perfmon_dump(&xtensa->dbg_mod, counter, &result);
2372 if (res != ERROR_OK)
2374 snprintf(result_buf + result_pos, sizeof(result_buf) - result_pos,
2377 result.overflow ? " (overflow)" : "");
2378 LOG_INFO("%s", result_buf);
2384 COMMAND_HANDLER(xtensa_cmd_perfmon_dump)
2386 return CALL_COMMAND_HANDLER(xtensa_cmd_perfmon_dump_do,
2387 target_to_xtensa(get_current_target(CMD_CTX)));
2390 COMMAND_HELPER(xtensa_cmd_mask_interrupts_do, struct xtensa *xtensa)
2396 state = xtensa->stepping_isr_mode;
2397 if (state == XT_STEPPING_ISR_ON)
2399 else if (state == XT_STEPPING_ISR_OFF)
2403 command_print(CMD, "Current ISR step mode: %s", st);
2406 /* Masking is ON -> interrupts during stepping are OFF, and vice versa */
2407 if (!strcasecmp(CMD_ARGV[0], "off"))
2408 state = XT_STEPPING_ISR_ON;
2409 else if (!strcasecmp(CMD_ARGV[0], "on"))
2410 state = XT_STEPPING_ISR_OFF;
2413 command_print(CMD, "Argument unknown. Please pick one of ON, OFF");
2416 xtensa->stepping_isr_mode = state;
2420 COMMAND_HANDLER(xtensa_cmd_mask_interrupts)
2422 return CALL_COMMAND_HANDLER(xtensa_cmd_mask_interrupts_do,
2423 target_to_xtensa(get_current_target(CMD_CTX)));
2426 COMMAND_HELPER(xtensa_cmd_smpbreak_do, struct target *target)
2431 if (CMD_ARGC >= 1) {
2432 for (unsigned int i = 0; i < CMD_ARGC; i++) {
2433 if (!strcasecmp(CMD_ARGV[0], "none")) {
2435 } else if (!strcasecmp(CMD_ARGV[i], "BreakIn")) {
2436 val |= OCDDCR_BREAKINEN;
2437 } else if (!strcasecmp(CMD_ARGV[i], "BreakOut")) {
2438 val |= OCDDCR_BREAKOUTEN;
2439 } else if (!strcasecmp(CMD_ARGV[i], "RunStallIn")) {
2440 val |= OCDDCR_RUNSTALLINEN;
2441 } else if (!strcasecmp(CMD_ARGV[i], "DebugModeOut")) {
2442 val |= OCDDCR_DEBUGMODEOUTEN;
2443 } else if (!strcasecmp(CMD_ARGV[i], "BreakInOut")) {
2444 val |= OCDDCR_BREAKINEN | OCDDCR_BREAKOUTEN;
2445 } else if (!strcasecmp(CMD_ARGV[i], "RunStall")) {
2446 val |= OCDDCR_RUNSTALLINEN | OCDDCR_DEBUGMODEOUTEN;
2448 command_print(CMD, "Unknown arg %s", CMD_ARGV[i]);
2451 "use either BreakInOut, None or RunStall as arguments, or any combination of BreakIn, BreakOut, RunStallIn and DebugModeOut.");
2455 res = xtensa_smpbreak_set(target, val);
2456 if (res != ERROR_OK)
2457 command_print(CMD, "Failed to set smpbreak config %d", res);
2459 struct xtensa *xtensa = target_to_xtensa(target);
2460 res = xtensa_smpbreak_read(xtensa, &val);
2461 if (res == ERROR_OK) {
2462 command_print(CMD, "Current bits set:%s%s%s%s",
2463 (val & OCDDCR_BREAKINEN) ? " BreakIn" : "",
2464 (val & OCDDCR_BREAKOUTEN) ? " BreakOut" : "",
2465 (val & OCDDCR_RUNSTALLINEN) ? " RunStallIn" : "",
2466 (val & OCDDCR_DEBUGMODEOUTEN) ? " DebugModeOut" : ""
2469 command_print(CMD, "Failed to get smpbreak config %d", res);
2475 COMMAND_HANDLER(xtensa_cmd_smpbreak)
2477 return CALL_COMMAND_HANDLER(xtensa_cmd_smpbreak_do,
2478 get_current_target(CMD_CTX));
2481 COMMAND_HELPER(xtensa_cmd_tracestart_do, struct xtensa *xtensa)
2483 struct xtensa_trace_status trace_status;
2484 struct xtensa_trace_start_config cfg = {
2486 .stopmask = XTENSA_STOPMASK_DISABLED,
2488 .after_is_words = false
2491 /* Parse arguments */
2492 for (unsigned int i = 0; i < CMD_ARGC; i++) {
2493 if ((!strcasecmp(CMD_ARGV[i], "pc")) && CMD_ARGC > i) {
2496 cfg.stoppc = strtol(CMD_ARGV[i], &e, 0);
2499 cfg.stopmask = strtol(e, NULL, 0);
2500 } else if ((!strcasecmp(CMD_ARGV[i], "after")) && CMD_ARGC > i) {
2502 cfg.after = strtol(CMD_ARGV[i], NULL, 0);
2503 } else if (!strcasecmp(CMD_ARGV[i], "ins")) {
2504 cfg.after_is_words = 0;
2505 } else if (!strcasecmp(CMD_ARGV[i], "words")) {
2506 cfg.after_is_words = 1;
2508 command_print(CMD, "Did not understand %s", CMD_ARGV[i]);
2513 int res = xtensa_dm_trace_status_read(&xtensa->dbg_mod, &trace_status);
2514 if (res != ERROR_OK)
2516 if (trace_status.stat & TRAXSTAT_TRACT) {
2517 LOG_WARNING("Silently stop active tracing!");
2518 res = xtensa_dm_trace_stop(&xtensa->dbg_mod, false);
2519 if (res != ERROR_OK)
2523 res = xtensa_dm_trace_start(&xtensa->dbg_mod, &cfg);
2524 if (res != ERROR_OK)
2527 xtensa->trace_active = true;
2528 command_print(CMD, "Trace started.");
2532 COMMAND_HANDLER(xtensa_cmd_tracestart)
2534 return CALL_COMMAND_HANDLER(xtensa_cmd_tracestart_do,
2535 target_to_xtensa(get_current_target(CMD_CTX)));
2538 COMMAND_HELPER(xtensa_cmd_tracestop_do, struct xtensa *xtensa)
2540 struct xtensa_trace_status trace_status;
2542 int res = xtensa_dm_trace_status_read(&xtensa->dbg_mod, &trace_status);
2543 if (res != ERROR_OK)
2546 if (!(trace_status.stat & TRAXSTAT_TRACT)) {
2547 command_print(CMD, "No trace is currently active.");
2551 res = xtensa_dm_trace_stop(&xtensa->dbg_mod, true);
2552 if (res != ERROR_OK)
2555 xtensa->trace_active = false;
2556 command_print(CMD, "Trace stop triggered.");
2560 COMMAND_HANDLER(xtensa_cmd_tracestop)
2562 return CALL_COMMAND_HANDLER(xtensa_cmd_tracestop_do,
2563 target_to_xtensa(get_current_target(CMD_CTX)));
2566 COMMAND_HELPER(xtensa_cmd_tracedump_do, struct xtensa *xtensa, const char *fname)
2568 struct xtensa_trace_config trace_config;
2569 struct xtensa_trace_status trace_status;
2570 uint32_t memsz, wmem;
2572 int res = xtensa_dm_trace_status_read(&xtensa->dbg_mod, &trace_status);
2573 if (res != ERROR_OK)
2576 if (trace_status.stat & TRAXSTAT_TRACT) {
2577 command_print(CMD, "Tracing is still active. Please stop it first.");
2581 res = xtensa_dm_trace_config_read(&xtensa->dbg_mod, &trace_config);
2582 if (res != ERROR_OK)
2585 if (!(trace_config.ctrl & TRAXCTRL_TREN)) {
2586 command_print(CMD, "No active trace found; nothing to dump.");
2590 memsz = trace_config.memaddr_end - trace_config.memaddr_start + 1;
2591 LOG_INFO("Total trace memory: %d words", memsz);
2592 if ((trace_config.addr &
2593 ((TRAXADDR_TWRAP_MASK << TRAXADDR_TWRAP_SHIFT) | TRAXADDR_TWSAT)) == 0) {
2594 /*Memory hasn't overwritten itself yet. */
2595 wmem = trace_config.addr & TRAXADDR_TADDR_MASK;
2596 LOG_INFO("...but trace is only %d words", wmem);
2600 if (trace_config.addr & TRAXADDR_TWSAT) {
2601 LOG_INFO("Real trace is many times longer than that (overflow)");
2603 uint32_t trc_sz = (trace_config.addr >> TRAXADDR_TWRAP_SHIFT) & TRAXADDR_TWRAP_MASK;
2604 trc_sz = (trc_sz * memsz) + (trace_config.addr & TRAXADDR_TADDR_MASK);
2605 LOG_INFO("Real trace is %d words, but the start has been truncated.", trc_sz);
2609 uint8_t *tracemem = malloc(memsz * 4);
2611 command_print(CMD, "Failed to alloc memory for trace data!");
2614 res = xtensa_dm_trace_data_read(&xtensa->dbg_mod, tracemem, memsz * 4);
2615 if (res != ERROR_OK) {
2620 int f = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
2623 command_print(CMD, "Unable to open file %s", fname);
2626 if (write(f, tracemem, memsz * 4) != (int)memsz * 4)
2627 command_print(CMD, "Unable to write to file %s", fname);
2629 command_print(CMD, "Written %d bytes of trace data to %s", memsz * 4, fname);
2632 bool is_all_zeroes = true;
2633 for (unsigned int i = 0; i < memsz * 4; i++) {
2634 if (tracemem[i] != 0) {
2635 is_all_zeroes = false;
2643 "WARNING: File written is all zeroes. Are you sure you enabled trace memory?");
2648 COMMAND_HANDLER(xtensa_cmd_tracedump)
2650 if (CMD_ARGC != 1) {
2651 command_print(CMD, "Command takes exactly 1 parameter.Need filename to dump to as output!");
2655 return CALL_COMMAND_HANDLER(xtensa_cmd_tracedump_do,
2656 target_to_xtensa(get_current_target(CMD_CTX)), CMD_ARGV[0]);
2659 const struct command_registration xtensa_command_handlers[] = {
2661 .name = "set_permissive",
2662 .handler = xtensa_cmd_permissive_mode,
2663 .mode = COMMAND_ANY,
2664 .help = "When set to 1, enable Xtensa permissive mode (less client-side checks)",
2669 .handler = xtensa_cmd_mask_interrupts,
2670 .mode = COMMAND_ANY,
2671 .help = "mask Xtensa interrupts at step",
2672 .usage = "['on'|'off']",
2676 .handler = xtensa_cmd_smpbreak,
2677 .mode = COMMAND_ANY,
2678 .help = "Set the way the CPU chains OCD breaks",
2680 "[none|breakinout|runstall] | [BreakIn] [BreakOut] [RunStallIn] [DebugModeOut]",
2683 .name = "perfmon_enable",
2684 .handler = xtensa_cmd_perfmon_enable,
2685 .mode = COMMAND_EXEC,
2686 .help = "Enable and start performance counter",
2687 .usage = "<counter_id> <select> [mask] [kernelcnt] [tracelevel]",
2690 .name = "perfmon_dump",
2691 .handler = xtensa_cmd_perfmon_dump,
2692 .mode = COMMAND_EXEC,
2694 "Dump performance counter value. If no argument specified, dumps all counters.",
2695 .usage = "[counter_id]",
2698 .name = "tracestart",
2699 .handler = xtensa_cmd_tracestart,
2700 .mode = COMMAND_EXEC,
2702 "Tracing: Set up and start a trace. Optionally set stop trigger address and amount of data captured after.",
2703 .usage = "[pc <pcval>/[maskbitcount]] [after <n> [ins|words]]",
2706 .name = "tracestop",
2707 .handler = xtensa_cmd_tracestop,
2708 .mode = COMMAND_EXEC,
2709 .help = "Tracing: Stop current trace as started by the tracestart command",
2713 .name = "tracedump",
2714 .handler = xtensa_cmd_tracedump,
2715 .mode = COMMAND_EXEC,
2716 .help = "Tracing: Dump trace memory to a files. One file per core.",
2717 .usage = "<outfile>",
2719 COMMAND_REGISTRATION_DONE