Home | History | Annotate | Download | only in qemu
      1 /* Copyright (C) 2006-2007 The Android Open Source Project
      2 **
      3 ** This software is licensed under the terms of the GNU General Public
      4 ** License version 2, as published by the Free Software Foundation, and
      5 ** may be copied, distributed, and modified under those terms.
      6 **
      7 ** This program is distributed in the hope that it will be useful,
      8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 ** GNU General Public License for more details.
     11 */
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <limits.h>
     17 #include <inttypes.h>
     18 #include <sys/stat.h>
     19 #include <sys/types.h>
     20 #include <errno.h>
     21 #include <sys/time.h>
     22 #include <time.h>
     23 #include "cpu.h"
     24 #include "exec-all.h"
     25 #include "trace.h"
     26 #include "varint.h"
     27 
     28 TraceBB trace_bb;
     29 TraceInsn trace_insn;
     30 TraceStatic trace_static;
     31 TraceAddr trace_load;
     32 TraceAddr trace_store;
     33 TraceExc trace_exc;
     34 TracePid trace_pid;
     35 TraceMethod trace_method;
     36 static TraceHeader header;
     37 
     38 const char *trace_filename;
     39 int tracing;
     40 int trace_cache_miss;
     41 int trace_all_addr;
     42 
     43 // The simulation time in cpu clock cycles
     44 uint64_t sim_time = 1;
     45 
     46 // The current process id
     47 int current_pid;
     48 
     49 // The start and end (wall-clock) time in microseconds
     50 uint64_t start_time, end_time;
     51 uint64_t elapsed_usecs;
     52 
     53 // For debugging output
     54 FILE *ftrace_debug;
     55 
     56 // The maximum number of bytes consumed by an InsnRec after compression.
     57 // This is very conservative but needed to ensure no buffer overflows.
     58 #define kMaxInsnCompressed 14
     59 
     60 // The maximum number of bytes consumed by an BBRec after compression.
     61 // This is very conservative but needed to ensure no buffer overflows.
     62 #define kMaxBBCompressed 32
     63 
     64 // The maximum number of bytes consumed by an AddrRec after compression.
     65 // This is very conservative but needed to ensure no buffer overflows.
     66 #define kMaxAddrCompressed 14
     67 
     68 // The maximum number of bytes consumed by a MethodRec after compression.
     69 // This is very conservative but needed to ensure no buffer overflows.
     70 #define kMaxMethodCompressed 18
     71 
     72 // The maximum number of bytes consumed by an exception record after
     73 // compression.
     74 #define kMaxExcCompressed 38
     75 
     76 // The maximum number of bytes consumed by a pid record for
     77 // kPidSwitch, or kPidExit after compression.
     78 #define kMaxPidCompressed 15
     79 
     80 // The maximum number of bytes consumed by a pid record for kPidFork,
     81 // or kPidClone after compression.
     82 #define kMaxPid2Compressed 20
     83 
     84 // The maximum number of bytes consumed by a pid record for kPidExecArgs
     85 // after compression, not counting the bytes for the args.
     86 #define kMaxExecArgsCompressed 15
     87 
     88 // The maximum number of bytes consumed by a pid record for kPidName
     89 // after compression, not counting the bytes for the name.
     90 #define kMaxNameCompressed 20
     91 
     92 // The maximum number of bytes consumed by a pid record for kPidMmap
     93 // after compression, not counting the bytes for the pathname.
     94 #define kMaxMmapCompressed 33
     95 
     96 // The maximum number of bytes consumed by a pid record for kPidMunmap,
     97 // after compression.
     98 #define kMaxMunmapCompressed 28
     99 
    100 // The maximum number of bytes consumed by a pid record for kPidSymbol
    101 // after compression, not counting the bytes for the symbol name.
    102 #define kMaxSymbolCompressed 24
    103 
    104 // The maximum number of bytes consumed by a pid record for kPidKthreadName
    105 // after compression, not counting the bytes for the name.
    106 #define kMaxKthreadNameCompressed 25
    107 
    108 void trace_cleanup();
    109 
    110 // Return current time in microseconds as a 64-bit integer.
    111 uint64 Now() {
    112     struct timeval        tv;
    113 
    114     gettimeofday(&tv, NULL);
    115     uint64 val = tv.tv_sec;
    116     val = val * 1000000ull + tv.tv_usec;
    117     return val;
    118 }
    119 
    120 static void create_trace_dir(const char *dirname)
    121 {
    122     int err;
    123 
    124     err = path_mkdir(dirname, 0755);
    125     if (err != 0 && errno != EEXIST) {
    126         printf("err: %d\n", err);
    127         perror(dirname);
    128         exit(1);
    129     }
    130 }
    131 
    132 static char *create_trace_path(const char *filename, const char *ext)
    133 {
    134     char *fname;
    135     const char *base_start, *base_end;
    136     int ii, len, base_len, dir_len, path_len, qtrace_len;
    137 
    138     // Handle error cases
    139     if (filename == NULL || *filename == 0 || strcmp(filename, "/") == 0)
    140         return NULL;
    141 
    142     // Ignore a trailing slash, if any
    143     len = strlen(filename);
    144     if (filename[len - 1] == '/')
    145         len -= 1;
    146 
    147     // Find the basename.  We don't use basename(3) because there are
    148     // different behaviors for GNU and Posix in the case where the
    149     // last character is a slash.
    150     base_start = base_end = &filename[len];
    151     for (ii = 0; ii < len; ++ii) {
    152         base_start -= 1;
    153         if (*base_start == '/') {
    154             base_start += 1;
    155             break;
    156         }
    157     }
    158     base_len = base_end - base_start;
    159     dir_len = len - base_len;
    160     qtrace_len = strlen("/qtrace");
    161 
    162     // Create space for the pathname: "/dir/basename/qtrace.ext"
    163     // The "ext" string already contains the dot, so just add a byte
    164     // for the terminating zero.
    165     path_len = dir_len + base_len + qtrace_len + strlen(ext) + 1;
    166     fname = malloc(path_len);
    167     if (dir_len > 0)
    168         strncpy(fname, filename, dir_len);
    169     fname[dir_len] = 0;
    170     strncat(fname, base_start, base_len);
    171     strcat(fname, "/qtrace");
    172     strcat(fname, ext);
    173     return fname;
    174 }
    175 
    176 void convert_secs_to_date_time(time_t secs, uint32_t *pdate, uint32_t *ptime)
    177 {
    178     struct tm *tm = localtime(&secs);
    179     uint32_t year = tm->tm_year + 1900;
    180     uint32_t thousands = year / 1000;
    181     year -= thousands * 1000;
    182     uint32_t hundreds = year / 100;
    183     year -= hundreds * 100;
    184     uint32_t tens = year / 10;
    185     year -= tens * 10;
    186     uint32_t ones = year;
    187     year = (thousands << 12) | (hundreds << 8) | (tens << 4) | ones;
    188 
    189     uint32_t mon = tm->tm_mon + 1;
    190     tens = mon / 10;
    191     ones = (mon - tens * 10);
    192     mon = (tens << 4) | ones;
    193 
    194     uint32_t day = tm->tm_mday;
    195     tens = day / 10;
    196     ones = (day - tens * 10);
    197     day = (tens << 4) | ones;
    198 
    199     *pdate = (year << 16) | (mon << 8) | day;
    200 
    201     uint32_t hour = tm->tm_hour;
    202     tens = hour / 10;
    203     ones = (hour - tens * 10);
    204     hour = (tens << 4) | ones;
    205 
    206     uint32_t min = tm->tm_min;
    207     tens = min / 10;
    208     ones = (min - tens * 10);
    209     min = (tens << 4) | ones;
    210 
    211     uint32_t sec = tm->tm_sec;
    212     tens = sec / 10;
    213     ones = (sec - tens * 10);
    214     sec = (tens << 4) | ones;
    215 
    216     *ptime = (hour << 16) | (min << 8) | sec;
    217 }
    218 
    219 void write_trace_header(TraceHeader *header)
    220 {
    221     TraceHeader swappedHeader;
    222 
    223     memcpy(&swappedHeader, header, sizeof(TraceHeader));
    224 
    225     convert32(swappedHeader.version);
    226     convert32(swappedHeader.start_sec);
    227     convert32(swappedHeader.start_usec);
    228     convert32(swappedHeader.pdate);
    229     convert32(swappedHeader.ptime);
    230     convert32(swappedHeader.num_used_pids);
    231     convert32(swappedHeader.first_unused_pid);
    232     convert64(swappedHeader.num_static_bb);
    233     convert64(swappedHeader.num_static_insn);
    234     convert64(swappedHeader.num_dynamic_bb);
    235     convert64(swappedHeader.num_dynamic_insn);
    236     convert64(swappedHeader.elapsed_usecs);
    237 
    238     fwrite(&swappedHeader, sizeof(TraceHeader), 1, trace_static.fstream);
    239 }
    240 
    241 void create_trace_bb(const char *filename)
    242 {
    243     char *fname = create_trace_path(filename, ".bb");
    244     trace_bb.filename = fname;
    245 
    246     FILE *fstream = fopen(fname, "wb");
    247     if (fstream == NULL) {
    248         perror(fname);
    249         exit(1);
    250     }
    251     trace_bb.fstream = fstream;
    252     trace_bb.next = &trace_bb.buffer[0];
    253     trace_bb.flush_time = 0;
    254     trace_bb.compressed_ptr = trace_bb.compressed;
    255     trace_bb.high_water_ptr = &trace_bb.compressed[kCompressedSize] - kMaxBBCompressed;
    256     trace_bb.prev_bb_num = 0;
    257     trace_bb.prev_bb_time = 0;
    258     trace_bb.num_insns = 0;
    259     trace_bb.recnum = 0;
    260 }
    261 
    262 void create_trace_insn(const char *filename)
    263 {
    264     // Create the instruction time trace file
    265     char *fname = create_trace_path(filename, ".insn");
    266     trace_insn.filename = fname;
    267 
    268     FILE *fstream = fopen(fname, "wb");
    269     if (fstream == NULL) {
    270         perror(fname);
    271         exit(1);
    272     }
    273     trace_insn.fstream = fstream;
    274     trace_insn.current = &trace_insn.dummy;
    275     trace_insn.dummy.time_diff = 0;
    276     trace_insn.dummy.repeat = 0;
    277     trace_insn.prev_time = 0;
    278     trace_insn.compressed_ptr = trace_insn.compressed;
    279     trace_insn.high_water_ptr = &trace_insn.compressed[kCompressedSize] - kMaxInsnCompressed;
    280 }
    281 
    282 void create_trace_static(const char *filename)
    283 {
    284     // Create the static basic block trace file
    285     char *fname = create_trace_path(filename, ".static");
    286     trace_static.filename = fname;
    287 
    288     FILE *fstream = fopen(fname, "wb");
    289     if (fstream == NULL) {
    290         perror(fname);
    291         exit(1);
    292     }
    293     trace_static.fstream = fstream;
    294     trace_static.next_insn = 0;
    295     trace_static.bb_num = 1;
    296     trace_static.bb_addr = 0;
    297 
    298     // Write an empty header to reserve space for it in the file.
    299     // The header will be filled in later when post-processing the
    300     // trace file.
    301     memset(&header, 0, sizeof(TraceHeader));
    302 
    303     // Write out the version number so that tools can detect if the trace
    304     // file format is the same as what they expect.
    305     header.version = TRACE_VERSION;
    306 
    307     // Record the start time in the header now.
    308     struct timeval tv;
    309     struct timezone tz;
    310     gettimeofday(&tv, &tz);
    311     header.start_sec = tv.tv_sec;
    312     header.start_usec = tv.tv_usec;
    313     convert_secs_to_date_time(header.start_sec, &header.pdate, &header.ptime);
    314     write_trace_header(&header);
    315 
    316     // Write out the record for the unused basic block number 0.
    317     uint64_t zero = 0;
    318     fwrite(&zero, sizeof(uint64_t), 1, trace_static.fstream);	// bb_num
    319     fwrite(&zero, sizeof(uint32_t), 1, trace_static.fstream);	// bb_addr
    320     fwrite(&zero, sizeof(uint32_t), 1, trace_static.fstream);	// num_insns
    321 }
    322 
    323 void create_trace_addr(const char *filename)
    324 {
    325     // The "qtrace.load" and "qtrace.store" files are optional
    326     trace_load.fstream = NULL;
    327     trace_store.fstream = NULL;
    328     if (trace_all_addr || trace_cache_miss) {
    329         // Create the "qtrace.load" file
    330         char *fname = create_trace_path(filename, ".load");
    331         trace_load.filename = fname;
    332 
    333         FILE *fstream = fopen(fname, "wb");
    334         if (fstream == NULL) {
    335             perror(fname);
    336             exit(1);
    337         }
    338         trace_load.fstream = fstream;
    339         trace_load.next = &trace_load.buffer[0];
    340         trace_load.compressed_ptr = trace_load.compressed;
    341         trace_load.high_water_ptr = &trace_load.compressed[kCompressedSize] - kMaxAddrCompressed;
    342         trace_load.prev_addr = 0;
    343         trace_load.prev_time = 0;
    344 
    345         // Create the "qtrace.store" file
    346         fname = create_trace_path(filename, ".store");
    347         trace_store.filename = fname;
    348 
    349         fstream = fopen(fname, "wb");
    350         if (fstream == NULL) {
    351             perror(fname);
    352             exit(1);
    353         }
    354         trace_store.fstream = fstream;
    355         trace_store.next = &trace_store.buffer[0];
    356         trace_store.compressed_ptr = trace_store.compressed;
    357         trace_store.high_water_ptr = &trace_store.compressed[kCompressedSize] - kMaxAddrCompressed;
    358         trace_store.prev_addr = 0;
    359         trace_store.prev_time = 0;
    360     }
    361 }
    362 
    363 void create_trace_exc(const char *filename)
    364 {
    365     // Create the exception trace file
    366     char *fname = create_trace_path(filename, ".exc");
    367     trace_exc.filename = fname;
    368 
    369     FILE *fstream = fopen(fname, "wb");
    370     if (fstream == NULL) {
    371         perror(fname);
    372         exit(1);
    373     }
    374     trace_exc.fstream = fstream;
    375     trace_exc.compressed_ptr = trace_exc.compressed;
    376     trace_exc.high_water_ptr = &trace_exc.compressed[kCompressedSize] - kMaxExcCompressed;
    377     trace_exc.prev_time = 0;
    378     trace_exc.prev_bb_recnum = 0;
    379 }
    380 
    381 void create_trace_pid(const char *filename)
    382 {
    383     // Create the pid trace file
    384     char *fname = create_trace_path(filename, ".pid");
    385     trace_pid.filename = fname;
    386 
    387     FILE *fstream = fopen(fname, "wb");
    388     if (fstream == NULL) {
    389         perror(fname);
    390         exit(1);
    391     }
    392     trace_pid.fstream = fstream;
    393     trace_pid.compressed_ptr = trace_pid.compressed;
    394     trace_pid.prev_time = 0;
    395 }
    396 
    397 void create_trace_method(const char *filename)
    398 {
    399     // Create the method trace file
    400     char *fname = create_trace_path(filename, ".method");
    401     trace_method.filename = fname;
    402 
    403     FILE *fstream = fopen(fname, "wb");
    404     if (fstream == NULL) {
    405         perror(fname);
    406         exit(1);
    407     }
    408     trace_method.fstream = fstream;
    409     trace_method.compressed_ptr = trace_method.compressed;
    410     trace_method.prev_time = 0;
    411     trace_method.prev_addr = 0;
    412     trace_method.prev_pid = 0;
    413 }
    414 
    415 void trace_init(const char *filename)
    416 {
    417     // Create the trace files
    418     create_trace_dir(filename);
    419     create_trace_bb(filename);
    420     create_trace_insn(filename);
    421     create_trace_static(filename);
    422     create_trace_addr(filename);
    423     create_trace_exc(filename);
    424     create_trace_pid(filename);
    425     create_trace_method(filename);
    426 
    427 #if 0
    428     char *fname = create_trace_path(filename, ".debug");
    429     ftrace_debug = fopen(fname, "wb");
    430     if (ftrace_debug == NULL) {
    431         perror(fname);
    432         exit(1);
    433     }
    434 #else
    435     ftrace_debug = NULL;
    436 #endif
    437     atexit(trace_cleanup);
    438 
    439     // If tracing is on, then start timing the simulator
    440     if (tracing)
    441         start_time = Now();
    442 }
    443 
    444 /* the following array is used to deal with def-use register interlocks, which we
    445  * can compute statically (ignoring conditions), very fortunately.
    446  *
    447  * the idea is that interlock_base contains the number of cycles "executed" from
    448  * the start of a basic block. It is set to 0 in trace_bb_start, and incremented
    449  * in each call to get_insn_ticks_arm.
    450  *
    451  * interlocks[N] correspond to the value of interlock_base after which a register N
    452  * can be used by another operation, it is set each time an instruction writes to
    453  * the register in get_insn_ticks()
    454  */
    455 
    456 static int   interlocks[16];
    457 static int   interlock_base;
    458 
    459 static void
    460 _interlock_def(int  reg, int  delay)
    461 {
    462     if (reg >= 0)
    463         interlocks[reg] = interlock_base + delay;
    464 }
    465 
    466 static int
    467 _interlock_use(int  reg)
    468 {
    469     int  delay = 0;
    470 
    471     if (reg >= 0)
    472     {
    473         delay = interlocks[reg] - interlock_base;
    474         if (delay < 0)
    475             delay = 0;
    476     }
    477     return delay;
    478 }
    479 
    480 void trace_bb_start(uint32_t bb_addr)
    481 {
    482     int  nn;
    483 
    484     trace_static.bb_addr = bb_addr;
    485     trace_static.is_thumb = 0;
    486 
    487     interlock_base = 0;
    488     for (nn = 0; nn < 16; nn++)
    489         interlocks[nn] = 0;
    490 }
    491 
    492 void trace_add_insn(uint32_t insn, int is_thumb)
    493 {
    494     trace_static.insns[trace_static.next_insn++] = insn;
    495     // This relies on the fact that a basic block does not contain a mix
    496     // of ARM and Thumb instructions.  If that is not true, then many
    497     // software tools that read the trace will have to change.
    498     trace_static.is_thumb = is_thumb;
    499 }
    500 
    501 void trace_bb_end()
    502 {
    503     int		ii, num_insns;
    504     uint32_t	insn;
    505 
    506     uint64_t bb_num = hostToLE64(trace_static.bb_num);
    507     // If these are Thumb instructions, then encode that fact by setting
    508     // the low bit of the basic-block address to 1.
    509     uint32_t bb_addr = trace_static.bb_addr | trace_static.is_thumb;
    510     bb_addr = hostToLE32(bb_addr);
    511     num_insns = hostToLE32(trace_static.next_insn);
    512     fwrite(&bb_num, sizeof(bb_num), 1, trace_static.fstream);
    513     fwrite(&bb_addr, sizeof(bb_addr), 1, trace_static.fstream);
    514     fwrite(&num_insns, sizeof(num_insns), 1, trace_static.fstream);
    515     for (ii = 0; ii < trace_static.next_insn; ++ii) {
    516         insn = hostToLE32(trace_static.insns[ii]);
    517         fwrite(&insn, sizeof(insn), 1, trace_static.fstream);
    518     }
    519 
    520     trace_static.bb_num += 1;
    521     trace_static.next_insn = 0;
    522 }
    523 
    524 void trace_cleanup()
    525 {
    526     if (tracing) {
    527         end_time = Now();
    528         elapsed_usecs += end_time - start_time;
    529     }
    530     header.elapsed_usecs = elapsed_usecs;
    531     double elapsed_secs = elapsed_usecs / 1000000.0;
    532     double cycles_per_sec = 0;
    533     if (elapsed_secs != 0)
    534         cycles_per_sec = sim_time / elapsed_secs;
    535     char *suffix = "";
    536     if (cycles_per_sec >= 1000000) {
    537         cycles_per_sec /= 1000000.0;
    538         suffix = "M";
    539     } else if (cycles_per_sec > 1000) {
    540         cycles_per_sec /= 1000.0;
    541         suffix = "K";
    542     }
    543     printf("Elapsed seconds: %.2f, simulated cycles/sec: %.1f%s\n",
    544            elapsed_secs, cycles_per_sec, suffix);
    545     if (trace_bb.fstream) {
    546         BBRec *ptr;
    547         BBRec *next = trace_bb.next;
    548         char *comp_ptr = trace_bb.compressed_ptr;
    549         int64_t prev_bb_num = trace_bb.prev_bb_num;
    550         uint64_t prev_bb_time = trace_bb.prev_bb_time;
    551         for (ptr = trace_bb.buffer; ptr != next; ++ptr) {
    552             if (comp_ptr >= trace_bb.high_water_ptr) {
    553                 uint32_t size = comp_ptr - trace_bb.compressed;
    554                 fwrite(trace_bb.compressed, sizeof(char), size,
    555                        trace_bb.fstream);
    556                 comp_ptr = trace_bb.compressed;
    557             }
    558             int64_t bb_diff = ptr->bb_num - prev_bb_num;
    559             prev_bb_num = ptr->bb_num;
    560             uint64_t time_diff = ptr->start_time - prev_bb_time;
    561             prev_bb_time = ptr->start_time;
    562             comp_ptr = varint_encode_signed(bb_diff, comp_ptr);
    563             comp_ptr = varint_encode(time_diff, comp_ptr);
    564             comp_ptr = varint_encode(ptr->repeat, comp_ptr);
    565             if (ptr->repeat)
    566                 comp_ptr = varint_encode(ptr->time_diff, comp_ptr);
    567         }
    568 
    569         // Add an extra record at the end containing the ending simulation
    570         // time and a basic block number of 0.
    571         uint64_t time_diff = sim_time - prev_bb_time;
    572         if (time_diff > 0) {
    573             int64_t bb_diff = -prev_bb_num;
    574             comp_ptr = varint_encode_signed(bb_diff, comp_ptr);
    575             comp_ptr = varint_encode(time_diff, comp_ptr);
    576             comp_ptr = varint_encode(0, comp_ptr);
    577         }
    578 
    579         uint32_t size = comp_ptr - trace_bb.compressed;
    580         if (size)
    581             fwrite(trace_bb.compressed, sizeof(char), size, trace_bb.fstream);
    582 
    583         // Terminate the file with three zeros so that we can detect
    584         // the end of file quickly.
    585         uint32_t zeros = 0;
    586         fwrite(&zeros, 3, 1, trace_bb.fstream);
    587         fclose(trace_bb.fstream);
    588     }
    589 
    590     if (trace_insn.fstream) {
    591         InsnRec *ptr;
    592         InsnRec *current = trace_insn.current + 1;
    593         char *comp_ptr = trace_insn.compressed_ptr;
    594         for (ptr = trace_insn.buffer; ptr != current; ++ptr) {
    595             if (comp_ptr >= trace_insn.high_water_ptr) {
    596                 uint32_t size = comp_ptr - trace_insn.compressed;
    597                 uint32_t rval = fwrite(trace_insn.compressed, sizeof(char),
    598                                        size, trace_insn.fstream);
    599                 if (rval != size) {
    600                     fprintf(stderr, "fwrite() failed\n");
    601                     perror(trace_insn.filename);
    602                     exit(1);
    603                 }
    604                 comp_ptr = trace_insn.compressed;
    605             }
    606             comp_ptr = varint_encode(ptr->time_diff, comp_ptr);
    607             comp_ptr = varint_encode(ptr->repeat, comp_ptr);
    608         }
    609 
    610         uint32_t size = comp_ptr - trace_insn.compressed;
    611         if (size) {
    612             uint32_t rval = fwrite(trace_insn.compressed, sizeof(char), size,
    613                                    trace_insn.fstream);
    614             if (rval != size) {
    615                 fprintf(stderr, "fwrite() failed\n");
    616                 perror(trace_insn.filename);
    617                 exit(1);
    618             }
    619         }
    620         fclose(trace_insn.fstream);
    621     }
    622 
    623     if (trace_static.fstream) {
    624         fseek(trace_static.fstream, 0, SEEK_SET);
    625         write_trace_header(&header);
    626         fclose(trace_static.fstream);
    627     }
    628 
    629     if (trace_load.fstream) {
    630         AddrRec *ptr;
    631         char *comp_ptr = trace_load.compressed_ptr;
    632         AddrRec *next = trace_load.next;
    633         uint32_t prev_addr = trace_load.prev_addr;
    634         uint64_t prev_time = trace_load.prev_time;
    635         for (ptr = trace_load.buffer; ptr != next; ++ptr) {
    636             if (comp_ptr >= trace_load.high_water_ptr) {
    637                 uint32_t size = comp_ptr - trace_load.compressed;
    638                 fwrite(trace_load.compressed, sizeof(char), size,
    639                        trace_load.fstream);
    640                 comp_ptr = trace_load.compressed;
    641             }
    642 
    643             int addr_diff = ptr->addr - prev_addr;
    644             uint64_t time_diff = ptr->time - prev_time;
    645             prev_addr = ptr->addr;
    646             prev_time = ptr->time;
    647 
    648             comp_ptr = varint_encode_signed(addr_diff, comp_ptr);
    649             comp_ptr = varint_encode(time_diff, comp_ptr);
    650         }
    651 
    652         uint32_t size = comp_ptr - trace_load.compressed;
    653         if (size) {
    654             fwrite(trace_load.compressed, sizeof(char), size,
    655                    trace_load.fstream);
    656         }
    657 
    658         // Terminate the file with two zeros so that we can detect
    659         // the end of file quickly.
    660         uint32_t zeros = 0;
    661         fwrite(&zeros, 2, 1, trace_load.fstream);
    662         fclose(trace_load.fstream);
    663     }
    664 
    665     if (trace_store.fstream) {
    666         AddrRec *ptr;
    667         char *comp_ptr = trace_store.compressed_ptr;
    668         AddrRec *next = trace_store.next;
    669         uint32_t prev_addr = trace_store.prev_addr;
    670         uint64_t prev_time = trace_store.prev_time;
    671         for (ptr = trace_store.buffer; ptr != next; ++ptr) {
    672             if (comp_ptr >= trace_store.high_water_ptr) {
    673                 uint32_t size = comp_ptr - trace_store.compressed;
    674                 fwrite(trace_store.compressed, sizeof(char), size,
    675                        trace_store.fstream);
    676                 comp_ptr = trace_store.compressed;
    677             }
    678 
    679             int addr_diff = ptr->addr - prev_addr;
    680             uint64_t time_diff = ptr->time - prev_time;
    681             prev_addr = ptr->addr;
    682             prev_time = ptr->time;
    683 
    684             comp_ptr = varint_encode_signed(addr_diff, comp_ptr);
    685             comp_ptr = varint_encode(time_diff, comp_ptr);
    686         }
    687 
    688         uint32_t size = comp_ptr - trace_store.compressed;
    689         if (size) {
    690             fwrite(trace_store.compressed, sizeof(char), size,
    691                    trace_store.fstream);
    692         }
    693 
    694         // Terminate the file with two zeros so that we can detect
    695         // the end of file quickly.
    696         uint32_t zeros = 0;
    697         fwrite(&zeros, 2, 1, trace_store.fstream);
    698         fclose(trace_store.fstream);
    699     }
    700 
    701     if (trace_exc.fstream) {
    702         uint32_t size = trace_exc.compressed_ptr - trace_exc.compressed;
    703         if (size) {
    704             fwrite(trace_exc.compressed, sizeof(char), size,
    705                    trace_exc.fstream);
    706         }
    707 
    708         // Terminate the file with 7 zeros so that we can detect
    709         // the end of file quickly.
    710         uint64_t zeros = 0;
    711         fwrite(&zeros, 7, 1, trace_exc.fstream);
    712         fclose(trace_exc.fstream);
    713     }
    714     if (trace_pid.fstream) {
    715         uint32_t size = trace_pid.compressed_ptr - trace_pid.compressed;
    716         if (size) {
    717             fwrite(trace_pid.compressed, sizeof(char), size,
    718                    trace_pid.fstream);
    719         }
    720 
    721         // Terminate the file with 2 zeros so that we can detect
    722         // the end of file quickly.
    723         uint64_t zeros = 0;
    724         fwrite(&zeros, 2, 1, trace_pid.fstream);
    725         fclose(trace_pid.fstream);
    726     }
    727     if (trace_method.fstream) {
    728         uint32_t size = trace_method.compressed_ptr - trace_method.compressed;
    729         if (size) {
    730             fwrite(trace_method.compressed, sizeof(char), size,
    731                    trace_method.fstream);
    732         }
    733 
    734         // Terminate the file with 2 zeros so that we can detect
    735         // the end of file quickly.
    736         uint64_t zeros = 0;
    737         fwrite(&zeros, 2, 1, trace_method.fstream);
    738         fclose(trace_method.fstream);
    739     }
    740     if (ftrace_debug)
    741         fclose(ftrace_debug);
    742 }
    743 
    744 // Define the number of clock ticks for some instructions.  Add one to these
    745 // (in some cases) if there is an interlock.  We currently do not check for
    746 // interlocks.
    747 #define TICKS_OTHER	1
    748 #define TICKS_SMULxy	1
    749 #define TICKS_SMLAWy	1
    750 #define TICKS_SMLALxy	2
    751 #define TICKS_MUL	2
    752 #define TICKS_MLA	2
    753 #define TICKS_MULS	4	// no interlock penalty
    754 #define TICKS_MLAS	4	// no interlock penalty
    755 #define TICKS_UMULL	3
    756 #define TICKS_UMLAL	3
    757 #define TICKS_SMULL	3
    758 #define TICKS_SMLAL	3
    759 #define TICKS_UMULLS	5	// no interlock penalty
    760 #define TICKS_UMLALS	5	// no interlock penalty
    761 #define TICKS_SMULLS	5	// no interlock penalty
    762 #define TICKS_SMLALS	5	// no interlock penalty
    763 
    764 // Compute the number of cycles that this instruction will take,
    765 // not including any I-cache or D-cache misses.  This function
    766 // is called for each instruction in a basic block when that
    767 // block is being translated.
    768 int get_insn_ticks_arm(uint32_t insn)
    769 {
    770 #if 1
    771     int   result   =  1;   /* by default, use 1 cycle */
    772 
    773     /* See Chapter 12 of the ARM920T Reference Manual for details about clock cycles */
    774 
    775     /* first check for invalid condition codes */
    776     if ((insn >> 28) == 0xf)
    777     {
    778         if ((insn >> 25) == 0x7d) {  /* BLX */
    779             result = 3;
    780             goto Exit;
    781         }
    782         /* XXX: if we get there, we're either in an UNDEFINED instruction     */
    783         /*      or in co-processor related ones. For now, only return 1 cycle */
    784         goto Exit;
    785     }
    786 
    787     /* other cases */
    788     switch ((insn >> 25) & 7)
    789     {
    790         case 0:
    791             if ((insn & 0x00000090) == 0x00000090)  /* Multiplies, extra load/store, Table 3-2 */
    792             {
    793                 /* XXX: TODO: Add support for multiplier operand content penalties in the translator */
    794 
    795                 if ((insn & 0x0fc000f0) == 0x00000090)   /* 3-2: Multiply (accumulate) */
    796                 {
    797                     int  Rm = (insn & 15);
    798                     int  Rs = (insn >> 8) & 15;
    799                     int  Rn = (insn >> 12) & 15;
    800 
    801                     if ((insn & 0x00200000) != 0) {  /* MLA */
    802                         result += _interlock_use(Rn);
    803                     } else {   /* MLU */
    804                         if (Rn != 0)      /* UNDEFINED */
    805                             goto Exit;
    806                     }
    807                     /* cycles=2+m, assume m=1, this should be adjusted at interpretation time */
    808                     result += 2 + _interlock_use(Rm) + _interlock_use(Rs);
    809                 }
    810                 else if ((insn & 0x0f8000f0) == 0x00800090)  /* 3-2: Multiply (accumulate) long */
    811                 {
    812                     int  Rm   = (insn & 15);
    813                     int  Rs   = (insn >> 8) & 15;
    814                     int  RdLo = (insn >> 12) & 15;
    815                     int  RdHi = (insn >> 16) & 15;
    816 
    817                     if ((insn & 0x00200000) != 0) { /* SMLAL & UMLAL */
    818                         result += _interlock_use(RdLo) + _interlock_use(RdHi);
    819                     }
    820                     /* else SMLL and UMLL */
    821 
    822                     /* cucles=3+m, assume m=1, this should be adjusted at interpretation time */
    823                     result += 3 + _interlock_use(Rm) + _interlock_use(Rs);
    824                 }
    825                 else if ((insn & 0x0fd00ff0) == 0x01000090)  /* 3-2: Swap/swap byte */
    826                 {
    827                     int  Rm = (insn & 15);
    828                     int  Rd = (insn >> 8) & 15;
    829 
    830                     result = 2 + _interlock_use(Rm);
    831                     _interlock_def(Rd, result+1);
    832                 }
    833                 else if ((insn & 0x0e400ff0) == 0x00000090)  /* 3-2: load/store halfword, reg offset */
    834                 {
    835                     int  Rm = (insn & 15);
    836                     int  Rd = (insn >> 12) & 15;
    837                     int  Rn = (insn >> 16) & 15;
    838 
    839                     result += _interlock_use(Rn) + _interlock_use(Rm);
    840                     if ((insn & 0x00100000) != 0)  /* it's a load, there's a 2-cycle interlock */
    841                         _interlock_def(Rd, result+2);
    842                 }
    843                 else if ((insn & 0x0e400ff0) == 0x00400090)  /* 3-2: load/store halfword, imm offset */
    844                 {
    845                     int  Rd = (insn >> 12) & 15;
    846                     int  Rn = (insn >> 16) & 15;
    847 
    848                     result += _interlock_use(Rn);
    849                     if ((insn & 0x00100000) != 0)  /* it's a load, there's a 2-cycle interlock */
    850                         _interlock_def(Rd, result+2);
    851                 }
    852                 else if ((insn & 0x0e500fd0) == 0x000000d0) /* 3-2: load/store two words, reg offset */
    853                 {
    854                     /* XXX: TODO: Enhanced DSP instructions */
    855                 }
    856                 else if ((insn & 0x0e500fd0) == 0x001000d0) /* 3-2: load/store half/byte, reg offset */
    857                 {
    858                     int  Rm = (insn & 15);
    859                     int  Rd = (insn >> 12) & 15;
    860                     int  Rn = (insn >> 16) & 15;
    861 
    862                     result += _interlock_use(Rn) + _interlock_use(Rm);
    863                     if ((insn & 0x00100000) != 0)  /* load, 2-cycle interlock */
    864                         _interlock_def(Rd, result+2);
    865                 }
    866                 else if ((insn & 0x0e5000d0) == 0x004000d0) /* 3-2: load/store two words, imm offset */
    867                 {
    868                     /* XXX: TODO: Enhanced DSP instructions */
    869                 }
    870                 else if ((insn & 0x0e5000d0) == 0x005000d0) /* 3-2: load/store half/byte, imm offset */
    871                 {
    872                     int  Rd = (insn >> 12) & 15;
    873                     int  Rn = (insn >> 16) & 15;
    874 
    875                     result += _interlock_use(Rn);
    876                     if ((insn & 0x00100000) != 0)  /* load, 2-cycle interlock */
    877                         _interlock_def(Rd, result+2);
    878                 }
    879                 else
    880                 {
    881                     /* UNDEFINED */
    882                 }
    883             }
    884             else if ((insn & 0x0f900000) == 0x01000000)  /* Misc. instructions, table 3-3 */
    885             {
    886                 switch ((insn >> 4) & 15)
    887                 {
    888                     case 0:
    889                         if ((insn & 0x0fb0fff0) == 0x0120f000) /* move register to status register */
    890                         {
    891                             int  Rm = (insn & 15);
    892                             result += _interlock_use(Rm);
    893                         }
    894                         break;
    895 
    896                     case 1:
    897                         if ( ((insn & 0x0ffffff0) == 0x01200010) ||  /* branch/exchange */
    898                              ((insn & 0x0fff0ff0) == 0x01600010) )   /* count leading zeroes */
    899                         {
    900                             int  Rm = (insn & 15);
    901                             result += _interlock_use(Rm);
    902                         }
    903                         break;
    904 
    905                     case 3:
    906                         if ((insn & 0x0ffffff0) == 0x01200030)   /* link/exchange */
    907                         {
    908                             int  Rm = (insn & 15);
    909                             result += _interlock_use(Rm);
    910                         }
    911                         break;
    912 
    913                     default:
    914                         /* TODO: Enhanced DSP instructions */
    915                         ;
    916                 }
    917             }
    918             else  /* Data processing */
    919             {
    920                 int  Rm = (insn & 15);
    921                 int  Rn = (insn >> 16) & 15;
    922 
    923                 result += _interlock_use(Rn) + _interlock_use(Rm);
    924                 if ((insn & 0x10)) {   /* register-controlled shift => 1 cycle penalty */
    925                     int  Rs = (insn >> 8) & 15;
    926                     result += 1 + _interlock_use(Rs);
    927                 }
    928             }
    929             break;
    930 
    931         case 1:
    932             if ((insn & 0x01900000) == 0x01900000)
    933             {
    934                 /* either UNDEFINED or move immediate to CPSR */
    935             }
    936             else  /* Data processing immediate */
    937             {
    938                 int  Rn = (insn >> 12) & 15;
    939                 result += _interlock_use(Rn);
    940             }
    941             break;
    942 
    943         case 2:  /* load/store immediate */
    944             {
    945                 int  Rn = (insn >> 16) & 15;
    946 
    947                 result += _interlock_use(Rn);
    948                 if (insn & 0x00100000) {  /* LDR */
    949                     int  Rd = (insn >> 12) & 15;
    950 
    951                     if (Rd == 15)  /* loading PC */
    952                         result = 5;
    953                     else
    954                         _interlock_def(Rd,result+1);
    955                 }
    956             }
    957             break;
    958 
    959         case 3:
    960             if ((insn & 0x10) == 0)  /* load/store register offset */
    961             {
    962                 int  Rm = (insn & 15);
    963                 int  Rn = (insn >> 16) & 15;
    964 
    965                 result += _interlock_use(Rm) + _interlock_use(Rn);
    966 
    967                 if (insn & 0x00100000) {  /* LDR */
    968                     int  Rd = (insn >> 12) & 15;
    969                     if (Rd == 15)
    970                         result = 5;
    971                     else
    972                         _interlock_def(Rd,result+1);
    973                 }
    974             }
    975             /* else UNDEFINED */
    976             break;
    977 
    978         case 4:  /* load/store multiple */
    979             {
    980                 int       Rn   = (insn >> 16) & 15;
    981                 uint32_t  mask = (insn & 0xffff);
    982                 int       count;
    983 
    984                 for (count = 0; mask; count++)
    985                     mask &= (mask-1);
    986 
    987                 result += _interlock_use(Rn);
    988 
    989                 if (insn & 0x00100000)  /* LDM */
    990                 {
    991                     int  nn;
    992 
    993                     if (insn & 0x8000) {  /* loading PC */
    994                         result = count+4;
    995                     } else {  /* not loading PC */
    996                         result = (count < 2) ? 2 : count;
    997                     }
    998                     /* create defs, all registers locked until the end of the load */
    999                     for (nn = 0; nn < 15; nn++)
   1000                         if ((insn & (1U << nn)) != 0)
   1001                             _interlock_def(nn,result);
   1002                 }
   1003                 else  /* STM */
   1004                     result = (count < 2) ? 2 : count;
   1005             }
   1006             break;
   1007 
   1008         case 5:  /* branch and branch+link */
   1009             break;
   1010 
   1011         case 6:  /* coprocessor load/store */
   1012             {
   1013                 int  Rn = (insn >> 16) & 15;
   1014 
   1015                 if (insn & 0x00100000)
   1016                     result += _interlock_use(Rn);
   1017 
   1018                 /* XXX: other things to do ? */
   1019             }
   1020             break;
   1021 
   1022         default: /* i.e. 7 */
   1023             /* XXX: TODO: co-processor related things */
   1024             ;
   1025     }
   1026 Exit:
   1027     interlock_base += result;
   1028     return result;
   1029 #else /* old code - this seems to be completely buggy ?? */
   1030     if ((insn & 0x0ff0f090) == 0x01600080) {
   1031         return TICKS_SMULxy;
   1032     } else if ((insn & 0x0ff00090) == 0x01200080) {
   1033         return TICKS_SMLAWy;
   1034     } else if ((insn & 0x0ff00090) == 0x01400080) {
   1035         return TICKS_SMLALxy;
   1036     } else if ((insn & 0x0f0000f0) == 0x00000090) {
   1037         // multiply
   1038         uint8_t bit23 = (insn >> 23) & 0x1;
   1039         uint8_t bit22_U = (insn >> 22) & 0x1;
   1040         uint8_t bit21_A = (insn >> 21) & 0x1;
   1041         uint8_t bit20_S = (insn >> 20) & 0x1;
   1042 
   1043         if (bit23 == 0) {
   1044             // 32-bit multiply
   1045             if (bit22_U != 0) {
   1046                 // This is an unexpected bit pattern.
   1047                 return TICKS_OTHER;
   1048             }
   1049             if (bit21_A == 0) {
   1050                 if (bit20_S)
   1051                     return TICKS_MULS;
   1052                 return TICKS_MUL;
   1053             }
   1054             if (bit20_S)
   1055                 return TICKS_MLAS;
   1056             return TICKS_MLA;
   1057         }
   1058         // 64-bit multiply
   1059         if (bit22_U == 0) {
   1060             // Unsigned multiply long
   1061             if (bit21_A == 0) {
   1062                 if (bit20_S)
   1063                     return TICKS_UMULLS;
   1064                 return TICKS_UMULL;
   1065             }
   1066             if (bit20_S)
   1067                 return TICKS_UMLALS;
   1068             return TICKS_UMLAL;
   1069         }
   1070         // Signed multiply long
   1071         if (bit21_A == 0) {
   1072             if (bit20_S)
   1073                 return TICKS_SMULLS;
   1074             return TICKS_SMULL;
   1075         }
   1076         if (bit20_S)
   1077             return TICKS_SMLALS;
   1078         return TICKS_SMLAL;
   1079     }
   1080     return TICKS_OTHER;
   1081 #endif
   1082 }
   1083 
   1084 int  get_insn_ticks_thumb(uint32_t  insn)
   1085 {
   1086 #if 1
   1087     int  result = 1;
   1088 
   1089     switch ((insn >> 11) & 31)
   1090     {
   1091         case 0:
   1092         case 1:
   1093         case 2:   /* Shift by immediate */
   1094             {
   1095                 int  Rm = (insn >> 3) & 7;
   1096                 result += _interlock_use(Rm);
   1097             }
   1098             break;
   1099 
   1100         case 3:  /* Add/Substract */
   1101             {
   1102                 int  Rn = (insn >> 3) & 7;
   1103                 result += _interlock_use(Rn);
   1104 
   1105                 if ((insn & 0x0400) == 0) {  /* register value */
   1106                     int  Rm = (insn >> 6) & 7;
   1107                     result += _interlock_use(Rm);
   1108                 }
   1109             }
   1110             break;
   1111 
   1112         case 4:  /* move immediate */
   1113             break;
   1114 
   1115         case 5:
   1116         case 6:
   1117         case 7:  /* add/substract/compare immediate */
   1118             {
   1119                 int  Rd = (insn >> 8) & 7;
   1120                 result += _interlock_use(Rd);
   1121             }
   1122             break;
   1123 
   1124         case 8:
   1125             {
   1126                 if ((insn & 0x0400) == 0)  /* data processing register */
   1127                 {
   1128                     /* the registers can also be Rs and Rn in some cases */
   1129                     /* but they're always read anyway and located at the */
   1130                     /* same place, so we don't check the opcode          */
   1131                     int  Rm = (insn >> 3) & 7;
   1132                     int  Rd = (insn >> 3) & 7;
   1133 
   1134                     result += _interlock_use(Rm) + _interlock_use(Rd);
   1135                 }
   1136                 else switch ((insn >> 8) & 3)
   1137                 {
   1138                     case 0:
   1139                     case 1:
   1140                     case 2:  /* special data processing */
   1141                         {
   1142                             int  Rn = (insn & 7) | ((insn >> 4) & 0x8);
   1143                             int  Rm = ((insn >> 3) & 15);
   1144 
   1145                             result += _interlock_use(Rn) + _interlock_use(Rm);
   1146                         }
   1147                         break;
   1148 
   1149                     case 3:
   1150                         if ((insn & 0xff07) == 0x4700)  /* branch/exchange */
   1151                         {
   1152                             int  Rm = (insn >> 3) & 15;
   1153 
   1154                             result = 3 + _interlock_use(Rm);
   1155                         }
   1156                         /* else UNDEFINED */
   1157                         break;
   1158                 }
   1159             }
   1160             break;
   1161 
   1162         case 9:  /* load from literal pool */
   1163             {
   1164                 int  Rd = (insn >> 8) & 7;
   1165                 _interlock_def(Rd,result+1);
   1166             }
   1167             break;
   1168 
   1169         case 10:
   1170         case 11:  /* load/store register offset */
   1171             {
   1172                 int  Rd = (insn & 7);
   1173                 int  Rn = (insn >> 3) & 7;
   1174                 int  Rm = (insn >> 6) & 7;
   1175 
   1176                 result += _interlock_use(Rn) + _interlock_use(Rm);
   1177 
   1178                 switch ((insn >> 9) & 7)
   1179                 {
   1180                     case 0: /* STR  */
   1181                     case 1: /* STRH */
   1182                     case 2: /* STRB */
   1183                         result += _interlock_use(Rd);
   1184                         break;
   1185 
   1186                     case 3: /* LDRSB */
   1187                     case 5: /* LDRH */
   1188                     case 6: /* LDRB */
   1189                     case 7: /* LDRSH */
   1190                         _interlock_def(Rd,result+2);
   1191                         break;
   1192 
   1193                     case 4: /* LDR */
   1194                         _interlock_def(Rd,result+1);
   1195                 }
   1196             }
   1197             break;
   1198 
   1199         case 12:  /* store word immediate offset */
   1200         case 14:  /* store byte immediate offset */
   1201             {
   1202                 int  Rd = (insn & 7);
   1203                 int  Rn = (insn >> 3) & 7;
   1204 
   1205                 result += _interlock_use(Rd) + _interlock_use(Rn);
   1206             }
   1207             break;
   1208 
   1209         case 13:  /* load word immediate offset */
   1210             {
   1211                 int  Rd = (insn & 7);
   1212                 int  Rn = (insn >> 3) & 7;
   1213 
   1214                 result += _interlock_use(Rn);
   1215                 _interlock_def(Rd,result+1);
   1216             }
   1217             break;
   1218 
   1219         case 15:  /* load byte immediate offset */
   1220             {
   1221                 int  Rd = (insn & 7);
   1222                 int  Rn = (insn >> 3) & 7;
   1223 
   1224                 result += _interlock_use(Rn);
   1225                 _interlock_def(Rd,result+2);
   1226             }
   1227             break;
   1228 
   1229         case 16:  /* store halfword immediate offset */
   1230             {
   1231                 int  Rd = (insn & 7);
   1232                 int  Rn = (insn >> 3) & 7;
   1233 
   1234                 result += _interlock_use(Rn) + _interlock_use(Rd);
   1235             }
   1236             break;
   1237 
   1238         case 17:  /* load halfword immediate offset */
   1239             {
   1240                 int  Rd = (insn & 7);
   1241                 int  Rn = (insn >> 3) & 7;
   1242 
   1243                 result += _interlock_use(Rn);
   1244                 _interlock_def(Rd,result+2);
   1245             }
   1246             break;
   1247 
   1248         case 18:  /* store to stack */
   1249             {
   1250                 int  Rd = (insn >> 8) & 3;
   1251                 result += _interlock_use(Rd);
   1252             }
   1253             break;
   1254 
   1255         case 19:  /* load from stack */
   1256             {
   1257                 int  Rd = (insn >> 8) & 3;
   1258                 _interlock_def(Rd,result+1);
   1259             }
   1260             break;
   1261 
   1262         case 20:  /* add to PC */
   1263         case 21:  /* add to SP */
   1264             {
   1265                 int  Rd = (insn >> 8) & 3;
   1266                 result += _interlock_use(Rd);
   1267             }
   1268             break;
   1269 
   1270         case 22:
   1271         case 23:  /* misc. instructions, table 6-2 */
   1272             {
   1273                 if ((insn & 0xff00) == 0xb000)  /* adjust stack pointer */
   1274                 {
   1275                     result += _interlock_use(14);
   1276                 }
   1277                 else if ((insn & 0x0600) == 0x0400)  /* push pop register list */
   1278                 {
   1279                     uint32_t  mask = insn & 0x01ff;
   1280                     int       count, nn;
   1281 
   1282                     for (count = 0; mask; count++)
   1283                         mask &= (mask-1);
   1284 
   1285                     result = (count < 2) ? 2 : count;
   1286 
   1287                     if (insn & 0x0800)  /* pop register list */
   1288                     {
   1289                         for (nn = 0; nn < 9; nn++)
   1290                             if (insn & (1 << nn))
   1291                                 _interlock_def(nn, result);
   1292                     }
   1293                     else  /* push register list */
   1294                     {
   1295                         for (nn = 0; nn < 9; nn++)
   1296                             if (insn & (1 << nn))
   1297                                 result += _interlock_use(nn);
   1298                     }
   1299                 }
   1300                 /* else  software breakpoint */
   1301             }
   1302             break;
   1303 
   1304         case 24:  /* store multiple */
   1305             {
   1306                 int  Rd = (insn >> 8) & 7;
   1307                 uint32_t  mask = insn & 255;
   1308                 int       count, nn;
   1309 
   1310                 for (count = 0; mask; count++)
   1311                     mask &= (mask-1);
   1312 
   1313                 result = (count < 2) ? 2 : count;
   1314                 result += _interlock_use(Rd);
   1315 
   1316                 for (nn = 0; nn < 8; nn++)
   1317                     if (insn & (1 << nn))
   1318                         result += _interlock_use(nn);
   1319             }
   1320             break;
   1321 
   1322         case 25:  /* load multiple */
   1323             {
   1324                 int  Rd = (insn >> 8) & 7;
   1325                 uint32_t  mask = insn & 255;
   1326                 int       count, nn;
   1327 
   1328                 for (count = 0; mask; count++)
   1329                     mask &= (mask-1);
   1330 
   1331                 result  = (count < 2) ? 2 : count;
   1332                 result += _interlock_use(Rd);
   1333 
   1334                 for (nn = 0; nn < 8; nn++)
   1335                     if (insn & (1 << nn))
   1336                         _interlock_def(nn, result);
   1337             }
   1338             break;
   1339 
   1340         case 26:
   1341         case 27:  /* conditional branch / undefined / software interrupt */
   1342             switch ((insn >> 8) & 15)
   1343             {
   1344                 case 14: /* UNDEFINED */
   1345                 case 15: /* SWI */
   1346                     break;
   1347 
   1348                 default:  /* conditional branch */
   1349                     result = 3;
   1350             }
   1351             break;
   1352 
   1353         case 28:  /* unconditional branch */
   1354             result = 3;
   1355             break;
   1356 
   1357         case 29:  /* BLX suffix or undefined */
   1358             if ((insn & 1) == 0)
   1359                 result = 3;
   1360             break;
   1361 
   1362         case 30:  /* BLX/BLX prefix */
   1363             break;
   1364 
   1365         case 31:  /* BL suffix */
   1366             result = 3;
   1367             break;
   1368     }
   1369     interlock_base += result;
   1370     return result;
   1371 #else /* old code */
   1372     if ((insn & 0xfc00) == 0x4340) /* MUL */
   1373         return TICKS_SMULxy;
   1374 
   1375     return TICKS_OTHER;
   1376 #endif
   1377 }
   1378 
   1379 // Adds an exception trace record.
   1380 void trace_exception(uint32 target_pc)
   1381 {
   1382     if (trace_exc.fstream == NULL)
   1383         return;
   1384 
   1385     // Sometimes we get an unexpected exception as the first record.  If the
   1386     // basic block number is zero, then we know it is bogus.
   1387     if (trace_bb.current_bb_num == 0)
   1388         return;
   1389 
   1390     uint32_t current_pc = trace_bb.current_bb_addr + 4 * (trace_bb.num_insns - 1);
   1391 #if 0
   1392     if (ftrace_debug) {
   1393         fprintf(ftrace_debug, "t%llu exc pc: 0x%x bb_addr: 0x%x num_insns: %d current_pc: 0x%x bb_num %llu bb_start_time %llu\n",
   1394                 sim_time, target_pc, trace_bb.current_bb_addr,
   1395                 trace_bb.num_insns, current_pc, trace_bb.current_bb_num,
   1396                 trace_bb.current_bb_start_time);
   1397     }
   1398 #endif
   1399     char *comp_ptr = trace_exc.compressed_ptr;
   1400     if (comp_ptr >= trace_exc.high_water_ptr) {
   1401         uint32_t size = comp_ptr - trace_exc.compressed;
   1402         fwrite(trace_exc.compressed, sizeof(char), size, trace_exc.fstream);
   1403         comp_ptr = trace_exc.compressed;
   1404     }
   1405     uint64_t time_diff = sim_time - trace_exc.prev_time;
   1406     trace_exc.prev_time = sim_time;
   1407     uint64_t bb_recnum_diff = trace_bb.recnum - trace_exc.prev_bb_recnum;
   1408     trace_exc.prev_bb_recnum = trace_bb.recnum;
   1409     comp_ptr = varint_encode(time_diff, comp_ptr);
   1410     comp_ptr = varint_encode(current_pc, comp_ptr);
   1411     comp_ptr = varint_encode(bb_recnum_diff, comp_ptr);
   1412     comp_ptr = varint_encode(target_pc, comp_ptr);
   1413     comp_ptr = varint_encode(trace_bb.current_bb_num, comp_ptr);
   1414     comp_ptr = varint_encode(trace_bb.current_bb_start_time, comp_ptr);
   1415     comp_ptr = varint_encode(trace_bb.num_insns, comp_ptr);
   1416     trace_exc.compressed_ptr = comp_ptr;
   1417 }
   1418 
   1419 void trace_pid_1arg(int pid, int rec_type)
   1420 {
   1421     if (trace_pid.fstream == NULL)
   1422         return;
   1423     char *comp_ptr = trace_pid.compressed_ptr;
   1424     char *max_end_ptr = comp_ptr + kMaxPidCompressed;
   1425     if (max_end_ptr >= &trace_pid.compressed[kCompressedSize]) {
   1426         uint32_t size = comp_ptr - trace_pid.compressed;
   1427         fwrite(trace_pid.compressed, sizeof(char), size, trace_pid.fstream);
   1428         comp_ptr = trace_pid.compressed;
   1429     }
   1430     uint64_t time_diff = sim_time - trace_pid.prev_time;
   1431     trace_pid.prev_time = sim_time;
   1432     comp_ptr = varint_encode(time_diff, comp_ptr);
   1433     comp_ptr = varint_encode(rec_type, comp_ptr);
   1434     comp_ptr = varint_encode(pid, comp_ptr);
   1435     trace_pid.compressed_ptr = comp_ptr;
   1436 }
   1437 
   1438 void trace_pid_2arg(int tgid, int pid, int rec_type)
   1439 {
   1440     if (trace_pid.fstream == NULL)
   1441         return;
   1442     char *comp_ptr = trace_pid.compressed_ptr;
   1443     char *max_end_ptr = comp_ptr + kMaxPid2Compressed;
   1444     if (max_end_ptr >= &trace_pid.compressed[kCompressedSize]) {
   1445         uint32_t size = comp_ptr - trace_pid.compressed;
   1446         fwrite(trace_pid.compressed, sizeof(char), size, trace_pid.fstream);
   1447         comp_ptr = trace_pid.compressed;
   1448     }
   1449     uint64_t time_diff = sim_time - trace_pid.prev_time;
   1450     trace_pid.prev_time = sim_time;
   1451     comp_ptr = varint_encode(time_diff, comp_ptr);
   1452     comp_ptr = varint_encode(rec_type, comp_ptr);
   1453     comp_ptr = varint_encode(tgid, comp_ptr);
   1454     comp_ptr = varint_encode(pid, comp_ptr);
   1455     trace_pid.compressed_ptr = comp_ptr;
   1456 }
   1457 
   1458 void trace_switch(int pid)
   1459 {
   1460 #if 0
   1461     if (ftrace_debug && trace_pid.fstream)
   1462         fprintf(ftrace_debug, "t%lld switch %d\n", sim_time, pid);
   1463 #endif
   1464     trace_pid_1arg(pid, kPidSwitch);
   1465     current_pid = pid;
   1466 }
   1467 
   1468 void trace_fork(int tgid, int pid)
   1469 {
   1470 #if 0
   1471     if (ftrace_debug && trace_pid.fstream)
   1472         fprintf(ftrace_debug, "t%lld fork %d\n", sim_time, pid);
   1473 #endif
   1474     trace_pid_2arg(tgid, pid, kPidFork);
   1475 }
   1476 
   1477 void trace_clone(int tgid, int pid)
   1478 {
   1479 #if 0
   1480     if (ftrace_debug && trace_pid.fstream)
   1481         fprintf(ftrace_debug, "t%lld clone %d\n", sim_time, pid);
   1482 #endif
   1483     trace_pid_2arg(tgid, pid, kPidClone);
   1484 }
   1485 
   1486 void trace_exit(int exitcode)
   1487 {
   1488 #if 0
   1489     if (ftrace_debug && trace_pid.fstream)
   1490         fprintf(ftrace_debug, "t%lld exit %d\n", sim_time, exitcode);
   1491 #endif
   1492     trace_pid_1arg(exitcode, kPidExit);
   1493 }
   1494 
   1495 void trace_name(char *name)
   1496 {
   1497 #if 0
   1498     if (ftrace_debug && trace_pid.fstream) {
   1499         fprintf(ftrace_debug, "t%lld pid %d name %s\n",
   1500                 sim_time, current_pid, name);
   1501     }
   1502 #endif
   1503     if (trace_pid.fstream == NULL)
   1504         return;
   1505     int len = strlen(name);
   1506     char *comp_ptr = trace_pid.compressed_ptr;
   1507     char *max_end_ptr = comp_ptr + len + kMaxNameCompressed;
   1508     if (max_end_ptr >= &trace_pid.compressed[kCompressedSize]) {
   1509         uint32_t size = comp_ptr - trace_pid.compressed;
   1510         fwrite(trace_pid.compressed, sizeof(char), size, trace_pid.fstream);
   1511         comp_ptr = trace_pid.compressed;
   1512     }
   1513     uint64_t time_diff = sim_time - trace_pid.prev_time;
   1514     trace_pid.prev_time = sim_time;
   1515     comp_ptr = varint_encode(time_diff, comp_ptr);
   1516     int rec_type = kPidName;
   1517     comp_ptr = varint_encode(rec_type, comp_ptr);
   1518     comp_ptr = varint_encode(current_pid, comp_ptr);
   1519     comp_ptr = varint_encode(len, comp_ptr);
   1520     strncpy(comp_ptr, name, len);
   1521     comp_ptr += len;
   1522     trace_pid.compressed_ptr = comp_ptr;
   1523 }
   1524 
   1525 void trace_execve(const char *argv, int len)
   1526 {
   1527     int ii;
   1528 
   1529     if (trace_pid.fstream == NULL)
   1530         return;
   1531     // Count the number of args
   1532     int alen = 0;
   1533     int sum_len = 0;
   1534     int argc = 0;
   1535     const char *ptr = argv;
   1536     while (sum_len < len) {
   1537         argc += 1;
   1538         alen = strlen(ptr);
   1539         ptr += alen + 1;
   1540         sum_len += alen + 1;
   1541     }
   1542 
   1543 #if 0
   1544     if (ftrace_debug) {
   1545         fprintf(ftrace_debug, "t%lld argc: %d\n", sim_time, argc);
   1546         alen = 0;
   1547         ptr = argv;
   1548         for (ii = 0; ii < argc; ++ii) {
   1549             fprintf(ftrace_debug, "  argv[%d]: %s\n", ii, ptr);
   1550             alen = strlen(ptr);
   1551             ptr += alen + 1;
   1552         }
   1553     }
   1554 #endif
   1555 
   1556     char *comp_ptr = trace_pid.compressed_ptr;
   1557     char *max_end_ptr = comp_ptr + len + 5 * argc + kMaxExecArgsCompressed;
   1558     if (max_end_ptr >= &trace_pid.compressed[kCompressedSize]) {
   1559         uint32_t size = comp_ptr - trace_pid.compressed;
   1560         fwrite(trace_pid.compressed, sizeof(char), size, trace_pid.fstream);
   1561         comp_ptr = trace_pid.compressed;
   1562     }
   1563     uint64_t time_diff = sim_time - trace_pid.prev_time;
   1564     trace_pid.prev_time = sim_time;
   1565     comp_ptr = varint_encode(time_diff, comp_ptr);
   1566     int rec_type = kPidExec;
   1567     comp_ptr = varint_encode(rec_type, comp_ptr);
   1568     comp_ptr = varint_encode(argc, comp_ptr);
   1569 
   1570     ptr = argv;
   1571     for (ii = 0; ii < argc; ++ii) {
   1572         alen = strlen(ptr);
   1573         comp_ptr = varint_encode(alen, comp_ptr);
   1574         strncpy(comp_ptr, ptr, alen);
   1575         comp_ptr += alen;
   1576         ptr += alen + 1;
   1577     }
   1578     trace_pid.compressed_ptr = comp_ptr;
   1579 }
   1580 
   1581 void trace_mmap(unsigned long vstart, unsigned long vend,
   1582                 unsigned long offset, const char *path)
   1583 {
   1584     if (trace_pid.fstream == NULL)
   1585         return;
   1586 #if 0
   1587     if (ftrace_debug)
   1588         fprintf(ftrace_debug, "t%lld mmap %08lx - %08lx, offset %08lx '%s'\n",
   1589                 sim_time, vstart, vend, offset, path);
   1590 #endif
   1591     int len = strlen(path);
   1592     char *comp_ptr = trace_pid.compressed_ptr;
   1593     char *max_end_ptr = comp_ptr + len + kMaxMmapCompressed;
   1594     if (max_end_ptr >= &trace_pid.compressed[kCompressedSize]) {
   1595         uint32_t size = comp_ptr - trace_pid.compressed;
   1596         fwrite(trace_pid.compressed, sizeof(char), size, trace_pid.fstream);
   1597         comp_ptr = trace_pid.compressed;
   1598     }
   1599     uint64_t time_diff = sim_time - trace_pid.prev_time;
   1600     trace_pid.prev_time = sim_time;
   1601     comp_ptr = varint_encode(time_diff, comp_ptr);
   1602     int rec_type = kPidMmap;
   1603     comp_ptr = varint_encode(rec_type, comp_ptr);
   1604     comp_ptr = varint_encode(vstart, comp_ptr);
   1605     comp_ptr = varint_encode(vend, comp_ptr);
   1606     comp_ptr = varint_encode(offset, comp_ptr);
   1607     comp_ptr = varint_encode(len, comp_ptr);
   1608     strncpy(comp_ptr, path, len);
   1609     trace_pid.compressed_ptr = comp_ptr + len;
   1610 }
   1611 
   1612 void trace_munmap(unsigned long vstart, unsigned long vend)
   1613 {
   1614     if (trace_pid.fstream == NULL)
   1615         return;
   1616 #if 0
   1617     if (ftrace_debug)
   1618         fprintf(ftrace_debug, "t%lld munmap %08lx - %08lx\n",
   1619                 sim_time, vstart, vend);
   1620 #endif
   1621     char *comp_ptr = trace_pid.compressed_ptr;
   1622     char *max_end_ptr = comp_ptr + kMaxMunmapCompressed;
   1623     if (max_end_ptr >= &trace_pid.compressed[kCompressedSize]) {
   1624         uint32_t size = comp_ptr - trace_pid.compressed;
   1625         fwrite(trace_pid.compressed, sizeof(char), size, trace_pid.fstream);
   1626         comp_ptr = trace_pid.compressed;
   1627     }
   1628     uint64_t time_diff = sim_time - trace_pid.prev_time;
   1629     trace_pid.prev_time = sim_time;
   1630     comp_ptr = varint_encode(time_diff, comp_ptr);
   1631     int rec_type = kPidMunmap;
   1632     comp_ptr = varint_encode(rec_type, comp_ptr);
   1633     comp_ptr = varint_encode(vstart, comp_ptr);
   1634     comp_ptr = varint_encode(vend, comp_ptr);
   1635     trace_pid.compressed_ptr = comp_ptr;
   1636 }
   1637 
   1638 void trace_dynamic_symbol_add(unsigned long vaddr, const char *name)
   1639 {
   1640     if (trace_pid.fstream == NULL)
   1641         return;
   1642 #if 0
   1643     if (ftrace_debug)
   1644         fprintf(ftrace_debug, "t%lld sym %08lx '%s'\n", sim_time, vaddr, name);
   1645 #endif
   1646     int len = strlen(name);
   1647     char *comp_ptr = trace_pid.compressed_ptr;
   1648     char *max_end_ptr = comp_ptr + len + kMaxSymbolCompressed;
   1649     if (max_end_ptr >= &trace_pid.compressed[kCompressedSize]) {
   1650         uint32_t size = comp_ptr - trace_pid.compressed;
   1651         fwrite(trace_pid.compressed, sizeof(char), size, trace_pid.fstream);
   1652         comp_ptr = trace_pid.compressed;
   1653     }
   1654     uint64_t time_diff = sim_time - trace_pid.prev_time;
   1655     trace_pid.prev_time = sim_time;
   1656     comp_ptr = varint_encode(time_diff, comp_ptr);
   1657     int rec_type = kPidSymbolAdd;
   1658     comp_ptr = varint_encode(rec_type, comp_ptr);
   1659     comp_ptr = varint_encode(vaddr, comp_ptr);
   1660     comp_ptr = varint_encode(len, comp_ptr);
   1661     strncpy(comp_ptr, name, len);
   1662     trace_pid.compressed_ptr = comp_ptr + len;
   1663 }
   1664 
   1665 void trace_dynamic_symbol_remove(unsigned long vaddr)
   1666 {
   1667     if (trace_pid.fstream == NULL)
   1668         return;
   1669 #if 0
   1670     if (ftrace_debug)
   1671         fprintf(ftrace_debug, "t%lld remove %08lx\n", sim_time, vaddr);
   1672 #endif
   1673     char *comp_ptr = trace_pid.compressed_ptr;
   1674     char *max_end_ptr = comp_ptr + kMaxSymbolCompressed;
   1675     if (max_end_ptr >= &trace_pid.compressed[kCompressedSize]) {
   1676         uint32_t size = comp_ptr - trace_pid.compressed;
   1677         fwrite(trace_pid.compressed, sizeof(char), size, trace_pid.fstream);
   1678         comp_ptr = trace_pid.compressed;
   1679     }
   1680     uint64_t time_diff = sim_time - trace_pid.prev_time;
   1681     trace_pid.prev_time = sim_time;
   1682     comp_ptr = varint_encode(time_diff, comp_ptr);
   1683     int rec_type = kPidSymbolRemove;
   1684     comp_ptr = varint_encode(rec_type, comp_ptr);
   1685     comp_ptr = varint_encode(vaddr, comp_ptr);
   1686     trace_pid.compressed_ptr = comp_ptr;
   1687 }
   1688 
   1689 void trace_init_name(int tgid, int pid, const char *name)
   1690 {
   1691     if (trace_pid.fstream == NULL)
   1692         return;
   1693 #if 0
   1694     if (ftrace_debug)
   1695         fprintf(ftrace_debug, "t%lld kthread %d %s\n", sim_time, pid, name);
   1696 #endif
   1697     int len = strlen(name);
   1698     char *comp_ptr = trace_pid.compressed_ptr;
   1699     char *max_end_ptr = comp_ptr + len + kMaxKthreadNameCompressed;
   1700     if (max_end_ptr >= &trace_pid.compressed[kCompressedSize]) {
   1701         uint32_t size = comp_ptr - trace_pid.compressed;
   1702         fwrite(trace_pid.compressed, sizeof(char), size, trace_pid.fstream);
   1703         comp_ptr = trace_pid.compressed;
   1704     }
   1705     uint64_t time_diff = sim_time - trace_pid.prev_time;
   1706     trace_pid.prev_time = sim_time;
   1707     comp_ptr = varint_encode(time_diff, comp_ptr);
   1708     int rec_type = kPidKthreadName;
   1709     comp_ptr = varint_encode(rec_type, comp_ptr);
   1710     comp_ptr = varint_encode(tgid, comp_ptr);
   1711     comp_ptr = varint_encode(pid, comp_ptr);
   1712     comp_ptr = varint_encode(len, comp_ptr);
   1713     strncpy(comp_ptr, name, len);
   1714     trace_pid.compressed_ptr = comp_ptr + len;
   1715 }
   1716 
   1717 void trace_init_exec(unsigned long start, unsigned long end,
   1718                      unsigned long offset, const char *exe)
   1719 {
   1720 }
   1721 
   1722 // This function is called by the generated code to record the basic
   1723 // block number.
   1724 void trace_bb_helper(uint64_t bb_num, TranslationBlock *tb)
   1725 {
   1726     BBRec *bb_rec = tb->bb_rec;
   1727     uint64_t prev_time = tb->prev_time;
   1728     trace_bb.current_bb_addr = tb->pc;
   1729     trace_bb.current_bb_num = bb_num;
   1730     trace_bb.current_bb_start_time = sim_time;
   1731     trace_bb.num_insns = 0;
   1732     trace_bb.recnum += 1;
   1733 
   1734 #if 0
   1735     if (ftrace_debug)
   1736         fprintf(ftrace_debug, "t%lld %lld\n", sim_time, bb_num);
   1737 #endif
   1738     if (bb_rec && bb_rec->bb_num == bb_num && prev_time > trace_bb.flush_time) {
   1739         uint64_t time_diff = sim_time - prev_time;
   1740         if (bb_rec->repeat == 0) {
   1741             bb_rec->repeat = 1;
   1742             bb_rec->time_diff = time_diff;
   1743             tb->prev_time = sim_time;
   1744             return;
   1745         } else if (time_diff == bb_rec->time_diff) {
   1746             bb_rec->repeat += 1;
   1747             tb->prev_time = sim_time;
   1748             return;
   1749         }
   1750     }
   1751 
   1752     BBRec *next = trace_bb.next;
   1753     if (next == &trace_bb.buffer[kMaxNumBasicBlocks]) {
   1754         BBRec *ptr;
   1755         char *comp_ptr = trace_bb.compressed_ptr;
   1756         int64_t prev_bb_num = trace_bb.prev_bb_num;
   1757         uint64_t prev_bb_time = trace_bb.prev_bb_time;
   1758         for (ptr = trace_bb.buffer; ptr != next; ++ptr) {
   1759             if (comp_ptr >= trace_bb.high_water_ptr) {
   1760                 uint32_t size = comp_ptr - trace_bb.compressed;
   1761                 fwrite(trace_bb.compressed, sizeof(char), size, trace_bb.fstream);
   1762                 comp_ptr = trace_bb.compressed;
   1763             }
   1764             int64_t bb_diff = ptr->bb_num - prev_bb_num;
   1765             prev_bb_num = ptr->bb_num;
   1766             uint64_t time_diff = ptr->start_time - prev_bb_time;
   1767             prev_bb_time = ptr->start_time;
   1768             comp_ptr = varint_encode_signed(bb_diff, comp_ptr);
   1769             comp_ptr = varint_encode(time_diff, comp_ptr);
   1770             comp_ptr = varint_encode(ptr->repeat, comp_ptr);
   1771             if (ptr->repeat)
   1772                 comp_ptr = varint_encode(ptr->time_diff, comp_ptr);
   1773         }
   1774         trace_bb.compressed_ptr = comp_ptr;
   1775         trace_bb.prev_bb_num = prev_bb_num;
   1776         trace_bb.prev_bb_time = prev_bb_time;
   1777 
   1778         next = trace_bb.buffer;
   1779         trace_bb.flush_time = sim_time;
   1780     }
   1781     tb->bb_rec = next;
   1782     next->bb_num = bb_num;
   1783     next->start_time = sim_time;
   1784     next->time_diff = 0;
   1785     next->repeat = 0;
   1786     tb->prev_time = sim_time;
   1787     next += 1;
   1788     trace_bb.next = next;
   1789 }
   1790 
   1791 // This function is called by the generated code to record the simulation
   1792 // time at the start of each instruction.
   1793 void trace_insn_helper()
   1794 {
   1795     InsnRec *current = trace_insn.current;
   1796     uint64_t time_diff = sim_time - trace_insn.prev_time;
   1797     trace_insn.prev_time = sim_time;
   1798 
   1799     // Keep track of the number of traced instructions so far in this
   1800     // basic block in case we get an exception in the middle of the bb.
   1801     trace_bb.num_insns += 1;
   1802 
   1803 #if 0
   1804     if (ftrace_debug) {
   1805         uint32_t current_pc = trace_bb.current_bb_addr + 4 * (trace_bb.num_insns - 1);
   1806         fprintf(ftrace_debug, "%llu %x\n", sim_time, current_pc);
   1807     }
   1808 #endif
   1809     if (time_diff == current->time_diff) {
   1810         current->repeat += 1;
   1811         if (current->repeat != 0)
   1812             return;
   1813 
   1814         // The repeat count wrapped around, so back up one and create
   1815         // a new record.
   1816         current->repeat -= 1;
   1817     }
   1818     current += 1;
   1819 
   1820     if (current == &trace_insn.buffer[kInsnBufferSize]) {
   1821         InsnRec *ptr;
   1822         char *comp_ptr = trace_insn.compressed_ptr;
   1823         for (ptr = trace_insn.buffer; ptr != current; ++ptr) {
   1824             if (comp_ptr >= trace_insn.high_water_ptr) {
   1825                 uint32_t size = comp_ptr - trace_insn.compressed;
   1826                 uint32_t rval = fwrite(trace_insn.compressed, sizeof(char),
   1827                                        size, trace_insn.fstream);
   1828                 if (rval != size) {
   1829                     fprintf(stderr, "fwrite() failed\n");
   1830                     perror(trace_insn.filename);
   1831                     exit(1);
   1832                 }
   1833                 comp_ptr = trace_insn.compressed;
   1834             }
   1835             comp_ptr = varint_encode(ptr->time_diff, comp_ptr);
   1836             comp_ptr = varint_encode(ptr->repeat, comp_ptr);
   1837         }
   1838         trace_insn.compressed_ptr = comp_ptr;
   1839         current = trace_insn.buffer;
   1840     }
   1841     current->time_diff = time_diff;
   1842     current->repeat = 0;
   1843     trace_insn.current = current;
   1844 }
   1845 
   1846 // Adds an interpreted method trace record.  Each trace record is a time
   1847 // stamped entry or exit to a method in a language executed by a "virtual
   1848 // machine".  This allows profiling tools to show the method names instead
   1849 // of the core virtual machine interpreter.
   1850 void trace_interpreted_method(uint32_t addr, int call_type)
   1851 {
   1852     if (trace_method.fstream == NULL)
   1853         return;
   1854 #if 0
   1855     fprintf(stderr, "trace_method time: %llu p%d 0x%x %d\n",
   1856             sim_time, current_pid, addr, call_type);
   1857 #endif
   1858     char *comp_ptr = trace_method.compressed_ptr;
   1859     char *max_end_ptr = comp_ptr + kMaxMethodCompressed;
   1860     if (max_end_ptr >= &trace_method.compressed[kCompressedSize]) {
   1861         uint32_t size = comp_ptr - trace_method.compressed;
   1862         fwrite(trace_method.compressed, sizeof(char), size, trace_method.fstream);
   1863         comp_ptr = trace_method.compressed;
   1864     }
   1865     uint64_t time_diff = sim_time - trace_method.prev_time;
   1866     trace_method.prev_time = sim_time;
   1867 
   1868     int32_t addr_diff = addr - trace_method.prev_addr;
   1869     trace_method.prev_addr = addr;
   1870 
   1871     int32_t pid_diff = current_pid - trace_method.prev_pid;
   1872     trace_method.prev_pid = current_pid;
   1873 
   1874     comp_ptr = varint_encode(time_diff, comp_ptr);
   1875     comp_ptr = varint_encode_signed(addr_diff, comp_ptr);
   1876     comp_ptr = varint_encode_signed(pid_diff, comp_ptr);
   1877     comp_ptr = varint_encode(call_type, comp_ptr);
   1878     trace_method.compressed_ptr = comp_ptr;
   1879 }
   1880