1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Cachegrind: everything but the simulation itself.            ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                    cg_main.c ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Cachegrind, a Valgrind tool for cache
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   profiling programs.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2002-2013 Nicholas Nethercote
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      njn@valgrind.org
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h"
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_vki.h"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_debuginfo.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcfile.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcproc.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_options.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_oset.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_xarray.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_clientstate.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h"      // VG_(fnptr_to_fnentry)
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "cg_arch.h"
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "cg_sim.c"
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "cg_branchpred.c"
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Constants                                            ---*/
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set to 1 for very verbose debugging */
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DEBUG_CG 0
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MIN_LINE_SIZE         16
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FILE_LEN              VKI_PATH_MAX
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FN_LEN                256
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Options                                              ---*/
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool  clo_cache_sim  = True;  /* do cache simulation? */
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool  clo_branch_sim = False; /* do branch simulation? */
70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic const HChar* clo_cachegrind_out_file = "cachegrind.out.%p";
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*--- Cachesim configuration                               ---*/
74663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
75663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
76663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic Int min_line_size = 0; /* min of L1 and LL cache line sizes */
77663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*------------------------------------------------------------*/
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Types and Data Structures                            ---*/
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong a;  /* total # memory accesses of this kind */
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong m1; /* misses in the first level cache */
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong mL; /* misses in the second level cache */
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CacheCC;
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong b;  /* total # branches of this kind */
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong mp; /* number of branches mispredicted */
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   BranchCC;
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//------------------------------------------------------------
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Primary data structure #1: CC table
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Holds the per-source-line hit/miss stats, grouped by file/function/line.
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - an ordered set of CCs.  CC indexing done by file/function/line (as
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   determined from the instrAddr).
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Traversed for dumping stats at end in file/func/line hierarchy.
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct {
105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar* file;
106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar* fn;
107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int    line;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCodeLoc;
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct {
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CodeLoc  loc; /* Source location that these counts pertain to */
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CacheCC  Ir;  /* Insn read counts */
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CacheCC  Dr;  /* Data read counts */
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CacheCC  Dw;  /* Data write/modify counts */
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   BranchCC Bc;  /* Conditional branch counts */
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   BranchCC Bi;  /* Indirect branch counts */
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} LineCC;
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// First compare file, then fn, then line.
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Word cmp_CodeLoc_LineCC(const void *vloc, const void *vcc)
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word res;
124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const CodeLoc* a = (const CodeLoc*)vloc;
125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const CodeLoc* b = &(((const LineCC*)vcc)->loc);
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(strcmp)(a->file, b->file);
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0 != res)
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(strcmp)(a->fn, b->fn);
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0 != res)
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return res;
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return a->line - b->line;
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic OSet* CC_table;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//------------------------------------------------------------
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Primary data structure #2: InstrInfo table
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Holds the cached info about each instr that is used for simulation.
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - table(SB_start_addr, list(InstrInfo))
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - For each SB, each InstrInfo in the list holds info about the
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   instruction (instrLen, instrAddr, etc), plus a pointer to its line
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   CC.  This node is what's passed to the simulation function.
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - When SBs are discarded the relevant list(instr_details) is freed.
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct _InstrInfo InstrInfo;
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct _InstrInfo {
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr    instr_addr;
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar   instr_len;
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LineCC* parent;         // parent line-CC
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct _SB_info SB_info;
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct _SB_info {
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr      SB_addr;      // key;  MUST BE FIRST
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int       n_instrs;
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   InstrInfo instrs[0];
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic OSet* instrInfoTable;
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//------------------------------------------------------------
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Secondary data structure: string table
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - holds strings, avoiding dups
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - used for filenames and function names, each of which will be
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   pointed to by one or more CCs.
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - it also allows equality checks just by pointer comparison, which
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   is good when printing the output file at the end.
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic OSet* stringTable;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//------------------------------------------------------------
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Stats
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int  distinct_files      = 0;
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int  distinct_fns        = 0;
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int  distinct_lines      = 0;
180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Int  distinct_instrsGen  = 0;
181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Int  distinct_instrsNoX  = 0;
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int  full_debugs         = 0;
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int  file_line_debugs    = 0;
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int  fn_debugs           = 0;
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int  no_debugs           = 0;
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- String table operations                              ---*/
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Word stringCmp( const void* key, const void* elem )
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return VG_(strcmp)(*(const HChar *const *)key, *(const HChar *const *)elem);
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Get a permanent string;  either pull it out of the string table if it's
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// been encountered before, or dup it and put it into the string table.
199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic HChar* get_perm_string(HChar* s)
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar** s_ptr = VG_(OSetGen_Lookup)(stringTable, &s);
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (s_ptr) {
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return *s_ptr;
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      HChar** s_node = VG_(OSetGen_AllocNode)(stringTable, sizeof(HChar*));
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *s_node = VG_(strdup)("cg.main.gps.1", s);
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(OSetGen_Insert)(stringTable, s_node);
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return *s_node;
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- CC table operations                                  ---*/
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void get_debug_info(Addr instr_addr, HChar file[FILE_LEN],
217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                           HChar fn[FN_LEN], UInt* line)
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar dir[FILE_LEN];
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool found_dirname;
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool found_file_line = VG_(get_filename_linenum)(
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             instr_addr,
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             file, FILE_LEN,
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             dir,  FILE_LEN, &found_dirname,
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             line
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          );
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool found_fn        = VG_(get_fnname)(instr_addr, fn, FN_LEN);
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!found_file_line) {
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(strcpy)(file, "???");
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *line = 0;
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!found_fn) {
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(strcpy)(fn,  "???");
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (found_dirname) {
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // +1 for the '/'.
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(VG_(strlen)(dir) + VG_(strlen)(file) + 1 < FILE_LEN);
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(strcat)(dir, "/");     // Append '/'
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(strcat)(dir, file);    // Append file to dir
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(strcpy)(file, dir);    // Move dir+file to file
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (found_file_line) {
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (found_fn) full_debugs++;
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else          file_line_debugs++;
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (found_fn) fn_debugs++;
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else          no_debugs++;
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Do a three step traversal: by file, then fn, then line.
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Returns a pointer to the line CC, creates a new one if necessary.
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic LineCC* get_lineCC(Addr origAddr)
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar   file[FILE_LEN], fn[FN_LEN];
259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt    line;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CodeLoc loc;
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LineCC* lineCC;
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   get_debug_info(origAddr, file, fn, &line);
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   loc.file = file;
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   loc.fn   = fn;
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   loc.line = line;
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lineCC = VG_(OSetGen_Lookup)(CC_table, &loc);
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!lineCC) {
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Allocate and zero a new node.
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC           = VG_(OSetGen_AllocNode)(CC_table, sizeof(LineCC));
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->loc.file = get_perm_string(loc.file);
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->loc.fn   = get_perm_string(loc.fn);
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->loc.line = loc.line;
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Ir.a     = 0;
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Ir.m1    = 0;
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Ir.mL    = 0;
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Dr.a     = 0;
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Dr.m1    = 0;
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Dr.mL    = 0;
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Dw.a     = 0;
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Dw.m1    = 0;
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Dw.mL    = 0;
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Bc.b     = 0;
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Bc.mp    = 0;
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Bi.b     = 0;
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lineCC->Bi.mp    = 0;
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(OSetGen_Insert)(CC_table, lineCC);
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return lineCC;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Cache simulation functions                           ---*/
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* A common case for an instruction read event is that the
300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * bytes read belong to the same cache line in both L1I and LL
301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * (if cache line sizes of L1 and LL are the same).
302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * As this can be detected at instrumentation time, and results
303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * in faster simulation, special-casing is benefical.
304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *
305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Abbrevations used in var/function names:
306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *  IrNoX - instruction read does not cross cache lines
307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *  IrGen - generic instruction read; not detected as IrNoX
308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *  Ir    - not known / not important whether it is an IrNoX
309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */
310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Only used with --cache-sim=no.
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1)
313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_1Ir(InstrInfo* n)
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Ir.a++;
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Only used with --cache-sim=no.
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2)
320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_2Ir(InstrInfo* n, InstrInfo* n2)
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Ir.a++;
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n2->parent->Ir.a++;
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Only used with --cache-sim=no.
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(3)
328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_3Ir(InstrInfo* n, InstrInfo* n2, InstrInfo* n3)
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Ir.a++;
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n2->parent->Ir.a++;
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n3->parent->Ir.a++;
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Generic case for instruction reads: may cross cache lines.
336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// All other Ir handlers expect IrNoX instruction reads.
337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic VG_REGPARM(1)
338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_1IrGen_0D_cache_access(InstrInfo* n)
339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //VG_(printf)("1IrGen_0D :  CCaddr=0x%010lx,  iaddr=0x%010lx,  isize=%lu\n",
341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //             n, n->instr_addr, n->instr_len);
342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_I1_doref_Gen(n->instr_addr, n->instr_len,
343436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov			 &n->parent->Ir.m1, &n->parent->Ir.mL);
344436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   n->parent->Ir.a++;
345436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(1)
348436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_1IrNoX_0D_cache_access(InstrInfo* n)
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //VG_(printf)("1IrNoX_0D :  CCaddr=0x%010lx,  iaddr=0x%010lx,  isize=%lu\n",
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //             n, n->instr_addr, n->instr_len);
352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_I1_doref_NoX(n->instr_addr, n->instr_len,
353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov			 &n->parent->Ir.m1, &n->parent->Ir.mL);
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Ir.a++;
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2)
358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_2IrNoX_0D_cache_access(InstrInfo* n, InstrInfo* n2)
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //VG_(printf)("2IrNoX_0D : CC1addr=0x%010lx, i1addr=0x%010lx, i1size=%lu\n"
361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //            "            CC2addr=0x%010lx, i2addr=0x%010lx, i2size=%lu\n",
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            n,  n->instr_addr,  n->instr_len,
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            n2, n2->instr_addr, n2->instr_len);
364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_I1_doref_NoX(n->instr_addr, n->instr_len,
365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov			 &n->parent->Ir.m1, &n->parent->Ir.mL);
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Ir.a++;
367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_I1_doref_NoX(n2->instr_addr, n2->instr_len,
368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov			 &n2->parent->Ir.m1, &n2->parent->Ir.mL);
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n2->parent->Ir.a++;
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(3)
373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_3IrNoX_0D_cache_access(InstrInfo* n, InstrInfo* n2, InstrInfo* n3)
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //VG_(printf)("3IrNoX_0D : CC1addr=0x%010lx, i1addr=0x%010lx, i1size=%lu\n"
376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //            "            CC2addr=0x%010lx, i2addr=0x%010lx, i2size=%lu\n"
377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //            "            CC3addr=0x%010lx, i3addr=0x%010lx, i3size=%lu\n",
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            n,  n->instr_addr,  n->instr_len,
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            n2, n2->instr_addr, n2->instr_len,
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            n3, n3->instr_addr, n3->instr_len);
381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_I1_doref_NoX(n->instr_addr, n->instr_len,
382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov			 &n->parent->Ir.m1, &n->parent->Ir.mL);
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Ir.a++;
384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_I1_doref_NoX(n2->instr_addr, n2->instr_len,
385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov			 &n2->parent->Ir.m1, &n2->parent->Ir.mL);
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n2->parent->Ir.a++;
387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_I1_doref_NoX(n3->instr_addr, n3->instr_len,
388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov			 &n3->parent->Ir.m1, &n3->parent->Ir.mL);
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n3->parent->Ir.a++;
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(3)
393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_1IrNoX_1Dr_cache_access(InstrInfo* n, Addr data_addr, Word data_size)
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //VG_(printf)("1IrNoX_1Dr:  CCaddr=0x%010lx,  iaddr=0x%010lx,  isize=%lu\n"
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            "                               daddr=0x%010lx,  dsize=%lu\n",
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            n, n->instr_addr, n->instr_len, data_addr, data_size);
398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_I1_doref_NoX(n->instr_addr, n->instr_len,
399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov			 &n->parent->Ir.m1, &n->parent->Ir.mL);
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Ir.a++;
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cachesim_D1_doref(data_addr, data_size,
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     &n->parent->Dr.m1, &n->parent->Dr.mL);
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Dr.a++;
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(3)
408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_1IrNoX_1Dw_cache_access(InstrInfo* n, Addr data_addr, Word data_size)
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //VG_(printf)("1IrNoX_1Dw:  CCaddr=0x%010lx,  iaddr=0x%010lx,  isize=%lu\n"
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            "                               daddr=0x%010lx,  dsize=%lu\n",
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            n, n->instr_addr, n->instr_len, data_addr, data_size);
413436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_I1_doref_NoX(n->instr_addr, n->instr_len,
414436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov			 &n->parent->Ir.m1, &n->parent->Ir.mL);
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Ir.a++;
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cachesim_D1_doref(data_addr, data_size,
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     &n->parent->Dw.m1, &n->parent->Dw.mL);
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Dw.a++;
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
422436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Note that addEvent_D_guarded assumes that log_0Ir_1Dr_cache_access
423436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   and log_0Ir_1Dw_cache_access have exactly the same prototype.  If
424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   you change them, you must change addEvent_D_guarded too. */
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(3)
426436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_0Ir_1Dr_cache_access(InstrInfo* n, Addr data_addr, Word data_size)
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
428436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //VG_(printf)("0Ir_1Dr:  CCaddr=0x%010lx,  daddr=0x%010lx,  dsize=%lu\n",
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            n, data_addr, data_size);
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cachesim_D1_doref(data_addr, data_size,
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     &n->parent->Dr.m1, &n->parent->Dr.mL);
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Dr.a++;
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
435436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* See comment on log_0Ir_1Dr_cache_access. */
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(3)
437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid log_0Ir_1Dw_cache_access(InstrInfo* n, Addr data_addr, Word data_size)
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   //VG_(printf)("0Ir_1Dw:  CCaddr=0x%010lx,  daddr=0x%010lx,  dsize=%lu\n",
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //            n, data_addr, data_size);
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cachesim_D1_doref(data_addr, data_size,
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     &n->parent->Dw.m1, &n->parent->Dw.mL);
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Dw.a++;
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For branches, we consult two different predictors, one which
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   predicts taken/untaken for conditional branches, and the other
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which predicts the branch target address for indirect branches
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (jump-to-register style ones). */
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2)
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid log_cond_branch(InstrInfo* n, Word taken)
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //VG_(printf)("cbrnch:  CCaddr=0x%010lx,  taken=0x%010lx\n",
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //             n, taken);
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Bc.b++;
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Bc.mp
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      += (1 & do_cond_branch_predict(n->instr_addr, taken));
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2)
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid log_ind_branch(InstrInfo* n, UWord actual_dst)
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //VG_(printf)("ibrnch:  CCaddr=0x%010lx,    dst=0x%010lx\n",
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //             n, actual_dst);
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Bi.b++;
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n->parent->Bi.mp
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      += (1 & do_ind_branch_predict(n->instr_addr, actual_dst));
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Instrumentation types and structures                 ---*/
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Maintain an ordered list of memory events which are outstanding, in
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the sense that no IR has yet been generated to do the relevant
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   helper calls.  The BB is scanned top to bottom and memory events
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are added to the end of the list, merging with the most recent
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notified event where possible (Dw immediately following Dr and
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   having the same size and EA can be merged).
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This merging is done so that for architectures which have
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   load-op-store instructions (x86, amd64), the insn is treated as if
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it makes just one memory reference (a modify), rather than two (a
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read followed by a write at the same address).
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   At various points the list will need to be flushed, that is, IR
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   generated from it.  That must happen before any possible exit from
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the block (the end, or an IRStmt_Exit).  Flushing also takes place
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   when there is no space to add a new event.
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If we require the simulation statistics to be up to date with
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   respect to possible memory exceptions, then the list would have to
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be flushed before each memory reference.  That would however lose
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   performance by inhibiting event-merging during flushing.
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Flushing the list consists of walking it start to end and emitting
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instrumentation IR for each event, in the order in which they
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   appear.  It may be possible to emit a single call for two adjacent
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   events in order to reduce the number of helper function calls made.
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For example, it could well be profitable to handle two adjacent Ir
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   events with a single helper call.  */
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom;
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum {
511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Ev_IrNoX,  // Instruction read not crossing cache lines
512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Ev_IrGen,  // Generic Ir, not being detected as IrNoX
513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Ev_Dr,     // Data read
514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Ev_Dw,     // Data write
515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Ev_Dm,     // Data modify (read then write)
516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Ev_Bc,     // branch conditional
517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Ev_Bi      // branch indirect (to unknown destination)
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   EventTag;
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      EventTag   tag;
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      InstrInfo* inode;
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union {
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } IrGen;
528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         struct {
529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         } IrNoX;
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRAtom* ea;
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int     szB;
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Dr;
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRAtom* ea;
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int     szB;
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Dw;
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRAtom* ea;
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int     szB;
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Dm;
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRAtom* taken; /* :: Ity_I1 */
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Bc;
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRAtom* dst;
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Bi;
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } Ev;
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event;
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_Event ( Event* ev ) {
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(ev, 0, sizeof(Event));
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* get_Event_dea ( Event* ev ) {
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ev->tag) {
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dr: return ev->Ev.Dr.ea;
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dw: return ev->Ev.Dw.ea;
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dm: return ev->Ev.Dm.ea;
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:    tl_assert(0);
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int get_Event_dszB ( Event* ev ) {
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ev->tag) {
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dr: return ev->Ev.Dr.szB;
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dw: return ev->Ev.Dw.szB;
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dm: return ev->Ev.Dm.szB;
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:    tl_assert(0);
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Up to this many unnotified events are allowed.  Number is
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arbitrary.  Larger numbers allow more event merging to occur, but
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   potentially induce more spilling due to extending live ranges of
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address temporaries. */
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_EVENTS 16
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A struct which holds all the running state during instrumentation.
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Mostly to avoid passing loads of parameters everywhere. */
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The current outstanding-memory-event list. */
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Event events[N_EVENTS];
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int   events_used;
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The array of InstrInfo bins for the BB. */
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SB_info* sbInfo;
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Number InstrInfo bins 'used' so far. */
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int sbInfo_i;
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The output SB being constructed. */
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRSB* sbOut;
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CgState;
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Instrumentation main                                 ---*/
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Note that origAddr is the real origAddr, not the address of the first
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// instruction in the block (they can be different due to redirection).
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSB_info* get_SB_info(IRSB* sbIn, Addr origAddr)
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      i, n_instrs;
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*  st;
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SB_info* sbInfo;
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Count number of original instrs in SB
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_instrs = 0;
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < sbIn->stmts_used; i++) {
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sbIn->stmts[i];
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (Ist_IMark == st->tag) n_instrs++;
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Check that we don't have an entry for this BB in the instr-info table.
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // If this assertion fails, there has been some screwup:  some
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // translations must have been discarded but Cachegrind hasn't discarded
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // the corresponding entries in the instr-info table.
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sbInfo = VG_(OSetGen_Lookup)(instrInfoTable, &origAddr);
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(NULL == sbInfo);
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // BB never translated before (at this address, at least;  could have
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // been unloaded and then reloaded elsewhere in memory)
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sbInfo = VG_(OSetGen_AllocNode)(instrInfoTable,
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                sizeof(SB_info) + n_instrs*sizeof(InstrInfo));
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sbInfo->SB_addr  = origAddr;
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sbInfo->n_instrs = n_instrs;
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_Insert)( instrInfoTable, sbInfo );
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return sbInfo;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void showEvent ( Event* ev )
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ev->tag) {
644436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ev_IrGen:
645436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(printf)("IrGen %p\n", ev->inode);
646436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         break;
647436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      case Ev_IrNoX:
648436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         VG_(printf)("IrNoX %p\n", ev->inode);
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dr:
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("Dr %p %d EA=", ev->inode, ev->Ev.Dr.szB);
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ev->Ev.Dr.ea);
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dw:
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("Dw %p %d EA=", ev->inode, ev->Ev.Dw.szB);
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ev->Ev.Dw.ea);
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dm:
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("Dm %p %d EA=", ev->inode, ev->Ev.Dm.szB);
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ev->Ev.Dm.ea);
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Bc:
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("Bc %p   GA=", ev->inode);
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ev->Ev.Bc.taken);
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Bi:
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("Bi %p  DST=", ev->inode);
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ev->Ev.Bi.dst);
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(0);
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Reserve and initialise an InstrInfo for the first mention of a new insn.
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInstrInfo* setup_InstrInfo ( CgState* cgs, Addr instr_addr, UInt instr_len )
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   InstrInfo* i_node;
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cgs->sbInfo_i >= 0);
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cgs->sbInfo_i < cgs->sbInfo->n_instrs);
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i_node = &cgs->sbInfo->instrs[ cgs->sbInfo_i ];
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i_node->instr_addr = instr_addr;
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i_node->instr_len  = instr_len;
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i_node->parent     = get_lineCC(instr_addr);
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs->sbInfo_i++;
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return i_node;
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code for all outstanding memory events, and mark the queue
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   empty.  Code is generated into cgs->bbOut, and this activity
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'consumes' slots in cgs->sbInfo. */
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void flushEvents ( CgState* cgs )
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, regparms;
704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* helperName;
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*      helperAddr;
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr**   argv;
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*    i_node_expr;
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty*   di;
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event*     ev;
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event*     ev2;
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event*     ev3;
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = 0;
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (i < cgs->events_used) {
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      helperName = NULL;
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      helperAddr = NULL;
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv       = NULL;
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      regparms   = 0;
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* generate IR to notify event i and possibly the ones
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         immediately following it. */
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(i >= 0 && i < cgs->events_used);
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ev  = &cgs->events[i];
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ev2 = ( i < cgs->events_used-1 ? &cgs->events[i+1] : NULL );
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ev3 = ( i < cgs->events_used-2 ? &cgs->events[i+2] : NULL );
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (DEBUG_CG) {
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("   flush ");
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         showEvent( ev );
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i_node_expr = mkIRExpr_HWord( (HWord)ev->inode );
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Decide on helper fn to call and args to pass it, and advance
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i appropriately. */
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ev->tag) {
739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ev_IrNoX:
740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Merge an IrNoX with a following Dr/Dm. */
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ev2 && (ev2->tag == Ev_Dr || ev2->tag == Ev_Dm)) {
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Why is this true?  It's because we're merging an Ir
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  with a following Dr or Dm.  The Ir derives from the
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  instruction's IMark and the Dr/Dm from data
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  references which follow it.  In short it holds
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  because each insn starts with an IMark, hence an
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Ev_Ir, and so these Dr/Dm must pertain to the
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  immediately preceding Ir.  Same applies to analogous
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  assertions in the subsequent cases. */
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(ev2->inode == ev->inode);
751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               helperName = "log_1IrNoX_1Dr_cache_access";
752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               helperAddr = &log_1IrNoX_1Dr_cache_access;
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argv = mkIRExprVec_3( i_node_expr,
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     get_Event_dea(ev2),
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkIRExpr_HWord( get_Event_dszB(ev2) ) );
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               regparms = 3;
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i += 2;
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
759436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Merge an IrNoX with a following Dw. */
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (ev2 && ev2->tag == Ev_Dw) {
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(ev2->inode == ev->inode);
763436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               helperName = "log_1IrNoX_1Dw_cache_access";
764436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               helperAddr = &log_1IrNoX_1Dw_cache_access;
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argv = mkIRExprVec_3( i_node_expr,
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     get_Event_dea(ev2),
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkIRExpr_HWord( get_Event_dszB(ev2) ) );
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               regparms = 3;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i += 2;
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
771436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Merge an IrNoX with two following IrNoX's. */
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
773436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ev2 && ev3 && ev2->tag == Ev_IrNoX && ev3->tag == Ev_IrNoX)
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (clo_cache_sim) {
776436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperName = "log_3IrNoX_0D_cache_access";
777436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperAddr = &log_3IrNoX_0D_cache_access;
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperName = "log_3Ir";
780436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperAddr = &log_3Ir;
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argv = mkIRExprVec_3( i_node_expr,
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkIRExpr_HWord( (HWord)ev2->inode ),
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkIRExpr_HWord( (HWord)ev3->inode ) );
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               regparms = 3;
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i += 3;
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
788436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            /* Merge an IrNoX with one following IrNoX. */
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
790436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (ev2 && ev2->tag == Ev_IrNoX) {
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (clo_cache_sim) {
792436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperName = "log_2IrNoX_0D_cache_access";
793436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperAddr = &log_2IrNoX_0D_cache_access;
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperName = "log_2Ir";
796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperAddr = &log_2Ir;
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argv = mkIRExprVec_2( i_node_expr,
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkIRExpr_HWord( (HWord)ev2->inode ) );
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               regparms = 2;
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i += 2;
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* No merging possible; emit as-is. */
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else {
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (clo_cache_sim) {
806436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperName = "log_1IrNoX_0D_cache_access";
807436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperAddr = &log_1IrNoX_0D_cache_access;
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperName = "log_1Ir";
810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                  helperAddr = &log_1Ir;
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               argv = mkIRExprVec_1( i_node_expr );
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               regparms = 1;
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i++;
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ev_IrGen:
818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            if (clo_cache_sim) {
819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	       helperName = "log_1IrGen_0D_cache_access";
820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	       helperAddr = &log_1IrGen_0D_cache_access;
821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    } else {
822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	       helperName = "log_1Ir";
823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	       helperAddr = &log_1Ir;
824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    }
825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    argv = mkIRExprVec_1( i_node_expr );
826436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    regparms = 1;
827436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    i++;
828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ev_Dr:
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ev_Dm:
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Data read or modify */
832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            helperName = "log_0Ir_1Dr_cache_access";
833436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            helperAddr = &log_0Ir_1Dr_cache_access;
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argv = mkIRExprVec_3( i_node_expr,
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  get_Event_dea(ev),
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkIRExpr_HWord( get_Event_dszB(ev) ) );
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparms = 3;
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i++;
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ev_Dw:
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Data write */
842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            helperName = "log_0Ir_1Dw_cache_access";
843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            helperAddr = &log_0Ir_1Dw_cache_access;
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argv = mkIRExprVec_3( i_node_expr,
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  get_Event_dea(ev),
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkIRExpr_HWord( get_Event_dszB(ev) ) );
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparms = 3;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i++;
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ev_Bc:
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Conditional branch */
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperName = "log_cond_branch";
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperAddr = &log_cond_branch;
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bc.taken );
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparms = 2;
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i++;
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ev_Bi:
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Branch to an unknown destination */
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperName = "log_ind_branch";
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperAddr = &log_ind_branch;
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bi.dst );
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparms = 2;
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i++;
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(0);
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add the helper. */
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(helperName);
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(helperAddr);
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(argv);
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N( regparms,
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              helperName, VG_(fnptr_to_fnentry)( helperAddr ),
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              argv );
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( cgs->sbOut, IRStmt_Dirty(di) );
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs->events_used = 0;
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addEvent_Ir ( CgState* cgs, InstrInfo* inode )
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cgs->events_used == N_EVENTS)
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(cgs);
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cgs->events_used >= 0 && cgs->events_used < N_EVENTS);
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &cgs->events[cgs->events_used];
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode    = inode;
892436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (cachesim_is_IrNoX(inode->instr_addr, inode->instr_len)) {
893436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      evt->tag = Ev_IrNoX;
894436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      distinct_instrsNoX++;
895436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
896436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      evt->tag = Ev_IrGen;
897436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      distinct_instrsGen++;
898436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs->events_used++;
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Dr ( CgState* cgs, InstrInfo* inode, Int datasize, IRAtom* ea )
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(ea));
907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(datasize >= 1 && datasize <= min_line_size);
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!clo_cache_sim)
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cgs->events_used == N_EVENTS)
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(cgs);
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cgs->events_used >= 0 && cgs->events_used < N_EVENTS);
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &cgs->events[cgs->events_used];
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag       = Ev_Dr;
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode     = inode;
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Dr.szB = datasize;
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Dr.ea  = ea;
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs->events_used++;
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Dw ( CgState* cgs, InstrInfo* inode, Int datasize, IRAtom* ea )
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* lastEvt;
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(ea));
929663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(datasize >= 1 && datasize <= min_line_size);
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!clo_cache_sim)
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Is it possible to merge this write with the preceding read? */
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lastEvt = &cgs->events[cgs->events_used-1];
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cgs->events_used > 0
937436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       && lastEvt->tag       == Ev_Dr
938436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       && lastEvt->Ev.Dr.szB == datasize
939436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       && lastEvt->inode     == inode
940436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       && eqIRAtom(lastEvt->Ev.Dr.ea, ea))
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lastEvt->tag   = Ev_Dm;
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* No.  Add as normal. */
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cgs->events_used == N_EVENTS)
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(cgs);
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cgs->events_used >= 0 && cgs->events_used < N_EVENTS);
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &cgs->events[cgs->events_used];
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag       = Ev_Dw;
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode     = inode;
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Dw.szB = datasize;
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Dw.ea  = ea;
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs->events_used++;
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid addEvent_D_guarded ( CgState* cgs, InstrInfo* inode,
961436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          Int datasize, IRAtom* ea, IRAtom* guard,
962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          Bool isWrite )
963436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(isIRAtom(ea));
965436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(guard);
966436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(isIRAtom(guard));
967436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(datasize >= 1 && datasize <= min_line_size);
968436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
969436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (!clo_cache_sim)
970436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      return;
971436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Adding guarded memory actions and merging them with the existing
973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      queue is too complex.  Simply flush the queue and add this
974436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      action immediately.  Since guarded loads and stores are pretty
975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      rare, this is not thought likely to cause any noticeable
976436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      performance loss as a result of the loss of event-merging
977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      opportunities. */
978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(cgs->events_used >= 0);
979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   flushEvents(cgs);
980436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(cgs->events_used == 0);
981436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Same as case Ev_Dw / case Ev_Dr in flushEvents, except with guard */
982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRExpr*      i_node_expr;
983436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* helperName;
984436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   void*        helperAddr;
985436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRExpr**     argv;
986436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int          regparms;
987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRDirty*     di;
988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   i_node_expr = mkIRExpr_HWord( (HWord)inode );
989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   helperName  = isWrite ? "log_0Ir_1Dw_cache_access"
990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         : "log_0Ir_1Dr_cache_access";
991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   helperAddr  = isWrite ? &log_0Ir_1Dw_cache_access
992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         : &log_0Ir_1Dr_cache_access;
993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   argv        = mkIRExprVec_3( i_node_expr,
994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                ea, mkIRExpr_HWord( datasize ) );
995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   regparms    = 3;
996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   di          = unsafeIRDirty_0_N(
997436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    regparms,
998436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    helperName, VG_(fnptr_to_fnentry)( helperAddr ),
999436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    argv );
1000436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   di->guard = guard;
1001436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   addStmtToIRSB( cgs->sbOut, IRStmt_Dirty(di) );
1002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1003436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Bc ( CgState* cgs, InstrInfo* inode, IRAtom* guard )
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(guard));
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(typeOfIRExpr(cgs->sbOut->tyenv, guard)
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64));
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!clo_branch_sim)
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cgs->events_used == N_EVENTS)
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(cgs);
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cgs->events_used >= 0 && cgs->events_used < N_EVENTS);
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &cgs->events[cgs->events_used];
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag         = Ev_Bc;
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode       = inode;
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Bc.taken = guard;
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs->events_used++;
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Bi ( CgState* cgs, InstrInfo* inode, IRAtom* whereTo )
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(whereTo));
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(typeOfIRExpr(cgs->sbOut->tyenv, whereTo)
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64));
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!clo_branch_sim)
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cgs->events_used == N_EVENTS)
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(cgs);
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cgs->events_used >= 0 && cgs->events_used < N_EVENTS);
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &cgs->events[cgs->events_used];
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag       = Ev_Bi;
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode     = inode;
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Bi.dst = whereTo;
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs->events_used++;
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown////////////////////////////////////////////////////////////
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* cg_instrument ( VgCallbackClosure* closure,
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRSB* sbIn,
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      VexGuestLayout* layout,
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      VexGuestExtents* vge,
1053436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                      VexArchInfo* archinfo_host,
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRType gWordTy, IRType hWordTy )
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, isize;
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRStmt*    st;
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr64     cia; /* address of current insn */
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CgState    cgs;
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTypeEnv* tyenv = sbIn->tyenv;
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   InstrInfo* curr_inode = NULL;
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (gWordTy != hWordTy) {
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We don't currently support this case. */
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(tool_panic)("host/guest word size mismatch");
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Set up new SB
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs.sbOut = deepCopyIRSBExceptStmts(sbIn);
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Copy verbatim any IR preamble preceding the first IMark
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = 0;
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( cgs.sbOut, sbIn->stmts[i] );
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i++;
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Get the first statement, and initial cia from it
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(sbIn->stmts_used > 0);
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(i < sbIn->stmts_used);
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st = sbIn->stmts[i];
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(Ist_IMark == st->tag);
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cia   = st->Ist.IMark.addr;
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   isize = st->Ist.IMark.len;
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // If Vex fails to decode an instruction, the size will be zero.
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Pretend otherwise.
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (isize == 0) isize = VG_MIN_INSTR_SZB;
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Set up running state and get block info
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(closure->readdr == vge->base[0]);
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs.events_used = 0;
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs.sbInfo      = get_SB_info(sbIn, (Addr)closure->readdr);
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cgs.sbInfo_i    = 0;
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DEBUG_CG)
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n\n---------- cg_instrument ----------\n");
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Traverse the block, initialising inodes, adding events and flushing as
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // necessary.
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (/*use current i*/; i < sbIn->stmts_used; i++) {
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sbIn->stmts[i];
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(isFlatIRStmt(st));
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_NoOp:
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_AbiHint:
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Put:
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_PutI:
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_MBE:
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_IMark:
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cia   = st->Ist.IMark.addr;
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            isize = st->Ist.IMark.len;
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // If Vex fails to decode an instruction, the size will be zero.
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // Pretend otherwise.
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (isize == 0) isize = VG_MIN_INSTR_SZB;
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // Sanity-check size.
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert( (VG_MIN_INSTR_SZB <= isize && isize <= VG_MAX_INSTR_SZB)
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     || VG_CLREQ_SZB == isize );
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // Get space for and init the inode, record it as the current one.
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // Subsequent Dr/Dw/Dm events from the same instruction will
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // also use it.
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            curr_inode = setup_InstrInfo(&cgs, cia, isize);
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addEvent_Ir( &cgs, curr_inode );
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_WrTmp: {
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* data = st->Ist.WrTmp.data;
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (data->tag == Iex_Load) {
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr* aexpr = data->Iex.Load.addr;
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // Note also, endianness info is ignored.  I guess
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // that's not interesting.
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addEvent_Dr( &cgs, curr_inode, sizeofIRType(data->Iex.Load.ty),
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  aexpr );
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Store: {
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* data  = st->Ist.Store.data;
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* aexpr = st->Ist.Store.addr;
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addEvent_Dw( &cgs, curr_inode,
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         sizeofIRType(typeOfIRExpr(tyenv, data)), aexpr );
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_StoreG: {
1155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRStoreG* sg   = st->Ist.StoreG.details;
1156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr*   data = sg->data;
1157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr*   addr = sg->addr;
1158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRType    type = typeOfIRExpr(tyenv, data);
1159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            tl_assert(type != Ity_INVALID);
1160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addEvent_D_guarded( &cgs, curr_inode,
1161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                sizeofIRType(type), addr, sg->guard,
1162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                True/*isWrite*/ );
1163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
1164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_LoadG: {
1167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRLoadG* lg       = st->Ist.LoadG.details;
1168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRType   type     = Ity_INVALID; /* loaded type */
1169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRType   typeWide = Ity_INVALID; /* after implicit widening */
1170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr*  addr     = lg->addr;
1171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            typeOfIRLoadGOp(lg->cvt, &typeWide, &type);
1172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            tl_assert(type != Ity_INVALID);
1173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addEvent_D_guarded( &cgs, curr_inode,
1174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                sizeofIRType(type), addr, lg->guard,
1175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                False/*!isWrite*/ );
1176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
1177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Dirty: {
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int      dataSize;
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRDirty* d = st->Ist.Dirty.details;
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (d->mFx != Ifx_None) {
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* This dirty helper accesses memory.  Collect the details. */
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(d->mAddr != NULL);
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(d->mSize != 0);
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dataSize = d->mSize;
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // Large (eg. 28B, 108B, 512B on x86) data-sized
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // instructions will be done inaccurately, but they're
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // very rare and this avoids errors from hitting more
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // than two cache lines in the simulation.
1191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               if (dataSize > min_line_size)
1192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  dataSize = min_line_size;
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify)
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  addEvent_Dr( &cgs, curr_inode, dataSize, d->mAddr );
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify)
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  addEvent_Dw( &cgs, curr_inode, dataSize, d->mAddr );
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(d->mAddr == NULL);
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(d->mSize == 0);
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS: {
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We treat it as a read and a write of the location.  I
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               think that is the same behaviour as it was before IRCAS
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               was introduced, since prior to that point, the Vex
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               front ends would translate a lock-prefixed instruction
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               into a (normal) read followed by a (normal) write. */
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int    dataSize;
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRCAS* cas = st->Ist.CAS.details;
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(cas->addr != NULL);
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(cas->dataLo != NULL);
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dataSize = sizeofIRType(typeOfIRExpr(tyenv, cas->dataLo));
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (cas->dataHi != NULL)
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dataSize *= 2; /* since it's a doubleword-CAS */
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* I don't think this can ever happen, but play safe. */
1218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            if (dataSize > min_line_size)
1219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               dataSize = min_line_size;
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addEvent_Dr( &cgs, curr_inode, dataSize, cas->addr );
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addEvent_Dw( &cgs, curr_inode, dataSize, cas->addr );
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_LLSC: {
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRType dataTy;
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (st->Ist.LLSC.storedata == NULL) {
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* LL */
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dataTy = typeOfIRTemp(tyenv, st->Ist.LLSC.result);
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addEvent_Dr( &cgs, curr_inode,
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            sizeofIRType(dataTy), st->Ist.LLSC.addr );
1232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* flush events before LL, should help SC to succeed */
1233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               flushEvents( &cgs );
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* SC */
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dataTy = typeOfIRExpr(tyenv, st->Ist.LLSC.storedata);
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addEvent_Dw( &cgs, curr_inode,
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            sizeofIRType(dataTy), st->Ist.LLSC.addr );
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_Exit: {
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // call branch predictor only if this is a branch in guest code
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ( (st->Ist.Exit.jk == Ijk_Boring) ||
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 (st->Ist.Exit.jk == Ijk_Call) ||
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 (st->Ist.Exit.jk == Ijk_Ret) )
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Stuff to widen the guard expression to a host word, so
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  we can pass it to the branch predictor simulation
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  functions easily. */
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Bool     inverted;
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Addr64   nia, sea;
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRConst* dst;
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRType   tyW    = hWordTy;
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp     widen  = tyW==Ity_I32  ? Iop_1Uto32  : Iop_1Uto64;
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IROp     opXOR  = tyW==Ity_I32  ? Iop_Xor32   : Iop_Xor64;
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp   guard1 = newIRTemp(cgs.sbOut->tyenv, Ity_I1);
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp   guardW = newIRTemp(cgs.sbOut->tyenv, tyW);
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRTemp   guard  = newIRTemp(cgs.sbOut->tyenv, tyW);
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr*  one    = tyW==Ity_I32 ? IRExpr_Const(IRConst_U32(1))
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              : IRExpr_Const(IRConst_U64(1));
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* First we need to figure out whether the side exit got
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  inverted by the ir optimiser.  To do that, figure out
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  the next (fallthrough) instruction's address and the
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  side exit address and see if they are the same. */
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               nia = cia + (Addr64)isize;
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (tyW == Ity_I32)
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  nia &= 0xFFFFFFFFULL;
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Side exit address */
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dst = st->Ist.Exit.dst;
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (tyW == Ity_I32) {
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tl_assert(dst->tag == Ico_U32);
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  sea = (Addr64)(UInt)dst->Ico.U32;
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               } else {
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tl_assert(tyW == Ity_I64);
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tl_assert(dst->tag == Ico_U64);
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  sea = dst->Ico.U64;
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               inverted = nia == sea;
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* Widen the guard expression. */
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addStmtToIRSB( cgs.sbOut,
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRStmt_WrTmp( guard1, st->Ist.Exit.guard ));
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addStmtToIRSB( cgs.sbOut,
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRStmt_WrTmp( guardW,
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            IRExpr_Unop(widen,
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        IRExpr_RdTmp(guard1))) );
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* If the exit is inverted, invert the sense of the guard. */
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addStmtToIRSB(
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     cgs.sbOut,
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IRStmt_WrTmp(
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           guard,
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           inverted ? IRExpr_Binop(opXOR, IRExpr_RdTmp(guardW), one)
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    : IRExpr_RdTmp(guardW)
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ));
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* And post the event. */
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addEvent_Bc( &cgs, curr_inode, IRExpr_RdTmp(guard) );
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We may never reach the next statement, so need to flush
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               all outstanding transactions now. */
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            flushEvents( &cgs );
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            ppIRStmt(st);
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(0);
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Copy the original statement */
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( cgs.sbOut, st );
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (DEBUG_CG) {
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRStmt(st);
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with branches to unknown destinations.  Except ignore ones
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      which are function returns as we assume the return stack
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      predictor never mispredicts. */
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((sbIn->jumpkind == Ijk_Boring) || (sbIn->jumpkind == Ijk_Call)) {
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) { ppIRExpr( sbIn->next ); VG_(printf)("\n"); }
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (sbIn->next->tag) {
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iex_Const:
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break; /* boring - branch to known address */
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iex_RdTmp:
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* looks like an indirect branch (branch to unknown) */
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addEvent_Bi( &cgs, curr_inode, sbIn->next );
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* shouldn't happen - if the incoming IR is properly
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               flattened, should only have tmp and const cases to
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               consider. */
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(0);
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* At the end of the bb.  Flush outstandings. */
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   flushEvents( &cgs );
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* done.  stay sane ... */
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(cgs.sbInfo_i == cgs.sbInfo->n_instrs);
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DEBUG_CG) {
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)( "goto {");
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRJumpKind(sbIn->jumpkind);
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)( "} ");
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ppIRExpr( sbIn->next );
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)( "}\n");
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return cgs.sbOut;
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Cache configuration                                  ---*/
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define UNDEFINED_CACHE     { -1, -1, -1 }
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic cache_t clo_I1_cache = UNDEFINED_CACHE;
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic cache_t clo_D1_cache = UNDEFINED_CACHE;
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic cache_t clo_LL_cache = UNDEFINED_CACHE;
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- cg_fini() and related function                       ---*/
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Total reads/writes/misses.  Calculated during CC traversal at the end.
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// All auto-zeroed.
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CacheCC  Ir_total;
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CacheCC  Dr_total;
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CacheCC  Dw_total;
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic BranchCC Bc_total;
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic BranchCC Bi_total;
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void fprint_CC_table_and_calc_totals(void)
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, fd;
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes  sres;
1388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar    buf[512];
1389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar   *currFile = NULL, *currFn = NULL;
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LineCC* lineCC;
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Setup output filename.  Nb: it's important to do this now, ie. as late
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // as possible.  If we do it at start-up and the program forks and the
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // output file format string contains a %p (pid) specifier, both the
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // parent and child will incorrectly write to the same file;  this
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // happened in 3.3.0.
1397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar* cachegrind_out_file =
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(expand_file_name)("--cachegrind-out-file", clo_cachegrind_out_file);
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sres = VG_(open)(cachegrind_out_file, VKI_O_CREAT|VKI_O_TRUNC|VKI_O_WRONLY,
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         VKI_S_IRUSR|VKI_S_IWUSR);
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sr_isError(sres)) {
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // If the file can't be opened for whatever reason (conflict
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // between multiple cachegrinded processes?), give up now.
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("error: can't open cache simulation output file '%s'\n",
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                cachegrind_out_file );
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("       ... so simulation results will be missing.\n");
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(cachegrind_out_file);
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fd = sr_Res(sres);
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(free)(cachegrind_out_file);
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // "desc:" lines (giving I1/D1/LL cache configuration).  The spaces after
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // the 2nd colon makes cg_annotate's output look nicer.
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sprintf)(buf, "desc: I1 cache:         %s\n"
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "desc: D1 cache:         %s\n"
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "desc: LL cache:         %s\n",
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     I1.desc_line, D1.desc_line, LL.desc_line);
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // "cmd:" line
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(strcpy)(buf, "cmd:");
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(args_the_exename)) {
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(write)(fd, " ", 1);
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(write)(fd, VG_(args_the_exename),
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     VG_(strlen)( VG_(args_the_exename) ));
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* arg = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (arg) {
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(write)(fd, " ", 1);
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(write)(fd, arg, VG_(strlen)( arg ));
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // "events:" line
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clo_cache_sim && clo_branch_sim) {
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "\nevents: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw "
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  "Bc Bcm Bi Bim\n");
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (clo_cache_sim && !clo_branch_sim) {
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "\nevents: Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw "
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  "\n");
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (!clo_cache_sim && clo_branch_sim) {
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "\nevents: Ir "
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  "Bc Bcm Bi Bim\n");
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "\nevents: Ir\n");
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Traverse every lineCC
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(CC_table);
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while ( (lineCC = VG_(OSetGen_Next)(CC_table)) ) {
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool just_hit_a_new_file = False;
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // If we've hit a new file, print a "fl=" line.  Note that because
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // each string is stored exactly once in the string table, we can use
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // pointer comparison rather than strcmp() to test for equality, which
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // is good because most of the time the comparisons are equal and so
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // the whole strings would have to be checked.
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( lineCC->loc.file != currFile ) {
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         currFile = lineCC->loc.file;
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf)(buf, "fl=%s\n", currFile);
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         distinct_files++;
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         just_hit_a_new_file = True;
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // If we've hit a new function, print a "fn=" line.  We know to do
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // this when the function name changes, and also every time we hit a
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // new file (in which case the new function name might be the same as
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // in the old file, hence the just_hit_a_new_file test).
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( just_hit_a_new_file || lineCC->loc.fn != currFn ) {
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         currFn = lineCC->loc.fn;
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf)(buf, "fn=%s\n", currFn);
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         distinct_fns++;
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Print the LineCC
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (clo_cache_sim && clo_branch_sim) {
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf)(buf, "%u %llu %llu %llu"
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             " %llu %llu %llu"
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             " %llu %llu %llu"
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             " %llu %llu %llu %llu\n",
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->loc.line,
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Ir.a, lineCC->Ir.m1, lineCC->Ir.mL,
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Dr.a, lineCC->Dr.m1, lineCC->Dr.mL,
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Dw.a, lineCC->Dw.m1, lineCC->Dw.mL,
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Bc.b, lineCC->Bc.mp,
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Bi.b, lineCC->Bi.mp);
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (clo_cache_sim && !clo_branch_sim) {
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf)(buf, "%u %llu %llu %llu"
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             " %llu %llu %llu"
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             " %llu %llu %llu\n",
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->loc.line,
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Ir.a, lineCC->Ir.m1, lineCC->Ir.mL,
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Dr.a, lineCC->Dr.m1, lineCC->Dr.mL,
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Dw.a, lineCC->Dw.m1, lineCC->Dw.mL);
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (!clo_cache_sim && clo_branch_sim) {
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf)(buf, "%u %llu"
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             " %llu %llu %llu %llu\n",
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->loc.line,
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Ir.a,
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Bc.b, lineCC->Bc.mp,
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Bi.b, lineCC->Bi.mp);
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(sprintf)(buf, "%u %llu\n",
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->loc.line,
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            lineCC->Ir.a);
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Update summary stats
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ir_total.a  += lineCC->Ir.a;
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ir_total.m1 += lineCC->Ir.m1;
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ir_total.mL += lineCC->Ir.mL;
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Dr_total.a  += lineCC->Dr.a;
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Dr_total.m1 += lineCC->Dr.m1;
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Dr_total.mL += lineCC->Dr.mL;
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Dw_total.a  += lineCC->Dw.a;
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Dw_total.m1 += lineCC->Dw.m1;
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Dw_total.mL += lineCC->Dw.mL;
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bc_total.b  += lineCC->Bc.b;
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bc_total.mp += lineCC->Bc.mp;
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bi_total.b  += lineCC->Bi.b;
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bi_total.mp += lineCC->Bi.mp;
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      distinct_lines++;
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Summary stats must come after rest of table, since we calculate them
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // during traversal.  */
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clo_cache_sim && clo_branch_sim) {
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "summary:"
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu %llu %llu"
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu %llu %llu"
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu %llu %llu"
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu %llu %llu %llu\n",
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Ir_total.a, Ir_total.m1, Ir_total.mL,
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Dr_total.a, Dr_total.m1, Dr_total.mL,
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Dw_total.a, Dw_total.m1, Dw_total.mL,
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Bc_total.b, Bc_total.mp,
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Bi_total.b, Bi_total.mp);
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (clo_cache_sim && !clo_branch_sim) {
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "summary:"
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu %llu %llu"
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu %llu %llu"
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu %llu %llu\n",
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Ir_total.a, Ir_total.m1, Ir_total.mL,
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Dr_total.a, Dr_total.m1, Dr_total.mL,
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Dw_total.a, Dw_total.m1, Dw_total.mL);
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (!clo_cache_sim && clo_branch_sim) {
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "summary:"
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu"
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu %llu %llu %llu\n",
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Ir_total.a,
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Bc_total.b, Bc_total.mp,
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Bi_total.b, Bi_total.mp);
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "summary:"
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        " %llu\n",
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        Ir_total.a);
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(write)(fd, (void*)buf, VG_(strlen)(buf));
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(close)(fd);
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ULong_width(ULong n)
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt w = 0;
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (n > 0) {
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n = n / 10;
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      w++;
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (w == 0) w = 1;
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return w + (w-1)/3;   // add space for commas
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cg_fini(Int exitcode)
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1594436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   static HChar buf1[128], buf2[128], buf3[128], buf4[123];
1595436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   static HChar fmt[128];
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CacheCC  D_total;
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   BranchCC B_total;
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong LL_total_m, LL_total_mr, LL_total_mw,
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         LL_total, LL_total_r, LL_total_w;
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int l1, l2, l3;
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fprint_CC_table_and_calc_totals();
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) == 0)
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Nb: this isn't called "MAX" because that overshadows a global on Darwin.
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   #define CG_MAX(a, b)  ((a) >= (b) ? (a) : (b))
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* I cache results.  Use the I_refs value to determine the first column
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * width. */
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   l1 = ULong_width(Ir_total.a);
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   l2 = ULong_width(CG_MAX(Dr_total.a, Bc_total.b));
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   l3 = ULong_width(CG_MAX(Dw_total.a, Bi_total.b));
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make format string, getting width right for numbers */
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sprintf)(fmt, "%%s %%,%dllu\n", l1);
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Always print this */
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(umsg)(fmt, "I   refs:     ", Ir_total.a);
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If cache profiling is enabled, show D access numbers and all
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      miss numbers */
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clo_cache_sim) {
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)(fmt, "I1  misses:   ", Ir_total.m1);
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)(fmt, "LLi misses:   ", Ir_total.mL);
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 == Ir_total.a) Ir_total.a = 1;
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(Ir_total.m1, Ir_total.a, 2, l1+1, buf1);
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("I1  miss rate: %s\n", buf1);
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(Ir_total.mL, Ir_total.a, 2, l1+1, buf1);
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("LLi miss rate: %s\n", buf1);
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("\n");
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* D cache results.  Use the D_refs.rd and D_refs.wr values to
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * determine the width of columns 2 & 3. */
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      D_total.a  = Dr_total.a  + Dw_total.a;
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      D_total.m1 = Dr_total.m1 + Dw_total.m1;
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      D_total.mL = Dr_total.mL + Dw_total.mL;
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Make format string, getting width right for numbers */
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(fmt, "%%s %%,%dllu  (%%,%dllu rd   + %%,%dllu wr)\n",
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        l1, l2, l3);
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)(fmt, "D   refs:     ",
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     D_total.a, Dr_total.a, Dw_total.a);
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)(fmt, "D1  misses:   ",
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     D_total.m1, Dr_total.m1, Dw_total.m1);
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)(fmt, "LLd misses:   ",
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     D_total.mL, Dr_total.mL, Dw_total.mL);
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 == D_total.a)  D_total.a = 1;
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 == Dr_total.a) Dr_total.a = 1;
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 == Dw_total.a) Dw_total.a = 1;
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)( D_total.m1,  D_total.a, 1, l1+1, buf1);
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(Dr_total.m1, Dr_total.a, 1, l2+1, buf2);
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(Dw_total.m1, Dw_total.a, 1, l3+1, buf3);
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("D1  miss rate: %s (%s     + %s  )\n", buf1, buf2,buf3);
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)( D_total.mL,  D_total.a, 1, l1+1, buf1);
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(Dr_total.mL, Dr_total.a, 1, l2+1, buf2);
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(Dw_total.mL, Dw_total.a, 1, l3+1, buf3);
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("LLd miss rate: %s (%s     + %s  )\n", buf1, buf2,buf3);
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("\n");
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LL overall results */
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      LL_total   = Dr_total.m1 + Dw_total.m1 + Ir_total.m1;
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      LL_total_r = Dr_total.m1 + Ir_total.m1;
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      LL_total_w = Dw_total.m1;
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)(fmt, "LL refs:      ",
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     LL_total, LL_total_r, LL_total_w);
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      LL_total_m  = Dr_total.mL + Dw_total.mL + Ir_total.mL;
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      LL_total_mr = Dr_total.mL + Ir_total.mL;
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      LL_total_mw = Dw_total.mL;
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)(fmt, "LL misses:    ",
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     LL_total_m, LL_total_mr, LL_total_mw);
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(LL_total_m,  (Ir_total.a + D_total.a),  1, l1+1, buf1);
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(LL_total_mr, (Ir_total.a + Dr_total.a), 1, l2+1, buf2);
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(LL_total_mw, Dw_total.a,                1, l3+1, buf3);
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("LL miss rate:  %s (%s     + %s  )\n", buf1, buf2,buf3);
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If branch profiling is enabled, show branch overall results. */
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clo_branch_sim) {
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Make format string, getting width right for numbers */
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(fmt, "%%s %%,%dllu  (%%,%dllu cond + %%,%dllu ind)\n",
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        l1, l2, l3);
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 == Bc_total.b)  Bc_total.b = 1;
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0 == Bi_total.b)  Bi_total.b = 1;
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      B_total.b  = Bc_total.b  + Bi_total.b;
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      B_total.mp = Bc_total.mp + Bi_total.mp;
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("\n");
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)(fmt, "Branches:     ",
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     B_total.b, Bc_total.b, Bi_total.b);
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)(fmt, "Mispredicts:  ",
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     B_total.mp, Bc_total.mp, Bi_total.mp);
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(B_total.mp,  B_total.b,  1, l1+1, buf1);
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(Bc_total.mp, Bc_total.b, 1, l2+1, buf2);
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(Bi_total.mp, Bi_total.b, 1, l3+1, buf3);
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("Mispred rate:  %s (%s     + %s   )\n", buf1, buf2,buf3);
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Various stats
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_stats)) {
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int debug_lookups = full_debugs      + fn_debugs +
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          file_line_debugs + no_debugs;
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(dmsg)("\n");
1719436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(dmsg)("cachegrind: distinct files     : %d\n", distinct_files);
1720436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(dmsg)("cachegrind: distinct functions : %d\n", distinct_fns);
1721436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(dmsg)("cachegrind: distinct lines     : %d\n", distinct_lines);
1722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(dmsg)("cachegrind: distinct instrs NoX: %d\n", distinct_instrsNoX);
1723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(dmsg)("cachegrind: distinct instrs Gen: %d\n", distinct_instrsGen);
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(dmsg)("cachegrind: debug lookups      : %d\n", debug_lookups);
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(full_debugs,      debug_lookups, 1, 6, buf1);
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(file_line_debugs, debug_lookups, 1, 6, buf2);
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(fn_debugs,        debug_lookups, 1, 6, buf3);
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(no_debugs,        debug_lookups, 1, 6, buf4);
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(dmsg)("cachegrind: with full      info:%s (%d)\n",
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                buf1, full_debugs);
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(dmsg)("cachegrind: with file/line info:%s (%d)\n",
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                buf2, file_line_debugs);
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(dmsg)("cachegrind: with fn name   info:%s (%d)\n",
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                buf3, fn_debugs);
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(dmsg)("cachegrind: with zero      info:%s (%d)\n",
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                buf4, no_debugs);
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(dmsg)("cachegrind: string table size: %lu\n",
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VG_(OSetGen_Size)(stringTable));
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(dmsg)("cachegrind: CC table size: %lu\n",
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VG_(OSetGen_Size)(CC_table));
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(dmsg)("cachegrind: InstrInfo table size: %lu\n",
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                VG_(OSetGen_Size)(instrInfoTable));
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Discarding BB info                                           ---*/
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Called when a translation is removed from the translation cache for
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// any reason at all: to free up space, because the guest code was
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// unmapped or modified, or for any arbitrary reason.
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid cg_discard_superblock_info ( Addr64 orig_addr64, VexGuestExtents vge )
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SB_info* sbInfo;
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr     orig_addr = (Addr)vge.base[0];
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(vge.n_used > 0);
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (DEBUG_CG)
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)( "discard_basic_block_info: %p, %p, %llu\n",
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (void*)(Addr)orig_addr,
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (void*)(Addr)vge.base[0], (ULong)vge.len[0]);
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Get BB info, remove from table, free BB info.  Simple!  Note that we
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // use orig_addr, not the first instruction address in vge.
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sbInfo = VG_(OSetGen_Remove)(instrInfoTable, &orig_addr);
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(NULL != sbInfo);
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_FreeNode)(instrInfoTable, sbInfo);
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Command line processing                                      ---*/
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool cg_process_cmd_line_option(const HChar* arg)
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (VG_(str_clo_cache_opt)(arg,
1782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              &clo_I1_cache,
1783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              &clo_D1_cache,
1784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              &clo_LL_cache)) {}
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_STR_CLO( arg, "--cachegrind-out-file", clo_cachegrind_out_file) {}
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--cache-sim",  clo_cache_sim)  {}
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--branch-sim", clo_branch_sim) {}
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cg_print_usage(void)
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(print_cache_clo_opts)();
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)(
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --cache-sim=yes|no  [yes]        collect cache stats?\n"
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --branch-sim=yes|no [no]         collect branch prediction stats?\n"
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --cachegrind-out-file=<file>     output file name [cachegrind.out.%%p]\n"
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cg_print_debug_usage(void)
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)(
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    (none)\n"
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Setup                                                        ---*/
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cg_post_clo_init(void); /* just below */
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cg_pre_clo_init(void)
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_name)            ("Cachegrind");
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_version)         (NULL);
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_description)     ("a cache and branch-prediction profiler");
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_copyright_author)(
1824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      "Copyright (C) 2002-2013, and GNU GPL'd, by Nicholas Nethercote et al.");
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_bug_reports_to)  (VG_BUGS_TO);
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(details_avg_translation_sizeB) ( 500 );
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(clo_vex_control).iropt_register_updates
1829436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      = VexRegUpdSpAtMemAccess; // overridable by the user.
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(basic_tool_funcs)          (cg_post_clo_init,
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   cg_instrument,
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   cg_fini);
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(needs_superblock_discards)(cg_discard_superblock_info);
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(needs_command_line_options)(cg_process_cmd_line_option,
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   cg_print_usage,
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   cg_print_debug_usage);
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cg_post_clo_init(void)
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cache_t I1c, D1c, LLc;
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CC_table =
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(OSetGen_Create)(offsetof(LineCC, loc),
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          cmp_CodeLoc_LineCC,
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(malloc), "cg.main.cpci.1",
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(free));
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instrInfoTable =
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(OSetGen_Create)(/*keyOff*/0,
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          NULL,
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(malloc), "cg.main.cpci.2",
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(free));
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stringTable =
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(OSetGen_Create)(/*keyOff*/0,
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          stringCmp,
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(malloc), "cg.main.cpci.3",
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VG_(free));
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(post_clo_init_configure_caches)(&I1c, &D1c, &LLc,
1861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       &clo_I1_cache,
1862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       &clo_D1_cache,
1863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       &clo_LL_cache);
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // min_line_size is used to make sure that we never feed
1866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // accesses to the simulator straddling more than two
1867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // cache lines at any cache level
1868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   min_line_size = (I1c.line_size < D1c.line_size) ? I1c.line_size : D1c.line_size;
1869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   min_line_size = (LLc.line_size < min_line_size) ? LLc.line_size : min_line_size;
1870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   Int largest_load_or_store_size
1872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      = VG_(machine_get_size_of_largest_guest_register)();
1873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (min_line_size < largest_load_or_store_size) {
1874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* We can't continue, because the cache simulation might
1875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         straddle more than 2 lines, and it will assert.  So let's
1876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         just stop before we start. */
1877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(umsg)("Cachegrind: cannot continue: the minimum line size (%d)\n",
1878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                (Int)min_line_size);
1879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(umsg)("  must be equal to or larger than the maximum register size (%d)\n",
1880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                largest_load_or_store_size );
1881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(umsg)("  but it is not.  Exiting now.\n");
1882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      VG_(exit)(1);
1883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1885436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cachesim_initcaches(I1c, D1c, LLc);
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_DETERMINE_INTERFACE_VERSION(cg_pre_clo_init)
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1894