* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: rstzip.H
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: rstzip.H
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
#include "rz_insttypes.h"
#include "spix6plus/IHASH.h"
#include "spix6plus/ITYPES.h"
#include "spix6plus/MISC.h"
#include "spix6plus/reguse.h"
#define comDebug( str ) fprintf( stderr, str )
#define comDebugP( str, var ) fprintf( stderr, str, var )
#define comDebugP( str, var )
#define decDebug( str ) fprintf( stderr, str )
#define decDebugP( str, var ) fprintf( stderr, str, var )
#define decDebugP( str, var )
#if 0 // removed - 20040210 (vp)
static int ih_ispcrelcti(int ih) {
return (ih_isbranch(ih) || ih == IH_CALL);
// static int carry_ea(int ih, int ea_valid) { // changed - 20040210 (vp)
static int carry_ea(uint32_t iw, int ea_valid) {
// return (ea_valid == 1 && ih_ispcrelcti(ih) == 0); // replaced - 20040210 (vp)
return (ea_valid == 1 && !rz_is_pc_relative_cti(iw));
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
RSTZIP_MAX_CONTEXTS = 8192
z_HEADER_T = NEW_RTYPES_START,
z_INSTR_T, // compressed chunk
zL_INSTR_T, // compressed loop chunk
z0_PAVADIFF_T, // compresed pavadiff at cache index n
z_CCR_T, // condition-code register
z_REGID_T, // register id
z_REGVAL_8_T, // 1-byte register value
z_REGVAL_16_T, // 2-byte register value
z_REGVAL_32_T, // 4-byte register value
z_REGVAL_64_T, // 8-byte register value
z_REGIDX_T, // 2-byte register index
z_VALUE_MINUS1_T, // These are the literal values -1 to 8
z_REGPAIR_T, // indicates that the next two register values should be
// merged into a single RST regval record.
OFFSET_8BITS_RESERVED_IDX = 1,
RESERVED_OFFSET_8BITS = -125, // (0xffffff83)
RESERVED_OFFSET_16BITS = -123, // (0xffffff85)
RESERVED_OFFSET_32BITS = 123, // (0x7b)
RESERVED_OFFSET_64BITS = 125, // (0x7d)
NUM_RESERVED_OFFSETS = 4,
FILENAME_STRING_SIZE = 256,
HASH_FUNC_STRING_SIZE = 64,
bool compress; // Set to 1 to compress, 0 to decompress
uint8_t checksum_freq; // Add checksum every n chunks (default=16)
uint64_t total_loop_chunk;
uint64_t total_nonloop_chunk;
uint64_t total_zpavadiff;
uint64_t zero_offset_count;
uint64_t offset_count[OFFSET_64BITS_IDX + 1];
uint64_t chunksize_count[CHUNKSIZE_RES];
RstzipPavadiffCache pava_cache;
// Constructor (initialize file footer variables).
memset(offset_count, 0, (OFFSET_64BITS_IDX + 1) * sizeof(uint64_t));
memset(chunksize_count, 0, CHUNKSIZE_RES * sizeof(uint64_t));
print_chunk_chunk_counter = 0;
checksum_freq = CHECKSUM_FREQ;
} // RstzipBase::RstzipBase()
uint16_t num_instr; // number of instructions in chunk
uint64_t pc_start; // pc of 1st instruction in chunk
uint32_t instr_buf[MAX_CHUNKSIZE]; // instruction words in chunk
uint64_t ea_buf[MAX_CHUNKSIZE]; // ea of ld/st+cti instructions
flags_t flags_buf[MAX_CHUNKSIZE]; // flags for each instruction
uint8_t noninstr_count_buf[MAX_CHUNKSIZE]; // counts of non-instr chunks
int lastRegIdBuf[MAX_CHUNKSIZE]; // the regid observed in an instruction
rstf_instrT noninstr_buf[MAX_CHUNKSIZE]; // non-instr records in chunk
int num_ea; // number of ld/st+cti instrs in chunk
int num_noninstr; // non-instruction records in chunk
int num_total; // num_instr + num_noninstr
int num_noninstr_count; // size of noninstr_count_buf[]
flags_t set_flags(flags_t* flags, int mask, int val) {
} // RstzipBase::set_flags()
uint64_t compute_checksum64() {
chksm = rtype + num_instr + pc_start;
for (i = 0; i < num_instr; i++) {
chksm += instr_buf[i] + flags_buf[i];
for (i = 0; i < num_ea; i++) {
for (i = 0; i < num_noninstr; i++) {
chksm += noninstr_buf[i].rtype;
for (i = 0; i < num_noninstr_count; i++) {
chksm += noninstr_count_buf[i];
} // RstzipBase::compute_checksum64()
int check_buffersize(int nrecs) {
if (nrecs < MAX_CHUNKSIZE) {
return MAX_CHUNKSIZE - nrecs;
} // RstzipBase::check_buffersize()
int get_flags(flags_t flags, int mask) {
return ((flags & mask) ? 1 : 0);
} // RstzipBase::get_flags()
uint64_t print_chunk_chksm;
uint64_t print_chunk_chunk_counter;
void print_chunk(FILE* fp) {
fprintf(fp, "[BOC] rtype=%d\n", rtype);
fprintf(fp, "num_instr=%d\n", num_instr);
fprintf(fp, "pc_start=0x%llx\n", pc_start);
fprintf(fp, "num_ea=%d\n", num_ea);
fprintf(fp, "num_noninstr=%d\n", num_noninstr);
fprintf(fp, "num_total=%d\n", num_total);
fprintf(fp, "num_noninstr_count=%d\n", num_noninstr_count);
for (i = 0; i < num_instr; i++) {
fprintf(fp, "(%x)\n", instr_buf[i]);
for (i = 0; i < num_instr; i++) {
fprintf(fp, "(%02x)\n", flags_buf[i]);
for (i = 0; i < num_ea; i++) {
fprintf(fp, "(0x%llx)\n", ea_buf[i]);
for (i = 0; i < num_noninstr_count; i++) {
fprintf(fp, "%d ", noninstr_count_buf[i]);
for (i = 0; i < num_noninstr; i++) {
print_rstrec(fp, &noninstr_buf[i]);
if (checksum_freq != 0) {
print_chunk_chksm += compute_checksum64();
print_chunk_chunk_counter++;
if (print_chunk_chunk_counter % checksum_freq == 0) {
fprintf(fp, "checksum=%016llx\n", print_chunk_chksm);
fprintf(fp, "[EOC] max_chunksize=%d\n", max_chunksize);
} // RstzipBase::print_chunk()
void print_rstbuf(FILE* fp, rstf_instrT buf[], int num) {
for (i = 0; i < num; i++) {
print_rstrec(fp, &buf[i]);
} // RstzipBase::print_rstbuf()
void print_rstrec(FILE* fp, rstf_instrT* rst) {
fprintf(fp, "rstheader\n");
fprintf(fp, "[0x%llx] ", rst->pc_va);
// fprintDiss(fp, rst->instr, rst->pc_va);
fprintf( fp, "memval\n" );
fprintf(fp, "trapexit\n");
fprintf(fp, "timestamp\n");
fprintf(fp, "process\n");
fprintf(fp, "strdesc\n");
fprintf(fp, "leftdelim\n");
fprintf(fp, "rightdelim\n");
fprintf(fp, "physaddr\n");
fprintf(fp, "pavadiff\n");
memcpy(&rst_pava, rst, sizeof(rstf_unionT));
fprintf(fp, "pavadiff: icontext=%d dcontext=%d pc_pa_va=0x%016llx ea_pa_va=0x%016llx\n",
rst_pava.icontext, rst_pava.dcontext, rst_pava.pc_pa_va, rst_pava.ea_pa_va);
fprintf(fp, "nullrec\n");
fprintf(fp, "strcont\n");
fprintf(fp, "filemarker\n");
fprintf(fp, "file header\n");
fprintf(fp, "file footer\n");
fprintf(fp, "compressed header\n");
fprintf(fp, "compressed loop header\n");
fprintf(fp, "compressed pavadiff [0]\n");
fprintf(fp, "compressed pavadiff [1]\n");
fprintf(fp, "compressed pavadiff [2]\n");
fprintf(fp, "compressed pavadiff [3]\n");
fprintf(fp, "compressed pavadiff [4]\n");
fprintf(fp, "compressed pavadiff [5]\n");
fprintf(fp, "compressed pavadiff [6]\n");
fprintf(fp, "compressed pavadiff [7]\n");
fprintf(fp, "Condition Code Register\n" );
fprintf(fp, "Integer Register Id\n" );
fprintf(fp, "1-byte register value\n" );
fprintf(fp, "2-byte register value\n" );
fprintf(fp, "4-byte register value\n" );
fprintf(fp, "8-byte register value\n" );
fprintf(fp, "register value cache index\n" );
fprintf(fp, "integer value -1\n" );
fprintf(fp, "integer value 0\n" );
fprintf(fp, "integer value 1\n" );
fprintf(fp, "integer value 2\n" );
fprintf(fp, "integer value 3\n" );
fprintf(fp, "integer value 4\n" );
fprintf(fp, "integer value 5\n" );
fprintf(fp, "integer value 6\n" );
fprintf(fp, "integer value 7\n" );
fprintf(fp, "integer value 8\n" );
fprintf(fp, "register pair marker\n" );
uint8_t* c_ptr = (uint8_t*) (rst - range);
for (i = range; i > 0; i--) {
for (j = 0; j < sizeof(rstf_instrT); j++) {
fprintf(fp, "%02x", *c_ptr);
fprintf(fp, " -> -%d\n", i);
for (j = 0; j < sizeof(rstf_instrT); j++) {
fprintf(fp, "%02x", *c_ptr);
fprintf(fp, " -> Unknown rtype (%02x)\n", rst->rtype);
for (i = 1; i <= range; i++) {
for (j = 0; j < sizeof(rstf_instrT); j++) {
fprintf(fp, "%02x", *c_ptr);
fprintf(fp, " -> +%d\n", i);
} // RstzipBase::print_rstrec()
bool isIntRegCompressable( const rstf_regvalT *r )
return r->regtype[0] == RSTREG_INT_RT &&
( r->regtype[1] == RSTREG_UNUSED_RT || r->regtype[1] == RSTREG_CC_RT || r->regtype[1] == RSTREG_INT_RT );
bool compressedRegType( int rt )
// RST decompression class.
class Rstunzip : public RstzipBase {
rstz_decompress_unzipped_recs = 0;
rstz_decompress_fbytes = 0;
//rstz_decompress_prev_nrecs = 0;
unzip_chunk_chksm_sum = 0;
unzip_chunk_chunk_counter = 0;
memset(&read_noninstr_rec_rst, 0, sizeof(rstf_unionT));
int rstz_decompress_unzipped_recs; // new recs unzipped in next chunk in outbuf
int rstz_decompress_fbytes; // number of bytes of compressed data fread()
// Decompress up to nrecs RST records from *infp into buf[].
// Returns number of records decompressed. Upon return, *infp will
// point to the start of the next compressed record.
int rstz_decompress(uint8_t** zbufptr, rstf_unionT* rstbuf, int nrecs) {
int total_recs = 0; // total recs copied to buf[]
rstf_instrT* buf_ptr = &rstbuf[0].instr;
outbuf = &rstbuf[0].instr;
rstz_decompress_fbytes = 0;
rstz_decompress_unzipped_recs = 0;
// Unzip chunks from inbuf[] until buf[] cannot take another chunk.
while (total_recs < nrecs) {
rstz_decompress_unzipped_recs = unzip_chunk();
max_chunksize = MAX(max_chunksize, rstz_decompress_unzipped_recs);
fprintf(DBGFP, "zrecs_o()=%d total_recs=%d nrecs=%d\n\n", zrecs_o(), total_recs, nrecs);
total_recs += rstz_decompress_unzipped_recs;
total_instr += num_instr;
total_noninstr += rstz_decompress_unzipped_recs - num_instr;
if (*inbuf_ptr == z_FOOTER_T) {
*zbufptr = inbuf_ptr + 1;
} // Rstunzip::rstz_decompress()
// rd-compression member data:
///////////////////////////////
uint8_t* inbuf; // input buffer for (de)compressed traces
uint8_t* inbuf_ptr; // always points to current inbuf location
rstf_instrT* outbuf; // output buffer for (de)compressed traces
rstf_instrT* outbuf_ptr; // always points to current outbuf location
uint64_t unzip_chunk_chksm_sum;
uint64_t unzip_chunk_chunk_counter;
// Decompress one chunk from inbuf[] into outbuf[]. Return the
// number of records decompressed.
int prerecs, hashval, set;
// init some data members
memset(noninstr_count_buf, 0, MAX_CHUNKSIZE * sizeof(uint8_t));
// find next compressed chunk rtype
while ((*inbuf_ptr < z_FOOTER_T || *inbuf_ptr > zL_INSTR_T) && prerecs < MAX_CHUNKSIZE) {
//print_rstrec(DBGFP, (rstf_instrT*) inbuf_ptr);
if (*inbuf_ptr == PREG_T) {
memcpy(&preg, inbuf_ptr, sizeof(rstf_pregT));
//pstate[preg.primD].pstate = preg.pstate;
pstate.pstate = preg.pstate;
} else if (*inbuf_ptr == PAVADIFF_T) {
memcpy(&pavadiff, inbuf_ptr, sizeof(rstf_pavadiffT));
icontext = pavadiff.icontext;
write_rst2outbuf(read_noninstr_rec(), 1);
// If there were any non-instruction records before the chunk,
// just return so the next time unzip_chunk() is called it will
// start pointing at an instruction record. This is necessary in
// case prerecs + num_instr + num_noninstr > nrecs.
if (prerecs == 0 && *inbuf_ptr != z_FOOTER_T) {
// inbuf_ptr now points to a compressed chunk rtype
read_inbuf(&rtype, sizeof(rtype));
read_inbuf(&num_instr, sizeof(num_instr));
read_inbuf(&pc_start, sizeof(pc_start));
static int chunkNumber = 0;
fprintf(stderr, "Chunk #%d\n", chunkNumber++ );
fprintf(stderr, " decoding %u instructions starting at pc 0x%llx\n", num_instr, pc_start );
for( int i = 0; i < num_instr; ++i ){
fprintf( stderr, " %d) instr\n", iCtr++ );
hashval = hash.hash(pc_start);
if (rtype <= z_INSTR_T) { // non-loop rtype
read_inbuf(instr_buf, num_instr * sizeof(uint32_t));
read_inbuf(flags_buf, num_instr * sizeof(flags_t));
hash.write(pc_start, num_instr, instr_buf, num_ea, ea_buf, hashval);
set = hash.search(pc_start, num_instr, NULL, hashval);
fprintf(stderr, "Error: hash.search() returned NOT_FOUND "
"for zL64_INSTR_T, pc=0x%llx num_instr=%d\n",
table = hash.read(set, hashval);
memcpy(instr_buf, table->instr_buf, num_instr * sizeof(uint32_t));
read_inbuf(flags_buf, num_instr * sizeof(flags_t));
hash.update(num_ea, ea_buf, hashval, set);
find_num_noninstr_count();
read_inbuf(noninstr_count_buf, num_noninstr_count * sizeof(uint8_t));
fprintf( stderr, " nr. non-instructions: %d\n", num_noninstr );
if (checksum_freq != 0) {
unzip_chunk_chksm_sum += compute_checksum64();
unzip_chunk_chunk_counter++;
if (unzip_chunk_chunk_counter % checksum_freq == 0) {
if (chksm != unzip_chunk_chksm_sum) {
//hash.print_set(hashval);
"\nError: checksum inequality (0x%llx != 0x%llx) after record %llu\n",
chksm, unzip_chunk_chksm_sum, total_instr + total_noninstr);
unzip_chunk_chksm_sum = 0;
if (num_instr + num_noninstr < MAX_CHUNKSIZE) {
chunksize_count[(num_instr + num_noninstr) / (MAX_CHUNKSIZE / CHUNKSIZE_RES)]++;
chunksize_count[CHUNKSIZE_RES - 1]++;
return num_instr + num_noninstr + prerecs;
} // Rstunzip::unzip_chunk()
// Build the RST's from instr_buf[], ea_buf[], flags_buf[], etc.,
// and writes the records in the chunk to *outbuf. Returns the
// number of records written.
int i, j, ea_cnt, noninstr_cnt, noninstr_buf_cnt;
for (i = 0; i < num_instr; i++) {
// rst.notused = get_flags(flags_buf[i], NOTUSED);
get_flags(flags_buf[i], NOTUSED);
rst.ea_valid = get_flags(flags_buf[i], EA_VALID);
rst.tr = get_flags(flags_buf[i], TR);
// rst.notused2 = get_flags(flags_buf[i], NOTUSED2);
get_flags(flags_buf[i], NOTUSED2);
rst.pr = get_flags(flags_buf[i], PR);
rst.bt = get_flags(flags_buf[i], BT);
rst.an = get_flags(flags_buf[i], AN);
rst.reservedCompress = 0; // this field might go away in the future
int reservedCompress = get_flags(flags_buf[i], RSRVD_CMPRSS);
// get_flags(flags_buf[i], RSRVD_CMPRSS);
// rst.ihash = getIHash(instr_buf[i]); // removed - 20040210 (vp)
rst.instr = instr_buf[i];
rst.pc_va = pc_start + 4*i;
// if (carry_ea(rst.ihash, rst.ea_valid)) { // replaced - 20040210 (vp)
if (carry_ea(rst.instr, rst.ea_valid)) {
rst.ea_va = ea_buf[ea_cnt];
} else if (rst.an == 0 && rz_is_pc_relative_cti(instr_buf[i])) {
// } else if (rst.an == 0 && ih_ispcrelcti(rst.ihash)) {
// rst.ea_va = getCtiEa(rst.instr, rst.ihash, rst.pc_va); // replaced 20040210 (vp)
if (rz_is_bpr(rst.instr)) {
rst.ea_va = rst.pc_va+BPR_DISP(rst.instr);
} else if (rz_is_bicc(rst.instr)||rz_is_fbfcc(rst.instr)) {
rst.ea_va = rst.pc_va+Bicc_DISP(rst.instr);
} else if (rz_is_bpcc(rst.instr)||rz_is_fbpfcc(rst.instr)) {
rst.ea_va = rst.pc_va+BPcc_DISP(rst.instr);
} else if (rz_is_call(rst.instr)) {
rst.ea_va = rst.pc_va+CALL_DISP(rst.instr);
fprintf(stderr, "Unknown branch type (rst.bt==1, instr word=%08x)\n", rst.instr);
if (pstate.getField(PSTATE_AM) == 1) {
rst.ea_va = rst.pc_va + 8;
// these need to be set (not just computed below) because these values
// are used in read_noninstr_rec() for register records that are not part
// of a chunk of instructions.
lastRd = rst.instr >> 25 & 0x01F;
// write some non-instruction recs?
if (reservedCompress == NONINSTR_FOLLOWS) {
// rst.reservedCompress = 0;
write_rst2outbuf(&rst, 1);
for (j = 0; j < noninstr_count_buf[noninstr_cnt]; j++) {
if (noninstr_buf[noninstr_buf_cnt].rtype == PREG_T) {
rstf_pregT* context = (rstf_pregT*) &noninstr_buf[noninstr_buf_cnt];
//pstate[context->primD].pstate = context->pstate;
pstate.pstate = context->pstate;
} else if (noninstr_buf[noninstr_buf_cnt].rtype == PAVADIFF_T) {
rstf_pavadiffT* pavadiff = (rstf_pavadiffT*) &noninstr_buf[noninstr_buf_cnt];
icontext = pavadiff->icontext;
} else if ( noninstr_buf[noninstr_buf_cnt].rtype == REGVAL_T ) {
// DECOMPRESS: setting proper register id
rstf_regvalT *rv = (rstf_regvalT*) &noninstr_buf[noninstr_buf_cnt];
// not the best solution, but these values don't make it into the trace
// so we're free to adopt a better solution later. SH
if ( rv->regid[0] == 255 ){
decDebugP( "[write_chunk()] Setting regid[0] to %u\n", lastRd );
if ( rv->regid[1] == 255 ){
decDebugP( "[write_chunk()] Setting regid[1] to %u\n", lastRd );
write_rst2outbuf(&noninstr_buf[noninstr_buf_cnt], 1);
return num_instr + num_noninstr;
} // Rstunzip::write_chunk()
// Read instr_buf[] to count number of (valid) ld/st instructions.
for (i = 0; i < num_instr; i++) {
// ih = getIHash(instr_buf[i]); // removed - 20040210 (vp)
// if (carry_ea(ih, get_flags(flags_buf[i], EA_VALID))) { // (replaced - 20040212 (vp)
if (carry_ea(instr_buf[i], get_flags(flags_buf[i], EA_VALID))) {
} // Rstunzip::find_num_ea()
// Read flags_buf[] to count RSRVD_CMPRSS=1 fields .
int find_num_noninstr_count() {
for (i = 0; i < num_instr; i++) {
if (get_flags(flags_buf[i], RSRVD_CMPRSS) == NONINSTR_FOLLOWS) {
} // Rstunzip::find_num_noninstr_count()
// Sum noninstr_count_buf[].
int find_num_noninstr() {
if (num_noninstr_count != 0) {
num_noninstr = noninstr_count_buf[0];
for (i = 1; i < num_noninstr_count; i++) {
num_noninstr += noninstr_count_buf[i];
} // Rstunzip::find_num_instr()
// Read n bytes from *inbuf_ptr into *to, and advance *inbuf_ptr.
// Return the number of bytes read.
int read_inbuf(void* to, size_t n) {
memcpy(to, inbuf_ptr, n);
} // Rstunzip::read_inbuf()
// Write n RST records from from into outbuf_ptr, and advance
// outbuf_ptr. Return the number of records written.
int write_rst2outbuf(rstf_instrT* from, size_t n) {
memcpy(outbuf_ptr, from, n * sizeof(rstf_instrT));
} // Rstunzip::write_rst2outbuf()
int read_ea(hash_table_t* table) {
if (rtype == z_INSTR_T) {
n = read_inbuf(ea_buf, num_ea * sizeof(uint64_t));
for (i = 0; i < num_ea; i++) {
n += read_inbuf(&offset8, sizeof(offset8));
case RESERVED_OFFSET_8BITS:
n += read_inbuf(&offset8, sizeof(offset8));
ea_buf[i] = table->ea_buf[i] + offset8;
offset_count[OFFSET_8BITS_RESERVED_IDX]++;
fprintf(DBGFP, "(Reserved 8) offset8=0x%02hx ", offset8);
"base=0x%llx offset8=0x%02hx ea=0x%llx\n",
table->ea_buf[i], offset8, ea_buf[i]);
case RESERVED_OFFSET_16BITS:
n += read_inbuf(&offset16, sizeof(offset16));
ea_buf[i] = table->ea_buf[i] + offset16;
offset_count[OFFSET_16BITS_IDX]++;
fprintf(DBGFP, "(Reserved 16) offset8=0x%02hx ", offset8);
"base=0x%llx offset16=0x%04hx ea=0x%llx\n",
table->ea_buf[i], offset16, ea_buf[i]);
case RESERVED_OFFSET_32BITS:
n += read_inbuf(&offset32, sizeof(offset32));
ea_buf[i] = table->ea_buf[i] + offset32;
offset_count[OFFSET_32BITS_IDX]++;
fprintf(DBGFP, "(Reserved 32) offset8=0x%02hx ", offset8);
"base=0x%llx offset32=0x%08x ea=0x%llx\n",
table->ea_buf[i], offset32, ea_buf[i]);
case RESERVED_OFFSET_64BITS:
n += read_inbuf(&offset64, sizeof(offset64));
ea_buf[i] = table->ea_buf[i] + offset64;
offset_count[OFFSET_64BITS_IDX]++;
fprintf(DBGFP, "(Reserved 64) offset8=0x%02hx ", offset8);
"base=0x%llx offset64=0x%016llx ea=0x%llx\n",
table->ea_buf[i], offset64, ea_buf[i]);
ea_buf[i] = table->ea_buf[i] + offset8;
offset_count[OFFSET_8BITS_IDX]++;
"base=0x%llx offset8=0x%02hx ea=0x%llx\n",
table->ea_buf[i], offset8, ea_buf[i]);
rstf_unionT read_noninstr_rec_rst;
rstf_instrT* read_noninstr_rec() {
read_noninstr_rec_rst.proto.rtype = *inbuf_ptr;
decDebugP( " %d) ", iCtr++ );
if (read_noninstr_rec_rst.proto.rtype >= z0_PAVADIFF_T &&
read_noninstr_rec_rst.proto.rtype <= z7_PAVADIFF_T) {
decDebug( "decoded a z*_PAVADIFF_T\n" );
switch (read_noninstr_rec_rst.proto.rtype) {
memcpy(&read_noninstr_rec_rst, pava_cache.read(0),
memcpy(&read_noninstr_rec_rst, pava_cache.read(1),
memcpy(&read_noninstr_rec_rst, pava_cache.read(2),
memcpy(&read_noninstr_rec_rst, pava_cache.read(3),
memcpy(&read_noninstr_rec_rst, pava_cache.read(4),
memcpy(&read_noninstr_rec_rst, pava_cache.read(5),
memcpy(&read_noninstr_rec_rst, pava_cache.read(6),
memcpy(&read_noninstr_rec_rst, pava_cache.read(7),
fprintf(stderr, "Error: pava_cache.search() returned NOT_FOUND "
"in read_noninstr_rec()\n");
} else if ( compressedRegType( read_noninstr_rec_rst.proto.rtype ) ) {
if( read_noninstr_rec_rst.proto.rtype == z_REGPAIR_T ){
decDebug( "*** z_REGPAIR_T ***" );
decompressReg( *inbuf_ptr, 0 );
decompressReg( *inbuf_ptr, 1 );
decompressReg( read_noninstr_rec_rst.proto.rtype, 0 );
memcpy(&read_noninstr_rec_rst, inbuf_ptr, sizeof(rstf_pavadiffT));
if (read_noninstr_rec_rst.proto.rtype == PAVADIFF_T) {
pava_cache.write(&read_noninstr_rec_rst.pavadiff);
print_rstrec( stderr, &read_noninstr_rec_rst.instr );
inbuf_ptr += sizeof(rstf_pavadiffT);
return &read_noninstr_rec_rst.instr;
} // Rstunzip::read_noninstr_rec()
void decompressReg( uint8_t curr_rt, int idx )
decDebugP( "z_REGID_T id = %u\n", regid );
memcpy( &value, inbuf_ptr, sizeof( uint64_t) );
inbuf_ptr += sizeof( uint64_t );
vcIdx = valueCache.insert( value );
decDebugP( "z_REGVAL_64_T value=%llu, ", value );
decDebugP( "indexed to %u\n", vcIdx );
memcpy( &val32, inbuf_ptr, sizeof( uint32_t ) );
inbuf_ptr += sizeof( uint32_t );
vcIdx = valueCache.insert( val32 );
decDebugP( "z_REGVAL_32_T value=%u, ", val32 );
decDebugP( "indexed to %u\n", vcIdx );
memcpy( &val16, inbuf_ptr, sizeof( uint16_t ) );
inbuf_ptr += sizeof( uint16_t );
decDebugP( "z_REGVAL_16_T value=%llu\n", val16 );
memcpy( &val8, inbuf_ptr, sizeof( uint8_t ) );
inbuf_ptr += sizeof( uint8_t );
decDebugP( "z_REGVAL_8_T value=%llu\n", val8 );
decDebugP( "z_VALUE_MINUS1_T [%u]\n", z_VALUE_MINUS1_T );
decDebugP( "z_VALUE_0_T [%u]\n", z_VALUE_0_T );
decDebugP( "z_VALUE_1_T [%u]\n", z_VALUE_1_T );
decDebugP( "z_VALUE_2_T [%u]\n", z_VALUE_2_T );
decDebugP( "z_VALUE_3_T [%u]\n", z_VALUE_3_T );
decDebugP( "z_VALUE_4_T [%u]\n", z_VALUE_4_T );
decDebugP( "z_VALUE_5_T [%u]\n", z_VALUE_5_T );
decDebugP( "z_VALUE_6_T [%u]\n", z_VALUE_6_T );
decDebugP( "z_VALUE_7_T [%u]\n", z_VALUE_7_T );
decDebugP( "z_VALUE_8_T [%u]\n", z_VALUE_8_T );
memcpy( &vcIdx, inbuf_ptr, sizeof( VCache::IdxT ) );
inbuf_ptr += sizeof( VCache::IdxT );
value = valueCache[vcIdx];
} catch ( InvalidIndexException &i ){
fprintf( stderr, "caught invalid index exception for index = %u\n", vcIdx );
decDebugP( "z_REGIDX_T, index = %u, ", vcIdx );
decDebugP( "value = %llu\n", value );
fprintf( stderr, "Found a record of type: " );
print_rstrec( stderr, &read_noninstr_rec_rst.instr );
// Special cases when the index is 0
if( *inbuf_ptr == z_CCR_T ){
read_noninstr_rec_rst.regval.regtype[1] = RSTREG_CC_RT;
read_noninstr_rec_rst.regval.regid[1] = *inbuf_ptr++;
decDebugP( "z_CCR_T value = 0x%x\n", read_noninstr_rec_rst.regval.regid[1] );
read_noninstr_rec_rst.regval.regtype[1] = RSTREG_UNUSED_RT;
read_noninstr_rec_rst.regval.regid[1] = 0;
read_noninstr_rec_rst.regval.rtype = REGVAL_T;
read_noninstr_rec_rst.regval.postInstr = 1;
read_noninstr_rec_rst.regval.reg64[1] = 0;
read_noninstr_rec_rst.regval.reg64[idx] = value;
read_noninstr_rec_rst.regval.regtype[idx] = RSTREG_INT_RT;
read_noninstr_rec_rst.regval.regid[idx] = regid;
read_noninstr_rec_rst.regval.regid[idx] = 255;
decDebugP( "[read_noninstr_rec()] Setting regid[%d] to ", idx );
decDebugP( "%u\n", read_noninstr_rec_rst.regval.regid[idx] );
int read_noninstr_recs() {
for (i = 0; i < num_noninstr; i++) {
memcpy(&noninstr_buf[i], read_noninstr_rec(), sizeof(rstf_instrT));
n += sizeof(rstf_instrT);
} // Rstunzip::read_noninstr_recs()
return outbuf_ptr - outbuf;
return inbuf_ptr - inbuf;
} // Rstunzip::zbytes_i()
class Rstzipv2 : public RstzipBase {
rstf_instrT* inbuf_ptr; // always points to current inbuf location
uint8_t* outbuf_ptr; // always points to current outbuf location
rstz_compress_prev_nrecs = 0;
zip_chunk_chunk_counter = 0;
in_same_chunk_prev_pc = 0;
int rstz_compress_prev_nrecs;
// Compress nrecs RST records from rstbuf[] to rz2buf[].
// Returns size of compressed nrecs records in rz2buf[].
int rstz_compress(uint8_t* rz2buf, rstf_unionT* rstbuf, int nrecs) {
inbuf = &rstbuf[0].instr;
while (zrecs_i() < nrecs) {
max_chunksize = MAX(max_chunksize, num_instr + num_noninstr);
fprintf(DBGFP, "zrecs_i()=%d zbytes_o()=%d nrecs=%d\n\n",
zrecs_i(), zbytes_o(), nrecs);
total_instr += buf_instr;
total_noninstr += zrecs_i() - buf_instr;
int rstz_write_prev_nrecs;
// Compress nrecs RST records from buf[] to *outfp; assume exactly
// nrecs records exist in buf[]. Returns number of records
int rstz_write(rstf_unionT buf[], int nrecs) {
if (outbuf == NULL || rstz_write_prev_nrecs < nrecs) {
rstz_write_prev_nrecs = nrecs;
outbuf = (uint8_t*) malloc((nrecs+MAX_CHUNKSIZE) * sizeof(rstf_instrT));
fprintf(stderr, "Error: could not allocate %d bytes "
"of memory in Rstzip::zip()\n",
(nrecs+MAX_CHUNKSIZE) * sizeof(rstf_instrT));
while (zrecs_i() < nrecs) {
max_chunksize = MAX(max_chunksize, num_instr + num_noninstr);
fprintf(DBGFP, "zrecs_i()=%d zbytes_o()=%d nrecs=%d\n\n",
zrecs_i(), zbytes_o(), nrecs);
total_instr += buf_instr;
total_noninstr += zrecs_i() - buf_instr;
zfwrite(outbuf, zbytes_o());
rstf_instrT* inbuf; // input rst buffer
uint8_t* outbuf; // output buffer for compressed traces
uint64_t zip_chunk_chksm;
uint64_t zip_chunk_chunk_counter;
// Compress one chunk of RST records from *inbuf_ptr to *outbuf_ptr.
void zip_chunk(int nrecs) {
rstf_instrT* inbuf_start = inbuf_ptr;
for( int i = 0; i < 5; i++ ){
print_rstrec(DBGFP, inbuf_start++ );
// Read_chunk() initializes pc_start to zero and will set pc_start
if (pc_start != 0 & num_instr > 0) {
hashval = hash.hash(pc_start);
set = hash.search(pc_start, num_instr, instr_buf, hashval);
hash.write(pc_start, num_instr, instr_buf, num_ea, ea_buf, hashval);
write_loop_chunk(hash.read(set, hashval));
hash.update(num_ea, ea_buf, hashval, set);
if (checksum_freq != 0) {
zip_chunk_chksm += compute_checksum64();
zip_chunk_chunk_counter++;
if (zip_chunk_chunk_counter % checksum_freq == 0) {
write_outbuf(&zip_chunk_chksm, 8);
int make_pavadiff_rtype(int index) {
fprintf(stderr, "Error: index param > 7 in rstzip::make_pavadiff_rtype()\n");
// Read one chunk of compressed data from *inbuf_ptr to instr_buf[],
// ea_buf[], flags_buf[], etc. Return the total number of records
int read_chunk(int nrecs) {
rstf_instrT* inbuf_start;
// init some data members
memset(noninstr_count_buf, 0, MAX_CHUNKSIZE * sizeof(uint8_t));
// find an INSTR_T record
while (zrecs_i() < nrecs && inbuf_ptr->rtype != INSTR_T) {
//print_rstrec(DBGFP, inbuf_ptr);
write_noninstr_rec(inbuf_ptr);
// inbuf_ptr points to an INSTR_T now
if (zrecs_i() < nrecs && inbuf_ptr->rtype == INSTR_T) {
//print_rstrec(DBGFP, inbuf_ptr);
pc_start = inbuf_ptr->pc_va;
fprintf( stderr, "writing chunk #%d\n", chunkNum++ );
while (zrecs_i() < nrecs && in_same_chunk(inbuf_ptr, nrecs, inbuf_ptr - inbuf_start + 1)) {
if (inbuf_ptr->rtype == INSTR_T) {
instr_buf[num_instr] = inbuf_ptr->instr;
// save the destination register for regval records
// that follow this instruction.
lastRegid = inbuf_ptr->instr >> 25 & 0x01f;
// ih = getIHash(inbuf_ptr->instr); // removed - 20040210 (vp)
// if (carry_ea(ih, inbuf_ptr->ea_valid)) { // replaced - 20040210 (vp)
if (carry_ea(inbuf_ptr->instr, inbuf_ptr->ea_valid)) {
ea_buf[num_ea] = inbuf_ptr->ea_va;
flags_buf[num_instr] = 0;
set_flags(&flags_buf[num_instr], NOTUSED, inbuf_ptr->notused);
set_flags(&flags_buf[num_instr], EA_VALID, inbuf_ptr->ea_valid);
set_flags(&flags_buf[num_instr], TR, inbuf_ptr->tr);
// set_flags(&flags_buf[num_instr], NOTUSED2, inbuf_ptr->notused2);
set_flags(&flags_buf[num_instr], NOTUSED2, 0);
set_flags(&flags_buf[num_instr], PR, inbuf_ptr->pr);
set_flags(&flags_buf[num_instr], BT, inbuf_ptr->bt);
set_flags(&flags_buf[num_instr], AN, inbuf_ptr->an);
set_flags(&flags_buf[num_instr], RSRVD_CMPRSS, INSTR_FOLLOWS);
if (num_instr == UINT16_MAX) {
fprintf(stderr, "Error: num_instr > UINT16_MAX in Rstzip::read_chunk()\n");
if (noninstr_count_buf[num_noninstr_count]) {
if (noninstr_count_buf[num_noninstr_count] == UINT8_MAX) {
fprintf(stderr, "Error: num_noninstr > %d in Rstzip::read_chunk()\n", UINT8_MAX);
// copy non-instrustion record to noninstr_buf[]
memcpy(&noninstr_buf[num_noninstr], inbuf_ptr, sizeof(rstf_unionT));
lastRegIdBuf[num_noninstr] = lastRegid;
// increment noninstr_count_buf[]
noninstr_count_buf[num_noninstr_count]++;
set_flags(&flags_buf[num_instr - 1], RSRVD_CMPRSS, NONINSTR_FOLLOWS);
fprintf( stderr, " wrote %d instructions\n", num_instr );
fprintf( stderr, " wrote %d non-instructions\n", num_noninstr );
if (num_instr + num_noninstr < MAX_CHUNKSIZE) {
chunksize_count[(num_instr + num_noninstr) / (MAX_CHUNKSIZE / CHUNKSIZE_RES)]++;
chunksize_count[CHUNKSIZE_RES - 1]++;
return inbuf_ptr - inbuf_start;
} // Rstzip::read_chunk()
uint64_t in_same_chunk_prev_pc;
// Chunks are terminated by:
// 1) non-sequential instructions
// 4) > UINT8_MAX sequential noninstruction records
// Chunks are not terminated by non-instruction records (to improve
bool in_same_chunk(rstf_instrT* rst, int nrecs, int chunk_recs) {
if (chunk_recs >= MAX_CHUNKSIZE) {
} else if (rst->rtype == INSTR_T) {
if (rst->pc_va != in_same_chunk_prev_pc + 4) {
in_same_chunk_prev_pc = rst->pc_va;
for (recs = zrecs_i(), ni_recs = 0;
recs < nrecs && ni_recs < UINT8_MAX && chunk_recs < MAX_CHUNKSIZE && rst->rtype != INSTR_T;
recs++, ni_recs++, chunk_recs++) {
if (recs < nrecs && chunk_recs < MAX_CHUNKSIZE) {
if (rst->rtype != INSTR_T) {
} else if (rst->pc_va != in_same_chunk_prev_pc + 4) {
} // Rstzip::in_same_chunk()
// Write the chunk data from instr_buf[], ea_buf[], flags_buf[],
// etc. to *outbuf_ptr. Return the number of bytes written.
n += write_outbuf(&rtype, sizeof(rtype));
n += write_outbuf(&num_instr, sizeof(num_instr));
n += write_outbuf(&pc_start, sizeof(pc_start));
n += write_outbuf(instr_buf, num_instr * sizeof(uint32_t));
n += write_outbuf(flags_buf, num_instr * sizeof(flags_t));
n += write_outbuf(noninstr_count_buf, num_noninstr_count * sizeof(uint8_t));
n += write_noninstr_recs();
} // Rstzip::write_chunk()
// Write the loop chunk data from instr_buf[], ea_buf[],
// flags_buf[], etc. to *outbuf_ptr. Return the number of bytes
int write_loop_chunk(hash_table_t* table) {
n += write_outbuf(&rtype, sizeof(rtype));
n += write_outbuf(&num_instr, sizeof(num_instr));
n += write_outbuf(&pc_start, sizeof(pc_start));
n += write_outbuf(flags_buf, num_instr * sizeof(flags_t));
n += write_outbuf(noninstr_count_buf, num_noninstr_count * sizeof(uint8_t));
n += write_noninstr_recs();
} // Rstzip::write_loop_chunk()
int write_ea(hash_table_t* table) {
// Nothing to write if num_ea == 0.
if (rtype == z_INSTR_T) { // no compression
n += write_outbuf(ea_buf, num_ea * sizeof(uint64_t));
for (i = 0; i < num_ea; i++) {
offset64 = ea_buf[i] - table->ea_buf[i];
if (offset64 >= INT8_MIN && offset64 <= INT8_MAX) {
if (offset64 == RESERVED_OFFSET_8BITS ||
offset64 == RESERVED_OFFSET_16BITS ||
offset64 == RESERVED_OFFSET_32BITS ||
offset64 == RESERVED_OFFSET_64BITS) {
offset8 = RESERVED_OFFSET_8BITS;
n += write_outbuf(&offset8, sizeof(offset8));
offset_count[OFFSET_8BITS_RESERVED_IDX]++;
fprintf(DBGFP, "(Reserved 8) offset8=0x%02hx ",
table->ea_buf[i], offset8, ea_buf[i]);
offset_count[OFFSET_8BITS_IDX]++;
offset8 = (int8_t) offset64 & 0xff;
n += write_outbuf(&offset8, sizeof(offset8));
fprintf(DBGFP, "base=0x%llx offset8=0x%02hx ea=0x%llx\n",
table->ea_buf[i], offset8, ea_buf[i]);
} else if (offset64 >= INT16_MIN && offset64 <= INT16_MAX) {
offset8 = RESERVED_OFFSET_16BITS;
offset16 = (int16_t) offset64 & 0xffff;
n += write_outbuf(&offset8, sizeof(offset8));
n += write_outbuf(&offset16, sizeof(offset16));
offset_count[OFFSET_16BITS_IDX]++;
fprintf(DBGFP, "(Reserved 16) offset8=0x%02hx ", offset8);
fprintf(DBGFP, "base=0x%llx offset16=0x%04hx ea=0x%llx\n",
table->ea_buf[i], offset16, ea_buf[i]);
} else if (offset64 >= INT32_MIN && offset64 <= INT32_MAX) {
offset8 = RESERVED_OFFSET_32BITS;
offset32 = (int32_t) offset64 & 0xffffffff;
n += write_outbuf(&offset8, sizeof(offset8));
n += write_outbuf(&offset32, sizeof(offset32));
offset_count[OFFSET_32BITS_IDX]++;
fprintf(DBGFP, "(Reserved 32) offset8=0x%02hx ", offset8);
"base=0x%llx offset32=0x%08x ea=0x%llx\n",
table->ea_buf[i], offset32, ea_buf[i]);
offset8 = RESERVED_OFFSET_64BITS;
n += write_outbuf(&offset8, sizeof(offset8));
n += write_outbuf(&offset64, sizeof(offset64));
offset_count[OFFSET_64BITS_IDX]++;
fprintf(DBGFP, "(Reserved 64) offset8=0x%02hx ", offset8);
fprintf(DBGFP, "base=0x%llx offset64=0x%016llx ea=0x%llx\n",
table->ea_buf[i], offset64, ea_buf[i]);
// Write n bytes from *from to *outbuf_ptr, and increment
// outbuf_ptr. Return the number of bytes written.
int write_outbuf(void* from, size_t n) {
memcpy(outbuf_ptr, from, n);
} // Rstzip::write_outbuf()
int write_noninstr_rec(rstf_instrT* rst) {
print_rstrec( stderr, rst );
if (rst->rtype == PAVADIFF_T) {
index = pava_cache.search((rstf_pavadiffT*) rst);
if (index == NOT_FOUND) {
n = write_outbuf(rst, sizeof(rstf_instrT));
pava_cache.write((rstf_pavadiffT*) rst);
uint8_t ztype = make_pavadiff_rtype(index);
n = write_outbuf(&ztype, sizeof(uint8_t));
pava_cache.update(index);
comDebug( "writing PAVADIFF_T\n" );
} else if ( rst->rtype == REGVAL_T ){
rstf_regvalT *regP = (rstf_regvalT*) rst;
if ( isIntRegCompressable( regP ) ){
comDebug( "* Processing compressable register " );
if( regP->regtype[1] == RSTREG_INT_RT ){
uint8_t tag = z_REGPAIR_T;
comDebug( "[ *** z_REGPAIR_T *** ]" );
n += write_outbuf( &tag, sizeof( uint8_t ) );
n += compressIntegerRecord( regP->regid[0], regP->reg64[0], regP->cpuid, lastRID );
if( regP->regtype[1] == RSTREG_INT_RT ){
n += compressIntegerRecord( regP->regid[1], regP->reg64[1], regP->cpuid, lastRID );
} else if( regP->regtype[1] == RSTREG_CC_RT ){
n += writeCCRecord( regP->regid[1] );
// we're not compressing this type of regval
n = write_outbuf( rst, sizeof(rstf_instrT) );
comDebug( "* Writing non-compressable REGVAL_T\n" );
n = write_outbuf(rst, sizeof(rstf_instrT));
unsigned compressIntegerRecord( uint8_t regid, uint64_t regval, uint8_t cpuid, int lastInstrRegId = -1 )
static uint8_t tagLookup[9] = { z_VALUE_0_T, z_VALUE_1_T, z_VALUE_2_T, z_VALUE_3_T,
z_VALUE_4_T, z_VALUE_5_T, z_VALUE_6_T, z_VALUE_7_T, z_VALUE_8_T };
static const char *tag2String[9] = { "z_VALUE_0_T", "z_VALUE_1_T", "z_VALUE_2_T", "z_VALUE_3_T",
"z_VALUE_4_T", "z_VALUE_5_T", "z_VALUE_6_T", "z_VALUE_7_T", "z_VALUE_8_T" };
comDebugP( "(last regid = %u)\n", lastInstrRegId );
// if we can't get the regid from the instruction, then
// we'll need to output it to the compressed trace.
if( regid != lastInstrRegId || !inChunk ){
comDebugP( "z_REGID_T id = %u\n ", regid );
totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
totalSize += write_outbuf( ®id, sizeof( uint8_t ) );
if( valueCache.hit( regval, idx ) ){
comDebugP( "z_REGIDX_T idx=%u ", idx );
comDebugP( " val=%llu\n", regval );
// if we hit in the value cache, then output the index.
totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
totalSize += write_outbuf( &idx, sizeof( VCache::IdxT ) );
} else if ( regval < 9 ){
// we have specific records for values < 8
totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
comDebugP( "%s ", tag2String[regval] );
comDebugP( "[%u]\n", tag );
} else if( (regval & 0x0ff) == regval ){
// if the regval can be expressed in one byte, then it's wasteful to
// enter it in the value cache. Instead, we output the 1-byte values
// to the trace. Note: we NEVER put these value in the value cache!!!
totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
totalSize += write_outbuf( &rv8, sizeof( uint8_t ) );
comDebugP( "z_REGVAL_8_T val=%u\n", rv8 );
} else if( (regval & 0x0ffff) == regval ){
// if the regval can be expressed in two bytes, then it's wasteful to
// enter it in the value cache. Instead, we output the 2-byte values
// to the trace. Note: we NEVER put these value in the value cache!!!
totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
totalSize += write_outbuf( &rv16, sizeof( uint16_t ) );
comDebugP( "z_REGVAL_16_T val=%u\n", rv16 );
} else if( regval == ~(0x0ULL) ){
totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
comDebugP( "z_VALUE_MINUS1_T [%u]", tag );
VCache::IdxT i = valueCache.insert( regval );
if( (regval & 0x0ffffffff ) == regval ){
totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
totalSize += write_outbuf( &rv32, sizeof( uint32_t ) );
comDebugP( "z_REGVAL_32_T val=%u", rv32 );
totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
totalSize += write_outbuf( ®val, sizeof( uint64_t ) );
comDebugP( "z_REGVAL_64_T val=%llu", regval );
comDebugP( " indexed to %u\n", i );
comDebugP( " size = %u\n", totalSize );
unsigned writeCCRecord( uint8_t CCRContents )
totalSize += write_outbuf( &tag, sizeof( uint8_t ) );
totalSize += write_outbuf( &CCRContents, sizeof( uint8_t ) );
comDebugP( " [CCR] = 0x%x\n", CCRContents );
int write_noninstr_recs() {
for (i = 0; i < num_noninstr; i++) {
lastRID = lastRegIdBuf[i];
n += write_noninstr_rec(&noninstr_buf[i]);
return inbuf_ptr - inbuf;
return outbuf_ptr - outbuf;
} // Rstzip::zbytes_o()()