Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / rst / rstzip3 / rstzip_v2 / rstzip.H
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: rstzip.H
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23// ========== Copyright Header Begin ==========================================
24//
25// OpenSPARC T2 Processor File: rstzip.H
26// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
27// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
28//
29// The above named program is free software; you can redistribute it and/or
30// modify it under the terms of the GNU General Public
31// License version 2 as published by the Free Software Foundation.
32//
33// The above named program is distributed in the hope that it will be
34// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
35// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
36// General Public License for more details.
37//
38// You should have received a copy of the GNU General Public
39// License along with this work; if not, write to the Free Software
40// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
41//
42// ========== Copyright Header End ============================================
43#ifndef _RSTZIP_H
44#define _RSTZIP_H
45
46// File: rstzip.H
47//
48
49#define DBGFP stdout
50
51#include <ctype.h>
52#include <limits.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <sys/types.h>
57
58#include "rz_insttypes.h"
59#if 0
60#include "spix6plus/IHASH.h"
61#include "spix6plus/ITYPES.h"
62#include "spix6plus/MISC.h"
63#include "spix6plus/reguse.h"
64#endif
65
66#include "rstf/rstf.h"
67#include "zlib.h"
68#include "hash.H"
69#include "pstate.H"
70#include "VCache.h"
71
72
73#ifdef COM_DEBUG
74 #define comDebug( str ) fprintf( stderr, str )
75 #define comDebugP( str, var ) fprintf( stderr, str, var )
76#else
77 #define comDebug( str )
78 #define comDebugP( str, var )
79#endif
80
81#ifdef DEC_DEBUG
82 #define decDebug( str ) fprintf( stderr, str )
83 #define decDebugP( str, var ) fprintf( stderr, str, var )
84#else
85 #define decDebug( str )
86 #define decDebugP( str, var )
87#endif
88
89#if 0 // removed - 20040210 (vp)
90static int ih_ispcrelcti(int ih) {
91 return (ih_isbranch(ih) || ih == IH_CALL);
92}
93#endif
94
95// static int carry_ea(int ih, int ea_valid) { // changed - 20040210 (vp)
96static int carry_ea(uint32_t iw, int ea_valid) {
97 // return (ea_valid == 1 && ih_ispcrelcti(ih) == 0); // replaced - 20040210 (vp)
98 return (ea_valid == 1 && !rz_is_pc_relative_cti(iw));
99}
100
101
102#define MAX(a, b) (((a) > (b)) ? (a) : (b))
103
104enum {
105 MAX_CHUNKSIZE = 1000,
106 CHECKSUM_FREQ = 16,
107
108 INSTR_FOLLOWS = 0,
109 NONINSTR_FOLLOWS = 1,
110
111 CHUNKSIZE_RES = 10,
112
113 NEW_RTYPES_START = 160,
114 NEW_RTYPES = 13,
115
116 RSTZIP_MAX_CONTEXTS = 8192
117};
118
119enum {
120 z_HEADER_T = NEW_RTYPES_START,
121 z_FOOTER_T,
122
123 z_INSTR_T, // compressed chunk
124 zL_INSTR_T, // compressed loop chunk
125
126 z0_PAVADIFF_T, // compresed pavadiff at cache index n
127 z1_PAVADIFF_T,
128 z2_PAVADIFF_T,
129 z3_PAVADIFF_T,
130 z4_PAVADIFF_T,
131 z5_PAVADIFF_T,
132 z6_PAVADIFF_T,
133 z7_PAVADIFF_T,
134
135 z_CCR_T, // condition-code register
136 z_REGID_T, // register id
137 z_REGVAL_8_T, // 1-byte register value
138 z_REGVAL_16_T, // 2-byte register value
139 z_REGVAL_32_T, // 4-byte register value
140 z_REGVAL_64_T, // 8-byte register value
141 z_REGIDX_T, // 2-byte register index
142 z_VALUE_MINUS1_T, // These are the literal values -1 to 8
143 z_VALUE_0_T,
144 z_VALUE_1_T,
145 z_VALUE_2_T,
146 z_VALUE_3_T,
147 z_VALUE_4_T,
148 z_VALUE_5_T,
149 z_VALUE_6_T,
150 z_VALUE_7_T,
151 z_VALUE_8_T,
152 z_REGPAIR_T, // indicates that the next two register values should be
153 // merged into a single RST regval record.
154 z_LAST_T
155};
156
157enum {
158 OFFSET_8BITS_IDX = 0,
159 OFFSET_8BITS_RESERVED_IDX = 1,
160 OFFSET_16BITS_IDX = 2,
161 OFFSET_32BITS_IDX = 3,
162 OFFSET_64BITS_IDX = 4,
163
164 RESERVED_OFFSET_8BITS = -125, // (0xffffff83)
165 RESERVED_OFFSET_16BITS = -123, // (0xffffff85)
166 RESERVED_OFFSET_32BITS = 123, // (0x7b)
167 RESERVED_OFFSET_64BITS = 125, // (0x7d)
168
169 NUM_RESERVED_OFFSETS = 4,
170
171 PADDING_SIZE0 = 2,
172 FILENAME_STRING_SIZE = 256,
173 DATE_STRING_SIZE = 32,
174 HASH_FUNC_STRING_SIZE = 64,
175 PADDING_SIZE1 = 630
176};
177
178enum {
179 NOTUSED = 0x80,
180 EA_VALID = 0x40,
181 TR = 0x20,
182 NOTUSED2 = 0x10,
183 PR = 0x08,
184 BT = 0x04,
185 AN = 0x02,
186 RSRVD_CMPRSS = 0x01
187};
188
189typedef uint8_t flags_t;
190
191class RstzipBase {
192public:
193 // Options
194 bool compress; // Set to 1 to compress, 0 to decompress
195 uint8_t checksum_freq; // Add checksum every n chunks (default=16)
196
197 // stats
198 uint32_t max_chunksize;
199 uint64_t total_instr;
200 uint64_t total_noninstr;
201 uint64_t total_loop_chunk;
202 uint64_t total_nonloop_chunk;
203 uint64_t total_zpavadiff;
204 uint64_t total_pavadiff;
205 uint64_t zero_offset_count;
206 uint64_t offset_count[OFFSET_64BITS_IDX + 1];
207 uint64_t chunksize_count[CHUNKSIZE_RES];
208
209 RstzipHash hash;
210 RstzipPavadiffCache pava_cache;
211
212 // Constructor (initialize file footer variables).
213 RstzipBase() {
214 max_chunksize = 0;
215 total_instr = 0;
216 total_noninstr = 0;
217 total_loop_chunk = 0;
218 total_nonloop_chunk = 0;
219 total_zpavadiff = 0;
220 total_pavadiff = 0;
221 zero_offset_count = 0;
222
223 memset(offset_count, 0, (OFFSET_64BITS_IDX + 1) * sizeof(uint64_t));
224 memset(chunksize_count, 0, CHUNKSIZE_RES * sizeof(uint64_t));
225
226 print_chunk_chksm = 0;
227 print_chunk_chunk_counter = 0;
228
229 compress = -1;
230 checksum_freq = CHECKSUM_FREQ;
231 } // RstzipBase::RstzipBase()
232
233protected:
234 // header info
235 uint8_t rtype;
236 uint16_t num_instr; // number of instructions in chunk
237 uint64_t pc_start; // pc of 1st instruction in chunk
238
239 // data buffers
240 uint32_t instr_buf[MAX_CHUNKSIZE]; // instruction words in chunk
241 uint64_t ea_buf[MAX_CHUNKSIZE]; // ea of ld/st+cti instructions
242 flags_t flags_buf[MAX_CHUNKSIZE]; // flags for each instruction
243 uint8_t noninstr_count_buf[MAX_CHUNKSIZE]; // counts of non-instr chunks
244 int lastRegIdBuf[MAX_CHUNKSIZE]; // the regid observed in an instruction
245 rstf_instrT noninstr_buf[MAX_CHUNKSIZE]; // non-instr records in chunk
246
247 // misc info
248 int num_ea; // number of ld/st+cti instrs in chunk
249 int num_noninstr; // non-instruction records in chunk
250 int num_total; // num_instr + num_noninstr
251 int num_noninstr_count; // size of noninstr_count_buf[]
252
253
254 // flags support
255 flags_t set_flags(flags_t* flags, int mask, int val) {
256 flags_t flgs = *flags;
257
258 if (val) {
259 flgs = flgs | mask;
260 } else {
261 flgs = flgs & ~mask;
262 }
263
264 *flags = flgs;
265
266 return flgs;
267 } // RstzipBase::set_flags()
268
269 uint64_t compute_checksum64() {
270 int i;
271 uint64_t chksm;
272
273 chksm = rtype + num_instr + pc_start;
274
275 for (i = 0; i < num_instr; i++) {
276 chksm += instr_buf[i] + flags_buf[i];
277 }
278
279 for (i = 0; i < num_ea; i++) {
280 chksm += ea_buf[i];
281 }
282
283 for (i = 0; i < num_noninstr; i++) {
284 chksm += noninstr_buf[i].rtype;
285 }
286
287 for (i = 0; i < num_noninstr_count; i++) {
288 chksm += noninstr_count_buf[i];
289 }
290
291 return chksm;
292 } // RstzipBase::compute_checksum64()
293
294 int check_buffersize(int nrecs) {
295 if (nrecs < MAX_CHUNKSIZE) {
296 return MAX_CHUNKSIZE - nrecs;
297 }
298
299 return 0;
300 } // RstzipBase::check_buffersize()
301
302 int get_flags(flags_t flags, int mask) {
303 return ((flags & mask) ? 1 : 0);
304 } // RstzipBase::get_flags()
305
306 uint64_t print_chunk_chksm;
307 uint64_t print_chunk_chunk_counter;
308
309 void print_chunk(FILE* fp) {
310 int i;
311
312 if (rtype != 0) {
313 fprintf(fp, "[BOC] rtype=%d\n", rtype);
314 fprintf(fp, "num_instr=%d\n", num_instr);
315 fprintf(fp, "pc_start=0x%llx\n", pc_start);
316 fprintf(fp, "\n");
317 fprintf(fp, "num_ea=%d\n", num_ea);
318 fprintf(fp, "num_noninstr=%d\n", num_noninstr);
319 fprintf(fp, "num_total=%d\n", num_total);
320 fprintf(fp, "num_noninstr_count=%d\n", num_noninstr_count);
321 fprintf(fp, "\n");
322
323 for (i = 0; i < num_instr; i++) {
324 fprintf(fp, "(%x)\n", instr_buf[i]);
325 }
326 fprintf(fp, "\n");
327
328 for (i = 0; i < num_instr; i++) {
329 fprintf(fp, "(%02x)\n", flags_buf[i]);
330 }
331 fprintf(fp, "\n");
332
333 for (i = 0; i < num_ea; i++) {
334 fprintf(fp, "(0x%llx)\n", ea_buf[i]);
335 }
336 fprintf(fp, "\n");
337
338 for (i = 0; i < num_noninstr_count; i++) {
339 fprintf(fp, "%d ", noninstr_count_buf[i]);
340 }
341 fprintf(fp, "\n\n");
342
343 for (i = 0; i < num_noninstr; i++) {
344 print_rstrec(fp, &noninstr_buf[i]);
345 }
346 fprintf(fp, "\n");
347
348 if (checksum_freq != 0) {
349 print_chunk_chksm += compute_checksum64();
350 print_chunk_chunk_counter++;
351
352 if (print_chunk_chunk_counter % checksum_freq == 0) {
353 fprintf(fp, "checksum=%016llx\n", print_chunk_chksm);
354 print_chunk_chksm = 0;
355 }
356 }
357
358 fprintf(fp, "[EOC] max_chunksize=%d\n", max_chunksize);
359 }
360 } // RstzipBase::print_chunk()
361
362 void print_rstbuf(FILE* fp, rstf_instrT buf[], int num) {
363 int i;
364
365 for (i = 0; i < num; i++) {
366 print_rstrec(fp, &buf[i]);
367 }
368 fprintf(fp, "\n");
369 } // RstzipBase::print_rstbuf()
370
371 void print_rstrec(FILE* fp, rstf_instrT* rst) {
372 switch (rst->rtype) {
373 case RSTHEADER_T:
374 fprintf(fp, "rstheader\n");
375 break;
376 case INSTR_T:
377 fprintf(fp, "[0x%llx] ", rst->pc_va);
378 // fprintDiss(fp, rst->instr, rst->pc_va);
379 fprintf(fp, "\n");
380 break;
381#if 0
382 case ASI_T:
383 fprintf(fp, "asi\n");
384 break;
385#endif
386 case MEMVAL_T:
387 fprintf( fp, "memval\n" );
388 break;
389 case TLB_T:
390 fprintf(fp, "tlb\n");
391 break;
392 case THREAD_T:
393 fprintf(fp, "thread\n");
394 break;
395 case TRAP_T:
396 fprintf(fp, "trap\n");
397 break;
398 case TRAPEXIT_T:
399 fprintf(fp, "trapexit\n");
400 break;
401 case REGVAL_T:
402 fprintf(fp, "regval\n");
403 break;
404 case TIMESTAMP_T:
405 fprintf(fp, "timestamp\n");
406 break;
407 case PROCESS_T:
408 fprintf(fp, "process\n");
409 break;
410 case DMA_T:
411 fprintf(fp, "dma\n");
412 break;
413 case STRDESC_T:
414 fprintf(fp, "strdesc\n");
415 break;
416 case LEFTDELIM_T:
417 fprintf(fp, "leftdelim\n");
418 break;
419 case RIGHTDELIM_T:
420 fprintf(fp, "rightdelim\n");
421 break;
422 case PREG_T:
423 fprintf(fp, "preg\n");
424 break;
425 case PHYSADDR_T:
426 fprintf(fp, "physaddr\n");
427 break;
428 case PAVADIFF_T:
429#if 0
430 fprintf(fp, "pavadiff\n");
431#else
432 rstf_pavadiffT rst_pava;
433
434 memcpy(&rst_pava, rst, sizeof(rstf_unionT));
435 fprintf(fp, "pavadiff: icontext=%d dcontext=%d pc_pa_va=0x%016llx ea_pa_va=0x%016llx\n",
436 rst_pava.icontext, rst_pava.dcontext, rst_pava.pc_pa_va, rst_pava.ea_pa_va);
437#endif
438 break;
439 case NULLREC_T:
440 fprintf(fp, "nullrec\n");
441 break;
442 case STRCONT_T:
443 fprintf(fp, "strcont\n");
444 break;
445 case FILEMARKER_T:
446 fprintf(fp, "filemarker\n");
447 break;
448 case PATCH_T:
449 fprintf(fp, "patch\n");
450 break;
451 case STATUS_T:
452 fprintf(fp, "status\n");
453 break;
454#if 0
455 case SNOOP_T:
456 fprintf(fp, "snoop\n");
457 break;
458#endif
459 case z_HEADER_T:
460 fprintf(fp, "file header\n");
461 break;
462 case z_FOOTER_T:
463 fprintf(fp, "file footer\n");
464 break;
465 case z_INSTR_T:
466 fprintf(fp, "compressed header\n");
467 break;
468 case zL_INSTR_T:
469 fprintf(fp, "compressed loop header\n");
470 break;
471 case z0_PAVADIFF_T:
472 fprintf(fp, "compressed pavadiff [0]\n");
473 break;
474 case z1_PAVADIFF_T:
475 fprintf(fp, "compressed pavadiff [1]\n");
476 break;
477 case z2_PAVADIFF_T:
478 fprintf(fp, "compressed pavadiff [2]\n");
479 break;
480 case z3_PAVADIFF_T:
481 fprintf(fp, "compressed pavadiff [3]\n");
482 break;
483 case z4_PAVADIFF_T:
484 fprintf(fp, "compressed pavadiff [4]\n");
485 break;
486 case z5_PAVADIFF_T:
487 fprintf(fp, "compressed pavadiff [5]\n");
488 break;
489 case z6_PAVADIFF_T:
490 fprintf(fp, "compressed pavadiff [6]\n");
491 break;
492 case z7_PAVADIFF_T:
493 fprintf(fp, "compressed pavadiff [7]\n");
494 break;
495 case z_CCR_T:
496 fprintf(fp, "Condition Code Register\n" );
497 break;
498 case z_REGID_T:
499 fprintf(fp, "Integer Register Id\n" );
500 break;
501 case z_REGVAL_8_T:
502 fprintf(fp, "1-byte register value\n" );
503 break;
504 case z_REGVAL_16_T:
505 fprintf(fp, "2-byte register value\n" );
506 break;
507 case z_REGVAL_32_T:
508 fprintf(fp, "4-byte register value\n" );
509 break;
510 case z_REGVAL_64_T:
511 fprintf(fp, "8-byte register value\n" );
512 break;
513 case z_REGIDX_T:
514 fprintf(fp, "register value cache index\n" );
515 break;
516 case z_VALUE_MINUS1_T:
517 fprintf(fp, "integer value -1\n" );
518 break;
519 case z_VALUE_0_T:
520 fprintf(fp, "integer value 0\n" );
521 break;
522 case z_VALUE_1_T:
523 fprintf(fp, "integer value 1\n" );
524 break;
525 case z_VALUE_2_T:
526 fprintf(fp, "integer value 2\n" );
527 break;
528 case z_VALUE_3_T:
529 fprintf(fp, "integer value 3\n" );
530 break;
531 case z_VALUE_4_T:
532 fprintf(fp, "integer value 4\n" );
533 break;
534 case z_VALUE_5_T:
535 fprintf(fp, "integer value 5\n" );
536 break;
537 case z_VALUE_6_T:
538 fprintf(fp, "integer value 6\n" );
539 break;
540 case z_VALUE_7_T:
541 fprintf(fp, "integer value 7\n" );
542 break;
543 case z_VALUE_8_T:
544 fprintf(fp, "integer value 8\n" );
545 break;
546 case z_REGPAIR_T:
547 fprintf(fp, "register pair marker\n" );
548 break;
549
550 default:
551 int i, j, range = 1;
552 uint8_t* c_ptr = (uint8_t*) (rst - range);
553
554 for (i = range; i > 0; i--) {
555 for (j = 0; j < sizeof(rstf_instrT); j++) {
556 fprintf(fp, "%02x", *c_ptr);
557 c_ptr++;
558 }
559 fprintf(fp, " -> -%d\n", i);
560 }
561
562 for (j = 0; j < sizeof(rstf_instrT); j++) {
563 fprintf(fp, "%02x", *c_ptr);
564 c_ptr++;
565 }
566 fprintf(fp, " -> Unknown rtype (%02x)\n", rst->rtype);
567
568 for (i = 1; i <= range; i++) {
569 for (j = 0; j < sizeof(rstf_instrT); j++) {
570 fprintf(fp, "%02x", *c_ptr);
571 c_ptr++;
572 }
573 fprintf(fp, " -> +%d\n", i);
574 }
575
576 exit(2);
577 }
578
579 fflush(fp);
580 } // RstzipBase::print_rstrec()
581
582 bool isIntRegCompressable( const rstf_regvalT *r )
583 {
584 return r->regtype[0] == RSTREG_INT_RT &&
585 ( r->regtype[1] == RSTREG_UNUSED_RT || r->regtype[1] == RSTREG_CC_RT || r->regtype[1] == RSTREG_INT_RT );
586 }
587
588
589 bool compressedRegType( int rt )
590 {
591
592 switch( rt ){
593 case z_CCR_T:
594 case z_REGID_T:
595 case z_REGVAL_8_T:
596 case z_REGVAL_16_T:
597 case z_REGVAL_32_T:
598 case z_REGVAL_64_T:
599 case z_REGIDX_T:
600 case z_VALUE_0_T:
601 case z_VALUE_1_T:
602 case z_VALUE_2_T:
603 case z_VALUE_3_T:
604 case z_VALUE_4_T:
605 case z_VALUE_5_T:
606 case z_VALUE_6_T:
607 case z_VALUE_7_T:
608 case z_VALUE_8_T:
609 case z_VALUE_MINUS1_T:
610 case z_REGPAIR_T:
611 return true;
612 default:
613 return false;
614 }
615 }
616
617
618}; // RstzipBase
619
620// RST decompression class.
621class Rstunzip : public RstzipBase {
622public:
623 Rstunzip() {
624 inbuf = NULL;
625 inbuf_ptr = NULL;
626 outbuf= NULL;
627 outbuf_ptr= NULL;
628
629 rstz_decompress_unzipped_recs = 0;
630 rstz_decompress_fbytes = 0;
631 //rstz_decompress_prev_nrecs = 0;
632 unzip_chunk_chksm_sum = 0;
633 unzip_chunk_chunk_counter = 0;
634 memset(&read_noninstr_rec_rst, 0, sizeof(rstf_unionT));
635
636 icontext = 0;
637#ifdef DEC_DEBUG
638 iCtr = 1;
639#endif
640 lastRd = -1;
641 }
642
643 ~Rstunzip() {
644 //free(inbuf);
645 free(outbuf);
646 }
647
648 int rstz_decompress_unzipped_recs; // new recs unzipped in next chunk in outbuf
649 int rstz_decompress_fbytes; // number of bytes of compressed data fread()
650 // Decompress up to nrecs RST records from *infp into buf[].
651 // Returns number of records decompressed. Upon return, *infp will
652 // point to the start of the next compressed record.
653 int rstz_decompress(uint8_t** zbufptr, rstf_unionT* rstbuf, int nrecs) {
654 int total_recs = 0; // total recs copied to buf[]
655 rstf_instrT* buf_ptr = &rstbuf[0].instr;
656
657#if 0
658 if (nrecs == 0) {
659 return 0;
660 }
661#endif
662
663 inbuf = *zbufptr;
664 outbuf = &rstbuf[0].instr;
665 inbuf_ptr = inbuf;
666 outbuf_ptr = outbuf;
667 rstz_decompress_fbytes = 0;
668 rstz_decompress_unzipped_recs = 0;
669
670 total_recs = 0;
671
672 // Unzip chunks from inbuf[] until buf[] cannot take another chunk.
673 while (total_recs < nrecs) {
674 rstz_decompress_unzipped_recs = unzip_chunk();
675
676 if (num_instr > 0) {
677 max_chunksize = MAX(max_chunksize, rstz_decompress_unzipped_recs);
678#if _DEBUG0
679 print_chunk(DBGFP);
680 fprintf(DBGFP, "zrecs_o()=%d total_recs=%d nrecs=%d\n\n", zrecs_o(), total_recs, nrecs);
681#endif
682 }
683
684 total_recs += rstz_decompress_unzipped_recs;
685 total_instr += num_instr;
686 total_noninstr += rstz_decompress_unzipped_recs - num_instr;
687
688 if (*inbuf_ptr == z_FOOTER_T) {
689 break;
690 }
691 }
692
693 *zbufptr = inbuf_ptr + 1;
694
695 return total_recs;
696 } // Rstunzip::rstz_decompress()
697
698protected:
699
700 // rd-compression member data:
701 VCache valueCache;
702 int lastRd;
703#ifdef DEC_DEBUG
704 int iCtr;
705#endif
706 ///////////////////////////////
707
708 uint8_t* inbuf; // input buffer for (de)compressed traces
709 uint8_t* inbuf_ptr; // always points to current inbuf location
710 rstf_instrT* outbuf; // output buffer for (de)compressed traces
711 rstf_instrT* outbuf_ptr; // always points to current outbuf location
712
713 Pstate pstate;
714 int icontext;
715
716 uint64_t unzip_chunk_chksm_sum;
717 uint64_t unzip_chunk_chunk_counter;
718 // Decompress one chunk from inbuf[] into outbuf[]. Return the
719 // number of records decompressed.
720 int unzip_chunk() {
721 int prerecs, hashval, set;
722 uint64_t chksm;
723 hash_table_t* table;
724
725 // init some data members
726 rtype = 0;
727 pc_start = 0;
728 num_instr = 0;
729 num_ea = 0;
730 num_noninstr = 0;
731 num_total = 0;
732 num_noninstr_count = 0;
733
734 memset(noninstr_count_buf, 0, MAX_CHUNKSIZE * sizeof(uint8_t));
735
736 prerecs = 0;
737
738 // find next compressed chunk rtype
739 while ((*inbuf_ptr < z_FOOTER_T || *inbuf_ptr > zL_INSTR_T) && prerecs < MAX_CHUNKSIZE) {
740 //print_rstrec(DBGFP, (rstf_instrT*) inbuf_ptr);
741
742 if (*inbuf_ptr == PREG_T) {
743 rstf_pregT preg;
744
745 memcpy(&preg, inbuf_ptr, sizeof(rstf_pregT));
746 //pstate[preg.primD].pstate = preg.pstate;
747 pstate.pstate = preg.pstate;
748 } else if (*inbuf_ptr == PAVADIFF_T) {
749 rstf_pavadiffT pavadiff;
750
751 memcpy(&pavadiff, inbuf_ptr, sizeof(rstf_pavadiffT));
752 icontext = pavadiff.icontext;
753 }
754
755 write_rst2outbuf(read_noninstr_rec(), 1);
756 prerecs++;
757 }
758
759 // If there were any non-instruction records before the chunk,
760 // just return so the next time unzip_chunk() is called it will
761 // start pointing at an instruction record. This is necessary in
762 // case prerecs + num_instr + num_noninstr > nrecs.
763 if (prerecs == 0 && *inbuf_ptr != z_FOOTER_T) {
764 // inbuf_ptr now points to a compressed chunk rtype
765 read_inbuf(&rtype, sizeof(rtype));
766 read_inbuf(&num_instr, sizeof(num_instr));
767 read_inbuf(&pc_start, sizeof(pc_start));
768
769#ifdef DEC_DEBUG
770 static int chunkNumber = 0;
771 fprintf(stderr, "Chunk #%d\n", chunkNumber++ );
772 fprintf(stderr, " decoding %u instructions starting at pc 0x%llx\n", num_instr, pc_start );
773 for( int i = 0; i < num_instr; ++i ){
774 fprintf( stderr, " %d) instr\n", iCtr++ );
775 }
776#endif
777
778 hashval = hash.hash(pc_start);
779
780 if (rtype <= z_INSTR_T) { // non-loop rtype
781 read_inbuf(instr_buf, num_instr * sizeof(uint32_t));
782 read_inbuf(flags_buf, num_instr * sizeof(flags_t));
783 find_num_ea();
784 read_ea(NULL);
785
786 hash.write(pc_start, num_instr, instr_buf, num_ea, ea_buf, hashval);
787 total_nonloop_chunk++;
788 } else { // loop rtype
789 set = hash.search(pc_start, num_instr, NULL, hashval);
790 if (set == NOT_FOUND) {
791 hash.print_set(hashval);
792
793 fprintf(stderr, "Error: hash.search() returned NOT_FOUND "
794 "for zL64_INSTR_T, pc=0x%llx num_instr=%d\n",
795 pc_start, num_instr);
796 exit(2);
797 }
798
799 table = hash.read(set, hashval);
800 memcpy(instr_buf, table->instr_buf, num_instr * sizeof(uint32_t));
801
802 read_inbuf(flags_buf, num_instr * sizeof(flags_t));
803 find_num_ea();
804 read_ea(table);
805
806 hash.update(num_ea, ea_buf, hashval, set);
807 total_loop_chunk++;
808 }
809
810 find_num_noninstr_count();
811 read_inbuf(noninstr_count_buf, num_noninstr_count * sizeof(uint8_t));
812 find_num_noninstr();
813#ifdef DEC_DEBUG
814 fprintf( stderr, " nr. non-instructions: %d\n", num_noninstr );
815#endif
816 read_noninstr_recs();
817
818 if (checksum_freq != 0) {
819 unzip_chunk_chksm_sum += compute_checksum64();
820 unzip_chunk_chunk_counter++;
821
822 if (unzip_chunk_chunk_counter % checksum_freq == 0) {
823 read_inbuf(&chksm, 8);
824 if (chksm != unzip_chunk_chksm_sum) {
825 //hash.print_set(hashval);
826 //print_chunk(stderr);
827
828 fprintf(stderr,
829 "\nError: checksum inequality (0x%llx != 0x%llx) after record %llu\n",
830 chksm, unzip_chunk_chksm_sum, total_instr + total_noninstr);
831 exit(3);
832 }
833 unzip_chunk_chksm_sum = 0;
834 }
835 }
836
837 if (num_instr > 0) {
838 if (num_instr + num_noninstr < MAX_CHUNKSIZE) {
839 chunksize_count[(num_instr + num_noninstr) / (MAX_CHUNKSIZE / CHUNKSIZE_RES)]++;
840 } else {
841 chunksize_count[CHUNKSIZE_RES - 1]++;
842 }
843 }
844
845 write_chunk();
846 }
847
848 return num_instr + num_noninstr + prerecs;
849 } // Rstunzip::unzip_chunk()
850
851 // Build the RST's from instr_buf[], ea_buf[], flags_buf[], etc.,
852 // and writes the records in the chunk to *outbuf. Returns the
853 // number of records written.
854 int write_chunk() {
855 int i, j, ea_cnt, noninstr_cnt, noninstr_buf_cnt;
856 bool write_noninstr;
857 rstf_instrT rst;
858
859 ea_cnt = 0;
860 noninstr_cnt = 0;
861 noninstr_buf_cnt = 0;
862
863 for (i = 0; i < num_instr; i++) {
864 write_noninstr = false;
865
866 rst.rtype = INSTR_T;
867
868 // rst.notused = get_flags(flags_buf[i], NOTUSED);
869 rst.notused = 0;
870 get_flags(flags_buf[i], NOTUSED);
871
872 rst.ea_valid = get_flags(flags_buf[i], EA_VALID);
873 rst.tr = get_flags(flags_buf[i], TR);
874
875 // rst.notused2 = get_flags(flags_buf[i], NOTUSED2);
876 get_flags(flags_buf[i], NOTUSED2);
877 rst.hpriv = 0;
878
879 rst.pr = get_flags(flags_buf[i], PR);
880 rst.bt = get_flags(flags_buf[i], BT);
881 rst.an = get_flags(flags_buf[i], AN);
882
883 rst.reservedCompress = 0; // this field might go away in the future
884 int reservedCompress = get_flags(flags_buf[i], RSRVD_CMPRSS);
885 // get_flags(flags_buf[i], RSRVD_CMPRSS);
886
887 // rst.ihash = getIHash(instr_buf[i]); // removed - 20040210 (vp)
888 rst.cpuid9_6 = 0;
889 rst.notused3 = 0;
890
891 rst.instr = instr_buf[i];
892 rst.pc_va = pc_start + 4*i;
893
894 // if (carry_ea(rst.ihash, rst.ea_valid)) { // replaced - 20040210 (vp)
895 if (carry_ea(rst.instr, rst.ea_valid)) {
896 rst.ea_va = ea_buf[ea_cnt];
897 ea_cnt++;
898 } else if (rst.an == 0 && rz_is_pc_relative_cti(instr_buf[i])) {
899 // } else if (rst.an == 0 && ih_ispcrelcti(rst.ihash)) {
900 if (rst.bt == 1) {
901 // rst.ea_va = getCtiEa(rst.instr, rst.ihash, rst.pc_va); // replaced 20040210 (vp)
902 if (rz_is_bpr(rst.instr)) {
903 rst.ea_va = rst.pc_va+BPR_DISP(rst.instr);
904 } else if (rz_is_bicc(rst.instr)||rz_is_fbfcc(rst.instr)) {
905 rst.ea_va = rst.pc_va+Bicc_DISP(rst.instr);
906 } else if (rz_is_bpcc(rst.instr)||rz_is_fbpfcc(rst.instr)) {
907 rst.ea_va = rst.pc_va+BPcc_DISP(rst.instr);
908 } else if (rz_is_call(rst.instr)) {
909 rst.ea_va = rst.pc_va+CALL_DISP(rst.instr);
910 } else {
911 fprintf(stderr, "Unknown branch type (rst.bt==1, instr word=%08x)\n", rst.instr);
912 }
913
914 if (pstate.getField(PSTATE_AM) == 1) {
915 rst.ea_va &= 0xffffffff;
916 }
917 } else {
918 rst.ea_va = rst.pc_va + 8;
919 }
920 } else {
921 rst.ea_va = 0;
922 }
923
924
925 // these need to be set (not just computed below) because these values
926 // are used in read_noninstr_rec() for register records that are not part
927 // of a chunk of instructions.
928 lastRd = rst.instr >> 25 & 0x01F;
929
930 // write some non-instruction recs?
931 if (reservedCompress == NONINSTR_FOLLOWS) {
932 write_noninstr = true;
933 // rst.reservedCompress = 0;
934 }
935
936 write_rst2outbuf(&rst, 1);
937
938 if (write_noninstr) {
939 for (j = 0; j < noninstr_count_buf[noninstr_cnt]; j++) {
940
941 if (noninstr_buf[noninstr_buf_cnt].rtype == PREG_T) {
942 rstf_pregT* context = (rstf_pregT*) &noninstr_buf[noninstr_buf_cnt];
943 //pstate[context->primD].pstate = context->pstate;
944 pstate.pstate = context->pstate;
945 } else if (noninstr_buf[noninstr_buf_cnt].rtype == PAVADIFF_T) {
946 rstf_pavadiffT* pavadiff = (rstf_pavadiffT*) &noninstr_buf[noninstr_buf_cnt];
947 icontext = pavadiff->icontext;
948 } else if ( noninstr_buf[noninstr_buf_cnt].rtype == REGVAL_T ) {
949 // DECOMPRESS: setting proper register id
950 rstf_regvalT *rv = (rstf_regvalT*) &noninstr_buf[noninstr_buf_cnt];
951
952 // not the best solution, but these values don't make it into the trace
953 // so we're free to adopt a better solution later. SH
954 if ( rv->regid[0] == 255 ){
955 decDebugP( "[write_chunk()] Setting regid[0] to %u\n", lastRd );
956 rv->regid[0] = lastRd;
957 }
958 if ( rv->regid[1] == 255 ){
959 decDebugP( "[write_chunk()] Setting regid[1] to %u\n", lastRd );
960 rv->regid[1] = lastRd;
961 }
962
963 }
964 write_rst2outbuf(&noninstr_buf[noninstr_buf_cnt], 1);
965 noninstr_buf_cnt++;
966 }
967
968 noninstr_cnt++;
969 }
970 }
971
972 return num_instr + num_noninstr;
973 } // Rstunzip::write_chunk()
974
975 // Read instr_buf[] to count number of (valid) ld/st instructions.
976 int find_num_ea() {
977 int i, ih;
978
979 num_ea = 0;
980
981 for (i = 0; i < num_instr; i++) {
982 // ih = getIHash(instr_buf[i]); // removed - 20040210 (vp)
983
984 // if (carry_ea(ih, get_flags(flags_buf[i], EA_VALID))) { // (replaced - 20040212 (vp)
985 if (carry_ea(instr_buf[i], get_flags(flags_buf[i], EA_VALID))) {
986 num_ea++;
987 }
988 }
989
990 return num_ea;
991 } // Rstunzip::find_num_ea()
992
993 // Read flags_buf[] to count RSRVD_CMPRSS=1 fields .
994 int find_num_noninstr_count() {
995 int i;
996
997 num_noninstr_count = 0;
998
999 for (i = 0; i < num_instr; i++) {
1000 if (get_flags(flags_buf[i], RSRVD_CMPRSS) == NONINSTR_FOLLOWS) {
1001 num_noninstr_count++;
1002 }
1003 }
1004
1005 return num_noninstr;
1006 } // Rstunzip::find_num_noninstr_count()
1007
1008 // Sum noninstr_count_buf[].
1009 int find_num_noninstr() {
1010 int i;
1011
1012 num_noninstr = 0;
1013
1014 if (num_noninstr_count != 0) {
1015 num_noninstr = noninstr_count_buf[0];
1016 }
1017
1018 for (i = 1; i < num_noninstr_count; i++) {
1019 num_noninstr += noninstr_count_buf[i];
1020 }
1021
1022 return num_noninstr;
1023 } // Rstunzip::find_num_instr()
1024
1025 // Read n bytes from *inbuf_ptr into *to, and advance *inbuf_ptr.
1026 // Return the number of bytes read.
1027 int read_inbuf(void* to, size_t n) {
1028 memcpy(to, inbuf_ptr, n);
1029 inbuf_ptr += n;
1030
1031 return n;
1032 } // Rstunzip::read_inbuf()
1033
1034 // Write n RST records from from into outbuf_ptr, and advance
1035 // outbuf_ptr. Return the number of records written.
1036 int write_rst2outbuf(rstf_instrT* from, size_t n) {
1037 memcpy(outbuf_ptr, from, n * sizeof(rstf_instrT));
1038 outbuf_ptr += n;
1039
1040 return n;
1041 } // Rstunzip::write_rst2outbuf()
1042
1043 int read_ea(hash_table_t* table) {
1044 int8_t offset8;
1045 int16_t offset16;
1046 int32_t offset32;
1047 int64_t offset64;
1048 int i, n;
1049
1050 n = 0;
1051
1052 if (num_ea > 0) {
1053 if (rtype == z_INSTR_T) {
1054 n = read_inbuf(ea_buf, num_ea * sizeof(uint64_t));
1055 } else {
1056 for (i = 0; i < num_ea; i++) {
1057 n += read_inbuf(&offset8, sizeof(offset8));
1058
1059 switch (offset8) {
1060 case RESERVED_OFFSET_8BITS:
1061 n += read_inbuf(&offset8, sizeof(offset8));
1062 ea_buf[i] = table->ea_buf[i] + offset8;
1063
1064 offset_count[OFFSET_8BITS_RESERVED_IDX]++;
1065#ifdef _DEBUG0
1066 fprintf(DBGFP, "(Reserved 8) offset8=0x%02hx ", offset8);
1067 fprintf(DBGFP,
1068 "base=0x%llx offset8=0x%02hx ea=0x%llx\n",
1069 table->ea_buf[i], offset8, ea_buf[i]);
1070#endif
1071 break;
1072 case RESERVED_OFFSET_16BITS:
1073 n += read_inbuf(&offset16, sizeof(offset16));
1074 ea_buf[i] = table->ea_buf[i] + offset16;
1075
1076 offset_count[OFFSET_16BITS_IDX]++;
1077#ifdef _DEBUG0
1078 fprintf(DBGFP, "(Reserved 16) offset8=0x%02hx ", offset8);
1079 fprintf(DBGFP,
1080 "base=0x%llx offset16=0x%04hx ea=0x%llx\n",
1081 table->ea_buf[i], offset16, ea_buf[i]);
1082#endif
1083 break;
1084 case RESERVED_OFFSET_32BITS:
1085 n += read_inbuf(&offset32, sizeof(offset32));
1086 ea_buf[i] = table->ea_buf[i] + offset32;
1087
1088 offset_count[OFFSET_32BITS_IDX]++;
1089#ifdef _DEBUG0
1090 fprintf(DBGFP, "(Reserved 32) offset8=0x%02hx ", offset8);
1091 fprintf(DBGFP,
1092 "base=0x%llx offset32=0x%08x ea=0x%llx\n",
1093 table->ea_buf[i], offset32, ea_buf[i]);
1094#endif
1095 break;
1096 case RESERVED_OFFSET_64BITS:
1097 n += read_inbuf(&offset64, sizeof(offset64));
1098 ea_buf[i] = table->ea_buf[i] + offset64;
1099
1100 offset_count[OFFSET_64BITS_IDX]++;
1101#ifdef _DEBUG0
1102 fprintf(DBGFP, "(Reserved 64) offset8=0x%02hx ", offset8);
1103 fprintf(DBGFP,
1104 "base=0x%llx offset64=0x%016llx ea=0x%llx\n",
1105 table->ea_buf[i], offset64, ea_buf[i]);
1106#endif
1107 break;
1108 default:
1109 ea_buf[i] = table->ea_buf[i] + offset8;
1110
1111 if (offset8 == 0) {
1112 zero_offset_count++;
1113 }
1114
1115 offset_count[OFFSET_8BITS_IDX]++;
1116#ifdef _DEBUG0
1117 fprintf(DBGFP,
1118 "base=0x%llx offset8=0x%02hx ea=0x%llx\n",
1119 table->ea_buf[i], offset8, ea_buf[i]);
1120#endif
1121 }
1122 }
1123 }
1124 }
1125
1126 return n;
1127 } // Rstunzip::read_ea()
1128
1129 rstf_unionT read_noninstr_rec_rst;
1130
1131 rstf_instrT* read_noninstr_rec() {
1132 uint8_t ccValue;
1133 bool setCC = false;
1134 read_noninstr_rec_rst.proto.rtype = *inbuf_ptr;
1135
1136 decDebugP( " %d) ", iCtr++ );
1137
1138 if (read_noninstr_rec_rst.proto.rtype >= z0_PAVADIFF_T &&
1139 read_noninstr_rec_rst.proto.rtype <= z7_PAVADIFF_T) {
1140
1141 decDebug( "decoded a z*_PAVADIFF_T\n" );
1142
1143 switch (read_noninstr_rec_rst.proto.rtype) {
1144 case z0_PAVADIFF_T:
1145 memcpy(&read_noninstr_rec_rst, pava_cache.read(0),
1146 sizeof(rstf_pavadiffT));
1147 pava_cache.update(0);
1148 break;
1149 case z1_PAVADIFF_T:
1150 memcpy(&read_noninstr_rec_rst, pava_cache.read(1),
1151 sizeof(rstf_pavadiffT));
1152 pava_cache.update(1);
1153 break;
1154 case z2_PAVADIFF_T:
1155 memcpy(&read_noninstr_rec_rst, pava_cache.read(2),
1156 sizeof(rstf_pavadiffT));
1157 pava_cache.update(2);
1158 break;
1159 case z3_PAVADIFF_T:
1160 memcpy(&read_noninstr_rec_rst, pava_cache.read(3),
1161 sizeof(rstf_pavadiffT));
1162 pava_cache.update(3);
1163 break;
1164 case z4_PAVADIFF_T:
1165 memcpy(&read_noninstr_rec_rst, pava_cache.read(4),
1166 sizeof(rstf_pavadiffT));
1167 pava_cache.update(4);
1168 break;
1169 case z5_PAVADIFF_T:
1170 memcpy(&read_noninstr_rec_rst, pava_cache.read(5),
1171 sizeof(rstf_pavadiffT));
1172 pava_cache.update(5);
1173 break;
1174 case z6_PAVADIFF_T:
1175 memcpy(&read_noninstr_rec_rst, pava_cache.read(6),
1176 sizeof(rstf_pavadiffT));
1177 pava_cache.update(6);
1178 break;
1179 case z7_PAVADIFF_T:
1180 memcpy(&read_noninstr_rec_rst, pava_cache.read(7),
1181 sizeof(rstf_pavadiffT));
1182 pava_cache.update(7);
1183 break;
1184 default:
1185 fprintf(stderr, "Error: pava_cache.search() returned NOT_FOUND "
1186 "in read_noninstr_rec()\n");
1187 exit(2);
1188 }
1189
1190 total_pavadiff++;
1191 total_zpavadiff++;
1192 inbuf_ptr++;
1193
1194
1195 } else if ( compressedRegType( read_noninstr_rec_rst.proto.rtype ) ) {
1196 // DECOMPRESS
1197 if( read_noninstr_rec_rst.proto.rtype == z_REGPAIR_T ){
1198 decDebug( "*** z_REGPAIR_T ***" );
1199 ++inbuf_ptr;
1200 decompressReg( *inbuf_ptr, 0 );
1201 decompressReg( *inbuf_ptr, 1 );
1202 } else {
1203 decompressReg( read_noninstr_rec_rst.proto.rtype, 0 );
1204 }
1205
1206 } else {
1207 memcpy(&read_noninstr_rec_rst, inbuf_ptr, sizeof(rstf_pavadiffT));
1208
1209 if (read_noninstr_rec_rst.proto.rtype == PAVADIFF_T) {
1210 total_pavadiff++;
1211 pava_cache.write(&read_noninstr_rec_rst.pavadiff);
1212 }
1213
1214#ifdef DEC_DEBUG
1215 print_rstrec( stderr, &read_noninstr_rec_rst.instr );
1216#endif
1217
1218 inbuf_ptr += sizeof(rstf_pavadiffT);
1219 }
1220
1221 return &read_noninstr_rec_rst.instr;
1222 } // Rstunzip::read_noninstr_rec()
1223
1224
1225
1226 void decompressReg( uint8_t curr_rt, int idx )
1227 {
1228 int regid = -1;
1229 int rt = curr_rt;
1230
1231 decDebug( " " );
1232 if ( rt == z_REGID_T ) {
1233 regid = *++inbuf_ptr;
1234 decDebugP( "z_REGID_T id = %u\n", regid );
1235 decDebug( " " );
1236 ++inbuf_ptr;
1237 }
1238
1239 rt = *inbuf_ptr++;
1240 VCache::IdxT vcIdx;
1241 uint64_t value = 0;
1242
1243 switch( rt ){
1244 case z_REGVAL_64_T:
1245 memcpy( &value, inbuf_ptr, sizeof( uint64_t) );
1246 inbuf_ptr += sizeof( uint64_t );
1247 vcIdx = valueCache.insert( value );
1248 decDebugP( "z_REGVAL_64_T value=%llu, ", value );
1249 decDebugP( "indexed to %u\n", vcIdx );
1250 break;
1251 case z_REGVAL_32_T:
1252 {
1253 uint32_t val32 = 0;
1254 memcpy( &val32, inbuf_ptr, sizeof( uint32_t ) );
1255 inbuf_ptr += sizeof( uint32_t );
1256 vcIdx = valueCache.insert( val32 );
1257 value = val32;
1258 decDebugP( "z_REGVAL_32_T value=%u, ", val32 );
1259 decDebugP( "indexed to %u\n", vcIdx );
1260 }
1261 break;
1262 case z_REGVAL_16_T:
1263 {
1264 uint16_t val16 = 0;
1265 memcpy( &val16, inbuf_ptr, sizeof( uint16_t ) );
1266 inbuf_ptr += sizeof( uint16_t );
1267 value = val16;
1268 decDebugP( "z_REGVAL_16_T value=%llu\n", val16 );
1269 }
1270 break;
1271 case z_REGVAL_8_T:
1272 {
1273 uint8_t val8 = 0;
1274 memcpy( &val8, inbuf_ptr, sizeof( uint8_t ) );
1275 inbuf_ptr += sizeof( uint8_t );
1276 value = val8;
1277 decDebugP( "z_REGVAL_8_T value=%llu\n", val8 );
1278 }
1279 break;
1280 case z_VALUE_MINUS1_T:
1281 value = ~( 0x0ULL );
1282 decDebugP( "z_VALUE_MINUS1_T [%u]\n", z_VALUE_MINUS1_T );
1283 break;
1284 case z_VALUE_0_T:
1285 value = 0;
1286 decDebugP( "z_VALUE_0_T [%u]\n", z_VALUE_0_T );
1287 break;
1288 case z_VALUE_1_T:
1289 value = 1;
1290 decDebugP( "z_VALUE_1_T [%u]\n", z_VALUE_1_T );
1291 break;
1292 case z_VALUE_2_T:
1293 value = 2;
1294 decDebugP( "z_VALUE_2_T [%u]\n", z_VALUE_2_T );
1295 break;
1296 case z_VALUE_3_T:
1297 value = 3;
1298 decDebugP( "z_VALUE_3_T [%u]\n", z_VALUE_3_T );
1299 break;
1300 case z_VALUE_4_T:
1301 value = 4;
1302 decDebugP( "z_VALUE_4_T [%u]\n", z_VALUE_4_T );
1303 break;
1304 case z_VALUE_5_T:
1305 value = 5;
1306 decDebugP( "z_VALUE_5_T [%u]\n", z_VALUE_5_T );
1307 break;
1308 case z_VALUE_6_T:
1309 value = 6;
1310 decDebugP( "z_VALUE_6_T [%u]\n", z_VALUE_6_T );
1311 break;
1312 case z_VALUE_7_T:
1313 value = 7;
1314 decDebugP( "z_VALUE_7_T [%u]\n", z_VALUE_7_T );
1315 break;
1316 case z_VALUE_8_T:
1317 value = 8;
1318 decDebugP( "z_VALUE_8_T [%u]\n", z_VALUE_8_T );
1319 break;
1320 case z_REGIDX_T:
1321 memcpy( &vcIdx, inbuf_ptr, sizeof( VCache::IdxT ) );
1322 inbuf_ptr += sizeof( VCache::IdxT );
1323 try {
1324 value = valueCache[vcIdx];
1325 } catch ( InvalidIndexException &i ){
1326 fprintf( stderr, "caught invalid index exception for index = %u\n", vcIdx );
1327 value = 0;
1328 }
1329 decDebugP( "z_REGIDX_T, index = %u, ", vcIdx );
1330 decDebugP( "value = %llu\n", value );
1331
1332 break;
1333 default:
1334 fprintf( stderr, "Found a record of type: " );
1335 print_rstrec( stderr, &read_noninstr_rec_rst.instr );
1336 assert( 0 );
1337 }
1338 decDebug( " " );
1339
1340 if( !idx ){
1341 // Special cases when the index is 0
1342
1343 if( *inbuf_ptr == z_CCR_T ){
1344 ++inbuf_ptr;
1345 read_noninstr_rec_rst.regval.regtype[1] = RSTREG_CC_RT;
1346 read_noninstr_rec_rst.regval.regid[1] = *inbuf_ptr++;
1347 decDebugP( "z_CCR_T value = 0x%x\n", read_noninstr_rec_rst.regval.regid[1] );
1348 } else {
1349 read_noninstr_rec_rst.regval.regtype[1] = RSTREG_UNUSED_RT;
1350 read_noninstr_rec_rst.regval.regid[1] = 0;
1351 }
1352 read_noninstr_rec_rst.regval.rtype = REGVAL_T;
1353 read_noninstr_rec_rst.regval.postInstr = 1;
1354 read_noninstr_rec_rst.regval.reg64[1] = 0;
1355 }
1356
1357 read_noninstr_rec_rst.regval.reg64[idx] = value;
1358 read_noninstr_rec_rst.regval.regtype[idx] = RSTREG_INT_RT;
1359
1360 if( regid >= 0 ){
1361 read_noninstr_rec_rst.regval.regid[idx] = regid;
1362 } else {
1363 read_noninstr_rec_rst.regval.regid[idx] = 255;
1364 }
1365 decDebugP( "[read_noninstr_rec()] Setting regid[%d] to ", idx );
1366 decDebugP( "%u\n", read_noninstr_rec_rst.regval.regid[idx] );
1367 }
1368
1369 int read_noninstr_recs() {
1370 int i, n;
1371
1372 n = 0;
1373
1374 for (i = 0; i < num_noninstr; i++) {
1375 memcpy(&noninstr_buf[i], read_noninstr_rec(), sizeof(rstf_instrT));
1376 n += sizeof(rstf_instrT);
1377 }
1378
1379 return n;
1380 } // Rstunzip::read_noninstr_recs()
1381
1382 int zrecs_o() {
1383 return outbuf_ptr - outbuf;
1384 } // Rstunzip::zrecs_o()
1385
1386 int zbytes_i() {
1387 return inbuf_ptr - inbuf;
1388 } // Rstunzip::zbytes_i()
1389
1390}; // class Rstunzip
1391
1392// Compression class.
1393class Rstzipv2 : public RstzipBase {
1394public:
1395 rstf_instrT* inbuf_ptr; // always points to current inbuf location
1396 uint8_t* outbuf_ptr; // always points to current outbuf location
1397
1398 Rstzipv2()
1399 {
1400 zip_init();
1401 }
1402
1403 ~Rstzipv2() {
1404 zip_close();
1405 }
1406
1407 void zip_init() {
1408 inbuf = NULL;
1409 inbuf_ptr = NULL;
1410 outbuf = NULL;
1411 outbuf_ptr = NULL;
1412
1413 rstz_compress_prev_nrecs = 0;
1414 zip_chunk_chksm = 0;
1415 zip_chunk_chunk_counter = 0;
1416 in_same_chunk_prev_pc = 0;
1417 lastRID = -1;
1418 inChunk = false;
1419 }
1420
1421 void zip_close() {
1422 //free(outbuf);
1423 }
1424
1425 int rstz_compress_prev_nrecs;
1426 // Compress nrecs RST records from rstbuf[] to rz2buf[].
1427 // Returns size of compressed nrecs records in rz2buf[].
1428 int rstz_compress(uint8_t* rz2buf, rstf_unionT* rstbuf, int nrecs) {
1429 int buf_instr = 0;
1430
1431 if (rstbuf == NULL) {
1432 return 0;
1433 }
1434
1435 inbuf = &rstbuf[0].instr;
1436 outbuf = rz2buf;
1437 inbuf_ptr = inbuf;
1438 outbuf_ptr = outbuf;
1439
1440 while (zrecs_i() < nrecs) {
1441 zip_chunk(nrecs);
1442
1443 max_chunksize = MAX(max_chunksize, num_instr + num_noninstr);
1444 buf_instr += num_instr;
1445#if _DEBUG0
1446 print_chunk(DBGFP);
1447 if (num_instr != 0) {
1448 fprintf(DBGFP, "zrecs_i()=%d zbytes_o()=%d nrecs=%d\n\n",
1449 zrecs_i(), zbytes_o(), nrecs);
1450 }
1451#endif
1452 }
1453
1454 total_instr += buf_instr;
1455 total_noninstr += zrecs_i() - buf_instr;
1456
1457 return zbytes_o();
1458 } // Rstzip::zip()
1459
1460#if 0
1461 int rstz_write_prev_nrecs;
1462 // Compress nrecs RST records from buf[] to *outfp; assume exactly
1463 // nrecs records exist in buf[]. Returns number of records
1464 // compressed.
1465 int rstz_write(rstf_unionT buf[], int nrecs) {
1466 int buf_instr = 0;
1467
1468 inbuf = &buf[0].instr;
1469
1470 if (outbuf == NULL || rstz_write_prev_nrecs < nrecs) {
1471 rstz_write_prev_nrecs = nrecs;
1472
1473 free(outbuf);
1474
1475 outbuf = (uint8_t*) malloc((nrecs+MAX_CHUNKSIZE) * sizeof(rstf_instrT));
1476 if (outbuf == NULL) {
1477 fprintf(stderr, "Error: could not allocate %d bytes "
1478 "of memory in Rstzip::zip()\n",
1479 (nrecs+MAX_CHUNKSIZE) * sizeof(rstf_instrT));
1480 exit(2);
1481 }
1482 }
1483
1484 inbuf_ptr = inbuf;
1485 outbuf_ptr = outbuf;
1486
1487 while (zrecs_i() < nrecs) {
1488 zip_chunk(nrecs);
1489
1490 max_chunksize = MAX(max_chunksize, num_instr + num_noninstr);
1491 buf_instr += num_instr;
1492#if _DEBUG0
1493 print_chunk(DBGFP);
1494 if (num_instr != 0) {
1495 fprintf(DBGFP, "zrecs_i()=%d zbytes_o()=%d nrecs=%d\n\n",
1496 zrecs_i(), zbytes_o(), nrecs);
1497 }
1498#endif
1499 }
1500
1501 total_instr += buf_instr;
1502 total_noninstr += zrecs_i() - buf_instr;
1503
1504 zfwrite(outbuf, zbytes_o());
1505
1506 return zrecs_i();
1507 } // Rstzip::zip()
1508#endif
1509
1510protected:
1511
1512 VCache valueCache;
1513 uint64_t currentPC;
1514 int lastRID;
1515 bool inChunk;
1516
1517 rstf_instrT* inbuf; // input rst buffer
1518 uint8_t* outbuf; // output buffer for compressed traces
1519
1520 uint64_t zip_chunk_chksm;
1521 uint64_t zip_chunk_chunk_counter;
1522 // Compress one chunk of RST records from *inbuf_ptr to *outbuf_ptr.
1523 void zip_chunk(int nrecs) {
1524 int hashval, set;
1525
1526 rstf_instrT* inbuf_start = inbuf_ptr;
1527
1528#if 0
1529 // CURRDEBUG
1530 for( int i = 0; i < 5; i++ ){
1531 print_rstrec(DBGFP, inbuf_start++ );
1532 }
1533#endif
1534
1535 read_chunk(nrecs);
1536
1537 // Read_chunk() initializes pc_start to zero and will set pc_start
1538 // if a chunk is read.
1539 if (pc_start != 0 & num_instr > 0) {
1540 hashval = hash.hash(pc_start);
1541 set = hash.search(pc_start, num_instr, instr_buf, hashval);
1542
1543 if (set == NOT_FOUND) {
1544 write_chunk();
1545 hash.write(pc_start, num_instr, instr_buf, num_ea, ea_buf, hashval);
1546 total_nonloop_chunk++;
1547 } else {
1548 write_loop_chunk(hash.read(set, hashval));
1549 hash.update(num_ea, ea_buf, hashval, set);
1550 total_loop_chunk++;
1551 }
1552
1553 if (checksum_freq != 0) {
1554 zip_chunk_chksm += compute_checksum64();
1555 zip_chunk_chunk_counter++;
1556
1557 if (zip_chunk_chunk_counter % checksum_freq == 0) {
1558 write_outbuf(&zip_chunk_chksm, 8);
1559 zip_chunk_chksm = 0;
1560 }
1561 }
1562 }
1563 } // Rstzip::zip_chunk()
1564
1565 int make_pavadiff_rtype(int index) {
1566 int ztype;
1567
1568 switch (index) {
1569 case 0:
1570 ztype = z0_PAVADIFF_T;
1571 break;
1572 case 1:
1573 ztype = z1_PAVADIFF_T;
1574 break;
1575 case 2:
1576 ztype = z2_PAVADIFF_T;
1577 break;
1578 case 3:
1579 ztype = z3_PAVADIFF_T;
1580 break;
1581 case 4:
1582 ztype = z4_PAVADIFF_T;
1583 break;
1584 case 5:
1585 ztype = z5_PAVADIFF_T;
1586 break;
1587 case 6:
1588 ztype = z6_PAVADIFF_T;
1589 break;
1590 case 7:
1591 ztype = z7_PAVADIFF_T;
1592 break;
1593 default:
1594 fprintf(stderr, "Error: index param > 7 in rstzip::make_pavadiff_rtype()\n");
1595 exit(2);
1596 }
1597
1598 return ztype;
1599 }
1600
1601 // Read one chunk of compressed data from *inbuf_ptr to instr_buf[],
1602 // ea_buf[], flags_buf[], etc. Return the total number of records
1603 // written.
1604 int read_chunk(int nrecs) {
1605 rstf_instrT* inbuf_start;
1606 int ih;
1607 int lastRegid = -1;
1608
1609 // init some data members
1610 rtype = 0;
1611 pc_start = 0;
1612 num_instr = 0;
1613 num_ea = 0;
1614 num_noninstr = 0;
1615 num_total = 0;
1616 num_noninstr_count = 0;
1617
1618 memset(noninstr_count_buf, 0, MAX_CHUNKSIZE * sizeof(uint8_t));
1619
1620 inbuf_start = inbuf_ptr;
1621
1622 // find an INSTR_T record
1623 inChunk = false;
1624 while (zrecs_i() < nrecs && inbuf_ptr->rtype != INSTR_T) {
1625 //print_rstrec(DBGFP, inbuf_ptr);
1626
1627 write_noninstr_rec(inbuf_ptr);
1628 inbuf_ptr++;
1629 }
1630
1631 // inbuf_ptr points to an INSTR_T now
1632 if (zrecs_i() < nrecs && inbuf_ptr->rtype == INSTR_T) {
1633 //print_rstrec(DBGFP, inbuf_ptr);
1634
1635 pc_start = inbuf_ptr->pc_va;
1636
1637#ifdef COM_DEBUG
1638 static int chunkNum = 0;
1639 fprintf( stderr, "writing chunk #%d\n", chunkNum++ );
1640#endif
1641 inChunk = true;
1642 while (zrecs_i() < nrecs && in_same_chunk(inbuf_ptr, nrecs, inbuf_ptr - inbuf_start + 1)) {
1643 if (inbuf_ptr->rtype == INSTR_T) {
1644 // set instr_buf[]
1645 instr_buf[num_instr] = inbuf_ptr->instr;
1646
1647 // save the destination register for regval records
1648 // that follow this instruction.
1649 lastRegid = inbuf_ptr->instr >> 25 & 0x01f;
1650
1651 // set ea_buf[]
1652 // ih = getIHash(inbuf_ptr->instr); // removed - 20040210 (vp)
1653
1654 // if (carry_ea(ih, inbuf_ptr->ea_valid)) { // replaced - 20040210 (vp)
1655 if (carry_ea(inbuf_ptr->instr, inbuf_ptr->ea_valid)) {
1656 ea_buf[num_ea] = inbuf_ptr->ea_va;
1657 num_ea++;
1658 }
1659
1660 // set flags_buf[]
1661 flags_buf[num_instr] = 0;
1662 set_flags(&flags_buf[num_instr], NOTUSED, inbuf_ptr->notused);
1663 set_flags(&flags_buf[num_instr], EA_VALID, inbuf_ptr->ea_valid);
1664 set_flags(&flags_buf[num_instr], TR, inbuf_ptr->tr);
1665 // set_flags(&flags_buf[num_instr], NOTUSED2, inbuf_ptr->notused2);
1666 set_flags(&flags_buf[num_instr], NOTUSED2, 0);
1667 set_flags(&flags_buf[num_instr], PR, inbuf_ptr->pr);
1668 set_flags(&flags_buf[num_instr], BT, inbuf_ptr->bt);
1669 set_flags(&flags_buf[num_instr], AN, inbuf_ptr->an);
1670 set_flags(&flags_buf[num_instr], RSRVD_CMPRSS, INSTR_FOLLOWS);
1671
1672 if (num_instr == UINT16_MAX) {
1673 fprintf(stderr, "Error: num_instr > UINT16_MAX in Rstzip::read_chunk()\n");
1674 exit(2);
1675 }
1676
1677 num_instr++;
1678
1679 if (noninstr_count_buf[num_noninstr_count]) {
1680 num_noninstr_count++;
1681 }
1682 } else {
1683 if (noninstr_count_buf[num_noninstr_count] == UINT8_MAX) {
1684 fprintf(stderr, "Error: num_noninstr > %d in Rstzip::read_chunk()\n", UINT8_MAX);
1685 exit(2);
1686 }
1687
1688 // copy non-instrustion record to noninstr_buf[]
1689 memcpy(&noninstr_buf[num_noninstr], inbuf_ptr, sizeof(rstf_unionT));
1690 lastRegIdBuf[num_noninstr] = lastRegid;
1691
1692 // increment noninstr_count_buf[]
1693 noninstr_count_buf[num_noninstr_count]++;
1694
1695 set_flags(&flags_buf[num_instr - 1], RSRVD_CMPRSS, NONINSTR_FOLLOWS);
1696 num_noninstr++;
1697 }
1698
1699 inbuf_ptr++;
1700 }
1701#ifdef COM_DEBUG
1702 fprintf( stderr, " wrote %d instructions\n", num_instr );
1703 fprintf( stderr, " wrote %d non-instructions\n", num_noninstr );
1704#endif
1705 }
1706
1707 if (num_instr > 0) {
1708 if (num_instr + num_noninstr < MAX_CHUNKSIZE) {
1709 chunksize_count[(num_instr + num_noninstr) / (MAX_CHUNKSIZE / CHUNKSIZE_RES)]++;
1710 } else {
1711 chunksize_count[CHUNKSIZE_RES - 1]++;
1712 }
1713 }
1714
1715 return inbuf_ptr - inbuf_start;
1716 } // Rstzip::read_chunk()
1717
1718 uint64_t in_same_chunk_prev_pc;
1719 // Chunks are terminated by:
1720 // 1) non-sequential instructions
1721 // 2) end of buffer
1722 // 3) MAX_CHUNKSIZE
1723 // 4) > UINT8_MAX sequential noninstruction records
1724 // Chunks are not terminated by non-instruction records (to improve
1725 // compression).
1726 bool in_same_chunk(rstf_instrT* rst, int nrecs, int chunk_recs) {
1727 int recs, ni_recs;
1728
1729 if (chunk_recs >= MAX_CHUNKSIZE) {
1730 return false;
1731 } else if (rst->rtype == INSTR_T) {
1732 if (num_instr > 0) {
1733 if (rst->pc_va != in_same_chunk_prev_pc + 4) {
1734 return false;
1735 }
1736 }
1737
1738 in_same_chunk_prev_pc = rst->pc_va;
1739 } else {
1740 // find next rstf_instrT
1741 for (recs = zrecs_i(), ni_recs = 0;
1742 recs < nrecs && ni_recs < UINT8_MAX && chunk_recs < MAX_CHUNKSIZE && rst->rtype != INSTR_T;
1743 recs++, ni_recs++, chunk_recs++) {
1744 rst++;
1745 }
1746
1747 if (recs < nrecs && chunk_recs < MAX_CHUNKSIZE) {
1748 if (rst->rtype != INSTR_T) {
1749 return false;
1750 } else if (rst->pc_va != in_same_chunk_prev_pc + 4) {
1751 return false;
1752 }
1753 } else {
1754 return false;
1755 }
1756 }
1757
1758 return true;
1759 } // Rstzip::in_same_chunk()
1760
1761 // Write the chunk data from instr_buf[], ea_buf[], flags_buf[],
1762 // etc. to *outbuf_ptr. Return the number of bytes written.
1763 int write_chunk() {
1764 int n = 0;
1765
1766 rtype = z_INSTR_T;
1767
1768 n += write_outbuf(&rtype, sizeof(rtype));
1769 n += write_outbuf(&num_instr, sizeof(num_instr));
1770 n += write_outbuf(&pc_start, sizeof(pc_start));
1771
1772 n += write_outbuf(instr_buf, num_instr * sizeof(uint32_t));
1773 n += write_outbuf(flags_buf, num_instr * sizeof(flags_t));
1774 n += write_ea(NULL);
1775 n += write_outbuf(noninstr_count_buf, num_noninstr_count * sizeof(uint8_t));
1776 n += write_noninstr_recs();
1777
1778 return n;
1779 } // Rstzip::write_chunk()
1780
1781 // Write the loop chunk data from instr_buf[], ea_buf[],
1782 // flags_buf[], etc. to *outbuf_ptr. Return the number of bytes
1783 // written.
1784 int write_loop_chunk(hash_table_t* table) {
1785 int n = 0;
1786
1787 rtype = zL_INSTR_T;
1788
1789 n += write_outbuf(&rtype, sizeof(rtype));
1790 n += write_outbuf(&num_instr, sizeof(num_instr));
1791 n += write_outbuf(&pc_start, sizeof(pc_start));
1792
1793 n += write_outbuf(flags_buf, num_instr * sizeof(flags_t));
1794 n += write_ea(table);
1795 n += write_outbuf(noninstr_count_buf, num_noninstr_count * sizeof(uint8_t));
1796 n += write_noninstr_recs();
1797
1798 return n;
1799 } // Rstzip::write_loop_chunk()
1800
1801 int write_ea(hash_table_t* table) {
1802 int8_t offset8;
1803 int16_t offset16;
1804 int32_t offset32;
1805 int64_t offset64;
1806 int i, n;
1807
1808 n = 0;
1809
1810 // Nothing to write if num_ea == 0.
1811 if (num_ea > 0) {
1812 if (rtype == z_INSTR_T) { // no compression
1813 n += write_outbuf(ea_buf, num_ea * sizeof(uint64_t));
1814 } else { // compression
1815 for (i = 0; i < num_ea; i++) {
1816 offset64 = ea_buf[i] - table->ea_buf[i];
1817
1818 if (offset64 >= INT8_MIN && offset64 <= INT8_MAX) {
1819 if (offset64 == RESERVED_OFFSET_8BITS ||
1820 offset64 == RESERVED_OFFSET_16BITS ||
1821 offset64 == RESERVED_OFFSET_32BITS ||
1822 offset64 == RESERVED_OFFSET_64BITS) {
1823 offset8 = RESERVED_OFFSET_8BITS;
1824 n += write_outbuf(&offset8, sizeof(offset8));
1825
1826 offset_count[OFFSET_8BITS_RESERVED_IDX]++;
1827#ifdef _DEBUG0
1828 fprintf(DBGFP, "(Reserved 8) offset8=0x%02hx ",
1829 table->ea_buf[i], offset8, ea_buf[i]);
1830#endif
1831 } else {
1832 offset_count[OFFSET_8BITS_IDX]++;
1833
1834 if (offset64 == 0) {
1835 zero_offset_count++;
1836 }
1837 }
1838
1839 offset8 = (int8_t) offset64 & 0xff;
1840 n += write_outbuf(&offset8, sizeof(offset8));
1841#ifdef _DEBUG0
1842 fprintf(DBGFP, "base=0x%llx offset8=0x%02hx ea=0x%llx\n",
1843 table->ea_buf[i], offset8, ea_buf[i]);
1844#endif
1845 } else if (offset64 >= INT16_MIN && offset64 <= INT16_MAX) {
1846 offset8 = RESERVED_OFFSET_16BITS;
1847 offset16 = (int16_t) offset64 & 0xffff;
1848 n += write_outbuf(&offset8, sizeof(offset8));
1849 n += write_outbuf(&offset16, sizeof(offset16));
1850
1851 offset_count[OFFSET_16BITS_IDX]++;
1852#ifdef _DEBUG0
1853 fprintf(DBGFP, "(Reserved 16) offset8=0x%02hx ", offset8);
1854 fprintf(DBGFP, "base=0x%llx offset16=0x%04hx ea=0x%llx\n",
1855 table->ea_buf[i], offset16, ea_buf[i]);
1856#endif
1857 } else if (offset64 >= INT32_MIN && offset64 <= INT32_MAX) {
1858 offset8 = RESERVED_OFFSET_32BITS;
1859 offset32 = (int32_t) offset64 & 0xffffffff;
1860 n += write_outbuf(&offset8, sizeof(offset8));
1861 n += write_outbuf(&offset32, sizeof(offset32));
1862
1863 offset_count[OFFSET_32BITS_IDX]++;
1864#ifdef _DEBUG0
1865 fprintf(DBGFP, "(Reserved 32) offset8=0x%02hx ", offset8);
1866 fprintf(DBGFP,
1867 "base=0x%llx offset32=0x%08x ea=0x%llx\n",
1868 table->ea_buf[i], offset32, ea_buf[i]);
1869#endif
1870 } else {
1871 offset8 = RESERVED_OFFSET_64BITS;
1872 n += write_outbuf(&offset8, sizeof(offset8));
1873 n += write_outbuf(&offset64, sizeof(offset64));
1874
1875 offset_count[OFFSET_64BITS_IDX]++;
1876#ifdef _DEBUG0
1877 fprintf(DBGFP, "(Reserved 64) offset8=0x%02hx ", offset8);
1878 fprintf(DBGFP, "base=0x%llx offset64=0x%016llx ea=0x%llx\n",
1879 table->ea_buf[i], offset64, ea_buf[i]);
1880#endif
1881 }
1882 }
1883 }
1884 }
1885
1886 return n;
1887 } // Rstzip::write_ea()
1888
1889 // Write n bytes from *from to *outbuf_ptr, and increment
1890 // outbuf_ptr. Return the number of bytes written.
1891 int write_outbuf(void* from, size_t n) {
1892 memcpy(outbuf_ptr, from, n);
1893 outbuf_ptr += n;
1894
1895 return n;
1896 } // Rstzip::write_outbuf()
1897
1898 int write_noninstr_rec(rstf_instrT* rst) {
1899 int index, n;
1900
1901 static int niNr = 0;
1902 n = 0;
1903
1904
1905#ifdef COM_DEBUG
1906 print_rstrec( stderr, rst );
1907#endif
1908
1909 comDebug( " " );
1910 if (rst->rtype == PAVADIFF_T) {
1911 total_pavadiff++;
1912 index = pava_cache.search((rstf_pavadiffT*) rst);
1913
1914 if (index == NOT_FOUND) {
1915 n = write_outbuf(rst, sizeof(rstf_instrT));
1916 pava_cache.write((rstf_pavadiffT*) rst);
1917 } else {
1918 uint8_t ztype = make_pavadiff_rtype(index);
1919
1920 n = write_outbuf(&ztype, sizeof(uint8_t));
1921 pava_cache.update(index);
1922
1923 total_zpavadiff++;
1924 }
1925 comDebug( "writing PAVADIFF_T\n" );
1926 // COMPRESS
1927 } else if ( rst->rtype == REGVAL_T ){
1928 rstf_regvalT *regP = (rstf_regvalT*) rst;
1929 if ( isIntRegCompressable( regP ) ){
1930 comDebug( "* Processing compressable register " );
1931
1932 if( regP->regtype[1] == RSTREG_INT_RT ){
1933 uint8_t tag = z_REGPAIR_T;
1934 comDebug( "[ *** z_REGPAIR_T *** ]" );
1935 n += write_outbuf( &tag, sizeof( uint8_t ) );
1936 }
1937
1938 n += compressIntegerRecord( regP->regid[0], regP->reg64[0], regP->cpuid, lastRID );
1939
1940 if( regP->regtype[1] == RSTREG_INT_RT ){
1941 n += compressIntegerRecord( regP->regid[1], regP->reg64[1], regP->cpuid, lastRID );
1942
1943 } else if( regP->regtype[1] == RSTREG_CC_RT ){
1944 n += writeCCRecord( regP->regid[1] );
1945 }
1946
1947 } else {
1948 // we're not compressing this type of regval
1949 n = write_outbuf( rst, sizeof(rstf_instrT) );
1950 comDebug( "* Writing non-compressable REGVAL_T\n" );
1951 }
1952 } else {
1953 n = write_outbuf(rst, sizeof(rstf_instrT));
1954 }
1955
1956 ++niNr;
1957 return n;
1958 }
1959
1960 unsigned compressIntegerRecord( uint8_t regid, uint64_t regval, uint8_t cpuid, int lastInstrRegId = -1 )
1961 {
1962 uint8_t tag;
1963 unsigned totalSize = 0;
1964 static uint8_t tagLookup[9] = { z_VALUE_0_T, z_VALUE_1_T, z_VALUE_2_T, z_VALUE_3_T,
1965 z_VALUE_4_T, z_VALUE_5_T, z_VALUE_6_T, z_VALUE_7_T, z_VALUE_8_T };
1966#ifdef COM_DEBUG
1967 static const char *tag2String[9] = { "z_VALUE_0_T", "z_VALUE_1_T", "z_VALUE_2_T", "z_VALUE_3_T",
1968 "z_VALUE_4_T", "z_VALUE_5_T", "z_VALUE_6_T", "z_VALUE_7_T", "z_VALUE_8_T" };
1969#endif
1970
1971 comDebugP( "(last regid = %u)\n", lastInstrRegId );
1972 comDebug( " " );
1973
1974
1975 // if we can't get the regid from the instruction, then
1976 // we'll need to output it to the compressed trace.
1977 if( regid != lastInstrRegId || !inChunk ){
1978 comDebugP( "z_REGID_T id = %u\n ", regid );
1979 tag = z_REGID_T;
1980 totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
1981 totalSize += write_outbuf( &regid, sizeof( uint8_t ) );
1982 }
1983
1984 VCache::IdxT idx;
1985 if( valueCache.hit( regval, idx ) ){
1986 comDebugP( "z_REGIDX_T idx=%u ", idx );
1987 comDebugP( " val=%llu\n", regval );
1988 // if we hit in the value cache, then output the index.
1989 tag = z_REGIDX_T;
1990 totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
1991 totalSize += write_outbuf( &idx, sizeof( VCache::IdxT ) );
1992
1993 } else if ( regval < 9 ){
1994 // we have specific records for values < 8
1995 tag = tagLookup[regval];
1996 totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
1997 comDebugP( "%s ", tag2String[regval] );
1998 comDebugP( "[%u]\n", tag );
1999
2000 } else if( (regval & 0x0ff) == regval ){
2001 // if the regval can be expressed in one byte, then it's wasteful to
2002 // enter it in the value cache. Instead, we output the 1-byte values
2003 // to the trace. Note: we NEVER put these value in the value cache!!!
2004 tag = z_REGVAL_8_T;
2005 totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
2006 uint8_t rv8 = regval;
2007 totalSize += write_outbuf( &rv8, sizeof( uint8_t ) );
2008 comDebugP( "z_REGVAL_8_T val=%u\n", rv8 );
2009
2010 } else if( (regval & 0x0ffff) == regval ){
2011 // if the regval can be expressed in two bytes, then it's wasteful to
2012 // enter it in the value cache. Instead, we output the 2-byte values
2013 // to the trace. Note: we NEVER put these value in the value cache!!!
2014 tag = z_REGVAL_16_T;
2015 totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
2016 uint16_t rv16 = regval;
2017 totalSize += write_outbuf( &rv16, sizeof( uint16_t ) );
2018 comDebugP( "z_REGVAL_16_T val=%u\n", rv16 );
2019
2020 } else if( regval == ~(0x0ULL) ){
2021 tag = z_VALUE_MINUS1_T;
2022 totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
2023 comDebugP( "z_VALUE_MINUS1_T [%u]", tag );
2024
2025 } else {
2026 uint8_t size;
2027 VCache::IdxT i = valueCache.insert( regval );
2028
2029 if( (regval & 0x0ffffffff ) == regval ){
2030 tag = z_REGVAL_32_T;
2031 uint32_t rv32 = regval;
2032 totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
2033 totalSize += write_outbuf( &rv32, sizeof( uint32_t ) );
2034 comDebugP( "z_REGVAL_32_T val=%u", rv32 );
2035 } else {
2036 tag = z_REGVAL_64_T;
2037 totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
2038 totalSize += write_outbuf( &regval, sizeof( uint64_t ) );
2039 comDebugP( "z_REGVAL_64_T val=%llu", regval );
2040 }
2041 comDebugP( " indexed to %u\n", i );
2042
2043 }
2044
2045 comDebugP( " size = %u\n", totalSize );
2046
2047 return totalSize;
2048 }
2049
2050
2051 unsigned writeCCRecord( uint8_t CCRContents )
2052 {
2053 unsigned totalSize = 0;
2054
2055 uint8_t tag = z_CCR_T;
2056 totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
2057 totalSize += write_outbuf( &CCRContents, sizeof( uint8_t ) );
2058 comDebugP( " [CCR] = 0x%x\n", CCRContents );
2059
2060 return totalSize;
2061 }
2062
2063
2064
2065
2066
2067 int write_noninstr_recs() {
2068 int i, n;
2069
2070 n = 0;
2071
2072 for (i = 0; i < num_noninstr; i++) {
2073 lastRID = lastRegIdBuf[i];
2074 n += write_noninstr_rec(&noninstr_buf[i]);
2075 }
2076
2077 return n;
2078 }
2079
2080 int zrecs_i() {
2081 return inbuf_ptr - inbuf;
2082 } // Rstzip::zrecs_i()()
2083
2084 int zbytes_o() {
2085 return outbuf_ptr - outbuf;
2086 } // Rstzip::zbytes_o()()
2087
2088}; // Rstzip
2089
2090#endif // _RSTZIP_H