Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: main.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 | #include <stdio.h> | |
22 | #include <stdlib.h> | |
23 | #include <string.h> | |
24 | ||
25 | #include "read_symbols.h" | |
26 | #include "trconv.H" | |
27 | ||
28 | #define BUFFER_SIZE (128 << 10) | |
29 | ||
30 | int process_buffer(Trace* itrace, Trace* otrace, | |
31 | void* itr_buf, void* otr_buf, | |
32 | int start, int ntr) { | |
33 | int i; | |
34 | static int buffer_instrs = 0; | |
35 | uint64_t prev_icount; | |
36 | int curcpu = -1; | |
37 | void* useless = itr_buf; // no CC warnings | |
38 | ||
39 | for (i = start; | |
40 | i < ntr && gbl.rcount < gbl.maxRecs && gbl.icount < gbl.maxInstrs; | |
41 | i++) { | |
42 | itrace->count(); | |
43 | ||
44 | curcpu = itrace->getCpuID(); | |
45 | if (curcpu == -1 || gbl.cpu[curcpu] == 1) { | |
46 | if (in_range(itrace->get_pc(), gbl.frompc, gbl.topc) && | |
47 | in_range(itrace->get_ea(), gbl.fromea, gbl.toea)) { | |
48 | prev_icount = gbl.icount; | |
49 | // -patchcleanrst, -pc_pavadiff, -ea_pavadiff done in count() | |
50 | ||
51 | // these records should be processed... | |
52 | if (!gbl.countOnly) { | |
53 | // only check for instruction opcode errors? | |
54 | if (gbl.checkError) { | |
55 | if (itrace->check_ihash_error()) { | |
56 | fprintf(stderr, "IHash Error (#%llu ih=%d): " | |
57 | "Incorrect ihash value in input file.\n", | |
58 | gbl.rcount - 1 + gbl.skipRecs, itrace->get_ihash()); | |
59 | } | |
60 | } else /* if not gbl.checkError */ { | |
61 | // is ihash valid? | |
62 | if (gbl.checkIHash) { | |
63 | // a valid nonzero ihash is assumed valid | |
64 | if (itrace->check_ihash_error() == 0) { | |
65 | if (itrace->get_ihash() >= SPIX_SPARC_IOP_BN) { | |
66 | gbl.checkIHash = false; | |
67 | } | |
68 | } else { // ERROR!!! | |
69 | fprintf(stderr, | |
70 | "\nIHash Error (#%llu ih=%d): " | |
71 | "Correcting ihash values in output.\n\n", | |
72 | gbl.rcount - 1 + gbl.skipRecs, itrace->get_ihash()); | |
73 | gbl.checkIHash = false; | |
74 | gbl.genIHash = true; // generate ihash values | |
75 | } | |
76 | } // if gbl.checkIHash | |
77 | ||
78 | // generate ihash? | |
79 | if (gbl.genIHash) { | |
80 | itrace->gen_ihash(); | |
81 | } | |
82 | ||
83 | // print or convert trace? | |
84 | if (gbl.totype == NONE) { // then we're printing | |
85 | uint64_t idx; | |
86 | ||
87 | if (gbl.reorderIns) { | |
88 | idx = gbl.icount - 1 - gbl.skipInstrs; | |
89 | } else if (gbl.reorderNoIns) { | |
90 | idx = gbl.rcount - gbl.icount + | |
91 | gbl.skipRecs + gbl.skipInstrsRecs; | |
92 | } else { | |
93 | idx = gbl.rcount - 1 + gbl.skipRecs + gbl.skipInstrsRecs; | |
94 | } | |
95 | ||
96 | if (gbl.record) { | |
97 | itrace->print_rec(idx); | |
98 | } else if (gbl.disassembly) { | |
99 | itrace->print_dasm(idx); | |
100 | } else { | |
101 | itrace->print_verb(idx); | |
102 | } | |
103 | } else if (gbl.fromtype == RST && gbl.totype == RST) { | |
104 | otrace->copy_to_rst(itrace->copy_from_rst()); | |
105 | } else { // then we're converting | |
106 | itrace->convert_to_master(); | |
107 | ||
108 | if (prev_icount != gbl.icount) { // instruction converted? | |
109 | otrace->convert_from_master(itrace->get_master()); | |
110 | } | |
111 | } | |
112 | } // checkError? | |
113 | } // if !gbl.countOnly | |
114 | ||
115 | if ((gbl.totype != NONE && prev_icount != gbl.icount) || | |
116 | (gbl.fromtype == RST && gbl.totype == RST)) { | |
117 | otrace->inc_tr(); | |
118 | buffer_instrs++; | |
119 | ||
120 | if (buffer_instrs == BUFFER_SIZE) { | |
121 | otrace->reset_tr(); | |
122 | fwrite(otr_buf, gbl.tosize, buffer_instrs, gbl.outfp); | |
123 | buffer_instrs = 0; | |
124 | } | |
125 | } | |
126 | } // in_range pc, ea? | |
127 | } | |
128 | ||
129 | itrace->inc_tr(); | |
130 | } | |
131 | ||
132 | return buffer_instrs; | |
133 | } | |
134 | ||
135 | void process_trace(Trace* itrace, Trace* otrace, | |
136 | void* itr_buf, void* otr_buf) { | |
137 | int i, ntr, buffer_instrs; | |
138 | ||
139 | itrace->set_tr(itr_buf); | |
140 | if (otrace != NULL) { | |
141 | otrace->set_tr(otr_buf); | |
142 | } | |
143 | ||
144 | if (gbl.skipRecs) { | |
145 | ||
146 | if (0 && (gbl.infp != stdin)) { | |
147 | off_t offset; | |
148 | off_t filesize; | |
149 | ||
150 | fseeko(gbl.infp, 0, SEEK_END); | |
151 | filesize = ftello(gbl.infp); | |
152 | ||
153 | offset = gbl.skipRecs * gbl.fromsize; | |
154 | ||
155 | if (offset < filesize) { | |
156 | fseeko(gbl.infp, offset, SEEK_SET); | |
157 | } else { | |
158 | fprintf(stderr, "Fewer than %lld records in file '%s' (%lld).\n", | |
159 | gbl.skipRecs, gbl.infile, filesize / gbl.fromsize); | |
160 | exit(2); | |
161 | } | |
162 | } else { | |
163 | master_64bit_trace_t *buf; | |
164 | ||
165 | buf = (master_64bit_trace_t*) malloc(BUFFER_SIZE * | |
166 | sizeof(master_64bit_trace_t)); | |
167 | ||
168 | for (i = 0; i < gbl.skipRecs / BUFFER_SIZE; i++) { | |
169 | if (fread(buf, gbl.fromsize, BUFFER_SIZE, gbl.infp) < BUFFER_SIZE) { | |
170 | fprintf(stderr, "Fewer than %lld records in file '%s'.\n", | |
171 | gbl.skipRecs, gbl.infile); | |
172 | exit(2); | |
173 | if (gbl.fromtype == RST) { | |
174 | rstf_unionT * ru = (rstf_unionT *) buf; | |
175 | if (ru->proto.rtype == RSTHEADER_T) { | |
176 | if (ru->header.majorVer*1000+ru->header.minorVer <= 2011) { | |
177 | gbl.rstf_pre212 = true; | |
178 | } | |
179 | } // if rstheader | |
180 | } // if fromtype==rst | |
181 | } // if not end-of-file | |
182 | } // for skip recs | |
183 | ||
184 | if (fread(buf, gbl.fromsize, (uint32_t)(gbl.skipRecs % BUFFER_SIZE), gbl.infp) < | |
185 | gbl.skipRecs % BUFFER_SIZE) { | |
186 | fprintf(stderr, "Fewer than %lld records in file '%s'.\n", | |
187 | gbl.skipRecs, gbl.infile); | |
188 | exit(2); | |
189 | } | |
190 | ||
191 | free(buf); | |
192 | } | |
193 | } | |
194 | ||
195 | else if (gbl.skipInstrs) { | |
196 | // if from type is rst, first record must be rstheader | |
197 | ||
198 | while ((ntr = fread(itr_buf, gbl.fromsize, BUFFER_SIZE, gbl.infp))) { | |
199 | if (gbl.fromtype == RST) { | |
200 | rstf_unionT * ru = (rstf_unionT *) itr_buf; | |
201 | if (ru->proto.rtype == RSTHEADER_T) { | |
202 | if (ru->header.majorVer*1000+ru->header.minorVer <= 2011) { | |
203 | gbl.rstf_pre212 = true; | |
204 | } | |
205 | } | |
206 | } | |
207 | for (i = 0; gbl.icount < gbl.skipInstrs && i < ntr; i++) { | |
208 | itrace->count(); // -patchcleanrst done here | |
209 | itrace->inc_tr(); | |
210 | } | |
211 | ||
212 | if (gbl.icount == gbl.skipInstrs) { | |
213 | break; | |
214 | } | |
215 | ||
216 | itrace->reset_tr(); | |
217 | } | |
218 | ||
219 | buffer_instrs = process_buffer(itrace, otrace, itr_buf, otr_buf, i, ntr); | |
220 | ||
221 | if (gbl.verify) { | |
222 | itrace->verify(); | |
223 | } | |
224 | ||
225 | itrace->reset_tr(); | |
226 | ||
227 | gbl.skipInstrsRecs = gbl.rcount; | |
228 | gbl.rcount = 0; | |
229 | gbl.icount = 0; | |
230 | } | |
231 | ||
232 | while (gbl.rcount < gbl.maxRecs && | |
233 | gbl.icount < gbl.maxInstrs && | |
234 | (ntr = fread(itr_buf, gbl.fromsize, BUFFER_SIZE, gbl.infp))) { | |
235 | buffer_instrs = process_buffer(itrace, otrace, itr_buf, otr_buf, 0, ntr); | |
236 | ||
237 | if (gbl.verify) { | |
238 | itrace->verify(); | |
239 | } | |
240 | ||
241 | itrace->reset_tr(); | |
242 | } | |
243 | ||
244 | // any leftover instrs to fwrite...? | |
245 | if (buffer_instrs) { | |
246 | fwrite(otr_buf, gbl.tosize, buffer_instrs, gbl.outfp); | |
247 | } | |
248 | ||
249 | if (gbl.verbose || gbl.countOnly) { | |
250 | print_counts(gbl.msgfp); | |
251 | } | |
252 | } | |
253 | ||
254 | int main(int argc, char *argv[]) { | |
255 | void* itr_buf; | |
256 | void* otr_buf; | |
257 | Trace* itrace; | |
258 | Trace* otrace; | |
259 | rtf99 itr_rtf99, otr_rtf99; | |
260 | Shade5 itr_shade5, otr_shade5; | |
261 | Shade6x32 itr_shade6x32, otr_shade6x32; | |
262 | Shade6x64 itr_shade6x64, otr_shade6x64; | |
263 | Master itr_master, otr_master; | |
264 | RSTF_Union itr_rstf_union, otr_rstf_union; | |
265 | ||
266 | init_globals(argv); | |
267 | parse_args(argc, argv); | |
268 | ||
269 | // make input trace buffer | |
270 | itr_buf = calloc(BUFFER_SIZE, gbl.fromsize); | |
271 | if (itr_buf == NULL) { | |
272 | fprintf(stderr, | |
273 | "Could not allocate memory for itr_buf[] in main().\n"); | |
274 | exit(2); | |
275 | } | |
276 | ||
277 | // make output trace buffer, if conversion specified | |
278 | if (gbl.totype != NONE) { | |
279 | otr_buf = calloc(BUFFER_SIZE, gbl.tosize); | |
280 | if (otr_buf == NULL) { | |
281 | fprintf(stderr, | |
282 | "Could not allocate memory for otr_buf[] in main().\n"); | |
283 | exit(2); | |
284 | } | |
285 | } | |
286 | ||
287 | switch (gbl.fromtype) { | |
288 | case RTF99: | |
289 | itrace = &itr_rtf99; | |
290 | break; | |
291 | case SHADE5: | |
292 | itrace = &itr_shade5; | |
293 | break; | |
294 | case SHADE6x32: | |
295 | itrace = &itr_shade6x32; | |
296 | break; | |
297 | case SHADE6x64: | |
298 | itrace = &itr_shade6x64; | |
299 | break; | |
300 | case MASTER64: | |
301 | itrace = &itr_master; | |
302 | break; | |
303 | case RST: | |
304 | itrace = &itr_rstf_union; | |
305 | break; | |
306 | case NONE: | |
307 | usage(argv[0]); | |
308 | exit(1); | |
309 | default: | |
310 | fprintf(stderr, switch_error_string, "fromtype", "main()", gbl.fromtype); | |
311 | exit(2); | |
312 | } | |
313 | ||
314 | switch (gbl.totype) { | |
315 | case RTF99: | |
316 | otrace = &otr_rtf99; | |
317 | break; | |
318 | case SHADE5: | |
319 | otrace = &otr_shade5; | |
320 | break; | |
321 | case SHADE6x32: | |
322 | otrace = &otr_shade6x32; | |
323 | break; | |
324 | case SHADE6x64: | |
325 | otrace = &otr_shade6x64; | |
326 | break; | |
327 | case MASTER64: | |
328 | otrace = &otr_master; | |
329 | break; | |
330 | case RST: | |
331 | otrace = &otr_rstf_union; | |
332 | break; | |
333 | case NONE: | |
334 | otrace = NULL; | |
335 | break; | |
336 | default: | |
337 | fprintf(stderr, switch_error_string, "totype", "main()", gbl.totype); | |
338 | exit(2); | |
339 | } | |
340 | ||
341 | process_trace(itrace, otrace, itr_buf, otr_buf); | |
342 | ||
343 | return 0; | |
344 | } // main() |