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