Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: trconv.C | |
4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
6 | // | |
7 | // The above named program is free software; you can redistribute it and/or | |
8 | // modify it under the terms of the GNU General Public | |
9 | // License version 2 as published by the Free Software Foundation. | |
10 | // | |
11 | // The above named program is distributed in the hope that it will be | |
12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | // General Public License for more details. | |
15 | // | |
16 | // You should have received a copy of the GNU General Public | |
17 | // License along with this work; if not, write to the Free Software | |
18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
19 | // | |
20 | // ========== Copyright Header End ============================================ | |
21 | /* Copyright (C) 2006 Sun Microsystems, Inc. | |
22 | * All Rights Reserved | |
23 | */ | |
24 | ||
25 | #pragma ident "@(#) trconv.C 1.6: 11/01/07 14:57:38 @(#)" | |
26 | #include <ctype.h> | |
27 | #include <limits.h> | |
28 | #include <stdlib.h> | |
29 | #include <string.h> | |
30 | ||
31 | #include "read_symbols.h" | |
32 | #include "trconv.H" | |
33 | ||
34 | Globals_T gbl; | |
35 | ||
36 | // allocating space... | |
37 | Tmaster64 Trace::this_master = {0}; | |
38 | ||
39 | char version_string[] = "(Version 1.5)"; | |
40 | ||
41 | char switch_error_string[] = "Invalid %s passed to %s: %d\n"; | |
42 | ||
43 | char usage_string[] = | |
44 | "Usage: %s [flags] [input-file]\n" | |
45 | "\n" | |
46 | "%s " | |
47 | "Prints and converts various trace formats.\n" | |
48 | "\n" | |
49 | "Format flags:\n" | |
50 | " -from FX = assume input data is in format FX\n" | |
51 | " -to FX = generate output format FX\n" | |
52 | " where FX is one of the following: \n" | |
53 | " shade5 = Shade5 format\n" | |
54 | " shade6x32 = Shade6 format, using 32 bit addresses\n" | |
55 | " shade6x64 = Shade6 format, using 64 bit addresses\n" | |
56 | " rtf99 = a deprecated format\n" | |
57 | " rst = (RQ's) really simple trace format (Default -from)\n" | |
58 | " null = (only for \"-to FX\"), do not convert (Default -to)\n" | |
59 | "Selection flags:\n" | |
60 | " -n N = stop after processing N records\n" | |
61 | " -n Ni = stop after processing N instructions\n" | |
62 | " -s N = skip the first N records\n" | |
63 | " -s Ni = skip the first N instructions\n" | |
64 | " -pc=pc1[,pc2] = only process instructions w/ pc=pc1 (or [pc1,pc2])\n" | |
65 | " -ea=ea1[,ea2] = only process instructions w/ ea=ea1 (or [ea1,ea2])\n" | |
66 | " -cpu=cpu1[,cpu2,...] = only process records from selected cpu's\n" | |
67 | " Example: -cpu=m,n-q,p selects records from \n" | |
68 | " cpu's m, p, and all cpu's from n through q\n" | |
69 | "Printing flags:\n" | |
70 | " -a = print in trace record field format\n" | |
71 | " -d = print in instruction disassembly format (Default)\n" | |
72 | " -x = print verbose output format\n" | |
73 | " -nid = suppress trace index in output\n" | |
74 | " -c = only count records from the trace file\n" | |
75 | #ifdef _PRINT_PA | |
76 | " -pa = print both VA and PA of effective address\n" | |
77 | #endif // _PRINT_PA | |
78 | " -sym [file] = read and use symbols from 'file'\n" | |
79 | #ifdef _VALUE_TRACE | |
80 | " -vt = print registers in value trace format\n" | |
81 | #endif // _VALUE_TRACE | |
82 | "Verification flags:\n" | |
83 | " -nv = do not verify pc values in trace file\n" | |
84 | " -e = only check for ihash errors\n" | |
85 | " -fast = turn off all verification and patching options\n" | |
86 | "RST flags:\n" | |
87 | " -i = only process RST instruction records\n" | |
88 | " -ic = like -i, but counts only instructions\n" | |
89 | " -ni = do not process any RST instruction records\n" | |
90 | " -nic = like -ni, but counts only non-instructions\n" | |
91 | " -rstdump || -r = macro for: -from rst -to null -d (Default)\n" | |
92 | " -nobranch = do not verify branch ea's against disassembly\n" | |
93 | " -nopc_pavadiff = do not verify rstf_pavadiffT.pc_pa_va field\n" | |
94 | " -noea_pavadiff = do not verify rstf_pavadiffT.ea_pa_va field\n" | |
95 | " -pstate_am 0|1 = set initial PSTATE.AM bit to 0 or 1 (Default: 0)\n" | |
96 | "Patching flags:\n" | |
97 | " -patchcleanrst = clean up \"dirty\" ea value to be RSTF_NOADDR " | |
98 | "in RST trace\n" | |
99 | " -patchihash = forces ihash value generation\n" | |
100 | "Output flags:\n" | |
101 | " -stdout = output to standard out (Default)\n" | |
102 | " -o File = output to File\n" | |
103 | "Miscellaneous:\n" | |
104 | " -help || -h = print this message and exit\n" | |
105 | " -version || -v = print version and exit\n" | |
106 | "\n" | |
107 | "Default flags are: -from rst -to null -d -stdout.\n" | |
108 | "(By default Spix5 ihash values are assumed for all trace formats\n" | |
109 | "*including* Shade6 traces...)\n" | |
110 | "\n" | |
111 | "Examples:\n" | |
112 | " %% %s < rstfile\n" | |
113 | " (print disassembled RST trace instructions)\n" | |
114 | "\n" | |
115 | " %% %s -from rst [-to null] -s 1000i -patchihash rstfile\n" | |
116 | " (print trace records, skip first 1000 instructions)\n" | |
117 | "\n" | |
118 | " %% %s -r -pc=0x12345678,0x22222222 rstfile\n" | |
119 | " (print disassembled RST trace instructions with pc values within \n" | |
120 | " [0x12345678 0x22222222])\n\n"; | |
121 | ||
122 | void usage(char progName[]) { | |
123 | fprintf(stderr, usage_string, progName, version_string, | |
124 | progName, progName, progName); | |
125 | } | |
126 | ||
127 | // initializes user_options | |
128 | void parse_args(int argc, char *argv[], bool debug) { | |
129 | int i; | |
130 | char* a; | |
131 | char* b; | |
132 | ||
133 | // parse arguments | |
134 | for (i = 1; i < argc; i++) { | |
135 | a = argv[i]; | |
136 | b = (i < argc) ? argv[i+1] : NULL; | |
137 | ||
138 | if (streq(a, "-from")) { | |
139 | if (streq(b, "null")) { | |
140 | usage(argv[0]); | |
141 | fprintf(stderr, "Invalid input format. Type %s -help\n", argv[0]); | |
142 | exit(1); | |
143 | } else { | |
144 | gbl.fromtype = format2int(b); | |
145 | } | |
146 | i++; | |
147 | } else if (streq(a, "-to")) { | |
148 | if (streq(b, "null")) { | |
149 | gbl.totype = NONE; | |
150 | } else { | |
151 | gbl.totype = format2int(b); | |
152 | } | |
153 | i++; | |
154 | ||
155 | } else if (streq(a, "-n")) { | |
156 | gbl.maxRecs = strtoll(b, NULL, 10); | |
157 | if (b[strlen(b) - 1] == 'i') { | |
158 | gbl.maxInstrs = gbl.maxRecs; | |
159 | gbl.maxRecs = INT64_MAX; | |
160 | } | |
161 | i++; | |
162 | } else if (streq(a, "-syms")) { | |
163 | if (b == NULL) { | |
164 | usage(argv[0]); | |
165 | fprintf(stderr, "Could not open file for writing: %s\n", b); | |
166 | exit(1); | |
167 | } | |
168 | else { | |
169 | if (gbl.symbol_table.read_symbol_file(b) == false) { | |
170 | fprintf(stderr, "Read of symbol table file '%s' failed\n", | |
171 | b); | |
172 | exit(1); | |
173 | } | |
174 | } | |
175 | gbl.show_syms = true; | |
176 | i++; | |
177 | } else if (streq(a, "-s")) { | |
178 | gbl.skipRecs = strtoll(b, NULL, 10); | |
179 | if (b[strlen(b) - 1] == 'i') { | |
180 | gbl.skipInstrs = gbl.skipRecs; | |
181 | gbl.skipRecs = 0; | |
182 | } | |
183 | i++; | |
184 | } else if (streqprefix(a, "-pc")) { | |
185 | get_range(a, &gbl.frompc, &gbl.topc); | |
186 | } else if (streqprefix(a, "-ea")) { | |
187 | get_range(a, &gbl.fromea, &gbl.toea); | |
188 | } else if (streqprefix(a, "-cpu")) { | |
189 | get_cpu_range(a); | |
190 | ||
191 | } else if (streq(a, "-a")) { | |
192 | gbl.disassembly = false; | |
193 | gbl.record = true; | |
194 | gbl.verbose = false; | |
195 | } else if (streq(a, "-d")) { | |
196 | gbl.disassembly = true; | |
197 | gbl.record = false; | |
198 | gbl.verbose = false; | |
199 | } else if (streq(a, "-x")) { | |
200 | gbl.disassembly = false; | |
201 | gbl.record = false; | |
202 | gbl.verbose = true; | |
203 | } else if (streq(a, "-nid")) { | |
204 | gbl.showIdx = false; | |
205 | } else if (streq(a, "-c")) { | |
206 | gbl.countOnly = true; | |
207 | #ifdef _PRINT_PA | |
208 | } else if (streq(a, "-pa")) { | |
209 | gbl.printPA = true; | |
210 | #endif // _PRINT_PA | |
211 | #ifdef _VALUE_TRACE | |
212 | } else if (streq(a, "-vt")) { | |
213 | gbl.valueTrace = true; | |
214 | #endif // _VALUE_TRACE | |
215 | ||
216 | } else if (streq(a, "-nv")) { | |
217 | gbl.verify = false; | |
218 | } else if (streq(a, "-e")) { | |
219 | gbl.checkError = true; | |
220 | } else if (streq(a, "-fast")) { | |
221 | gbl.fast = true; | |
222 | ||
223 | } else if (streq(a, "-i")) { | |
224 | gbl.onlyIns = true; | |
225 | } else if (streq(a, "-ic")) { | |
226 | gbl.onlyIns = true; | |
227 | gbl.reorderIns = true; | |
228 | } else if (streq(a, "-ni")) { | |
229 | gbl.noIns = true; | |
230 | } else if (streq(a, "-nic")) { | |
231 | gbl.noIns = true; | |
232 | gbl.reorderNoIns = true; | |
233 | } else if (streq(a, "-rstdump") || streq(a, "-r")) { | |
234 | gbl.fromtype = RST; | |
235 | gbl.totype = NONE; | |
236 | } else if (streq(a, "-nobranch")) { | |
237 | gbl.branch = false; | |
238 | } else if (streq(a, "-nopc_pavadiff")) { | |
239 | gbl.pc_pavadiff = false; | |
240 | } else if (streq(a, "-noea_pavadiff")) { | |
241 | gbl.ea_pavadiff = false; | |
242 | } else if (streq(a, "-pstate_am")) { | |
243 | unsigned am = atoi(b) << 3; | |
244 | int j; | |
245 | ||
246 | for (j = 0; j < MAX_CPUID + 1; j++) { | |
247 | gbl.pstate[j] = am; | |
248 | } | |
249 | ||
250 | i++; | |
251 | ||
252 | } else if (streq(a, "-patchcleanrst")) { | |
253 | gbl.clean = true; | |
254 | } else if (streq(a, "-patchihash")) { | |
255 | gbl.genIHash = true; | |
256 | ||
257 | } else if (streq(a, "-stdout")) { | |
258 | gbl.outfp = stdout; | |
259 | } else if (streq(a, "-o")) { | |
260 | gbl.outfp = fopen(b, "w"); | |
261 | if (gbl.outfp == NULL) { | |
262 | usage(argv[0]); | |
263 | fprintf(stderr, "Could not open file for writing: %s\n", b); | |
264 | exit(1); | |
265 | } | |
266 | i++; | |
267 | ||
268 | } else if (streq(a, "-help") || streq(a, "-h")) { | |
269 | usage(argv[0]); | |
270 | exit(0); | |
271 | } else if (streq(a, "-version") || streq(a, "-v")) { | |
272 | fprintf(stderr, "%s %s\n", argv[0], version_string); | |
273 | exit(0); | |
274 | ||
275 | } else if (a[0] == '-') { | |
276 | usage(argv[0]); | |
277 | fprintf(stderr, "Unknown flag: %s\n", a); | |
278 | exit(1); | |
279 | } else if (i < argc - 1) { | |
280 | usage(argv[0]); | |
281 | fprintf(stderr, "Unknown flag: %s\n", a); | |
282 | exit(1); | |
283 | } else if (i == argc - 1) { | |
284 | gbl.infile = a; | |
285 | ||
286 | gbl.infp = fopen(a, "r"); | |
287 | if (gbl.infp == NULL) { | |
288 | usage(argv[0]); | |
289 | fprintf(stderr, "Could not open input file: %s\n", a); | |
290 | exit(1); | |
291 | } | |
292 | } | |
293 | } | |
294 | ||
295 | if (gbl.fast) { | |
296 | gbl.verify = false; | |
297 | gbl.checkError = false; | |
298 | gbl.branch = false; | |
299 | gbl.pc_pavadiff = false; | |
300 | gbl.ea_pavadiff = false; | |
301 | gbl.clean = false; | |
302 | gbl.genIHash = false; | |
303 | gbl.checkIHash = false; | |
304 | } | |
305 | ||
306 | gbl.fromsize = format2size(gbl.fromtype); | |
307 | gbl.tosize = format2size(gbl.totype); | |
308 | ||
309 | if (debug) { | |
310 | for (i = 0; i < argc; i++) { | |
311 | fprintf(gbl.msgfp, "%s ", argv[i]); | |
312 | } | |
313 | fprintf(gbl.msgfp, "\n\n"); | |
314 | ||
315 | // format options | |
316 | fprintf(gbl.msgfp, "fromtype = %d\n", gbl.fromtype); | |
317 | fprintf(gbl.msgfp, "totype = %d\n", gbl.totype); | |
318 | fprintf(gbl.msgfp, "\n"); | |
319 | ||
320 | // selection options | |
321 | fprintf(gbl.msgfp, "maxRecs = %llu\n", gbl.maxRecs); | |
322 | fprintf(gbl.msgfp, "maxInstrs = %llu\n", gbl.maxInstrs); | |
323 | fprintf(gbl.msgfp, "skipRecs = %llu\n", gbl.skipRecs); | |
324 | fprintf(gbl.msgfp, "skipInstrs = %llu\n", gbl.skipInstrs); | |
325 | fprintf(gbl.msgfp, "frompc = 0x%llx\n", gbl.frompc); | |
326 | fprintf(gbl.msgfp, "topc = 0x%llx\n", gbl.topc); | |
327 | fprintf(gbl.msgfp, "fromea = 0x%llx\n", gbl.fromea); | |
328 | fprintf(gbl.msgfp, "toea = 0x%llx\n", gbl.toea); | |
329 | fprintf(gbl.msgfp, "\n"); | |
330 | ||
331 | // priting options | |
332 | fprintf(gbl.msgfp, "record = %d\n", gbl.record); | |
333 | fprintf(gbl.msgfp, "disassembly = %d\n", gbl.disassembly); | |
334 | fprintf(gbl.msgfp, "verbose = %d\n", gbl.verbose); | |
335 | fprintf(gbl.msgfp, "showIdx = %d\n", gbl.showIdx); | |
336 | fprintf(gbl.msgfp, "countOnly = %d\n", gbl.countOnly); | |
337 | #ifdef _PRINT_PA | |
338 | fprintf(gbl.msgfp, "print PA = %d\n", gbl.printPA); | |
339 | #endif // _PRINT_PA | |
340 | #ifdef _VALUE_TRACE | |
341 | fprintf(gbl.msgfp, "valueTrace = %d\n", gbl.valueTrace); | |
342 | #endif // _VALUE_TRACE | |
343 | fprintf(gbl.msgfp, "msgfp = 0x%x\n", gbl.msgfp); | |
344 | fprintf(gbl.msgfp, "\n"); | |
345 | ||
346 | // verification options | |
347 | fprintf(gbl.msgfp, "verify = %d\n", gbl.verify); | |
348 | fprintf(gbl.msgfp, "checkError = %d\n", gbl.checkError); | |
349 | fprintf(gbl.msgfp, "fast = %d\n", gbl.fast); | |
350 | fprintf(gbl.msgfp, "\n"); | |
351 | ||
352 | // rsttrace options | |
353 | fprintf(gbl.msgfp, "onlyIns = %d\n", gbl.onlyIns); | |
354 | fprintf(gbl.msgfp, "reorderIns = %d\n", gbl.reorderIns); | |
355 | fprintf(gbl.msgfp, "noIns = %d\n", gbl.noIns); | |
356 | fprintf(gbl.msgfp, "reorderNoIns = %d\n", gbl.reorderNoIns); | |
357 | fprintf(gbl.msgfp, "branch = %d\n", gbl.branch); | |
358 | fprintf(gbl.msgfp, "pc_pavadiff = %d\n", gbl.pc_pavadiff); | |
359 | fprintf(gbl.msgfp, "ea_pavadiff = %d\n", gbl.ea_pavadiff); | |
360 | fprintf(gbl.msgfp, "\n"); | |
361 | ||
362 | // patching options | |
363 | fprintf(gbl.msgfp, "clean = %d\n", gbl.clean); | |
364 | fprintf(gbl.msgfp, "genIHash = %d\n", gbl.genIHash); | |
365 | fprintf(gbl.msgfp, "\n"); | |
366 | ||
367 | // output options | |
368 | fprintf(gbl.msgfp, "infp = 0x%x\n", gbl.infp); | |
369 | fprintf(gbl.msgfp, "outfp = 0x%x\n", gbl.outfp); | |
370 | fprintf(gbl.msgfp, "\n"); | |
371 | ||
372 | // convenient variables | |
373 | fprintf(gbl.msgfp, "progname = %s\n", gbl.progname); | |
374 | fprintf(gbl.msgfp, "infile = %s\n", gbl.infile); | |
375 | fprintf(gbl.msgfp, "fromsize = %d bytes\n", gbl.fromsize); | |
376 | fprintf(gbl.msgfp, "tosize = %d bytes\n", gbl.tosize); | |
377 | ||
378 | fflush(gbl.msgfp); | |
379 | } | |
380 | } // parse_args | |
381 | ||
382 | void init_globals(char *argv[]) { | |
383 | // format options | |
384 | gbl.fromtype = RST; // -from | |
385 | gbl.totype = NONE; // -to | |
386 | ||
387 | // selection options | |
388 | gbl.maxRecs = INT64_MAX; // -n | |
389 | gbl.maxInstrs = INT64_MAX; // -n i | |
390 | gbl.skipRecs = 0; // -s | |
391 | gbl.skipInstrs = 0; // -s i | |
392 | gbl.frompc = 0; // -frompc | |
393 | gbl.topc = 0; // -topc | |
394 | gbl.fromea = 0; // -fromea | |
395 | gbl.toea = 0; // -toea | |
396 | for (int i = 0; i < MAX_CPUID; i++) { | |
397 | gbl.cpu[i] = 1; // -cpu | |
398 | } | |
399 | ||
400 | // printing options | |
401 | gbl.record = false; // -a | |
402 | gbl.disassembly = true; // -d | |
403 | gbl.verbose = false; // -x | |
404 | gbl.countOnly = false; // -c | |
405 | gbl.showIdx = true; // -nid | |
406 | #ifdef _PRINT_PA | |
407 | gbl.printPA = false; // -pa | |
408 | #endif // _PRINT_PA | |
409 | #ifdef _VALUE_TRACE | |
410 | gbl.valueTrace = false; // -vt | |
411 | #endif // _VALUE_TRACE | |
412 | gbl.show_syms = false; // -syms | |
413 | ||
414 | // verification options | |
415 | gbl.verify = true; // -nv | |
416 | gbl.checkError = false; // -e | |
417 | gbl.fast = false; // -fast | |
418 | ||
419 | // rsttrace options | |
420 | gbl.onlyIns = false; // -i | |
421 | gbl.reorderIns = false; // -ic | |
422 | gbl.noIns = false; // -ni | |
423 | gbl.reorderNoIns = false; // -nic | |
424 | gbl.branch = true; // -nobranch | |
425 | gbl.pc_pavadiff = true; // -nopc_pavadiff | |
426 | gbl.ea_pavadiff = true; // -noea_pavadiff | |
427 | gbl.msgfp = stderr; // -msg | |
428 | ||
429 | // patching options | |
430 | gbl.clean = false; // -patchcleanrst | |
431 | gbl.genIHash = false; // -patchihash | |
432 | ||
433 | // output options | |
434 | gbl.infp = stdin; // [input-file] | |
435 | gbl.outfp = stdout; // -stdout || -o | |
436 | ||
437 | // convenient variables | |
438 | gbl.progname = argv[0]; | |
439 | gbl.infile = (char*) malloc(8); | |
440 | if (gbl.infile == NULL) { | |
441 | fprintf(stderr, "Could not allocate 8 bytes for " | |
442 | "infile in init_globals()\n"); | |
443 | exit(1); | |
444 | } | |
445 | strcpy(gbl.infile, "stdin"); | |
446 | ||
447 | gbl.checkIHash = true; // check ihash until nonzero value confirmed | |
448 | ||
449 | gbl.icount = 0; | |
450 | gbl.rcount = 0; | |
451 | gbl.skipInstrsRecs = 0; | |
452 | ||
453 | for (int i = 0; i < MAX_CPUID + 1; i++) { | |
454 | gbl.pstate[i] = 0; // assume 64bit addresses by default | |
455 | } | |
456 | ||
457 | // rst-related | |
458 | gbl.rstf_pre212 = false; | |
459 | ||
460 | // rst types | |
461 | gbl.headercount = 0; | |
462 | //gbl.asicount = 0; | |
463 | gbl.tlbcount = 0; | |
464 | gbl.threadcount = 0; | |
465 | gbl.trapcount = 0; | |
466 | gbl.trapexitcount = 0; | |
467 | gbl.regvalcount = 0; | |
468 | gbl.cpucount = 0; | |
469 | gbl.pregcount = 0; | |
470 | gbl.dmacount = 0; | |
471 | gbl.stringcount = 0; | |
472 | gbl.delimcount = 0; | |
473 | gbl.physaddrcount = 0; | |
474 | gbl.pavadiffcount = 0; | |
475 | gbl.filemarkercount = 0; | |
476 | gbl.snoopcount = 0; | |
477 | ||
478 | gbl.unknowncount = 0; | |
479 | ||
480 | #ifdef _PRINT_PA | |
481 | for(int initCpuId=0; initCpuId<MAX_INSTR_CPUID; initCpuId++) { | |
482 | gbl.ea_pavadiff_valid[initCpuId] = false; | |
483 | gbl.ea_pavadiff_value[initCpuId] = 0; | |
484 | gbl.pc_pavadiff_valid[initCpuId] = false; | |
485 | gbl.pc_pavadiff_value[initCpuId] = 0; | |
486 | } | |
487 | #endif // _PRINT_PA | |
488 | } | |
489 | ||
490 | int format2int(const char str[]) { | |
491 | if (streq(str, "shade5") ) { | |
492 | return SHADE5; | |
493 | } else if (streq(str, "shade6x32") ) { | |
494 | return SHADE6x32; | |
495 | } else if (streq(str, "shade6x64") ) { | |
496 | return SHADE6x64; | |
497 | } else if (streq(str, "rtf99") ) { | |
498 | return RTF99; | |
499 | } else if (streq(str, "master") ){ | |
500 | return MASTER64; | |
501 | } else if (streq(str, "rst") ){ | |
502 | return RST; | |
503 | } else if (streq(str, "null") ) { | |
504 | return NONE; | |
505 | } else { | |
506 | usage(gbl.progname); | |
507 | fprintf(stderr, "Invalid data format: \"%s\"\n", str); | |
508 | exit(1); | |
509 | } | |
510 | } | |
511 | ||
512 | int format2size(int format) { | |
513 | int size; | |
514 | ||
515 | switch (format) { | |
516 | case RTF99: | |
517 | size = sizeof(Trtf99); | |
518 | break; | |
519 | case SHADE5: | |
520 | size = sizeof(Tshade5); | |
521 | break; | |
522 | case SHADE6x32: | |
523 | size = sizeof(Tshade6x32); | |
524 | break; | |
525 | case SHADE6x64: | |
526 | size = sizeof(Tshade6x64); | |
527 | break; | |
528 | case MASTER64: | |
529 | size = sizeof(Tmaster64); | |
530 | break; | |
531 | case RST: | |
532 | size = sizeof(rstf_unionT); | |
533 | break; | |
534 | case NONE: | |
535 | size = 0; | |
536 | break; | |
537 | default: | |
538 | fprintf(stderr, switch_error_string, "format", "format2size", format); | |
539 | exit(2); | |
540 | } | |
541 | ||
542 | return size; | |
543 | } | |
544 | ||
545 | bool streq(const char* a, const char* b) { | |
546 | return (strcmp(a, b) == 0); | |
547 | } | |
548 | ||
549 | bool streqprefix(const char* a, const char* b) { | |
550 | return (strncmp(a, b, strlen(b) ) == 0); | |
551 | } | |
552 | ||
553 | void get_range(char* str, uint64_t *from, uint64_t* to) { | |
554 | char* from_str; | |
555 | char* to_str; | |
556 | ||
557 | from_str = strstr(str, "="); | |
558 | if (from_str == NULL) { | |
559 | usage(gbl.progname); | |
560 | fprintf(stderr, "Invalid pc/ea given to -pc/-ea flag.\n"); | |
561 | exit(1); | |
562 | } else { | |
563 | *from = strtoull(from_str + 1, NULL, 16); | |
564 | } | |
565 | ||
566 | to_str = strstr(str, ","); | |
567 | if (to_str != NULL) { | |
568 | *to = strtoull(to_str + 1, NULL, 16); | |
569 | } | |
570 | } | |
571 | ||
572 | int is_valid_cpu(int cpuid) { | |
573 | return (cpuid >= 0 && cpuid <= MAX_CPUID); | |
574 | } | |
575 | ||
576 | void get_cpu_range(char* str) { | |
577 | int cpuid, prev_cpuid; | |
578 | int i; | |
579 | ||
580 | for (i = 0; i <= MAX_CPUID; i++) { | |
581 | gbl.cpu[i] = 0; // -cpu | |
582 | } | |
583 | ||
584 | str = strchr(str, '='); | |
585 | if (str == NULL) { | |
586 | usage(gbl.progname); | |
587 | fprintf(stderr, "Error: invalid -cpu id given.\n"); | |
588 | exit(1); | |
589 | } | |
590 | ||
591 | str++; | |
592 | while (isdigit(str[0])) { | |
593 | cpuid = strtol(str, &str, 10); | |
594 | if (is_valid_cpu(cpuid) == 0) { | |
595 | fprintf(stderr, "Error: invalid cpuid %d.\n", cpuid); | |
596 | exit(1); | |
597 | } | |
598 | prev_cpuid = cpuid; | |
599 | ||
600 | if (str[0] == '-') { | |
601 | str++; | |
602 | if (isdigit(str[0])) { | |
603 | cpuid = strtol(str, &str, 10); | |
604 | if (is_valid_cpu(cpuid) == 0) { | |
605 | fprintf(stderr, "Error: invalid cpuid %d.\n", cpuid); | |
606 | exit(1); | |
607 | } | |
608 | } | |
609 | } | |
610 | ||
611 | for (i = prev_cpuid; i <= cpuid; i++) { | |
612 | gbl.cpu[i] = 1; | |
613 | } | |
614 | ||
615 | str++; | |
616 | } | |
617 | } | |
618 | ||
619 | // range_ok(pc, frompc, topc); | |
620 | // range_ok(ea, fromea, toea); | |
621 | bool in_range(const uint64_t x, const uint64_t a, const uint64_t b) { | |
622 | if (a == 0 && b == 0) { // process all records | |
623 | return true; | |
624 | } else if (x == RSTF_NOADDR) { | |
625 | return false; // invalid x (address) | |
626 | } else { | |
627 | if (a != 0 && b == 0) { // process only x=a | |
628 | if (x == a) { | |
629 | return true; | |
630 | } | |
631 | } else if (a != 0 && b != 0) { // process a<=x<=b | |
632 | if (x >= a && x <= b) { | |
633 | return true; | |
634 | } | |
635 | } else if (a == 0 && b != 0) { // error | |
636 | // should never get here though... | |
637 | fprintf(stderr, "Invalid pc/ea given to -pc/-ea flag.\n"); | |
638 | exit(1); | |
639 | } | |
640 | } | |
641 | ||
642 | return false; | |
643 | } | |
644 | ||
645 | void print_counts(FILE* outfp) { | |
646 | if (gbl.skipInstrs) { | |
647 | gbl.rcount += gbl.skipInstrsRecs; | |
648 | } | |
649 | ||
650 | fprintf(outfp, "\n"); | |
651 | if (gbl.rcount == gbl.icount) { | |
652 | fprintf(outfp, "Counted: %lld instructions\n", gbl.icount); | |
653 | } else { | |
654 | fprintf(outfp, "Counted: %lld records\n\n", gbl.rcount); | |
655 | ||
656 | fprintf(outfp, " %lld instruction recs\n", gbl.icount); | |
657 | fprintf(outfp, " %lld header recs\n", gbl.headercount); | |
658 | fprintf(outfp, " %lld traceinfo recs\n", gbl.traceinfocount); | |
659 | fprintf(outfp, " %lld tlb recs\n", gbl.tlbcount); | |
660 | fprintf(outfp, " %lld thread recs\n", gbl.threadcount); | |
661 | fprintf(outfp, " %lld preg recs\n", gbl.pregcount); | |
662 | fprintf(outfp, " %lld trap recs\n", gbl.trapcount); | |
663 | fprintf(outfp, " %lld trapexit recs\n", gbl.trapexitcount); | |
664 | fprintf(outfp, " %lld cpu recs\n", gbl.cpucount); | |
665 | fprintf(outfp, " %lld dma recs\n", gbl.dmacount); | |
666 | fprintf(outfp, " %lld snoop recs\n", gbl.snoopcount); | |
667 | fprintf(outfp, " %lld delim recs\n", gbl.delimcount); | |
668 | fprintf(outfp, " %lld physaddr recs\n", gbl.physaddrcount); | |
669 | fprintf(outfp, " %lld pavadiff recs\n", gbl.pavadiffcount); | |
670 | fprintf(outfp, " %lld rfs_sechdr recs\n", gbl.rfs_section_header_count); | |
671 | fprintf(outfp, " %lld rfs_cachewarming recs\n", gbl.cachewarming_count); | |
672 | fprintf(outfp, " %lld rfs_bpwarming recs\n", gbl.bpwarming_count); | |
673 | fprintf(outfp, " %lld filemarker recs\n", gbl.filemarkercount); | |
674 | fprintf(outfp, " %lld recnum recs\n", gbl.recnumcount); | |
675 | fprintf(outfp, " %lld string recs\n", gbl.stringcount); | |
676 | fprintf(outfp, " %lld status recs\n", gbl.statuscount); | |
677 | fprintf(outfp, " %lld patch recs\n", gbl.patchcount); | |
678 | fprintf(outfp, " %lld regval recs\n", gbl.regvalcount); | |
679 | fprintf(outfp, " %lld memval64 recs\n", gbl.memval64count); | |
680 | fprintf(outfp, " %lld memval128 recs\n", gbl.memval128count); | |
681 | fprintf(outfp, " %lld bustrace recs\n", gbl.bustracecount); | |
682 | fprintf(outfp, " %lld process recs\n", gbl.processcount); | |
683 | fprintf(outfp, " %lld devidstr recs\n", gbl.devidstrcount); | |
684 | fprintf(outfp, " %lld timesync recs\n", gbl.timesynccount); | |
685 | fprintf(outfp, " %lld zero recs\n", gbl.zerocount); | |
686 | } | |
687 | ||
688 | if (gbl.unknowncount) { | |
689 | fprintf(outfp, " %lld unknown recs\n\n", gbl.unknowncount); | |
690 | } else { | |
691 | fprintf(outfp, "\n"); | |
692 | } | |
693 | ||
694 | if (gbl.skipRecs) { | |
695 | fprintf(outfp, " %lld recs skipped (not counted)\n", gbl.skipRecs); | |
696 | } | |
697 | if (gbl.skipInstrs) { | |
698 | fprintf(outfp, " %lld instruction recs skipped (counted)\n", | |
699 | gbl.skipInstrs); | |
700 | } | |
701 | } | |
702 |