1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Callgrind                                                    ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                       main.c ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Callgrind, a Valgrind tool for call graph
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   profiling programs.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2002-2013, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This tool is derived from and contains code from Cachegrind
14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2002-2013 Nicholas Nethercote (njn@valgrind.org)
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "callgrind.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "global.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_threadstate.h"
39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_tool_gdbserver.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "cg_branchpred.c"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Global variables                                     ---*/
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* for all threads */
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCommandLineOptions CLG_(clo);
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownStatistics CLG_(stat);
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool CLG_(instrument_state) = True; /* Instrumentation on ? */
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* thread and signal handler specific */
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownexec_state CLG_(current_state);
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* min of L1 and LL cache line sizes.  This only gets set to a
56663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   non-zero value if we are doing cache simulation. */
57663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengInt CLG_(min_line_size) = 0;
58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Statistics                                           ---*/
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void CLG_(init_statistics)(Statistics* s)
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->call_counter        = 0;
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->jcnd_counter        = 0;
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->jump_counter        = 0;
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->rec_call_counter    = 0;
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->ret_counter         = 0;
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->bb_executions       = 0;
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->context_counter     = 0;
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->bb_retranslations   = 0;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->distinct_objs       = 0;
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->distinct_files      = 0;
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->distinct_fns        = 0;
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->distinct_contexts   = 0;
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->distinct_bbs        = 0;
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->distinct_bbccs      = 0;
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->distinct_instrs     = 0;
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->distinct_skips      = 0;
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->bb_hash_resizes     = 0;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->bbcc_hash_resizes   = 0;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->jcc_hash_resizes    = 0;
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->cxt_hash_resizes    = 0;
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->fn_array_resizes    = 0;
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->call_stack_resizes  = 0;
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->fn_stack_resizes    = 0;
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->full_debug_BBs      = 0;
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->file_line_debug_BBs = 0;
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->fn_name_debug_BBs   = 0;
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->no_debug_BBs        = 0;
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->bbcc_lru_misses     = 0;
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->jcc_lru_misses      = 0;
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->cxt_lru_misses      = 0;
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->bbcc_clones         = 0;
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Simple callbacks (not cache similator)               ---*/
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(1)
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void log_global_event(InstrInfo* ii)
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ULong* cost_Bus;
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_global_event:  Ir  %#lx/%u\n",
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii->instr_offset, ii->instr_size);
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(current_state).collect) return;
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BUS))>0 );
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_state).cost[ fullOffset(EG_BUS) ]++;
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).nonskipped)
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cost_Bus = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BUS);
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cost_Bus = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BUS];
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cost_Bus[0]++;
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For branches, we consult two different predictors, one which
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   predicts taken/untaken for conditional branches, and the other
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which predicts the branch target address for indirect branches
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (jump-to-register style ones). */
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2)
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid log_cond_branch(InstrInfo* ii, Word taken)
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bool miss;
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int fullOffset_Bc;
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ULong* cost_Bc;
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_cond_branch:  Ir %#lx, taken %lu\n",
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii->instr_offset, taken);
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    miss = 1 & do_cond_branch_predict(CLG_(bb_base) + ii->instr_offset, taken);
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(current_state).collect) return;
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BC))>0 );
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).nonskipped)
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cost_Bc = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BC);
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cost_Bc = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BC];
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fullOffset_Bc = fullOffset(EG_BC);
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_state).cost[ fullOffset_Bc ]++;
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cost_Bc[0]++;
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (miss) {
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        CLG_(current_state).cost[ fullOffset_Bc+1 ]++;
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cost_Bc[1]++;
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VG_REGPARM(2)
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid log_ind_branch(InstrInfo* ii, UWord actual_dst)
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bool miss;
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int fullOffset_Bi;
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ULong* cost_Bi;
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_ind_branch:  Ir  %#lx, dst %#lx\n",
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii->instr_offset, actual_dst);
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    miss = 1 & do_ind_branch_predict(CLG_(bb_base) + ii->instr_offset, actual_dst);
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(current_state).collect) return;
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BI))>0 );
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).nonskipped)
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cost_Bi = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BI);
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cost_Bi = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BI];
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fullOffset_Bi = fullOffset(EG_BI);
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_state).cost[ fullOffset_Bi ]++;
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cost_Bi[0]++;
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (miss) {
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        CLG_(current_state).cost[ fullOffset_Bi+1 ]++;
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cost_Bi[1]++;
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Instrumentation structures and event queue handling  ---*/
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Maintain an ordered list of memory events which are outstanding, in
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the sense that no IR has yet been generated to do the relevant
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   helper calls.  The BB is scanned top to bottom and memory events
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are added to the end of the list, merging with the most recent
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   notified event where possible (Dw immediately following Dr and
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   having the same size and EA can be merged).
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This merging is done so that for architectures which have
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   load-op-store instructions (x86, amd64), the insn is treated as if
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it makes just one memory reference (a modify), rather than two (a
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   read followed by a write at the same address).
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   At various points the list will need to be flushed, that is, IR
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   generated from it.  That must happen before any possible exit from
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the block (the end, or an IRStmt_Exit).  Flushing also takes place
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   when there is no space to add a new event.
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If we require the simulation statistics to be up to date with
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   respect to possible memory exceptions, then the list would have to
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   be flushed before each memory reference.  That would however lose
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   performance by inhibiting event-merging during flushing.
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Flushing the list consists of walking it start to end and emitting
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instrumentation IR for each event, in the order in which they
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   appear.  It may be possible to emit a single call for two adjacent
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   events in order to reduce the number of helper function calls made.
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   For example, it could well be profitable to handle two adjacent Ir
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   events with a single helper call.  */
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRAtom;
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum {
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ev_Ir,  // Instruction read
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ev_Dr,  // Data read
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ev_Dw,  // Data write
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ev_Dm,  // Data modify (read then write)
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ev_Bc,  // branch conditional
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ev_Bi,  // branch indirect (to unknown destination)
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Ev_G    // Global bus event
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   EventTag;
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct {
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      EventTag   tag;
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      InstrInfo* inode;
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      union {
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 struct {
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 } Ir;
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 struct {
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    IRAtom* ea;
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    Int     szB;
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 } Dr;
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 struct {
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    IRAtom* ea;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    Int     szB;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 } Dw;
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 struct {
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    IRAtom* ea;
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    Int     szB;
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 } Dm;
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRAtom* taken; /* :: Ity_I1 */
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Bc;
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct {
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRAtom* dst;
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } Bi;
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 struct {
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 } G;
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } Ev;
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event;
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void init_Event ( Event* ev ) {
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)(ev, 0, sizeof(Event));
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRAtom* get_Event_dea ( Event* ev ) {
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ev->tag) {
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dr: return ev->Ev.Dr.ea;
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dw: return ev->Ev.Dw.ea;
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dm: return ev->Ev.Dm.ea;
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:    tl_assert(0);
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int get_Event_dszB ( Event* ev ) {
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ev->tag) {
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dr: return ev->Ev.Dr.szB;
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dw: return ev->Ev.Dw.szB;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dm: return ev->Ev.Dm.szB;
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:    tl_assert(0);
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Up to this many unnotified events are allowed.  Number is
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arbitrary.  Larger numbers allow more event merging to occur, but
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   potentially induce more spilling due to extending live ranges of
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address temporaries. */
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_EVENTS 16
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A struct which holds all the running state during instrumentation.
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Mostly to avoid passing loads of parameters everywhere. */
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct {
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* The current outstanding-memory-event list. */
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Event events[N_EVENTS];
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int   events_used;
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* The array of InstrInfo's is part of BB struct. */
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BB* bb;
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* BB seen before (ie. re-instrumentation) */
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bool seen_before;
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Number InstrInfo bins 'used' so far. */
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UInt ii_index;
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // current offset of guest instructions from BB start
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UInt instr_offset;
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* The output SB being constructed. */
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    IRSB* sbOut;
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} ClgState;
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void showEvent ( Event* ev )
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ev->tag) {
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Ir:
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("Ir (InstrInfo %p) at +%d\n",
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ev->inode, ev->inode->instr_offset);
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dr:
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("Dr (InstrInfo %p) at +%d %d EA=",
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ev->inode, ev->inode->instr_offset, ev->Ev.Dr.szB);
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 ppIRExpr(ev->Ev.Dr.ea);
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("\n");
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dw:
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("Dw (InstrInfo %p) at +%d %d EA=",
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ev->inode, ev->inode->instr_offset, ev->Ev.Dw.szB);
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 ppIRExpr(ev->Ev.Dw.ea);
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("\n");
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Dm:
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("Dm (InstrInfo %p) at +%d %d EA=",
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ev->inode, ev->inode->instr_offset, ev->Ev.Dm.szB);
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 ppIRExpr(ev->Ev.Dm.ea);
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("\n");
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Bc:
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("Bc %p   GA=", ev->inode);
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ev->Ev.Bc.taken);
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_Bi:
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("Bi %p  DST=", ev->inode);
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ppIRExpr(ev->Ev.Bi.dst);
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("\n");
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case Ev_G:
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("G  %p\n", ev->inode);
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 tl_assert(0);
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 break;
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate code for all outstanding memory events, and mark the queue
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   empty.  Code is generated into cgs->sbOut, and this activity
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'consumes' slots in cgs->bb. */
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void flushEvents ( ClgState* clgs )
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int        i, regparms, inew;
380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* helperName;
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*      helperAddr;
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr**   argv;
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*    i_node_expr;
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty*   di;
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event*     ev;
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event*     ev2;
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event*     ev3;
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!clgs->seen_before) {
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       // extend event sets as needed
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       // available sets: D0 Dr
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       for(i=0; i<clgs->events_used; i++) {
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   ev  = &clgs->events[i];
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   switch(ev->tag) {
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   case Ev_Ir:
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       // Ir event always is first for a guest instruction
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       CLG_ASSERT(ev->inode->eventset == 0);
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       ev->inode->eventset = CLG_(sets).base;
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       break;
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   case Ev_Dr:
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // extend event set by Dr counters
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown							   EG_DR);
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       break;
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   case Ev_Dw:
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   case Ev_Dm:
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // extend event set by Dw counters
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown							   EG_DW);
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       break;
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           case Ev_Bc:
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // extend event set by Bc counters
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                           EG_BC);
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           case Ev_Bi:
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // extend event set by Bi counters
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                           EG_BI);
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   case Ev_G:
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               // extend event set by Bus counter
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown							   EG_BUS);
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       break;
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   default:
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       tl_assert(0);
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   }
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       }
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for(i = 0; i < clgs->events_used; i = inew) {
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      helperName = NULL;
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      helperAddr = NULL;
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argv       = NULL;
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      regparms   = 0;
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* generate IR to notify event i and possibly the ones
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 immediately following it. */
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(i >= 0 && i < clgs->events_used);
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ev  = &clgs->events[i];
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ev2 = ( i < clgs->events_used-1 ? &clgs->events[i+1] : NULL );
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ev3 = ( i < clgs->events_used-2 ? &clgs->events[i+2] : NULL );
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_DEBUGIF(5) {
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("   flush ");
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 showEvent( ev );
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i_node_expr = mkIRExpr_HWord( (HWord)ev->inode );
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Decide on helper fn to call and args to pass it, and advance
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 i appropriately.
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 Dm events have same effect as Dw events */
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (ev->tag) {
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ev_Ir:
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Merge an Ir with a following Dr. */
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (ev2 && ev2->tag == Ev_Dr) {
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       /* Why is this true?  It's because we're merging an Ir
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  with a following Dr.  The Ir derives from the
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  instruction's IMark and the Dr from data
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  references which follow it.  In short it holds
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  because each insn starts with an IMark, hence an
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  Ev_Ir, and so these Dr must pertain to the
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  immediately preceding Ir.  Same applies to analogous
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  assertions in the subsequent cases. */
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       tl_assert(ev2->inode == ev->inode);
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperName = CLG_(cachesim).log_1I1Dr_name;
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperAddr = CLG_(cachesim).log_1I1Dr;
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       argv = mkIRExprVec_3( i_node_expr,
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				     get_Event_dea(ev2),
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				     mkIRExpr_HWord( get_Event_dszB(ev2) ) );
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       regparms = 3;
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       inew = i+2;
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Merge an Ir with a following Dw/Dm. */
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    else
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (ev2 && (ev2->tag == Ev_Dw || ev2->tag == Ev_Dm)) {
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       tl_assert(ev2->inode == ev->inode);
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperName = CLG_(cachesim).log_1I1Dw_name;
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperAddr = CLG_(cachesim).log_1I1Dw;
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       argv = mkIRExprVec_3( i_node_expr,
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				     get_Event_dea(ev2),
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				     mkIRExpr_HWord( get_Event_dszB(ev2) ) );
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       regparms = 3;
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       inew = i+2;
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Merge an Ir with two following Irs. */
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    else
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (ev2 && ev3 && ev2->tag == Ev_Ir && ev3->tag == Ev_Ir) {
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperName = CLG_(cachesim).log_3I0D_name;
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperAddr = CLG_(cachesim).log_3I0D;
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       argv = mkIRExprVec_3( i_node_expr,
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				     mkIRExpr_HWord( (HWord)ev2->inode ),
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				     mkIRExpr_HWord( (HWord)ev3->inode ) );
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       regparms = 3;
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       inew = i+3;
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Merge an Ir with one following Ir. */
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    else
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (ev2 && ev2->tag == Ev_Ir) {
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperName = CLG_(cachesim).log_2I0D_name;
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperAddr = CLG_(cachesim).log_2I0D;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       argv = mkIRExprVec_2( i_node_expr,
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				     mkIRExpr_HWord( (HWord)ev2->inode ) );
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       regparms = 2;
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       inew = i+2;
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* No merging possible; emit as-is. */
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    else {
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperName = CLG_(cachesim).log_1I0D_name;
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       helperAddr = CLG_(cachesim).log_1I0D;
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       argv = mkIRExprVec_1( i_node_expr );
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       regparms = 1;
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       inew = i+1;
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ev_Dr:
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Data read or modify */
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    helperName = CLG_(cachesim).log_0I1Dr_name;
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    helperAddr = CLG_(cachesim).log_0I1Dr;
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    argv = mkIRExprVec_3( i_node_expr,
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				  get_Event_dea(ev),
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				  mkIRExpr_HWord( get_Event_dszB(ev) ) );
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    regparms = 3;
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    inew = i+1;
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ev_Dw:
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ev_Dm:
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Data write */
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    helperName = CLG_(cachesim).log_0I1Dw_name;
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    helperAddr = CLG_(cachesim).log_0I1Dw;
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    argv = mkIRExprVec_3( i_node_expr,
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				  get_Event_dea(ev),
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				  mkIRExpr_HWord( get_Event_dszB(ev) ) );
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    regparms = 3;
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    inew = i+1;
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ev_Bc:
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Conditional branch */
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperName = "log_cond_branch";
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperAddr = &log_cond_branch;
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bc.taken );
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparms = 2;
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            inew = i+1;
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ev_Bi:
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Branch to an unknown destination */
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperName = "log_ind_branch";
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperAddr = &log_ind_branch;
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bi.dst );
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparms = 2;
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            inew = i+1;
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ev_G:
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Global bus event (CAS, LOCK-prefix, LL-SC, etc) */
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperName = "log_global_event";
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            helperAddr = &log_global_event;
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            argv = mkIRExprVec_1( i_node_expr );
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            regparms = 1;
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            inew = i+1;
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 default:
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    tl_assert(0);
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_DEBUGIF(5) {
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  if (inew > i+1) {
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      VG_(printf)("   merge ");
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      showEvent( ev2 );
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  }
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  if (inew > i+2) {
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      VG_(printf)("   merge ");
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      showEvent( ev3 );
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  }
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  if (helperAddr)
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      VG_(printf)("   call  %s (%p)\n",
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			  helperName, helperAddr);
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* helper could be unset depending on the simulator used */
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (helperAddr == 0) continue;
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Add the helper. */
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(helperName);
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(helperAddr);
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(argv);
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      di = unsafeIRDirty_0_N( regparms,
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			      helperName, VG_(fnptr_to_fnentry)( helperAddr ),
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			      argv );
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) );
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs->events_used = 0;
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void addEvent_Ir ( ClgState* clgs, InstrInfo* inode )
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(clgs->seen_before || (inode->eventset == 0));
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!CLG_(clo).simulate_cache) return;
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clgs->events_used == N_EVENTS)
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(clgs);
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &clgs->events[clgs->events_used];
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag      = Ev_Ir;
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode    = inode;
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs->events_used++;
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Dr ( ClgState* clgs, InstrInfo* inode, Int datasize, IRAtom* ea )
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(ea));
620663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(datasize >= 1);
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!CLG_(clo).simulate_cache) return;
622663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(datasize <= CLG_(min_line_size));
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clgs->events_used == N_EVENTS)
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(clgs);
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &clgs->events[clgs->events_used];
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag       = Ev_Dr;
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode     = inode;
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Dr.szB = datasize;
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Dr.ea  = ea;
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs->events_used++;
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Dw ( ClgState* clgs, InstrInfo* inode, Int datasize, IRAtom* ea )
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* lastEvt;
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(ea));
642663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(datasize >= 1);
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!CLG_(clo).simulate_cache) return;
644663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tl_assert(datasize <= CLG_(min_line_size));
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Is it possible to merge this write with the preceding read? */
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   lastEvt = &clgs->events[clgs->events_used-1];
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clgs->events_used > 0
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && lastEvt->tag       == Ev_Dr
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && lastEvt->Ev.Dr.szB == datasize
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && lastEvt->inode     == inode
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && eqIRAtom(lastEvt->Ev.Dr.ea, ea))
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lastEvt->tag   = Ev_Dm;
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* No.  Add as normal. */
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clgs->events_used == N_EVENTS)
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(clgs);
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &clgs->events[clgs->events_used];
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag       = Ev_Dw;
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode     = inode;
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Dw.szB = datasize;
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Dw.ea  = ea;
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs->events_used++;
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
672436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid addEvent_D_guarded ( ClgState* clgs, InstrInfo* inode,
673436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          Int datasize, IRAtom* ea, IRAtom* guard,
674436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                          Bool isWrite )
675436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
676436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(isIRAtom(ea));
677436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(guard);
678436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(isIRAtom(guard));
679436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(datasize >= 1);
680436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (!CLG_(clo).simulate_cache) return;
681436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(datasize <= CLG_(min_line_size));
682436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
683436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Adding guarded memory actions and merging them with the existing
684436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      queue is too complex.  Simply flush the queue and add this
685436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      action immediately.  Since guarded loads and stores are pretty
686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      rare, this is not thought likely to cause any noticeable
687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      performance loss as a result of the loss of event-merging
688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      opportunities. */
689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(clgs->events_used >= 0);
690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   flushEvents(clgs);
691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   tl_assert(clgs->events_used == 0);
692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Same as case Ev_Dw / case Ev_Dr in flushEvents, except with guard */
693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRExpr*      i_node_expr;
694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* helperName;
695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   void*        helperAddr;
696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRExpr**     argv;
697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int          regparms;
698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRDirty*     di;
699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   i_node_expr = mkIRExpr_HWord( (HWord)inode );
700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   helperName  = isWrite ? CLG_(cachesim).log_0I1Dw_name
701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         : CLG_(cachesim).log_0I1Dr_name;
702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   helperAddr  = isWrite ? CLG_(cachesim).log_0I1Dw
703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                         : CLG_(cachesim).log_0I1Dr;
704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   argv        = mkIRExprVec_3( i_node_expr,
705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                ea, mkIRExpr_HWord( datasize ) );
706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   regparms    = 3;
707436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   di          = unsafeIRDirty_0_N(
708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    regparms,
709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    helperName, VG_(fnptr_to_fnentry)( helperAddr ),
710436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                    argv );
711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   di->guard = guard;
712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) );
713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Bc ( ClgState* clgs, InstrInfo* inode, IRAtom* guard )
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(guard));
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(typeOfIRExpr(clgs->sbOut->tyenv, guard)
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64));
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!CLG_(clo).simulate_branch) return;
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clgs->events_used == N_EVENTS)
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(clgs);
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &clgs->events[clgs->events_used];
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag         = Ev_Bc;
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode       = inode;
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Bc.taken = guard;
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs->events_used++;
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_Bi ( ClgState* clgs, InstrInfo* inode, IRAtom* whereTo )
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(isIRAtom(whereTo));
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(typeOfIRExpr(clgs->sbOut->tyenv, whereTo)
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64));
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!CLG_(clo).simulate_branch) return;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clgs->events_used == N_EVENTS)
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(clgs);
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &clgs->events[clgs->events_used];
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag       = Ev_Bi;
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode     = inode;
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->Ev.Bi.dst = whereTo;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs->events_used++;
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addEvent_G ( ClgState* clgs, InstrInfo* inode )
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Event* evt;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!CLG_(clo).collect_bus) return;
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clgs->events_used == N_EVENTS)
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flushEvents(clgs);
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt = &clgs->events[clgs->events_used];
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   init_Event(evt);
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->tag       = Ev_G;
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   evt->inode     = inode;
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs->events_used++;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialise or check (if already seen before) an InstrInfo for next insn.
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We only can set instr_offset/instr_size here. The required event set and
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   resulting cost offset depend on events (Ir/Dr/Dw/Dm) in guest
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instructions. The event set is extended as required on flush of the event
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   queue (when Dm events were determined), cost offsets are determined at
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   end of BB instrumentation. */
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInstrInfo* next_InstrInfo ( ClgState* clgs, UInt instr_size )
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   InstrInfo* ii;
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(clgs->ii_index >= 0);
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(clgs->ii_index < clgs->bb->instr_count);
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ii = &clgs->bb->instr[ clgs->ii_index ];
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clgs->seen_before) {
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_ASSERT(ii->instr_offset == clgs->instr_offset);
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_ASSERT(ii->instr_size == instr_size);
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ii->instr_offset = clgs->instr_offset;
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ii->instr_size = instr_size;
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ii->cost_offset = 0;
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       ii->eventset = 0;
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs->ii_index++;
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs->instr_offset += instr_size;
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(stat).distinct_instrs++;
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ii;
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// return total number of cost values needed for this BB
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt update_cost_offsets( ClgState* clgs )
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int i;
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    InstrInfo* ii;
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UInt cost_offset = 0;
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(clgs->bb->instr_count == clgs->ii_index);
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0; i<clgs->ii_index; i++) {
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ii = &clgs->bb->instr[i];
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (clgs->seen_before) {
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_ASSERT(ii->cost_offset == cost_offset);
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	} else
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    ii->cost_offset = cost_offset;
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cost_offset += ii->eventset ? ii->eventset->size : 0;
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return cost_offset;
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Instrumentation                                      ---*/
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VG_BIGENDIAN)
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define CLGEndness Iend_BE
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VG_LITTLEENDIAN)
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define CLGEndness Iend_LE
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown endianness"
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr IRConst2Addr(IRConst* con)
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Addr addr;
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (sizeof(Addr) == 4) {
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_ASSERT( con->tag == Ico_U32 );
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	addr = con->Ico.U32;
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else if (sizeof(Addr) == 8) {
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_ASSERT( con->tag == Ico_U64 );
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	addr = con->Ico.U64;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(tool_panic)("Callgrind: invalid Addr type");
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return addr;
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* First pass over a BB to instrument, counting instructions and jumps
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This is needed for the size of the BB struct to allocate
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Called from CLG_(get_bb)
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(collectBlockInfo)(IRSB* sbIn,
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    /*INOUT*/ UInt* instrs,
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    /*INOUT*/ UInt* cjmps,
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    /*INOUT*/ Bool* cjmp_inverted)
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Int i;
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    IRStmt* st;
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Addr instrAddr =0, jumpDst;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UInt instrLen = 0;
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bool toNextInstr = False;
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // Ist_Exit has to be ignored in preamble code, before first IMark:
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // preamble code is added by VEX for self modifying code, and has
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // nothing to do with client code
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bool inPreamble = True;
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!sbIn) return;
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (i = 0; i < sbIn->stmts_used; i++) {
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  st = sbIn->stmts[i];
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  if (Ist_IMark == st->tag) {
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      inPreamble = False;
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      instrAddr = (Addr)ULong_to_Ptr(st->Ist.IMark.addr);
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      instrLen  = st->Ist.IMark.len;
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      (*instrs)++;
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      toNextInstr = False;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  }
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  if (inPreamble) continue;
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  if (Ist_Exit == st->tag) {
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      jumpDst = IRConst2Addr(st->Ist.Exit.dst);
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      toNextInstr =  (jumpDst == instrAddr + instrLen);
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      (*cjmps)++;
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  }
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if the last instructions of BB conditionally jumps to next instruction
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * (= first instruction of next BB in memory), this is a inverted by VEX.
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *cjmp_inverted = toNextInstr;
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addConstMemStoreStmt( IRSB* bbOut, UWord addr, UInt val, IRType hWordTy)
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    addStmtToIRSB( bbOut,
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   IRStmt_Store(CLGEndness,
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				IRExpr_Const(hWordTy == Ity_I32 ?
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					     IRConst_U32( addr ) :
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					     IRConst_U64( addr )),
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				IRExpr_Const(IRConst_U32(val)) ));
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* add helper call to setup_bbcc, with pointer to BB struct as argument
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * precondition for setup_bbcc:
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - jmps_passed has number of cond.jumps passed in last executed BB
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - current_bbcc has a pointer to the BBCC of the last executed BB
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   Thus, if bbcc_jmpkind is != -1 (JmpNone),
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *     current_bbcc->bb->jmp_addr
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   gives the address of the jump source.
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the setup does 2 things:
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - trace call:
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   * Unwind own call stack, i.e sync our ESP with real ESP
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *     This is for ESP manipulation (longjmps, C++ exec handling) and RET
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   * For CALLs or JMPs crossing objects, record call arg +
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *     push are on own call stack
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - prepare for cache log functions:
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   set current_bbcc to BBCC that gets the costs for this BB execution
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *   attached
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid addBBSetupCall(ClgState* clgs)
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRDirty* di;
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr  *arg1, **argv;
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   arg1 = mkIRExpr_HWord( (HWord)clgs->bb );
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argv = mkIRExprVec_1(arg1);
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   di = unsafeIRDirty_0_N( 1, "setup_bbcc",
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			      VG_(fnptr_to_fnentry)( & CLG_(setup_bbcc) ),
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			      argv);
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) );
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRSB* CLG_(instrument)( VgCallbackClosure* closure,
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			IRSB* sbIn,
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			VexGuestLayout* layout,
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			VexGuestExtents* vge,
956436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                        VexArchInfo* archinfo_host,
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			IRType gWordTy, IRType hWordTy )
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
959436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Int        i;
960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRStmt*    st;
961436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Addr       origAddr;
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   InstrInfo* curr_inode = NULL;
963436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   ClgState   clgs;
964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   UInt       cJumps = 0;
965436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRTypeEnv* tyenv = sbIn->tyenv;
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (gWordTy != hWordTy) {
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We don't currently support this case. */
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(tool_panic)("host/guest word size mismatch");
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // No instrumentation if it is switched off
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (! CLG_(instrument_state)) {
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_DEBUG(5, "instrument(BB %#lx) [Instrumentation OFF]\n",
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 (Addr)closure->readdr);
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return sbIn;
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_DEBUG(3, "+ instrument(BB %#lx)\n", (Addr)closure->readdr);
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set up SB for instrumented IR */
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs.sbOut = deepCopyIRSBExceptStmts(sbIn);
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Copy verbatim any IR preamble preceding the first IMark
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = 0;
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( clgs.sbOut, sbIn->stmts[i] );
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      i++;
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Get the first statement, and origAddr from it
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_ASSERT(sbIn->stmts_used >0);
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_ASSERT(i < sbIn->stmts_used);
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   st = sbIn->stmts[i];
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_ASSERT(Ist_IMark == st->tag);
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
997663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   origAddr = (Addr)st->Ist.IMark.addr + (Addr)st->Ist.IMark.delta;
998663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   CLG_ASSERT(origAddr == st->Ist.IMark.addr
999663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                          + st->Ist.IMark.delta);  // XXX: check no overflow
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Get BB struct (creating if necessary).
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * JS: The hash table is keyed with orig_addr_noredir -- important!
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * JW: Why? If it is because of different chasing of the redirection,
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *     this is not needed, as chasing is switched off in callgrind
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    */
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs.bb = CLG_(get_bb)(origAddr, sbIn, &(clgs.seen_before));
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addBBSetupCall(&clgs);
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Set up running state
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs.events_used = 0;
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs.ii_index = 0;
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clgs.instr_offset = 0;
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (/*use current i*/; i < sbIn->stmts_used; i++) {
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      st = sbIn->stmts[i];
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_ASSERT(isFlatIRStmt(st));
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (st->tag) {
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ist_NoOp:
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ist_AbiHint:
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ist_Put:
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ist_PutI:
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ist_MBE:
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ist_IMark: {
1029663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Addr64 cia   = st->Ist.IMark.addr + st->Ist.IMark.delta;
1030663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            Int    isize = st->Ist.IMark.len;
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CLG_ASSERT(clgs.instr_offset == (Addr)cia - origAddr);
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // If Vex fails to decode an instruction, the size will be zero.
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // Pretend otherwise.
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (isize == 0) isize = VG_MIN_INSTR_SZB;
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // Sanity-check size.
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    tl_assert( (VG_MIN_INSTR_SZB <= isize && isize <= VG_MAX_INSTR_SZB)
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     || VG_CLREQ_SZB == isize );
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // Init the inode, record it as the current one.
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // Subsequent Dr/Dw/Dm events from the same instruction will
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // also use it.
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    curr_inode = next_InstrInfo (&clgs, isize);
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    addEvent_Ir( &clgs, curr_inode );
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ist_WrTmp: {
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    IRExpr* data = st->Ist.WrTmp.data;
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (data->tag == Iex_Load) {
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       IRExpr* aexpr = data->Iex.Load.addr;
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       // Note also, endianness info is ignored.  I guess
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       // that's not interesting.
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       addEvent_Dr( &clgs, curr_inode,
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    sizeofIRType(data->Iex.Load.ty), aexpr );
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ist_Store: {
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    IRExpr* data  = st->Ist.Store.data;
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    IRExpr* aexpr = st->Ist.Store.addr;
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    addEvent_Dw( &clgs, curr_inode,
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 sizeofIRType(typeOfIRExpr(sbIn->tyenv, data)), aexpr );
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1069436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_StoreG: {
1070436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRStoreG* sg   = st->Ist.StoreG.details;
1071436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr*   data = sg->data;
1072436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr*   addr = sg->addr;
1073436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRType    type = typeOfIRExpr(tyenv, data);
1074436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            tl_assert(type != Ity_INVALID);
1075436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addEvent_D_guarded( &clgs, curr_inode,
1076436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                sizeofIRType(type), addr, sg->guard,
1077436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                True/*isWrite*/ );
1078436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
1079436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1080436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1081436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case Ist_LoadG: {
1082436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRLoadG* lg       = st->Ist.LoadG.details;
1083436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRType   type     = Ity_INVALID; /* loaded type */
1084436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRType   typeWide = Ity_INVALID; /* after implicit widening */
1085436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            IRExpr*  addr     = lg->addr;
1086436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            typeOfIRLoadGOp(lg->cvt, &typeWide, &type);
1087436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            tl_assert(type != Ity_INVALID);
1088436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            addEvent_D_guarded( &clgs, curr_inode,
1089436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                sizeofIRType(type), addr, lg->guard,
1090436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                                False/*!isWrite*/ );
1091436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov            break;
1092436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         }
1093436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 case Ist_Dirty: {
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    Int      dataSize;
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    IRDirty* d = st->Ist.Dirty.details;
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (d->mFx != Ifx_None) {
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       /* This dirty helper accesses memory.  Collect the details. */
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       tl_assert(d->mAddr != NULL);
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       tl_assert(d->mSize != 0);
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       dataSize = d->mSize;
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       // Large (eg. 28B, 108B, 512B on x86) data-sized
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       // instructions will be done inaccurately, but they're
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       // very rare and this avoids errors from hitting more
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       // than two cache lines in the simulation.
1106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	       if (CLG_(clo).simulate_cache && dataSize > CLG_(min_line_size))
1107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng		  dataSize = CLG_(min_line_size);
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify)
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  addEvent_Dr( &clgs, curr_inode, dataSize, d->mAddr );
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify)
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  addEvent_Dw( &clgs, curr_inode, dataSize, d->mAddr );
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    } else {
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       tl_assert(d->mAddr == NULL);
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       tl_assert(d->mSize == 0);
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_CAS: {
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We treat it as a read and a write of the location.  I
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               think that is the same behaviour as it was before IRCAS
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               was introduced, since prior to that point, the Vex
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               front ends would translate a lock-prefixed instruction
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               into a (normal) read followed by a (normal) write. */
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Int    dataSize;
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRCAS* cas = st->Ist.CAS.details;
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CLG_ASSERT(cas->addr && isIRAtom(cas->addr));
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            CLG_ASSERT(cas->dataLo);
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dataSize = sizeofIRType(typeOfIRExpr(sbIn->tyenv, cas->dataLo));
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (cas->dataHi != NULL)
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dataSize *= 2; /* since this is a doubleword-cas */
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addEvent_Dr( &clgs, curr_inode, dataSize, cas->addr );
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addEvent_Dw( &clgs, curr_inode, dataSize, cas->addr );
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addEvent_G(  &clgs, curr_inode );
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Ist_LLSC: {
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRType dataTy;
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (st->Ist.LLSC.storedata == NULL) {
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* LL */
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dataTy = typeOfIRTemp(sbIn->tyenv, st->Ist.LLSC.result);
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addEvent_Dr( &clgs, curr_inode,
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            sizeofIRType(dataTy), st->Ist.LLSC.addr );
1145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               /* flush events before LL, should help SC to succeed */
1146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov               flushEvents( &clgs );
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            } else {
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* SC */
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               dataTy = typeOfIRExpr(sbIn->tyenv, st->Ist.LLSC.storedata);
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addEvent_Dw( &clgs, curr_inode,
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            sizeofIRType(dataTy), st->Ist.LLSC.addr );
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               /* I don't know whether the global-bus-lock cost should
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  be attributed to the LL or the SC, but it doesn't
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  really matter since they always have to be used in
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pairs anyway.  Hence put it (quite arbitrarily) on
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  the SC. */
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               addEvent_G(  &clgs, curr_inode );
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 	 case Ist_Exit: {
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Bool guest_exit, inverted;
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* VEX code generation sometimes inverts conditional branches.
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * As Callgrind counts (conditional) jumps, it has to correct
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * inversions. The heuristic is the following:
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * (1) Callgrind switches off SB chasing and unrolling, and
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             *     therefore it assumes that a candidate for inversion only is
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             *     the last conditional branch in an SB.
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * (2) inversion is assumed if the branch jumps to the address of
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             *     the next guest instruction in memory.
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * This heuristic is precalculated in CLG_(collectBlockInfo)().
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             *
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * Branching behavior is also used for branch prediction. Note that
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * above heuristic is different from what Cachegrind does.
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * Cachegrind uses (2) for all branches.
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             */
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (cJumps+1 == clgs.bb->cjmp_count)
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                inverted = clgs.bb->cjmp_inverted;
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                inverted = False;
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // call branch predictor only if this is a branch in guest code
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            guest_exit = (st->Ist.Exit.jk == Ijk_Boring) ||
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         (st->Ist.Exit.jk == Ijk_Call) ||
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         (st->Ist.Exit.jk == Ijk_Ret);
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (guest_exit) {
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* Stuff to widen the guard expression to a host word, so
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   we can pass it to the branch predictor simulation
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   functions easily. */
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                IRType   tyW    = hWordTy;
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                IROp     widen  = tyW==Ity_I32  ? Iop_1Uto32  : Iop_1Uto64;
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                IROp     opXOR  = tyW==Ity_I32  ? Iop_Xor32   : Iop_Xor64;
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                IRTemp   guard1 = newIRTemp(clgs.sbOut->tyenv, Ity_I1);
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                IRTemp   guardW = newIRTemp(clgs.sbOut->tyenv, tyW);
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                IRTemp   guard  = newIRTemp(clgs.sbOut->tyenv, tyW);
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                IRExpr*  one    = tyW==Ity_I32 ? IRExpr_Const(IRConst_U32(1))
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               : IRExpr_Const(IRConst_U64(1));
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* Widen the guard expression. */
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                addStmtToIRSB( clgs.sbOut,
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               IRStmt_WrTmp( guard1, st->Ist.Exit.guard ));
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                addStmtToIRSB( clgs.sbOut,
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               IRStmt_WrTmp( guardW,
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             IRExpr_Unop(widen,
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         IRExpr_RdTmp(guard1))) );
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* If the exit is inverted, invert the sense of the guard. */
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                addStmtToIRSB(
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        clgs.sbOut,
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        IRStmt_WrTmp(
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                guard,
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                inverted ? IRExpr_Binop(opXOR, IRExpr_RdTmp(guardW), one)
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    : IRExpr_RdTmp(guardW)
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    ));
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                /* And post the event. */
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                addEvent_Bc( &clgs, curr_inode, IRExpr_RdTmp(guard) );
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* We may never reach the next statement, so need to flush
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       all outstanding transactions now. */
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    flushEvents( &clgs );
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_ASSERT(clgs.ii_index>0);
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (!clgs.seen_before) {
1227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	      ClgJumpKind jk;
1228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	      if      (st->Ist.Exit.jk == Ijk_Call) jk = jk_Call;
1230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	      else if (st->Ist.Exit.jk == Ijk_Ret)  jk = jk_Return;
1231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	      else {
1232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng		if (IRConst2Addr(st->Ist.Exit.dst) ==
1233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng		    origAddr + curr_inode->instr_offset + curr_inode->instr_size)
1234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng		  jk = jk_None;
1235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng		else
1236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng		  jk = jk_Jump;
1237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	      }
1238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	      clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
1240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	      clgs.bb->jmp[cJumps].jmpkind = jk;
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    /* Update global variable jmps_passed before the jump
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     * A correction is needed if VEX inverted the last jump condition
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    */
1246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	    UInt val = inverted ? cJumps+1 : cJumps;
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    addConstMemStoreStmt( clgs.sbOut,
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				  (UWord) &CLG_(current_state).jmps_passed,
1249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov				  val, hWordTy);
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cJumps++;
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 default:
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    tl_assert(0);
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    break;
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Copy the original statement */
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addStmtToIRSB( clgs.sbOut, st );
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_DEBUGIF(5) {
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("   pass  ");
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 ppIRStmt(st);
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("\n");
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Deal with branches to unknown destinations.  Except ignore ones
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      which are function returns as we assume the return stack
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      predictor never mispredicts. */
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((sbIn->jumpkind == Ijk_Boring) || (sbIn->jumpkind == Ijk_Call)) {
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) { ppIRExpr( sbIn->next ); VG_(printf)("\n"); }
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (sbIn->next->tag) {
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iex_Const:
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break; /* boring - branch to known address */
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         case Iex_RdTmp:
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* looks like an indirect branch (branch to unknown) */
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            addEvent_Bi( &clgs, curr_inode, sbIn->next );
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         default:
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* shouldn't happen - if the incoming IR is properly
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               flattened, should only have tmp and const cases to
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               consider. */
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(0);
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* At the end of the bb.  Flush outstandings. */
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   flushEvents( &clgs );
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Update global variable jmps_passed at end of SB.
1294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    * As CLG_(current_state).jmps_passed is reset to 0 in setup_bbcc,
1295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    * this can be omitted if there is no conditional jump in this SB.
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * A correction is needed if VEX inverted the last jump condition
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    */
1298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (cJumps>0) {
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt jmps_passed = cJumps;
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (clgs.bb->cjmp_inverted) jmps_passed--;
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addConstMemStoreStmt( clgs.sbOut,
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    (UWord) &CLG_(current_state).jmps_passed,
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			    jmps_passed, hWordTy);
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_ASSERT(clgs.bb->cjmp_count == cJumps);
1306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   CLG_ASSERT(clgs.bb->instr_count == clgs.ii_index);
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Info for final exit from BB */
1309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   {
1310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     ClgJumpKind jk;
1311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     if      (sbIn->jumpkind == Ijk_Call) jk = jk_Call;
1313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     else if (sbIn->jumpkind == Ijk_Ret)  jk = jk_Return;
1314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     else {
1315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       jk = jk_Jump;
1316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng       if ((sbIn->next->tag == Iex_Const) &&
1317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	   (IRConst2Addr(sbIn->next->Iex.Const.con) ==
1318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	    origAddr + clgs.instr_offset))
1319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng	 jk = jk_None;
1320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     }
1321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     clgs.bb->jmp[cJumps].jmpkind = jk;
1322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* Instruction index of the call/ret at BB end
1323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      * (it is wrong for fall-through, but does not matter) */
1324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
1325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* swap information of last exit with final exit if inverted */
1328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (clgs.bb->cjmp_inverted) {
1329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     ClgJumpKind jk;
1330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     UInt instr;
1331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     jk = clgs.bb->jmp[cJumps].jmpkind;
1333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     clgs.bb->jmp[cJumps].jmpkind = clgs.bb->jmp[cJumps-1].jmpkind;
1334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     clgs.bb->jmp[cJumps-1].jmpkind = jk;
1335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     instr = clgs.bb->jmp[cJumps].instr;
1336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     clgs.bb->jmp[cJumps].instr = clgs.bb->jmp[cJumps-1].instr;
1337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     clgs.bb->jmp[cJumps-1].instr = instr;
1338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clgs.seen_before) {
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_ASSERT(clgs.bb->cost_count == update_cost_offsets(&clgs));
1342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       CLG_ASSERT(clgs.bb->instr_len == clgs.instr_offset);
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       clgs.bb->cost_count = update_cost_offsets(&clgs);
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       clgs.bb->instr_len = clgs.instr_offset;
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_DEBUG(3, "- instrument(BB %#lx): byteLen %u, CJumps %u, CostLen %u\n",
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     origAddr, clgs.bb->instr_len,
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     clgs.bb->cjmp_count, clgs.bb->cost_count);
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (cJumps>0) {
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_DEBUG(3, "                     [ ");
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       for (i=0;i<cJumps;i++)
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   CLG_DEBUG(3, "%d ", clgs.bb->jmp[i].instr);
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_DEBUG(3, "], last inverted: %s \n",
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 clgs.bb->cjmp_inverted ? "yes":"no");
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return clgs.sbOut;
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Discarding BB info                                           ---*/
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Called when a translation is removed from the translation cache for
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// any reason at all: to free up space, because the guest code was
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// unmapped or modified, or for any arbitrary reason.
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid clg_discard_superblock_info ( Addr64 orig_addr64, VexGuestExtents vge )
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Addr orig_addr = (Addr)orig_addr64;
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tl_assert(vge.n_used > 0);
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)( "discard_superblock_info: %p, %p, %llu\n",
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (void*)(Addr)orig_addr,
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (void*)(Addr)vge.base[0], (ULong)vge.len[0]);
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Get BB info, remove from table, free BB info.  Simple!  Note that we
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // use orig_addr, not the first instruction address in vge.
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(delete_bb)(orig_addr);
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- CLG_(fini)() and related function                     ---*/
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void zero_thread_cost(thread_info* t)
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int i;
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(current_call_stack).entry[i].jcc) continue;
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* reset call counters to current for active calls */
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(copy_cost)( CLG_(sets).full,
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    CLG_(current_call_stack).entry[i].enter_cost,
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		    CLG_(current_state).cost );
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_call_stack).entry[i].jcc->call_counter = 0;
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(forall_bbccs)(CLG_(zero_bbcc));
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* set counter for last dump */
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(copy_cost)( CLG_(sets).full,
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  t->lastdump_cost, CLG_(current_state).cost );
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(zero_all_cost)(Bool only_current_thread)
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (VG_(clo_verbosity) > 1)
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(message)(Vg_DebugMsg, "  Zeroing costs...\n");
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (only_current_thread)
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    zero_thread_cost(CLG_(get_current_thread)());
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  else
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(forall_threads)(zero_thread_cost);
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (VG_(clo_verbosity) > 1)
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(message)(Vg_DebugMsg, "  ...done\n");
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid unwind_thread(thread_info* t)
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* unwind signal handlers */
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(CLG_(current_state).sig !=0)
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(post_signal)(CLG_(current_tid),CLG_(current_state).sig);
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* unwind regular call stack */
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(CLG_(current_call_stack).sp>0)
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(pop_call_stack)();
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* reset context and function stack for context generation */
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(init_exec_state)( &CLG_(current_state) );
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(current_fn_stack).top = CLG_(current_fn_stack).bottom;
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid zero_state_cost(thread_info* t)
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(zero_cost)( CLG_(sets).full, CLG_(current_state).cost );
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Ups, this can go very wrong...
1452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   FIXME: We should export this function or provide other means to get a handle */
1453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovextern void VG_(discard_translations) ( Addr64 start, ULong range, const HChar* who );
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CLG_(set_instrument_state)(const HChar* reason, Bool state)
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (CLG_(instrument_state) == state) {
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(2, "%s: instrumentation already %s\n",
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     reason, state ? "ON" : "OFF");
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return;
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(instrument_state) = state;
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(2, "%s: Switching instrumentation %s ...\n",
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   reason, state ? "ON" : "OFF");
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  VG_(discard_translations)( (Addr64)0x1000, (ULong) ~0xfffl, "callgrind");
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* reset internal state: call stacks, simulator */
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(forall_threads)(unwind_thread);
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(forall_threads)(zero_state_cost);
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*CLG_(cachesim).clear)();
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (VG_(clo_verbosity) > 1)
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(message)(Vg_DebugMsg, "%s: instrumentation switched %s\n",
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 reason, state ? "ON" : "OFF");
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* helper for dump_state_togdb */
1479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void dump_state_of_thread_togdb(thread_info* ti)
1480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    static HChar buf[512];
1482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    static FullCost sum = 0, tmp = 0;
1483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    Int t, p, i;
1484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    BBCC *from, *to;
1485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    call_entry* ce;
1486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    t = CLG_(current_tid);
1488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_(init_cost_lz)( CLG_(sets).full, &sum );
1489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_(copy_cost_lz)( CLG_(sets).full, &tmp, ti->lastdump_cost );
1490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_(add_diff_cost)( CLG_(sets).full, sum, ti->lastdump_cost,
1491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov			 ti->states.entry[0]->cost);
1492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost, tmp );
1493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_(sprint_mappingcost)(buf, CLG_(dumpmap), sum);
1494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("events-%d: %s\n", t, buf);
1495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("frames-%d: %d\n", t, CLG_(current_call_stack).sp);
1496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ce = 0;
1498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ce = CLG_(get_call_entry)(i);
1500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* if this frame is skipped, we don't have counters */
1501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (!ce->jcc) continue;
1502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      from = ce->jcc->from;
1504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(gdb_printf)("function-%d-%d: %s\n",t, i, from->cxt->fn[0]->name);
1505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(gdb_printf)("calls-%d-%d: %llu\n",t, i, ce->jcc->call_counter);
1506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* FIXME: EventSets! */
1508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      CLG_(copy_cost)( CLG_(sets).full, sum, ce->jcc->cost );
1509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      CLG_(copy_cost)( CLG_(sets).full, tmp, ce->enter_cost );
1510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      CLG_(add_diff_cost)( CLG_(sets).full, sum,
1511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov			  ce->enter_cost, CLG_(current_state).cost );
1512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      CLG_(copy_cost)( CLG_(sets).full, ce->enter_cost, tmp );
1513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      p = VG_(sprintf)(buf, "events-%d-%d: ",t, i);
1515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum );
1516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(gdb_printf)("%s\n", buf);
1517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (ce && ce->jcc) {
1519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      to = ce->jcc->to;
1520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(gdb_printf)("function-%d-%d: %s\n",t, i, to->cxt->fn[0]->name );
1521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Dump current state */
1525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void dump_state_togdb(void)
1526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    static HChar buf[512];
1528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    thread_info** th;
1529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int t, p;
1530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    Int orig_tid = CLG_(current_tid);
1531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("instrumentation: %s\n",
1533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		    CLG_(instrument_state) ? "on":"off");
1534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (!CLG_(instrument_state)) return;
1535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("executed-bbs: %llu\n", CLG_(stat).bb_executions);
1537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("executed-calls: %llu\n", CLG_(stat).call_counter);
1538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("distinct-bbs: %d\n", CLG_(stat).distinct_bbs);
1539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("distinct-calls: %d\n", CLG_(stat).distinct_jccs);
1540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("distinct-functions: %d\n", CLG_(stat).distinct_fns);
1541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("distinct-contexts: %d\n", CLG_(stat).distinct_contexts);
1542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* "events:" line. Given here because it will be dynamic in the future */
1544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    p = VG_(sprintf)(buf, "events: ");
1545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_(sprint_eventmapping)(buf+p, CLG_(dumpmap));
1546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("%s\n", buf);
1547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* "part:" line (number of last part. Is 0 at start */
1548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("part: %d\n", CLG_(get_dump_counter)());
1549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* threads */
1551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    th = CLG_(get_threads)();
1552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    p = VG_(sprintf)(buf, "threads:");
1553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    for(t=1;t<VG_N_THREADS;t++) {
1554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	if (!th[t]) continue;
1555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	p += VG_(sprintf)(buf+p, " %d", t);
1556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }
1557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("%s\n", buf);
1558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    VG_(gdb_printf)("current-tid: %d\n", orig_tid);
1559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    CLG_(forall_threads)(dump_state_of_thread_togdb);
1560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void print_monitor_help ( void )
1564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("\n");
1566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("callgrind monitor commands:\n");
1567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("  dump [<dump_hint>]\n");
1568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("        dump counters\n");
1569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("  zero\n");
1570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("        zero counters\n");
1571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("  status\n");
1572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("        print status\n");
1573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("  instrumentation [on|off]\n");
1574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("        get/set (if on/off given) instrumentation state\n");
1575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdb_printf) ("\n");
1576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* return True if request recognised, False otherwise */
1579436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool handle_gdb_monitor_command (ThreadId tid, const HChar *req)
1580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1581436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar* wcmd;
1582eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov   HChar s[VG_(strlen(req)) + 1]; /* copy for strtok_r */
1583436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar *ssaveptr;
1584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(strcpy) (s, req);
1586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   wcmd = VG_(strtok_r) (s, " ", &ssaveptr);
1588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (VG_(keyword_id) ("help dump zero status instrumentation",
1589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            wcmd, kwd_report_duplicated_matches)) {
1590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case -2: /* multiple matches */
1591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return True;
1592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case -1: /* not found */
1593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
1594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  0: /* help */
1595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      print_monitor_help();
1596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return True;
1597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  1: { /* dump */
1598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      CLG_(dump_profile)(req, False);
1599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return True;
1600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  2: { /* zero */
1602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      CLG_(zero_all_cost)(False);
1603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return True;
1604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 3: { /* status */
1607436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     HChar* arg = VG_(strtok_r) (0, " ", &ssaveptr);
1608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     if (arg && (VG_(strcmp)(arg, "internal") == 0)) {
1609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       /* internal interface to callgrind_control */
1610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       dump_state_togdb();
1611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       return True;
1612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     }
1613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     if (!CLG_(instrument_state)) {
1615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       VG_(gdb_printf)("No status available as instrumentation is switched off\n");
1616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     } else {
1617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       // Status information to be improved ...
1618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       thread_info** th = CLG_(get_threads)();
1619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       Int t, tcount = 0;
1620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       for(t=1;t<VG_N_THREADS;t++)
1621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	 if (th[t]) tcount++;
1622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       VG_(gdb_printf)("%d thread(s) running.\n", tcount);
1623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     }
1624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     return True;
1625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 4: { /* instrumentation */
1628436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     HChar* arg = VG_(strtok_r) (0, " ", &ssaveptr);
1629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     if (!arg) {
1630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       VG_(gdb_printf)("instrumentation: %s\n",
1631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		       CLG_(instrument_state) ? "on":"off");
1632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     }
1633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     else
1634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       CLG_(set_instrument_state)("Command", VG_(strcmp)(arg,"off")!=0);
1635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     return True;
1636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   default:
1639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      tl_assert(0);
1640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
1641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool CLG_(handle_client_request)(ThreadId tid, UWord *args, UWord *ret)
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!VG_IS_TOOL_USERREQ('C','T',args[0])
1648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       && VG_USERREQ__GDB_MONITOR_COMMAND   != args[0])
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch(args[0]) {
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VG_USERREQ__DUMP_STATS:
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(dump_profile)("Client Request", True);
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *ret = 0;                 /* meaningless */
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VG_USERREQ__DUMP_STATS_AT:
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     {
1659436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       HChar buf[512];
1660436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       VG_(sprintf)(buf,"Client Request: %s", (HChar*)args[1]);
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_(dump_profile)(buf, True);
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       *ret = 0;                 /* meaningless */
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     break;
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VG_USERREQ__ZERO_STATS:
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     CLG_(zero_all_cost)(True);
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *ret = 0;                 /* meaningless */
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VG_USERREQ__TOGGLE_COLLECT:
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     CLG_(current_state).collect = !CLG_(current_state).collect;
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     CLG_DEBUG(2, "Client Request: toggled collection state to %s\n",
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      CLG_(current_state).collect ? "ON" : "OFF");
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *ret = 0;                 /* meaningless */
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     break;
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VG_USERREQ__START_INSTRUMENTATION:
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     CLG_(set_instrument_state)("Client Request", True);
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *ret = 0;                 /* meaningless */
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     break;
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VG_USERREQ__STOP_INSTRUMENTATION:
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     CLG_(set_instrument_state)("Client Request", False);
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *ret = 0;                 /* meaningless */
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     break;
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case VG_USERREQ__GDB_MONITOR_COMMAND: {
1689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      Bool handled = handle_gdb_monitor_command (tid, (HChar*)args[1]);
1690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (handled)
1691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *ret = 1;
1692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else
1693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *ret = 0;
1694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return handled;
1695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Syscall Timing */
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* struct timeval syscalltime[VG_N_THREADS]; */
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if CLG_MICROSYSTIME
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/time.h>
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/syscall.h>
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern Int VG_(do_syscall) ( UInt, ... );
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong syscalltime[VG_N_THREADS];
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt syscalltime[VG_N_THREADS];
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(pre_syscalltime)(ThreadId tid, UInt syscallno,
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           UWord* args, UInt nArgs)
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (CLG_(clo).collect_systime) {
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if CLG_MICROSYSTIME
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct vki_timeval tv_now;
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now, (UInt)NULL);
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    syscalltime[tid] = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    syscalltime[tid] = VG_(read_millisecond_timer)();
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(post_syscalltime)(ThreadId tid, UInt syscallno,
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            UWord* args, UInt nArgs, SysRes res)
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (CLG_(clo).collect_systime &&
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(current_state).bbcc) {
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int o;
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if CLG_MICROSYSTIME
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    struct vki_timeval tv_now;
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ULong diff;
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now, (UInt)NULL);
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    diff = (tv_now.tv_sec * 1000000ULL + tv_now.tv_usec) - syscalltime[tid];
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UInt diff = VG_(read_millisecond_timer)() - syscalltime[tid];
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* offset o is for "SysCount", o+1 for "SysTime" */
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    o = fullOffset(EG_SYS);
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_ASSERT(o>=0);
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(0,"   Time (Off %d) for Syscall %d: %ull\n", o, syscallno, diff);
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_state).cost[o] ++;
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_state).cost[o+1] += diff;
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(current_state).bbcc->skipped)
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CLG_(init_cost_lz)(CLG_(sets).full,
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			&(CLG_(current_state).bbcc->skipped));
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_state).bbcc->skipped[o] ++;
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_state).bbcc->skipped[o+1] += diff;
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ULong_width(ULong n)
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt w = 0;
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (n > 0) {
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      n = n / 10;
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      w++;
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (w == 0) w = 1;
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return w + (w-1)/3;   // add space for commas
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid branchsim_printstat(int l1, int l2, int l3)
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1778436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    static HChar buf1[128], buf2[128], buf3[128];
1779436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    static HChar fmt[128];
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FullCost total;
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ULong Bc_total_b, Bc_total_mp, Bi_total_b, Bi_total_mp;
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ULong B_total_b, B_total_mp;
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total = CLG_(total_cost);
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bc_total_b  = total[ fullOffset(EG_BC)   ];
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bc_total_mp = total[ fullOffset(EG_BC)+1 ];
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bi_total_b  = total[ fullOffset(EG_BI)   ];
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Bi_total_mp = total[ fullOffset(EG_BI)+1 ];
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Make format string, getting width right for numbers */
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(sprintf)(fmt, "%%s %%,%dllu  (%%,%dllu cond + %%,%dllu ind)\n",
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 l1, l2, l3);
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (0 == Bc_total_b)  Bc_total_b = 1;
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (0 == Bi_total_b)  Bi_total_b = 1;
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    B_total_b  = Bc_total_b  + Bi_total_b;
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    B_total_mp = Bc_total_mp + Bi_total_mp;
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(umsg)("\n");
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(umsg)(fmt, "Branches:     ",
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              B_total_b, Bc_total_b, Bi_total_b);
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(umsg)(fmt, "Mispredicts:  ",
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              B_total_mp, Bc_total_mp, Bi_total_mp);
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(percentify)(B_total_mp,  B_total_b,  1, l1+1, buf1);
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(percentify)(Bc_total_mp, Bc_total_b, 1, l2+1, buf2);
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(percentify)(Bi_total_mp, Bi_total_b, 1, l3+1, buf3);
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(umsg)("Mispred rate:  %s (%s     + %s   )\n", buf1, buf2,buf3);
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1813436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic
1814436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid clg_print_stats(void)
1815436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
1816436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   int BB_lookups =
1817436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     CLG_(stat).full_debug_BBs +
1818436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     CLG_(stat).fn_name_debug_BBs +
1819436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     CLG_(stat).file_line_debug_BBs +
1820436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     CLG_(stat).no_debug_BBs;
1821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* Hash table stats */
1823436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Distinct objects: %d\n",
1824436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).distinct_objs);
1825436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Distinct files:   %d\n",
1826436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).distinct_files);
1827436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Distinct fns:     %d\n",
1828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).distinct_fns);
1829436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Distinct contexts:%d\n",
1830436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).distinct_contexts);
1831436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Distinct BBs:     %d\n",
1832436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).distinct_bbs);
1833436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Cost entries:     %d (Chunks %d)\n",
1834436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(costarray_entries), CLG_(costarray_chunks));
1835436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Distinct BBCCs:   %d\n",
1836436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).distinct_bbccs);
1837436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Distinct JCCs:    %d\n",
1838436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).distinct_jccs);
1839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Distinct skips:   %d\n",
1840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).distinct_skips);
1841436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "BB lookups:       %d\n",
1842436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		BB_lookups);
1843436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (BB_lookups>0) {
1844436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(message)(Vg_DebugMsg, "With full      debug info:%3d%% (%d)\n",
1845436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		   CLG_(stat).full_debug_BBs    * 100 / BB_lookups,
1846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		   CLG_(stat).full_debug_BBs);
1847436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(message)(Vg_DebugMsg, "With file/line debug info:%3d%% (%d)\n",
1848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		   CLG_(stat).file_line_debug_BBs * 100 / BB_lookups,
1849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		   CLG_(stat).file_line_debug_BBs);
1850436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(message)(Vg_DebugMsg, "With fn name   debug info:%3d%% (%d)\n",
1851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		   CLG_(stat).fn_name_debug_BBs * 100 / BB_lookups,
1852436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		   CLG_(stat).fn_name_debug_BBs);
1853436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(message)(Vg_DebugMsg, "With no        debug info:%3d%% (%d)\n",
1854436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		   CLG_(stat).no_debug_BBs      * 100 / BB_lookups,
1855436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		   CLG_(stat).no_debug_BBs);
1856436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1857436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "BBCC Clones:       %d\n",
1858436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).bbcc_clones);
1859436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "BBs Retranslated:  %d\n",
1860436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).bb_retranslations);
1861436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Distinct instrs:   %d\n",
1862436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).distinct_instrs);
1863436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "");
1864436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1865436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "LRU Contxt Misses: %d\n",
1866436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).cxt_lru_misses);
1867436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "LRU BBCC Misses:   %d\n",
1868436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).bbcc_lru_misses);
1869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "LRU JCC Misses:    %d\n",
1870436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).jcc_lru_misses);
1871436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "BBs Executed:      %llu\n",
1872436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).bb_executions);
1873436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Calls:             %llu\n",
1874436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).call_counter);
1875436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "CondJMP followed:  %llu\n",
1876436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).jcnd_counter);
1877436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Boring JMPs:       %llu\n",
1878436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).jump_counter);
1879436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Recursive calls:   %llu\n",
1880436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).rec_call_counter);
1881436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VG_(message)(Vg_DebugMsg, "Returns:           %llu\n",
1882436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		CLG_(stat).ret_counter);
1883436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
1884436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid finish(void)
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1889436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  HChar buf[32+COSTS_LEN];
1890436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  HChar fmt[128];
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int l1, l2, l3;
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FullCost total;
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(0, "finish()\n");
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*CLG_(cachesim).finish)();
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* pop all remaining items from CallStack for correct sum
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(forall_threads)(unwind_thread);
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(dump_profile)(0, False);
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (VG_(clo_verbosity) == 0) return;
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (VG_(clo_stats)) {
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(message)(Vg_DebugMsg, "\n");
1908436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    clg_print_stats();
1909436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    VG_(message)(Vg_DebugMsg, "\n");
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(sprint_eventmapping)(buf, CLG_(dumpmap));
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "Events    : %s\n", buf);
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(sprint_mappingcost)(buf, CLG_(dumpmap), CLG_(total_cost));
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "Collected : %s\n", buf);
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "\n");
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* determine value widths for statistics */
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  total = CLG_(total_cost);
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  l1 = ULong_width( total[fullOffset(EG_IR)] );
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  l2 = l3 = 0;
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (CLG_(clo).simulate_cache) {
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      l2 = ULong_width( total[fullOffset(EG_DR)] );
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      l3 = ULong_width( total[fullOffset(EG_DW)] );
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (CLG_(clo).simulate_branch) {
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int l2b = ULong_width( total[fullOffset(EG_BC)] );
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int l3b = ULong_width( total[fullOffset(EG_BI)] );
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (l2b > l2) l2 = l2b;
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (l3b > l3) l3 = l3b;
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* Make format string, getting width right for numbers */
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(sprintf)(fmt, "%%s %%,%dllu\n", l1);
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* Always print this */
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(umsg)(fmt, "I   refs:     ", total[fullOffset(EG_IR)] );
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (CLG_(clo).simulate_cache)
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (*CLG_(cachesim).printstat)(l1, l2, l3);
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (CLG_(clo).simulate_branch)
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      branchsim_printstat(l1, l2, l3);
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(fini)(Int exitcode)
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  finish();
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Setup                                                        ---*/
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void clg_start_client_code_callback ( ThreadId tid, ULong blocks_done )
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static ULong last_blocks_done = 0;
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("%d R %llu\n", (Int)tid, blocks_done);
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* throttle calls to CLG_(run_thread) by number of BBs executed */
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (blocks_done - last_blocks_done < 5000) return;
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   last_blocks_done = blocks_done;
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(run_thread)( tid );
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(post_clo_init)(void)
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (VG_(clo_vex_control).iropt_register_updates
1976436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       != VexRegUpdSpAtMemAccess) {
1977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      CLG_DEBUG(1, " Using user specified value for "
1978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                "--vex-iropt-register-updates\n");
1979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   } else {
1980436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      CLG_DEBUG(1,
1981436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                " Using default --vex-iropt-register-updates="
1982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                "sp-at-mem-access\n");
1983436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1985436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (VG_(clo_vex_control).iropt_unroll_thresh != 0) {
1986436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(message)(Vg_UserMsg,
1987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   "callgrind only works with --vex-iropt-unroll-thresh=0\n"
1988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   "=> resetting it back to 0\n");
1989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(clo_vex_control).iropt_unroll_thresh = 0;   // cannot be overriden.
1990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (VG_(clo_vex_control).guest_chase_thresh != 0) {
1992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(message)(Vg_UserMsg,
1993436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   "callgrind only works with --vex-guest-chase-thresh=0\n"
1994436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   "=> resetting it back to 0\n");
1995436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      VG_(clo_vex_control).guest_chase_thresh = 0; // cannot be overriden.
1996436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
1997436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_DEBUG(1, "  dump threads: %s\n", CLG_(clo).separate_threads ? "Yes":"No");
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_DEBUG(1, "  call sep. : %d\n", CLG_(clo).separate_callers);
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_DEBUG(1, "  rec. sep. : %d\n", CLG_(clo).separate_recursions);
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!CLG_(clo).dump_line && !CLG_(clo).dump_instr && !CLG_(clo).dump_bb) {
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(message)(Vg_UserMsg, "Using source line as position.\n");
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       CLG_(clo).dump_line = True;
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_dumps)();
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (*CLG_(cachesim).post_clo_init)();
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_eventsets)();
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_statistics)(& CLG_(stat));
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_cost_lz)( CLG_(sets).full, &CLG_(total_cost) );
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* initialize hash tables */
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_obj_table)();
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_cxt_table)();
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_bb_hash)();
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(init_threads)();
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(run_thread)(1);
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_(instrument_state) = CLG_(clo).instrument_atstart;
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity > 0)) {
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
2027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   "For interactive control, run 'callgrind_control%s%s -h'.\n",
2028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   (VG_(arg_vgdb_prefix) ? " " : ""),
2029436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov                   (VG_(arg_vgdb_prefix) ? VG_(arg_vgdb_prefix) : ""));
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(pre_clo_init)(void)
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(details_name)            ("Callgrind");
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(details_version)         (NULL);
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(details_description)     ("a call-graph generating cache profiler");
2039436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    VG_(details_copyright_author)("Copyright (C) 2002-2013, and GNU GPL'd, "
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				  "by Josef Weidendorfer et al.");
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(details_bug_reports_to)  (VG_BUGS_TO);
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(details_avg_translation_sizeB) ( 500 );
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2044436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    VG_(clo_vex_control).iropt_register_updates
2045436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       = VexRegUpdSpAtMemAccess; // overridable by the user.
2046436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    VG_(clo_vex_control).iropt_unroll_thresh = 0;   // cannot be overriden.
2047436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    VG_(clo_vex_control).guest_chase_thresh = 0;    // cannot be overriden.
2048436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(basic_tool_funcs)        (CLG_(post_clo_init),
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  CLG_(instrument),
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  CLG_(fini));
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(needs_superblock_discards)(clg_discard_superblock_info);
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(needs_command_line_options)(CLG_(process_cmd_line_option),
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				    CLG_(print_usage),
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				    CLG_(print_debug_usage));
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(needs_client_requests)(CLG_(handle_client_request));
2061436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    VG_(needs_print_stats)    (clg_print_stats);
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(needs_syscall_wrapper)(CLG_(pre_syscalltime),
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			       CLG_(post_syscalltime));
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(track_start_client_code)  ( & clg_start_client_code_callback );
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(track_pre_deliver_signal) ( & CLG_(pre_signal) );
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(track_post_deliver_signal)( & CLG_(post_signal) );
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(set_clo_defaults)();
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_DETERMINE_INTERFACE_VERSION(CLG_(pre_clo_init))
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                   main.c ---*/
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
2077