From Michael Bruck
[fw/openocd] / src / target / etm.c
1 /***************************************************************************\r
2  *   Copyright (C) 2005 by Dominic Rath                                    *\r
3  *   Dominic.Rath@gmx.de                                                   *\r
4  *                                                                         *\r
5  *   This program is free software; you can redistribute it and/or modify  *\r
6  *   it under the terms of the GNU General Public License as published by  *\r
7  *   the Free Software Foundation; either version 2 of the License, or     *\r
8  *   (at your option) any later version.                                   *\r
9  *                                                                         *\r
10  *   This program is distributed in the hope that it will be useful,       *\r
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
13  *   GNU General Public License for more details.                          *\r
14  *                                                                         *\r
15  *   You should have received a copy of the GNU General Public License     *\r
16  *   along with this program; if not, write to the                         *\r
17  *   Free Software Foundation, Inc.,                                       *\r
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
19  ***************************************************************************/\r
20 #ifdef HAVE_CONFIG_H\r
21 #include "config.h"\r
22 #endif\r
23 \r
24 #include <string.h>\r
25 \r
26 #include "etm.h"\r
27 #include "etb.h"\r
28 \r
29 #include "armv4_5.h"\r
30 #include "arm7_9_common.h"\r
31 #include "arm_disassembler.h"\r
32 #include "arm_simulator.h"\r
33 \r
34 #include "log.h"\r
35 #include "arm_jtag.h"\r
36 #include "types.h"\r
37 #include "binarybuffer.h"\r
38 #include "target.h"\r
39 #include "register.h"\r
40 #include "jtag.h"\r
41 #include "fileio.h"\r
42 \r
43 #include <stdlib.h>\r
44 \r
45 /* ETM register access functionality \r
46  * \r
47  */\r
48 \r
49 bitfield_desc_t etm_comms_ctrl_bitfield_desc[] = \r
50 {\r
51         {"R", 1},\r
52         {"W", 1},\r
53         {"reserved", 26},\r
54         {"version", 4}\r
55 };\r
56 \r
57 int etm_reg_arch_info[] =\r
58 {\r
59         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\r
60         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\r
61         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, \r
62         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, \r
63         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,\r
64         0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, \r
65         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,\r
66         0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,\r
67         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, \r
68         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, \r
69         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,\r
70         0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,\r
71         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, \r
72         0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, \r
73 };\r
74 \r
75 int etm_reg_arch_size_info[] =\r
76 {\r
77         32, 32, 17, 8, 3, 9, 32, 16,\r
78         17, 26, 25, 8, 17, 32, 32, 17,\r
79         32, 32, 32, 32, 32, 32, 32, 32, \r
80         32, 32, 32, 32, 32, 32, 32, 32, \r
81         7, 7, 7, 7, 7, 7, 7, 7, \r
82         7, 7, 7, 7, 7, 7, 7, 7, \r
83         32, 32, 32, 32, 32, 32, 32, 32, \r
84         32, 32, 32, 32, 32, 32, 32, 32, \r
85         32, 32, 32, 32, 32, 32, 32, 32, \r
86         32, 32, 32, 32, 32, 32, 32, 32, \r
87         16, 16, 16, 16, 18, 18, 18, 18,\r
88         17, 17, 17, 17, 16, 16, 16, 16,\r
89         17, 17, 17, 17, 17, 17, 2, \r
90         17, 17, 17, 17, 32, 32, 32, 32 \r
91 };\r
92 \r
93 char* etm_reg_list[] =\r
94 {\r
95         "ETM_CTRL",\r
96         "ETM_CONFIG",\r
97         "ETM_TRIG_EVENT",\r
98         "ETM_MMD_CTRL",\r
99         "ETM_STATUS",\r
100         "ETM_SYS_CONFIG",\r
101         "ETM_TRACE_RESOURCE_CTRL",\r
102         "ETM_TRACE_EN_CTRL2",\r
103         "ETM_TRACE_EN_EVENT",\r
104         "ETM_TRACE_EN_CTRL1",\r
105         "ETM_FIFOFULL_REGION",\r
106         "ETM_FIFOFULL_LEVEL",\r
107         "ETM_VIEWDATA_EVENT",\r
108         "ETM_VIEWDATA_CTRL1",\r
109         "ETM_VIEWDATA_CTRL2",\r
110         "ETM_VIEWDATA_CTRL3",\r
111         "ETM_ADDR_COMPARATOR_VALUE1",\r
112         "ETM_ADDR_COMPARATOR_VALUE2",\r
113         "ETM_ADDR_COMPARATOR_VALUE3",\r
114         "ETM_ADDR_COMPARATOR_VALUE4",\r
115         "ETM_ADDR_COMPARATOR_VALUE5",\r
116         "ETM_ADDR_COMPARATOR_VALUE6",\r
117         "ETM_ADDR_COMPARATOR_VALUE7",\r
118         "ETM_ADDR_COMPARATOR_VALUE8",\r
119         "ETM_ADDR_COMPARATOR_VALUE9",\r
120         "ETM_ADDR_COMPARATOR_VALUE10",\r
121         "ETM_ADDR_COMPARATOR_VALUE11",\r
122         "ETM_ADDR_COMPARATOR_VALUE12",\r
123         "ETM_ADDR_COMPARATOR_VALUE13",\r
124         "ETM_ADDR_COMPARATOR_VALUE14",\r
125         "ETM_ADDR_COMPARATOR_VALUE15",\r
126         "ETM_ADDR_COMPARATOR_VALUE16",\r
127         "ETM_ADDR_ACCESS_TYPE1",\r
128         "ETM_ADDR_ACCESS_TYPE2",\r
129         "ETM_ADDR_ACCESS_TYPE3",\r
130         "ETM_ADDR_ACCESS_TYPE4",\r
131         "ETM_ADDR_ACCESS_TYPE5",\r
132         "ETM_ADDR_ACCESS_TYPE6",\r
133         "ETM_ADDR_ACCESS_TYPE7",\r
134         "ETM_ADDR_ACCESS_TYPE8",\r
135         "ETM_ADDR_ACCESS_TYPE9",\r
136         "ETM_ADDR_ACCESS_TYPE10",\r
137         "ETM_ADDR_ACCESS_TYPE11",\r
138         "ETM_ADDR_ACCESS_TYPE12",\r
139         "ETM_ADDR_ACCESS_TYPE13",\r
140         "ETM_ADDR_ACCESS_TYPE14",\r
141         "ETM_ADDR_ACCESS_TYPE15",\r
142         "ETM_ADDR_ACCESS_TYPE16",\r
143         "ETM_DATA_COMPARATOR_VALUE1",\r
144         "ETM_DATA_COMPARATOR_VALUE2",\r
145         "ETM_DATA_COMPARATOR_VALUE3",\r
146         "ETM_DATA_COMPARATOR_VALUE4",\r
147         "ETM_DATA_COMPARATOR_VALUE5",\r
148         "ETM_DATA_COMPARATOR_VALUE6",\r
149         "ETM_DATA_COMPARATOR_VALUE7",\r
150         "ETM_DATA_COMPARATOR_VALUE8",\r
151         "ETM_DATA_COMPARATOR_VALUE9",\r
152         "ETM_DATA_COMPARATOR_VALUE10",\r
153         "ETM_DATA_COMPARATOR_VALUE11",\r
154         "ETM_DATA_COMPARATOR_VALUE12",\r
155         "ETM_DATA_COMPARATOR_VALUE13",\r
156         "ETM_DATA_COMPARATOR_VALUE14",\r
157         "ETM_DATA_COMPARATOR_VALUE15",\r
158         "ETM_DATA_COMPARATOR_VALUE16",\r
159         "ETM_DATA_COMPARATOR_MASK1",\r
160         "ETM_DATA_COMPARATOR_MASK2",\r
161         "ETM_DATA_COMPARATOR_MASK3",\r
162         "ETM_DATA_COMPARATOR_MASK4",\r
163         "ETM_DATA_COMPARATOR_MASK5",\r
164         "ETM_DATA_COMPARATOR_MASK6",\r
165         "ETM_DATA_COMPARATOR_MASK7",\r
166         "ETM_DATA_COMPARATOR_MASK8",\r
167         "ETM_DATA_COMPARATOR_MASK9",\r
168         "ETM_DATA_COMPARATOR_MASK10",\r
169         "ETM_DATA_COMPARATOR_MASK11",\r
170         "ETM_DATA_COMPARATOR_MASK12",\r
171         "ETM_DATA_COMPARATOR_MASK13",\r
172         "ETM_DATA_COMPARATOR_MASK14",\r
173         "ETM_DATA_COMPARATOR_MASK15",\r
174         "ETM_DATA_COMPARATOR_MASK16",\r
175         "ETM_COUNTER_INITAL_VALUE1",\r
176         "ETM_COUNTER_INITAL_VALUE2",\r
177         "ETM_COUNTER_INITAL_VALUE3",\r
178         "ETM_COUNTER_INITAL_VALUE4",\r
179         "ETM_COUNTER_ENABLE1",\r
180         "ETM_COUNTER_ENABLE2",\r
181         "ETM_COUNTER_ENABLE3",\r
182         "ETM_COUNTER_ENABLE4",\r
183         "ETM_COUNTER_RELOAD_VALUE1",\r
184         "ETM_COUNTER_RELOAD_VALUE2",\r
185         "ETM_COUNTER_RELOAD_VALUE3",\r
186         "ETM_COUNTER_RELOAD_VALUE4",\r
187         "ETM_COUNTER_VALUE1",\r
188         "ETM_COUNTER_VALUE2",\r
189         "ETM_COUNTER_VALUE3",\r
190         "ETM_COUNTER_VALUE4",\r
191         "ETM_SEQUENCER_CTRL1",\r
192         "ETM_SEQUENCER_CTRL2",\r
193         "ETM_SEQUENCER_CTRL3",\r
194         "ETM_SEQUENCER_CTRL4",\r
195         "ETM_SEQUENCER_CTRL5",\r
196         "ETM_SEQUENCER_CTRL6",\r
197         "ETM_SEQUENCER_STATE",\r
198         "ETM_EXTERNAL_OUTPUT1",\r
199         "ETM_EXTERNAL_OUTPUT2",\r
200         "ETM_EXTERNAL_OUTPUT3",\r
201         "ETM_EXTERNAL_OUTPUT4",\r
202         "ETM_CONTEXTID_COMPARATOR_VALUE1",\r
203         "ETM_CONTEXTID_COMPARATOR_VALUE2",\r
204         "ETM_CONTEXTID_COMPARATOR_VALUE3",\r
205         "ETM_CONTEXTID_COMPARATOR_MASK"\r
206 };  \r
207 \r
208 int etm_reg_arch_type = -1;\r
209 \r
210 int etm_get_reg(reg_t *reg);\r
211 int etm_set_reg(reg_t *reg, u32 value);\r
212 int etm_set_reg_w_exec(reg_t *reg, u8 *buf);\r
213 \r
214 int etm_write_reg(reg_t *reg, u32 value);\r
215 int etm_read_reg(reg_t *reg);\r
216 \r
217 command_t *etm_cmd = NULL;\r
218 \r
219 reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx)\r
220 {\r
221         reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));\r
222         reg_t *reg_list = NULL;\r
223         etm_reg_t *arch_info = NULL;\r
224         int num_regs = sizeof(etm_reg_arch_info)/sizeof(int);\r
225         int i;\r
226         u32 etm_ctrl_value;\r
227         \r
228         /* register a register arch-type for etm registers only once */\r
229         if (etm_reg_arch_type == -1)\r
230                 etm_reg_arch_type = register_reg_arch_type(etm_get_reg, etm_set_reg_w_exec);\r
231         \r
232         /* the actual registers are kept in two arrays */\r
233         reg_list = calloc(num_regs, sizeof(reg_t));\r
234         arch_info = calloc(num_regs, sizeof(etm_reg_t));\r
235         \r
236         /* fill in values for the reg cache */\r
237         reg_cache->name = "etm registers";\r
238         reg_cache->next = NULL;\r
239         reg_cache->reg_list = reg_list;\r
240         reg_cache->num_regs = num_regs;\r
241         \r
242         /* set up registers */\r
243         for (i = 0; i < num_regs; i++)\r
244         {\r
245                 reg_list[i].name = etm_reg_list[i];\r
246                 reg_list[i].size = 32;\r
247                 reg_list[i].dirty = 0;\r
248                 reg_list[i].valid = 0;\r
249                 reg_list[i].bitfield_desc = NULL;\r
250                 reg_list[i].num_bitfields = 0;\r
251                 reg_list[i].value = calloc(1, 4);\r
252                 reg_list[i].arch_info = &arch_info[i];\r
253                 reg_list[i].arch_type = etm_reg_arch_type;\r
254                 reg_list[i].size = etm_reg_arch_size_info[i];\r
255                 arch_info[i].addr = etm_reg_arch_info[i];\r
256                 arch_info[i].jtag_info = jtag_info;\r
257         }\r
258 \r
259         /* initialize some ETM control register settings */     \r
260         etm_get_reg(&reg_list[ETM_CTRL]);\r
261         etm_ctrl_value = buf_get_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size);\r
262         \r
263         /* clear the ETM powerdown bit (0) */\r
264         etm_ctrl_value &= ~0x1;\r
265                 \r
266         /* configure port width (6:4), mode (17:16) and clocking (13) */\r
267         etm_ctrl_value = (etm_ctrl_value & \r
268                 ~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_PORT_CLOCK_MASK)\r
269                 | etm_ctx->portmode;\r
270         \r
271         buf_set_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size, etm_ctrl_value);\r
272         etm_store_reg(&reg_list[ETM_CTRL]);\r
273         \r
274         /* the ETM might have an ETB connected */\r
275         if (strcmp(etm_ctx->capture_driver->name, "etb") == 0)\r
276         {\r
277                 etb_t *etb = etm_ctx->capture_driver_priv;\r
278                 \r
279                 if (!etb)\r
280                 {\r
281                         ERROR("etb selected as etm capture driver, but no ETB configured");\r
282                         return ERROR_OK;\r
283                 }\r
284                 \r
285                 reg_cache->next = etb_build_reg_cache(etb);\r
286                 \r
287                 etb->reg_cache = reg_cache->next;\r
288         }\r
289         \r
290         if (etm_ctx->capture_driver->init(etm_ctx) != ERROR_OK)\r
291         {\r
292                 ERROR("ETM capture driver initialization failed");\r
293                 exit(-1);\r
294         }\r
295         \r
296         return reg_cache;\r
297 }\r
298 \r
299 int etm_get_reg(reg_t *reg)\r
300 {\r
301         if (etm_read_reg(reg) != ERROR_OK)\r
302         {\r
303                 ERROR("BUG: error scheduling etm register read");\r
304                 exit(-1);\r
305         }\r
306         \r
307         if (jtag_execute_queue() != ERROR_OK)\r
308         {\r
309                 ERROR("register read failed");\r
310         }\r
311         \r
312         return ERROR_OK;\r
313 }\r
314 \r
315 int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)\r
316 {\r
317         etm_reg_t *etm_reg = reg->arch_info;\r
318         u8 reg_addr = etm_reg->addr & 0x7f;\r
319         scan_field_t fields[3];\r
320         \r
321         DEBUG("%i", etm_reg->addr);\r
322 \r
323         jtag_add_end_state(TAP_RTI);\r
324         arm_jtag_scann(etm_reg->jtag_info, 0x6);\r
325         arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);\r
326         \r
327         fields[0].device = etm_reg->jtag_info->chain_pos;\r
328         fields[0].num_bits = 32;\r
329         fields[0].out_value = reg->value;\r
330         fields[0].out_mask = NULL;\r
331         fields[0].in_value = NULL;\r
332         fields[0].in_check_value = NULL;\r
333         fields[0].in_check_mask = NULL;\r
334         fields[0].in_handler = NULL;\r
335         fields[0].in_handler_priv = NULL;\r
336         \r
337         fields[1].device = etm_reg->jtag_info->chain_pos;\r
338         fields[1].num_bits = 7;\r
339         fields[1].out_value = malloc(1);\r
340         buf_set_u32(fields[1].out_value, 0, 7, reg_addr);\r
341         fields[1].out_mask = NULL;\r
342         fields[1].in_value = NULL;\r
343         fields[1].in_check_value = NULL;\r
344         fields[1].in_check_mask = NULL;\r
345         fields[1].in_handler = NULL;\r
346         fields[1].in_handler_priv = NULL;\r
347 \r
348         fields[2].device = etm_reg->jtag_info->chain_pos;\r
349         fields[2].num_bits = 1;\r
350         fields[2].out_value = malloc(1);\r
351         buf_set_u32(fields[2].out_value, 0, 1, 0);\r
352         fields[2].out_mask = NULL;\r
353         fields[2].in_value = NULL;\r
354         fields[2].in_check_value = NULL;\r
355         fields[2].in_check_mask = NULL;\r
356         fields[2].in_handler = NULL;\r
357         fields[2].in_handler_priv = NULL;\r
358         \r
359         jtag_add_dr_scan(3, fields, -1);\r
360         \r
361         fields[0].in_value = reg->value;\r
362         jtag_set_check_value(fields+0, check_value, check_mask, NULL);  \r
363                 \r
364         jtag_add_dr_scan(3, fields, -1);\r
365 \r
366         free(fields[1].out_value);\r
367         free(fields[2].out_value);\r
368         \r
369         return ERROR_OK;\r
370 }\r
371 \r
372 int etm_read_reg(reg_t *reg)\r
373 {\r
374         return etm_read_reg_w_check(reg, NULL, NULL);   \r
375 }\r
376 \r
377 int etm_set_reg(reg_t *reg, u32 value)\r
378 {\r
379         if (etm_write_reg(reg, value) != ERROR_OK)\r
380         {\r
381                 ERROR("BUG: error scheduling etm register write");\r
382                 exit(-1);\r
383         }\r
384         \r
385         buf_set_u32(reg->value, 0, reg->size, value);\r
386         reg->valid = 1;\r
387         reg->dirty = 0;\r
388         \r
389         return ERROR_OK;\r
390 }\r
391 \r
392 int etm_set_reg_w_exec(reg_t *reg, u8 *buf)\r
393 {\r
394         etm_set_reg(reg, buf_get_u32(buf, 0, reg->size));\r
395         \r
396         if (jtag_execute_queue() != ERROR_OK)\r
397         {\r
398                 ERROR("register write failed");\r
399                 exit(-1);\r
400         }\r
401         return ERROR_OK;\r
402 }\r
403 \r
404 int etm_write_reg(reg_t *reg, u32 value)\r
405 {\r
406         etm_reg_t *etm_reg = reg->arch_info;\r
407         u8 reg_addr = etm_reg->addr & 0x7f;\r
408         scan_field_t fields[3];\r
409         \r
410         DEBUG("%i: 0x%8.8x", etm_reg->addr, value);\r
411         \r
412         jtag_add_end_state(TAP_RTI);\r
413         arm_jtag_scann(etm_reg->jtag_info, 0x6);\r
414         arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);\r
415         \r
416         fields[0].device = etm_reg->jtag_info->chain_pos;\r
417         fields[0].num_bits = 32;\r
418         fields[0].out_value = malloc(4);\r
419         buf_set_u32(fields[0].out_value, 0, 32, value);\r
420         fields[0].out_mask = NULL;\r
421         fields[0].in_value = NULL;\r
422         fields[0].in_check_value = NULL;\r
423         fields[0].in_check_mask = NULL;\r
424         fields[0].in_handler = NULL;\r
425         fields[0].in_handler_priv = NULL;\r
426         \r
427         fields[1].device = etm_reg->jtag_info->chain_pos;\r
428         fields[1].num_bits = 7;\r
429         fields[1].out_value = malloc(1);\r
430         buf_set_u32(fields[1].out_value, 0, 7, reg_addr);\r
431         fields[1].out_mask = NULL;\r
432         fields[1].in_value = NULL;\r
433         fields[1].in_check_value = NULL;\r
434         fields[1].in_check_mask = NULL;\r
435         fields[1].in_handler = NULL;\r
436         fields[1].in_handler_priv = NULL;\r
437 \r
438         fields[2].device = etm_reg->jtag_info->chain_pos;\r
439         fields[2].num_bits = 1;\r
440         fields[2].out_value = malloc(1);\r
441         buf_set_u32(fields[2].out_value, 0, 1, 1);\r
442         fields[2].out_mask = NULL;\r
443         fields[2].in_value = NULL;\r
444         fields[2].in_check_value = NULL;\r
445         fields[2].in_check_mask = NULL;\r
446         fields[2].in_handler = NULL;\r
447         fields[2].in_handler_priv = NULL;\r
448         \r
449         jtag_add_dr_scan(3, fields, -1);\r
450         \r
451         free(fields[0].out_value);\r
452         free(fields[1].out_value);\r
453         free(fields[2].out_value);\r
454         \r
455         return ERROR_OK;\r
456 }\r
457 \r
458 int etm_store_reg(reg_t *reg)\r
459 {\r
460         return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));\r
461 }\r
462 \r
463 /* ETM trace analysis functionality\r
464  * \r
465  */\r
466 extern etm_capture_driver_t etb_capture_driver;\r
467 extern etm_capture_driver_t etm_dummy_capture_driver;\r
468 #if BUILD_OOCD_TRACE == 1\r
469 extern etm_capture_driver_t oocd_trace_capture_driver;\r
470 #endif\r
471 \r
472 etm_capture_driver_t *etm_capture_drivers[] = \r
473 {\r
474         &etb_capture_driver,\r
475         &etm_dummy_capture_driver,\r
476 #if BUILD_OOCD_TRACE == 1\r
477         &oocd_trace_capture_driver,\r
478 #endif\r
479         NULL\r
480 };\r
481 \r
482 char *etmv1v1_branch_reason_strings[] =\r
483 {\r
484         "normal PC change",\r
485         "tracing enabled",\r
486         "trace restarted after overflow",\r
487         "exit from debug",\r
488         "periodic synchronization",\r
489         "reserved",\r
490         "reserved",\r
491         "reserved",\r
492 };\r
493 \r
494 int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)\r
495 {\r
496         int i;\r
497         int section = -1;\r
498         u32 size_read;\r
499         u32 opcode;\r
500         int retval;\r
501         \r
502         if (!ctx->image)\r
503                 return ERROR_TRACE_IMAGE_UNAVAILABLE;\r
504         \r
505         /* search for the section the current instruction belongs to */ \r
506         for (i = 0; i < ctx->image->num_sections; i++)\r
507         {\r
508                 if ((ctx->image->sections[i].base_address <= ctx->current_pc) &&\r
509                         (ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc))\r
510                 {\r
511                         section = i;\r
512                         break;\r
513                 }\r
514         }\r
515         \r
516         if (section == -1)\r
517         {\r
518                 /* current instruction couldn't be found in the image */\r
519                 return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
520         }\r
521         \r
522         if (ctx->core_state == ARMV4_5_STATE_ARM)\r
523         {\r
524                 u8 buf[4];\r
525                 if ((retval = image_read_section(ctx->image, section, \r
526                         ctx->current_pc - ctx->image->sections[section].base_address,\r
527                         4, buf, &size_read)) != ERROR_OK)\r
528                 {\r
529                         ERROR("error while reading instruction: %i", retval);\r
530                         return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
531                 }\r
532                 opcode = target_buffer_get_u32(ctx->target, buf);\r
533                 arm_evaluate_opcode(opcode, ctx->current_pc, instruction);\r
534         }\r
535         else if (ctx->core_state == ARMV4_5_STATE_THUMB)\r
536         {\r
537                 u8 buf[2];\r
538                 if ((retval = image_read_section(ctx->image, section, \r
539                         ctx->current_pc - ctx->image->sections[section].base_address,\r
540                         2, buf, &size_read)) != ERROR_OK)\r
541                 {\r
542                         ERROR("error while reading instruction: %i", retval);\r
543                         return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
544                 }\r
545                 opcode = target_buffer_get_u16(ctx->target, buf);\r
546                 thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);\r
547         }\r
548         else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)\r
549         {\r
550                 ERROR("BUG: tracing of jazelle code not supported");\r
551                 exit(-1);\r
552         }\r
553         else\r
554         {\r
555                 ERROR("BUG: unknown core state encountered");\r
556                 exit(-1);\r
557         }\r
558         \r
559         return ERROR_OK;\r
560 }\r
561 \r
562 int etmv1_next_packet(etm_context_t *ctx, u8 *packet, int apo)\r
563 {\r
564         while (ctx->data_index < ctx->trace_depth)\r
565         {\r
566                 /* if the caller specified an address packet offset, skip until the\r
567                  * we reach the n-th cycle marked with tracesync */\r
568                 if (apo > 0)\r
569                 {\r
570                         if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE)\r
571                                 apo--;\r
572                         \r
573                         if (apo > 0)\r
574                         {\r
575                                 ctx->data_index++;\r
576                                 ctx->data_half = 0;\r
577                         }\r
578                         continue;\r
579                 }\r
580                 \r
581                 /* no tracedata output during a TD cycle\r
582                  * or in a trigger cycle */\r
583                 if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD)\r
584                         || (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE))\r
585                 {\r
586                         ctx->data_index++;\r
587                         ctx->data_half = 0;\r
588                         continue;\r
589                 }\r
590                 \r
591                 if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT)\r
592                 {\r
593                         if (ctx->data_half == 0)\r
594                         {\r
595                                 *packet = ctx->trace_data[ctx->data_index].packet & 0xff;\r
596                                 ctx->data_half = 1;\r
597                         }\r
598                         else\r
599                         {\r
600                                 *packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8;\r
601                                 ctx->data_half = 0;\r
602                                 ctx->data_index++;\r
603                         }\r
604                 }\r
605                 else if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)\r
606                 {\r
607                         *packet = ctx->trace_data[ctx->data_index].packet & 0xff;\r
608                         ctx->data_index++;\r
609                 }\r
610                 else\r
611                 {\r
612                         /* on a 4-bit port, a packet will be output during two consecutive cycles */\r
613                         if (ctx->data_index > (ctx->trace_depth - 2))\r
614                                 return -1;\r
615                         \r
616                         *packet = ctx->trace_data[ctx->data_index].packet & 0xf;\r
617                         *packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4;\r
618                         ctx->data_index += 2;\r
619                 }\r
620                                         \r
621                 return 0;\r
622         }\r
623         \r
624         return -1;\r
625 }\r
626 \r
627 int etmv1_branch_address(etm_context_t *ctx)\r
628 {\r
629         int retval;\r
630         u8 packet;\r
631         int shift = 0;\r
632         int apo;\r
633         int i;\r
634         \r
635         /* quit analysis if less than two cycles are left in the trace\r
636          * because we can't extract the APO */\r
637         if (ctx->data_index > (ctx->trace_depth - 2))\r
638                 return -1;\r
639                 \r
640         /* a BE could be output during an APO cycle, skip the current\r
641          * and continue with the new one */\r
642         if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4)\r
643                 return 1;\r
644         if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4)\r
645                 return 2;\r
646                 \r
647         /* address packet offset encoded in the next two cycles' pipestat bits */\r
648         apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3;\r
649         apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2;\r
650         \r
651         /* count number of tracesync cycles between current pipe_index and data_index\r
652          * i.e. the number of tracesyncs that data_index already passed by\r
653          * to subtract them from the APO */\r
654         for (i = ctx->pipe_index; i < ctx->data_index; i++)\r
655         {\r
656                 if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE)\r
657                         apo--;\r
658         }\r
659         \r
660         /* extract up to four 7-bit packets */\r
661         do {\r
662                 if ((retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0)) != 0)\r
663                         return -1;\r
664                 ctx->last_branch &= ~(0x7f << shift);\r
665                 ctx->last_branch |= (packet & 0x7f) << shift;\r
666                 shift += 7;\r
667         } while ((packet & 0x80) && (shift < 28));\r
668         \r
669         /* one last packet holding 4 bits of the address, plus the branch reason code */\r
670         if ((shift == 28) && (packet & 0x80))\r
671         {\r
672                 if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)\r
673                         return -1;\r
674                 ctx->last_branch &= 0x0fffffff;\r
675                 ctx->last_branch |= (packet & 0x0f) << 28;\r
676                 ctx->last_branch_reason = (packet & 0x70) >> 4;\r
677                 shift += 4;\r
678         }\r
679         else\r
680         {\r
681                 ctx->last_branch_reason = 0;\r
682         }\r
683         \r
684         if (shift == 32)\r
685         {\r
686                 ctx->pc_ok = 1;\r
687         }\r
688         \r
689         /* if a full address was output, we might have branched into Jazelle state */\r
690         if ((shift == 32) && (packet & 0x80))\r
691         {\r
692                 ctx->core_state = ARMV4_5_STATE_JAZELLE;\r
693         }\r
694         else\r
695         {\r
696                 /* if we didn't branch into Jazelle state, the current processor state is\r
697                  * encoded in bit 0 of the branch target address */\r
698                 if (ctx->last_branch & 0x1)\r
699                 {\r
700                         ctx->core_state = ARMV4_5_STATE_THUMB;\r
701                         ctx->last_branch &= ~0x1;\r
702                 }\r
703                 else\r
704                 {\r
705                         ctx->core_state = ARMV4_5_STATE_ARM;\r
706                         ctx->last_branch &= ~0x3;\r
707                 }\r
708         }\r
709         \r
710         return 0;\r
711 }\r
712 \r
713 int etmv1_data(etm_context_t *ctx, int size, u32 *data)\r
714 {\r
715         int j;\r
716         u8 buf[4];\r
717         int retval;\r
718         \r
719         for (j = 0; j < size; j++)\r
720         {\r
721                 if ((retval = etmv1_next_packet(ctx, &buf[j], 0)) != 0)\r
722                         return -1;\r
723         }\r
724         \r
725         if (size == 8)\r
726                 ERROR("TODO: add support for 64-bit values");\r
727         else if (size == 4)\r
728                 *data = target_buffer_get_u32(ctx->target, buf);\r
729         else if (size == 2)\r
730                 *data = target_buffer_get_u16(ctx->target, buf);\r
731         else if (size == 1)\r
732                 *data = buf[0];\r
733                 \r
734         return 0;\r
735 }\r
736 \r
737 int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)\r
738 {\r
739         int retval;\r
740         arm_instruction_t instruction;\r
741         \r
742         /* read the trace data if it wasn't read already */\r
743         if (ctx->trace_depth == 0)\r
744                 ctx->capture_driver->read_trace(ctx);\r
745         \r
746         /* start at the beginning of the captured trace */\r
747         ctx->pipe_index = 0;\r
748         ctx->data_index = 0;\r
749         ctx->data_half = 0;\r
750 \r
751         /* neither the PC nor the data pointer are valid */     \r
752         ctx->pc_ok = 0;\r
753         ctx->ptr_ok = 0;\r
754         \r
755         while (ctx->pipe_index < ctx->trace_depth)\r
756         {\r
757                 u8 pipestat = ctx->trace_data[ctx->pipe_index].pipestat;\r
758                 u32 next_pc = ctx->current_pc;\r
759                 u32 old_data_index = ctx->data_index;\r
760                 u32 old_data_half = ctx->data_half;\r
761                 u32 old_index = ctx->pipe_index;\r
762                 u32 last_instruction = ctx->last_instruction;\r
763                 u32 cycles = 0;\r
764                 int current_pc_ok = ctx->pc_ok;\r
765                 \r
766                 if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)\r
767                 {\r
768                         command_print(cmd_ctx, "--- trigger ---");\r
769                 }\r
770 \r
771                 /* instructions execute in IE/D or BE/D cycles */\r
772                 if ((pipestat == STAT_IE) || (pipestat == STAT_ID))\r
773                         ctx->last_instruction = ctx->pipe_index;\r
774                 \r
775                 /* if we don't have a valid pc skip until we reach an indirect branch */\r
776                 if ((!ctx->pc_ok) && (pipestat != STAT_BE))\r
777                 {\r
778                         ctx->pipe_index++;\r
779                         continue;\r
780                 }\r
781                 \r
782                 /* any indirect branch could have interrupted instruction flow\r
783                  * - the branch reason code could indicate a trace discontinuity\r
784                  * - a branch to the exception vectors indicates an exception\r
785                  */\r
786                 if ((pipestat == STAT_BE) || (pipestat == STAT_BD))\r
787                 {\r
788                         /* backup current data index, to be able to consume the branch address\r
789                          * before examining data address and values\r
790                          */\r
791                         old_data_index = ctx->data_index;\r
792                         old_data_half = ctx->data_half;\r
793 \r
794                         ctx->last_instruction = ctx->pipe_index;\r
795                         \r
796                         if ((retval = etmv1_branch_address(ctx)) != 0)\r
797                         {\r
798                                 /* negative return value from etmv1_branch_address means we ran out of packets,\r
799                                  * quit analysing the trace */\r
800                                 if (retval < 0)\r
801                                         break;\r
802                                 \r
803                                 /* a positive return values means the current branch was abandoned,\r
804                                  * and a new branch was encountered in cycle ctx->pipe_index + retval;\r
805                                  */\r
806                                 WARNING("abandoned branch encountered, correctnes of analysis uncertain");\r
807                                 ctx->pipe_index += retval;\r
808                                 continue;\r
809                         }\r
810                         \r
811                         /* skip over APO cycles */\r
812                         ctx->pipe_index += 2;\r
813                         \r
814                         switch (ctx->last_branch_reason)\r
815                         {\r
816                                 case 0x0:       /* normal PC change */\r
817                                         next_pc = ctx->last_branch;\r
818                                         break;\r
819                                 case 0x1:       /* tracing enabled */\r
820                                         command_print(cmd_ctx, "--- tracing enabled at 0x%8.8x ---", ctx->last_branch);\r
821                                         ctx->current_pc = ctx->last_branch;\r
822                                         ctx->pipe_index++;\r
823                                         continue;\r
824                                         break;\r
825                                 case 0x2:       /* trace restarted after FIFO overflow */\r
826                                         command_print(cmd_ctx, "--- trace restarted after FIFO overflow at 0x%8.8x ---", ctx->last_branch);\r
827                                         ctx->current_pc = ctx->last_branch;\r
828                                         ctx->pipe_index++;\r
829                                         continue;\r
830                                         break;\r
831                                 case 0x3:       /* exit from debug state */\r
832                                         command_print(cmd_ctx, "--- exit from debug state at 0x%8.8x ---", ctx->last_branch);\r
833                                         ctx->current_pc = ctx->last_branch;\r
834                                         ctx->pipe_index++;\r
835                                         continue;\r
836                                         break;\r
837                                 case 0x4:       /* periodic synchronization point */\r
838                                         next_pc = ctx->last_branch;\r
839                                         /* if we had no valid PC prior to this synchronization point,\r
840                                          * we have to move on with the next trace cycle\r
841                                          */\r
842                                         if (!current_pc_ok)\r
843                                         {\r
844                                                 command_print(cmd_ctx, "--- periodic synchronization point at 0x%8.8x ---", next_pc);\r
845                                                 ctx->current_pc = next_pc;\r
846                                                 ctx->pipe_index++;\r
847                                                 continue;\r
848                                         }\r
849                                         break;\r
850                                 default:        /* reserved */\r
851                                         ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);             \r
852                                         exit(-1);\r
853                                         break;\r
854                         }\r
855                         \r
856                         /* if we got here the branch was a normal PC change\r
857                          * (or a periodic synchronization point, which means the same for that matter)\r
858                          * if we didn't accquire a complete PC continue with the next cycle\r
859                          */\r
860                         if (!ctx->pc_ok)\r
861                                 continue;\r
862                         \r
863                         /* indirect branch to the exception vector means an exception occured */\r
864                         if (((ctx->last_branch >= 0x0) && (ctx->last_branch <= 0x20))\r
865                                 || ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020)))\r
866                         {\r
867                                 if ((ctx->last_branch & 0xff) == 0x10)\r
868                                 {\r
869                                         command_print(cmd_ctx, "data abort");\r
870                                 }\r
871                                 else\r
872                                 {\r
873                                         command_print(cmd_ctx, "exception vector 0x%2.2x", ctx->last_branch);\r
874                                         ctx->current_pc = ctx->last_branch;\r
875                                         ctx->pipe_index++;\r
876                                         continue;\r
877                                 }\r
878                         }\r
879                 }\r
880                 \r
881                 /* an instruction was executed (or not, depending on the condition flags)\r
882                  * retrieve it from the image for displaying */\r
883                 if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) &&\r
884                         !(((pipestat == STAT_BE) || (pipestat == STAT_BD)) &&\r
885                                 ((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4))))  \r
886                 {\r
887                         if ((retval = etm_read_instruction(ctx, &instruction)) != ERROR_OK)\r
888                         {\r
889                                 /* can't continue tracing with no image available */\r
890                                 if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)\r
891                                 {\r
892                                         return retval;\r
893                                 }\r
894                                 else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)\r
895                                 {\r
896                                         /* TODO: handle incomplete images \r
897                                          * for now we just quit the analsysis*/\r
898                                         return retval;\r
899                                 }\r
900                         }\r
901                         \r
902                         cycles = old_index - last_instruction;\r
903                 }\r
904                 \r
905                 if ((pipestat == STAT_ID) || (pipestat == STAT_BD))\r
906                 {\r
907                         u32 new_data_index = ctx->data_index;\r
908                         u32 new_data_half = ctx->data_half;\r
909                         \r
910                         /* in case of a branch with data, the branch target address was consumed before\r
911                          * we temporarily go back to the saved data index */\r
912                         if (pipestat == STAT_BD)\r
913                         {\r
914                                 ctx->data_index = old_data_index;\r
915                                 ctx->data_half = old_data_half;\r
916                         }\r
917                         \r
918                         if (ctx->tracemode & ETMV1_TRACE_ADDR)\r
919                         {                       \r
920                                 u8 packet;\r
921                                 int shift = 0;\r
922                                 \r
923                                 do {\r
924                                         if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)\r
925                                                 return ERROR_ETM_ANALYSIS_FAILED;\r
926                                         ctx->last_ptr &= ~(0x7f << shift);\r
927                                         ctx->last_ptr |= (packet & 0x7f) << shift;\r
928                                         shift += 7;\r
929                                 } while ((packet & 0x80) && (shift < 32));\r
930                                 \r
931                                 if (shift >= 32)\r
932                                         ctx->ptr_ok = 1;\r
933                                 \r
934                                 if (ctx->ptr_ok)\r
935                                 {\r
936                                         command_print(cmd_ctx, "address: 0x%8.8x", ctx->last_ptr);\r
937                                 }\r
938                         }\r
939                         \r
940                         if (ctx->tracemode & ETMV1_TRACE_DATA)\r
941                         {\r
942                                 if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM))\r
943                                 {\r
944                                         int i;\r
945                                         for (i = 0; i < 16; i++)\r
946                                         {\r
947                                                 if (instruction.info.load_store_multiple.register_list & (1 << i))\r
948                                                 {\r
949                                                         u32 data;\r
950                                                         if (etmv1_data(ctx, 4, &data) != 0)\r
951                                                                 return ERROR_ETM_ANALYSIS_FAILED;\r
952                                                         command_print(cmd_ctx, "data: 0x%8.8x", data);\r
953                                                 }\r
954                                         }\r
955                                 }\r
956                                 else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_STRH))\r
957                                 {\r
958                                         u32 data;\r
959                                         if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0)\r
960                                                 return ERROR_ETM_ANALYSIS_FAILED;\r
961                                         command_print(cmd_ctx, "data: 0x%8.8x", data);\r
962                                 }\r
963                         }\r
964                         \r
965                         /* restore data index after consuming BD address and data */\r
966                         if (pipestat == STAT_BD)\r
967                         {\r
968                                 ctx->data_index = new_data_index;\r
969                                 ctx->data_half = new_data_half;\r
970                         }\r
971                 }\r
972                 \r
973                 /* adjust PC */\r
974                 if ((pipestat == STAT_IE) || (pipestat == STAT_ID))\r
975                 {\r
976                         if (((instruction.type == ARM_B) ||\r
977                                 (instruction.type == ARM_BL) ||\r
978                                 (instruction.type == ARM_BLX)) &&\r
979                                 (instruction.info.b_bl_bx_blx.target_address != -1))\r
980                         {\r
981                                 next_pc = instruction.info.b_bl_bx_blx.target_address;\r
982                         }\r
983                         else\r
984                         {\r
985                                 next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;\r
986                         }\r
987                 }\r
988                 else if (pipestat == STAT_IN)\r
989                 {\r
990                         next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;\r
991                 }\r
992 \r
993                 if ((pipestat != STAT_TD) && (pipestat != STAT_WT))\r
994                 {\r
995                         char cycles_text[32] = "";\r
996                         \r
997                         /* if the trace was captured with cycle accurate tracing enabled,\r
998                          * output the number of cycles since the last executed instruction\r
999                          */\r
1000                         if (ctx->tracemode & ETMV1_CYCLE_ACCURATE)\r
1001                         {\r
1002                                 snprintf(cycles_text, 32, " (%i %s)",\r
1003                                         cycles,\r
1004                                         (cycles == 1) ? "cycle" : "cycles");\r
1005                         }\r
1006                         \r
1007                         command_print(cmd_ctx, "%s%s%s",\r
1008                                 instruction.text,\r
1009                                 (pipestat == STAT_IN) ? " (not executed)" : "",\r
1010                                 cycles_text);\r
1011 \r
1012                         ctx->current_pc = next_pc;\r
1013                         \r
1014                         /* packets for an instruction don't start on or before the preceding\r
1015                          * functional pipestat (i.e. other than WT or TD)\r
1016                          */\r
1017                         if (ctx->data_index <= ctx->pipe_index)\r
1018                         {\r
1019                                 ctx->data_index = ctx->pipe_index + 1;\r
1020                                 ctx->data_half = 0;\r
1021                         }\r
1022                 }\r
1023                 \r
1024                 ctx->pipe_index += 1;\r
1025         }\r
1026         \r
1027         return ERROR_OK;\r
1028 }\r
1029 \r
1030 int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1031 {\r
1032         target_t *target;\r
1033         armv4_5_common_t *armv4_5;\r
1034         arm7_9_common_t *arm7_9;\r
1035         etmv1_tracemode_t tracemode;\r
1036         \r
1037         target = get_current_target(cmd_ctx);\r
1038         \r
1039         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1040         {\r
1041                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1042                 return ERROR_OK;\r
1043         }\r
1044         \r
1045         if (!arm7_9->etm_ctx)\r
1046         {\r
1047                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1048                 return ERROR_OK;\r
1049         }\r
1050         \r
1051         tracemode = arm7_9->etm_ctx->tracemode;\r
1052 \r
1053         if (argc == 4)\r
1054         {\r
1055                 if (strcmp(args[0], "none") == 0)\r
1056                 {\r
1057                         tracemode = ETMV1_TRACE_NONE;\r
1058                 }\r
1059                 else if (strcmp(args[0], "data") == 0)\r
1060                 {\r
1061                         tracemode = ETMV1_TRACE_DATA;\r
1062                 }\r
1063                 else if (strcmp(args[0], "address") == 0)\r
1064                 {\r
1065                         tracemode = ETMV1_TRACE_ADDR;\r
1066                 }\r
1067                 else if (strcmp(args[0], "all") == 0)\r
1068                 {\r
1069                         tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;\r
1070                 }\r
1071                 else\r
1072                 {\r
1073                         command_print(cmd_ctx, "invalid option '%s'", args[0]);\r
1074                         return ERROR_OK;\r
1075                 }\r
1076                 \r
1077                 switch (strtol(args[1], NULL, 0))\r
1078                 {\r
1079                         case 0:\r
1080                                 tracemode |= ETMV1_CONTEXTID_NONE;\r
1081                                 break;\r
1082                         case 8:\r
1083                                 tracemode |= ETMV1_CONTEXTID_8;\r
1084                                 break;\r
1085                         case 16:\r
1086                                 tracemode |= ETMV1_CONTEXTID_16;\r
1087                                 break;\r
1088                         case 32:\r
1089                                 tracemode |= ETMV1_CONTEXTID_32;\r
1090                                 break;\r
1091                         default:\r
1092                                 command_print(cmd_ctx, "invalid option '%s'", args[1]);\r
1093                                 return ERROR_OK;\r
1094                 }\r
1095                 \r
1096                 if (strcmp(args[2], "enable") == 0)\r
1097                 {\r
1098                         tracemode |= ETMV1_CYCLE_ACCURATE;\r
1099                 }\r
1100                 else if (strcmp(args[2], "disable") == 0)\r
1101                 {\r
1102                         tracemode |= 0;\r
1103                 }\r
1104                 else\r
1105                 {\r
1106                         command_print(cmd_ctx, "invalid option '%s'", args[2]);\r
1107                         return ERROR_OK;\r
1108                 }\r
1109                 \r
1110                 if (strcmp(args[3], "enable") == 0)\r
1111                 {\r
1112                         tracemode |= ETMV1_BRANCH_OUTPUT;\r
1113                 }\r
1114                 else if (strcmp(args[3], "disable") == 0)\r
1115                 {\r
1116                         tracemode |= 0;\r
1117                 }\r
1118                 else\r
1119                 {\r
1120                         command_print(cmd_ctx, "invalid option '%s'", args[2]);\r
1121                         return ERROR_OK;\r
1122                 }\r
1123         }\r
1124         else if (argc != 0)\r
1125         {\r
1126                 command_print(cmd_ctx, "usage: configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output>");\r
1127                 return ERROR_OK;\r
1128         }\r
1129         \r
1130         command_print(cmd_ctx, "current tracemode configuration:");\r
1131         \r
1132         switch (tracemode & ETMV1_TRACE_MASK)\r
1133         {\r
1134                 case ETMV1_TRACE_NONE:\r
1135                         command_print(cmd_ctx, "data tracing: none");\r
1136                         break;\r
1137                 case ETMV1_TRACE_DATA:\r
1138                         command_print(cmd_ctx, "data tracing: data only");\r
1139                         break;\r
1140                 case ETMV1_TRACE_ADDR:\r
1141                         command_print(cmd_ctx, "data tracing: address only");\r
1142                         break;\r
1143                 case ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR:\r
1144                         command_print(cmd_ctx, "data tracing: address and data");\r
1145                         break;\r
1146         }\r
1147         \r
1148         switch (tracemode & ETMV1_CONTEXTID_MASK)\r
1149         {\r
1150                 case ETMV1_CONTEXTID_NONE:\r
1151                         command_print(cmd_ctx, "contextid tracing: none");\r
1152                         break;\r
1153                 case ETMV1_CONTEXTID_8:\r
1154                         command_print(cmd_ctx, "contextid tracing: 8 bit");\r
1155                         break;\r
1156                 case ETMV1_CONTEXTID_16:\r
1157                         command_print(cmd_ctx, "contextid tracing: 16 bit");\r
1158                         break;\r
1159                 case ETMV1_CONTEXTID_32:\r
1160                         command_print(cmd_ctx, "contextid tracing: 32 bit");\r
1161                         break;\r
1162         }\r
1163         \r
1164         if (tracemode & ETMV1_CYCLE_ACCURATE)\r
1165         {\r
1166                 command_print(cmd_ctx, "cycle-accurate tracing enabled");\r
1167         }\r
1168         else\r
1169         {\r
1170                 command_print(cmd_ctx, "cycle-accurate tracing disabled");\r
1171         }\r
1172 \r
1173         if (tracemode & ETMV1_BRANCH_OUTPUT)\r
1174         {\r
1175                 command_print(cmd_ctx, "full branch address output enabled");\r
1176         }\r
1177         else\r
1178         {\r
1179                 command_print(cmd_ctx, "full branch address output disabled");\r
1180         }\r
1181         \r
1182         /* only update ETM_CTRL register if tracemode changed */\r
1183         if (arm7_9->etm_ctx->tracemode != tracemode)\r
1184         {\r
1185                 reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];\r
1186                 \r
1187                 etm_get_reg(etm_ctrl_reg);\r
1188                 \r
1189                 buf_set_u32(etm_ctrl_reg->value, 2, 2, tracemode & ETMV1_TRACE_MASK);\r
1190                 buf_set_u32(etm_ctrl_reg->value, 14, 2, (tracemode & ETMV1_CONTEXTID_MASK) >> 4);\r
1191                 buf_set_u32(etm_ctrl_reg->value, 12, 1, (tracemode & ETMV1_CYCLE_ACCURATE) >> 8);\r
1192                 buf_set_u32(etm_ctrl_reg->value, 8, 1, (tracemode & ETMV1_BRANCH_OUTPUT) >> 9);\r
1193                 etm_store_reg(etm_ctrl_reg);\r
1194                 \r
1195                 arm7_9->etm_ctx->tracemode = tracemode;\r
1196                 \r
1197                 /* invalidate old trace data */\r
1198                 arm7_9->etm_ctx->capture_status = TRACE_IDLE;\r
1199                 if (arm7_9->etm_ctx->trace_depth > 0)\r
1200                 {\r
1201                         free(arm7_9->etm_ctx->trace_data);\r
1202                         arm7_9->etm_ctx->trace_data = NULL;\r
1203                 }\r
1204                 arm7_9->etm_ctx->trace_depth = 0;\r
1205         }\r
1206         \r
1207         return ERROR_OK;\r
1208 }\r
1209 \r
1210 int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1211 {\r
1212         target_t *target;\r
1213         armv4_5_common_t *armv4_5;\r
1214         arm7_9_common_t *arm7_9;\r
1215         etm_portmode_t portmode = 0x0;\r
1216         etm_context_t *etm_ctx = malloc(sizeof(etm_context_t));\r
1217         int i;\r
1218         \r
1219         if (argc != 5)\r
1220         {\r
1221                 ERROR("incomplete 'etm config <target> <port_width> <port_mode> <clocking> <capture_driver>' command");\r
1222                 exit(-1);\r
1223         }\r
1224         \r
1225         target = get_target_by_num(strtoul(args[0], NULL, 0));\r
1226         \r
1227         if (!target)\r
1228         {\r
1229                 ERROR("target number '%s' not defined", args[0]);\r
1230                 exit(-1);\r
1231         }\r
1232         \r
1233         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1234         {\r
1235                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1236                 return ERROR_OK;\r
1237         }\r
1238         \r
1239         switch (strtoul(args[1], NULL, 0))\r
1240         {\r
1241                 case 4:\r
1242                         portmode |= ETM_PORT_4BIT;\r
1243                         break;\r
1244                 case 8:\r
1245                         portmode |= ETM_PORT_8BIT;\r
1246                         break;\r
1247                 case 16:\r
1248                         portmode |= ETM_PORT_16BIT;\r
1249                         break;\r
1250                 default:\r
1251                         command_print(cmd_ctx, "unsupported ETM port width '%s', must be 4, 8 or 16", args[1]);\r
1252                         return ERROR_OK;\r
1253         }\r
1254         \r
1255         if (strcmp("normal", args[2]) == 0)\r
1256         {\r
1257                 portmode |= ETM_PORT_NORMAL;\r
1258         }\r
1259         else if (strcmp("multiplexed", args[2]) == 0)\r
1260         {\r
1261                 portmode |= ETM_PORT_MUXED;\r
1262         }\r
1263         else if (strcmp("demultiplexed", args[2]) == 0)\r
1264         {\r
1265                 portmode |= ETM_PORT_DEMUXED;\r
1266         }\r
1267         else\r
1268         {\r
1269                 command_print(cmd_ctx, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", args[2]);\r
1270                 return ERROR_OK;\r
1271         }\r
1272         \r
1273         if (strcmp("half", args[3]) == 0)\r
1274         {\r
1275                 portmode |= ETM_PORT_HALF_CLOCK;\r
1276         }\r
1277         else if (strcmp("full", args[3]) == 0)\r
1278         {\r
1279                 portmode |= ETM_PORT_FULL_CLOCK;\r
1280         }\r
1281         else\r
1282         {\r
1283                 command_print(cmd_ctx, "unsupported ETM port clocking '%s', must be 'full' or 'half'", args[3]);\r
1284                 return ERROR_OK;\r
1285         }\r
1286         \r
1287         for (i=0; etm_capture_drivers[i]; i++)\r
1288         {\r
1289                 if (strcmp(args[4], etm_capture_drivers[i]->name) == 0)\r
1290                 {\r
1291                         if (etm_capture_drivers[i]->register_commands(cmd_ctx) != ERROR_OK)\r
1292                         {\r
1293                                 free(etm_ctx);\r
1294                                 exit(-1);\r
1295                         }\r
1296                 \r
1297                         etm_ctx->capture_driver = etm_capture_drivers[i];\r
1298 \r
1299                         break;\r
1300                 }\r
1301         }\r
1302         \r
1303         if (!etm_capture_drivers[i])\r
1304         {\r
1305                 /* no supported capture driver found, don't register an ETM */\r
1306                 free(etm_ctx);\r
1307                 ERROR("trace capture driver '%s' not found", args[4]);\r
1308                 return ERROR_OK;\r
1309         }\r
1310         \r
1311         etm_ctx->target = target;\r
1312         etm_ctx->trigger_percent = 50;\r
1313         etm_ctx->trace_data = NULL;\r
1314         etm_ctx->trace_depth = 0;\r
1315         etm_ctx->portmode = portmode;\r
1316         etm_ctx->tracemode = 0x0;\r
1317         etm_ctx->core_state = ARMV4_5_STATE_ARM;\r
1318         etm_ctx->image = NULL;\r
1319         etm_ctx->pipe_index = 0;\r
1320         etm_ctx->data_index = 0;\r
1321         etm_ctx->current_pc = 0x0;\r
1322         etm_ctx->pc_ok = 0;\r
1323         etm_ctx->last_branch = 0x0;\r
1324         etm_ctx->last_branch_reason = 0x0;\r
1325         etm_ctx->last_ptr = 0x0;\r
1326         etm_ctx->ptr_ok = 0x0;\r
1327         etm_ctx->context_id = 0x0;\r
1328         etm_ctx->last_instruction = 0;\r
1329         \r
1330         arm7_9->etm_ctx = etm_ctx;\r
1331         \r
1332         etm_register_user_commands(cmd_ctx);\r
1333         \r
1334         return ERROR_OK;\r
1335 }\r
1336 \r
1337 int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1338 {\r
1339         target_t *target;\r
1340         armv4_5_common_t *armv4_5;\r
1341         arm7_9_common_t *arm7_9;\r
1342         reg_t *etm_config_reg;\r
1343         reg_t *etm_sys_config_reg;\r
1344         \r
1345         int max_port_size;\r
1346                 \r
1347         target = get_current_target(cmd_ctx);\r
1348         \r
1349         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1350         {\r
1351                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1352                 return ERROR_OK;\r
1353         }\r
1354         \r
1355         if (!arm7_9->etm_ctx)\r
1356         {\r
1357                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1358                 return ERROR_OK;\r
1359         }\r
1360         \r
1361         etm_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CONFIG];\r
1362         etm_sys_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_SYS_CONFIG];\r
1363         \r
1364         etm_get_reg(etm_config_reg);\r
1365         command_print(cmd_ctx, "pairs of address comparators: %i", buf_get_u32(etm_config_reg->value, 0, 4));\r
1366         command_print(cmd_ctx, "pairs of data comparators: %i", buf_get_u32(etm_config_reg->value, 4, 4));\r
1367         command_print(cmd_ctx, "memory map decoders: %i", buf_get_u32(etm_config_reg->value, 8, 5));\r
1368         command_print(cmd_ctx, "number of counters: %i", buf_get_u32(etm_config_reg->value, 13, 3));\r
1369         command_print(cmd_ctx, "sequencer %spresent",\r
1370                         (buf_get_u32(etm_config_reg->value, 16, 1) == 1) ? "" : "not ");\r
1371         command_print(cmd_ctx, "number of ext. inputs: %i", buf_get_u32(etm_config_reg->value, 17, 3));\r
1372         command_print(cmd_ctx, "number of ext. outputs: %i", buf_get_u32(etm_config_reg->value, 20, 3));\r
1373         command_print(cmd_ctx, "FIFO full %spresent",\r
1374                         (buf_get_u32(etm_config_reg->value, 23, 1) == 1) ? "" : "not ");\r
1375         command_print(cmd_ctx, "protocol version: %i", buf_get_u32(etm_config_reg->value, 28, 3));\r
1376         \r
1377         etm_get_reg(etm_sys_config_reg);\r
1378 \r
1379         switch (buf_get_u32(etm_sys_config_reg->value, 0, 3))\r
1380         {\r
1381                 case 0:\r
1382                         max_port_size = 4;\r
1383                         break;\r
1384                 case 1:\r
1385                         max_port_size = 8;\r
1386                         break;\r
1387                 case 2:\r
1388                         max_port_size = 16;\r
1389                         break;\r
1390         }\r
1391         command_print(cmd_ctx, "max. port size: %i", max_port_size);\r
1392         \r
1393         command_print(cmd_ctx, "half-rate clocking %ssupported",\r
1394                         (buf_get_u32(etm_sys_config_reg->value, 3, 1) == 1) ? "" : "not ");\r
1395         command_print(cmd_ctx, "full-rate clocking %ssupported",\r
1396                         (buf_get_u32(etm_sys_config_reg->value, 4, 1) == 1) ? "" : "not ");\r
1397         command_print(cmd_ctx, "normal trace format %ssupported",\r
1398                         (buf_get_u32(etm_sys_config_reg->value, 5, 1) == 1) ? "" : "not ");\r
1399         command_print(cmd_ctx, "multiplex trace format %ssupported",\r
1400                         (buf_get_u32(etm_sys_config_reg->value, 6, 1) == 1) ? "" : "not ");\r
1401         command_print(cmd_ctx, "demultiplex trace format %ssupported",\r
1402                         (buf_get_u32(etm_sys_config_reg->value, 7, 1) == 1) ? "" : "not ");\r
1403         command_print(cmd_ctx, "FIFO full %ssupported",\r
1404                         (buf_get_u32(etm_sys_config_reg->value, 8, 1) == 1) ? "" : "not ");\r
1405         \r
1406         return ERROR_OK;\r
1407 }\r
1408 \r
1409 int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1410 {\r
1411         target_t *target;\r
1412         armv4_5_common_t *armv4_5;\r
1413         arm7_9_common_t *arm7_9;\r
1414         trace_status_t trace_status;\r
1415         \r
1416         target = get_current_target(cmd_ctx);\r
1417         \r
1418         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1419         {\r
1420                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1421                 return ERROR_OK;\r
1422         }\r
1423         \r
1424         if (!arm7_9->etm_ctx)\r
1425         {\r
1426                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1427                 return ERROR_OK;\r
1428         }\r
1429         \r
1430         trace_status = arm7_9->etm_ctx->capture_driver->status(arm7_9->etm_ctx);\r
1431         \r
1432         if (trace_status == TRACE_IDLE)\r
1433         {\r
1434                 command_print(cmd_ctx, "tracing is idle");\r
1435         }\r
1436         else\r
1437         {\r
1438                 static char *completed = " completed";\r
1439                 static char *running = " is running";\r
1440                 static char *overflowed = ", trace overflowed";\r
1441                 static char *triggered = ", trace triggered";\r
1442                 \r
1443                 command_print(cmd_ctx, "trace collection%s%s%s", \r
1444                         (trace_status & TRACE_RUNNING) ? running : completed,\r
1445                         (trace_status & TRACE_OVERFLOWED) ? overflowed : "",\r
1446                         (trace_status & TRACE_TRIGGERED) ? triggered : "");\r
1447                 \r
1448                 if (arm7_9->etm_ctx->trace_depth > 0)\r
1449                 {\r
1450                         command_print(cmd_ctx, "%i frames of trace data read", arm7_9->etm_ctx->trace_depth);\r
1451                 }\r
1452         }\r
1453         \r
1454         return ERROR_OK;\r
1455 }\r
1456 \r
1457 int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1458 {\r
1459         target_t *target;\r
1460         armv4_5_common_t *armv4_5;\r
1461         arm7_9_common_t *arm7_9;\r
1462         etm_context_t *etm_ctx;\r
1463 \r
1464         if (argc < 1)\r
1465         {\r
1466                 command_print(cmd_ctx, "usage: etm image <file> [base address] [type]");\r
1467                 return ERROR_OK;\r
1468         }\r
1469         \r
1470         target = get_current_target(cmd_ctx);\r
1471         \r
1472         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1473         {\r
1474                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1475                 return ERROR_OK;\r
1476         }\r
1477         \r
1478         if (!(etm_ctx = arm7_9->etm_ctx))\r
1479         {\r
1480                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1481                 return ERROR_OK;\r
1482         }\r
1483         \r
1484         if (etm_ctx->image)\r
1485         {\r
1486                 image_close(etm_ctx->image);\r
1487                 free(etm_ctx->image);\r
1488                 command_print(cmd_ctx, "previously loaded image found and closed");\r
1489         }\r
1490         \r
1491         etm_ctx->image = malloc(sizeof(image_t));\r
1492         etm_ctx->image->base_address_set = 0;\r
1493         etm_ctx->image->start_address_set = 0;\r
1494         \r
1495         /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */\r
1496         if (argc >= 2)\r
1497         {\r
1498                 etm_ctx->image->base_address_set = 1;\r
1499                 etm_ctx->image->base_address = strtoul(args[1], NULL, 0);\r
1500         }\r
1501         else\r
1502         {\r
1503                 etm_ctx->image->base_address_set = 0;\r
1504         }\r
1505                 \r
1506         if (image_open(etm_ctx->image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)\r
1507         {\r
1508                 command_print(cmd_ctx, "image opening error: %s", etm_ctx->image->error_str);\r
1509                 free(etm_ctx->image);\r
1510                 etm_ctx->image = NULL;\r
1511                 return ERROR_OK;\r
1512         }\r
1513         \r
1514         return ERROR_OK;\r
1515 }\r
1516 \r
1517 int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1518 {\r
1519         fileio_t file;\r
1520         target_t *target;\r
1521         armv4_5_common_t *armv4_5;\r
1522         arm7_9_common_t *arm7_9;\r
1523         etm_context_t *etm_ctx;\r
1524         int i;\r
1525         \r
1526         if (argc != 1)\r
1527         {\r
1528                 command_print(cmd_ctx, "usage: etm dump <file>");\r
1529                 return ERROR_OK;\r
1530         }\r
1531         \r
1532         target = get_current_target(cmd_ctx);\r
1533         \r
1534         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1535         {\r
1536                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1537                 return ERROR_OK;\r
1538         }\r
1539         \r
1540         if (!(etm_ctx = arm7_9->etm_ctx))\r
1541         {\r
1542                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1543                 return ERROR_OK;\r
1544         }\r
1545         \r
1546         if (etm_ctx->capture_driver->status == TRACE_IDLE)\r
1547         {\r
1548                 command_print(cmd_ctx, "trace capture wasn't enabled, no trace data captured");\r
1549                 return ERROR_OK;\r
1550         }\r
1551 \r
1552         if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)\r
1553         {\r
1554                 /* TODO: if on-the-fly capture is to be supported, this needs to be changed */\r
1555                 command_print(cmd_ctx, "trace capture not completed");\r
1556                 return ERROR_OK;\r
1557         }\r
1558         \r
1559         /* read the trace data if it wasn't read already */\r
1560         if (etm_ctx->trace_depth == 0)\r
1561                 etm_ctx->capture_driver->read_trace(etm_ctx);\r
1562         \r
1563         if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)\r
1564         {\r
1565                 command_print(cmd_ctx, "file open error: %s", file.error_str);\r
1566                 return ERROR_OK;\r
1567         }\r
1568         \r
1569         fileio_write_u32(&file, etm_ctx->capture_status);\r
1570         fileio_write_u32(&file, etm_ctx->portmode);\r
1571         fileio_write_u32(&file, etm_ctx->tracemode);\r
1572         fileio_write_u32(&file, etm_ctx->trace_depth);\r
1573         \r
1574         for (i = 0; i < etm_ctx->trace_depth; i++)\r
1575         {\r
1576                 fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat);\r
1577                 fileio_write_u32(&file, etm_ctx->trace_data[i].packet);\r
1578                 fileio_write_u32(&file, etm_ctx->trace_data[i].flags);\r
1579         }\r
1580         \r
1581         fileio_close(&file);\r
1582         \r
1583         return ERROR_OK;        \r
1584 }\r
1585 \r
1586 int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1587 {\r
1588         fileio_t file;\r
1589         target_t *target;\r
1590         armv4_5_common_t *armv4_5;\r
1591         arm7_9_common_t *arm7_9;\r
1592         etm_context_t *etm_ctx;\r
1593         int i;\r
1594         \r
1595         if (argc != 1)\r
1596         {\r
1597                 command_print(cmd_ctx, "usage: etm load <file>");\r
1598                 return ERROR_OK;\r
1599         }\r
1600         \r
1601         target = get_current_target(cmd_ctx);\r
1602         \r
1603         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1604         {\r
1605                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1606                 return ERROR_OK;\r
1607         }\r
1608         \r
1609         if (!(etm_ctx = arm7_9->etm_ctx))\r
1610         {\r
1611                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1612                 return ERROR_OK;\r
1613         }\r
1614         \r
1615         if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)\r
1616         {\r
1617                 command_print(cmd_ctx, "trace capture running, stop first");\r
1618                 return ERROR_OK;\r
1619         }\r
1620         \r
1621         if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)\r
1622         {\r
1623                 command_print(cmd_ctx, "file open error: %s", file.error_str);\r
1624                 return ERROR_OK;\r
1625         }\r
1626         \r
1627         if (file.size % 4)\r
1628         {\r
1629                 command_print(cmd_ctx, "size isn't a multiple of 4, no valid trace data");\r
1630                 return ERROR_OK;\r
1631         }\r
1632         \r
1633         if (etm_ctx->trace_depth > 0)\r
1634         {\r
1635                 free(etm_ctx->trace_data);\r
1636         }\r
1637         \r
1638         fileio_read_u32(&file, &etm_ctx->capture_status);\r
1639         fileio_read_u32(&file, &etm_ctx->portmode);\r
1640         fileio_read_u32(&file, &etm_ctx->tracemode);\r
1641         fileio_read_u32(&file, &etm_ctx->trace_depth);\r
1642         \r
1643         etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);\r
1644         \r
1645         for (i = 0; i < etm_ctx->trace_depth; i++)\r
1646         {\r
1647                 u32 pipestat, packet, flags;\r
1648                 fileio_read_u32(&file, &pipestat);\r
1649                 fileio_read_u32(&file, &packet);\r
1650                 fileio_read_u32(&file, &flags);\r
1651                 etm_ctx->trace_data[i].pipestat = pipestat & 0xff;\r
1652                 etm_ctx->trace_data[i].packet = packet & 0xffff;\r
1653                 etm_ctx->trace_data[i].flags = flags;\r
1654         }\r
1655         \r
1656         fileio_close(&file);\r
1657         \r
1658         return ERROR_OK;        \r
1659 }\r
1660 \r
1661 int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1662 {\r
1663         target_t *target;\r
1664         armv4_5_common_t *armv4_5;\r
1665         arm7_9_common_t *arm7_9;\r
1666         etm_context_t *etm_ctx;\r
1667         \r
1668         target = get_current_target(cmd_ctx);\r
1669         \r
1670         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1671         {\r
1672                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1673                 return ERROR_OK;\r
1674         }\r
1675         \r
1676         if (!(etm_ctx = arm7_9->etm_ctx))\r
1677         {\r
1678                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1679                 return ERROR_OK;\r
1680         }\r
1681         \r
1682         if (argc > 0)\r
1683         {\r
1684                 u32 new_value = strtoul(args[0], NULL, 0);\r
1685                 \r
1686                 if ((new_value < 2) || (new_value > 100))\r
1687                 {\r
1688                         command_print(cmd_ctx, "valid settings are 2% to 100%");\r
1689                 }\r
1690                 else\r
1691                 {\r
1692                         etm_ctx->trigger_percent = new_value;\r
1693                 }\r
1694         }\r
1695         \r
1696         command_print(cmd_ctx, "%i percent of the tracebuffer reserved for after the trigger", etm_ctx->trigger_percent);\r
1697 \r
1698         return ERROR_OK;\r
1699 }\r
1700 \r
1701 int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1702 {\r
1703         target_t *target;\r
1704         armv4_5_common_t *armv4_5;\r
1705         arm7_9_common_t *arm7_9;\r
1706         etm_context_t *etm_ctx;\r
1707         reg_t *etm_ctrl_reg;\r
1708 \r
1709         target = get_current_target(cmd_ctx);\r
1710         \r
1711         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1712         {\r
1713                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1714                 return ERROR_OK;\r
1715         }\r
1716         \r
1717         if (!(etm_ctx = arm7_9->etm_ctx))\r
1718         {\r
1719                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1720                 return ERROR_OK;\r
1721         }\r
1722         \r
1723         /* invalidate old tracing data */\r
1724         arm7_9->etm_ctx->capture_status = TRACE_IDLE;\r
1725         if (arm7_9->etm_ctx->trace_depth > 0)\r
1726         {\r
1727                 free(arm7_9->etm_ctx->trace_data);\r
1728                 arm7_9->etm_ctx->trace_data = NULL;\r
1729         }\r
1730         arm7_9->etm_ctx->trace_depth = 0;\r
1731                 \r
1732         etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];\r
1733         etm_get_reg(etm_ctrl_reg);\r
1734                 \r
1735         /* Clear programming bit (10), set port selection bit (11) */\r
1736         buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x2);\r
1737 \r
1738         etm_store_reg(etm_ctrl_reg);\r
1739         jtag_execute_queue();\r
1740 \r
1741         etm_ctx->capture_driver->start_capture(etm_ctx);\r
1742 \r
1743         return ERROR_OK;\r
1744 }\r
1745 \r
1746 int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1747 {\r
1748         target_t *target;\r
1749         armv4_5_common_t *armv4_5;\r
1750         arm7_9_common_t *arm7_9;\r
1751         etm_context_t *etm_ctx;\r
1752         reg_t *etm_ctrl_reg;\r
1753 \r
1754         target = get_current_target(cmd_ctx);\r
1755         \r
1756         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1757         {\r
1758                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1759                 return ERROR_OK;\r
1760         }\r
1761         \r
1762         if (!(etm_ctx = arm7_9->etm_ctx))\r
1763         {\r
1764                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1765                 return ERROR_OK;\r
1766         }\r
1767         \r
1768         etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];\r
1769         etm_get_reg(etm_ctrl_reg);\r
1770                 \r
1771         /* Set programming bit (10), clear port selection bit (11) */\r
1772         buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x1);\r
1773 \r
1774         etm_store_reg(etm_ctrl_reg);    \r
1775         jtag_execute_queue();\r
1776         \r
1777         etm_ctx->capture_driver->stop_capture(etm_ctx);\r
1778         \r
1779         return ERROR_OK;\r
1780 }\r
1781 \r
1782 int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
1783 {\r
1784         target_t *target;\r
1785         armv4_5_common_t *armv4_5;\r
1786         arm7_9_common_t *arm7_9;\r
1787         etm_context_t *etm_ctx;\r
1788         int retval;\r
1789 \r
1790         target = get_current_target(cmd_ctx);\r
1791         \r
1792         if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
1793         {\r
1794                 command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
1795                 return ERROR_OK;\r
1796         }\r
1797         \r
1798         if (!(etm_ctx = arm7_9->etm_ctx))\r
1799         {\r
1800                 command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
1801                 return ERROR_OK;\r
1802         }\r
1803         \r
1804         if ((retval = etmv1_analyze_trace(etm_ctx, cmd_ctx)) != ERROR_OK)\r
1805         {\r
1806                 switch(retval)\r
1807                 {\r
1808                         case ERROR_ETM_ANALYSIS_FAILED:\r
1809                                 command_print(cmd_ctx, "further analysis failed (corrupted trace data or just end of data");\r
1810                                 break;\r
1811                         case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:\r
1812                                 command_print(cmd_ctx, "no instruction for current address available, analysis aborted");\r
1813                                 break;\r
1814                         case ERROR_TRACE_IMAGE_UNAVAILABLE:\r
1815                                 command_print(cmd_ctx, "no image available for trace analysis");\r
1816                                 break;\r
1817                         default:\r
1818                                 command_print(cmd_ctx, "unknown error: %i", retval);\r
1819                 }\r
1820         }\r
1821         \r
1822         return ERROR_OK;\r
1823 }\r
1824 \r
1825 int etm_register_commands(struct command_context_s *cmd_ctx)\r
1826 {\r
1827         etm_cmd = register_command(cmd_ctx, NULL, "etm", NULL, COMMAND_ANY, "Embedded Trace Macrocell");\r
1828 \r
1829         register_command(cmd_ctx, etm_cmd, "config", handle_etm_config_command, COMMAND_CONFIG, NULL);\r
1830 \r
1831         return ERROR_OK;\r
1832 }\r
1833 \r
1834 int etm_register_user_commands(struct command_context_s *cmd_ctx)\r
1835 {\r
1836         register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,\r
1837                 COMMAND_EXEC, "configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output");\r
1838 \r
1839         register_command(cmd_ctx, etm_cmd, "info", handle_etm_info_command,\r
1840                 COMMAND_EXEC, "display info about the current target's ETM");\r
1841 \r
1842         register_command(cmd_ctx, etm_cmd, "trigger_percent <percent>", handle_etm_trigger_percent_command,\r
1843                 COMMAND_EXEC, "amount (<percent>) of trace buffer to be filled after the trigger occured");\r
1844         register_command(cmd_ctx, etm_cmd, "status", handle_etm_status_command,\r
1845                 COMMAND_EXEC, "display current target's ETM status");\r
1846         register_command(cmd_ctx, etm_cmd, "start", handle_etm_start_command,\r
1847                 COMMAND_EXEC, "start ETM trace collection");\r
1848         register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,\r
1849                 COMMAND_EXEC, "stop ETM trace collection");\r
1850 \r
1851         register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_analyze_command,\r
1852                 COMMAND_EXEC, "anaylze collected ETM trace");\r
1853 \r
1854         register_command(cmd_ctx, etm_cmd, "image", handle_etm_image_command,\r
1855                 COMMAND_EXEC, "load image from <file> [base address]");\r
1856 \r
1857         register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,\r
1858                 COMMAND_EXEC, "dump captured trace data <file>");\r
1859         register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,\r
1860                 COMMAND_EXEC, "load trace data for analysis <file>");\r
1861 \r
1862         return ERROR_OK;\r
1863 }\r