m_transtab.c revision e49d8e7dfd3a9c96feb9935b5920973dfc0b170a
1de4a1d01951937632098a6cda45859afa587a06fsewardj
2de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
3de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- Management of the translation table and cache.               ---*/
4de4a1d01951937632098a6cda45859afa587a06fsewardj/*---                                                vg_transtab.c ---*/
5de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
6de4a1d01951937632098a6cda45859afa587a06fsewardj
7de4a1d01951937632098a6cda45859afa587a06fsewardj/*
8de4a1d01951937632098a6cda45859afa587a06fsewardj   This file is part of Valgrind, an x86 protected-mode emulator
9de4a1d01951937632098a6cda45859afa587a06fsewardj   designed for debugging and profiling binaries on x86-Unixes.
10de4a1d01951937632098a6cda45859afa587a06fsewardj
11de4a1d01951937632098a6cda45859afa587a06fsewardj   Copyright (C) 2000-2002 Julian Seward
12de4a1d01951937632098a6cda45859afa587a06fsewardj      jseward@acm.org
13de4a1d01951937632098a6cda45859afa587a06fsewardj
14de4a1d01951937632098a6cda45859afa587a06fsewardj   This program is free software; you can redistribute it and/or
15de4a1d01951937632098a6cda45859afa587a06fsewardj   modify it under the terms of the GNU General Public License as
16de4a1d01951937632098a6cda45859afa587a06fsewardj   published by the Free Software Foundation; either version 2 of the
17de4a1d01951937632098a6cda45859afa587a06fsewardj   License, or (at your option) any later version.
18de4a1d01951937632098a6cda45859afa587a06fsewardj
19de4a1d01951937632098a6cda45859afa587a06fsewardj   This program is distributed in the hope that it will be useful, but
20de4a1d01951937632098a6cda45859afa587a06fsewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
21de4a1d01951937632098a6cda45859afa587a06fsewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22de4a1d01951937632098a6cda45859afa587a06fsewardj   General Public License for more details.
23de4a1d01951937632098a6cda45859afa587a06fsewardj
24de4a1d01951937632098a6cda45859afa587a06fsewardj   You should have received a copy of the GNU General Public License
25de4a1d01951937632098a6cda45859afa587a06fsewardj   along with this program; if not, write to the Free Software
26de4a1d01951937632098a6cda45859afa587a06fsewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27de4a1d01951937632098a6cda45859afa587a06fsewardj   02111-1307, USA.
28de4a1d01951937632098a6cda45859afa587a06fsewardj
29e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   The GNU General Public License is contained in the file COPYING.
30de4a1d01951937632098a6cda45859afa587a06fsewardj*/
31de4a1d01951937632098a6cda45859afa587a06fsewardj
32de4a1d01951937632098a6cda45859afa587a06fsewardj#include "vg_include.h"
33de4a1d01951937632098a6cda45859afa587a06fsewardj
3418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* #define DEBUG_TRANSTAB */
3518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj
36de4a1d01951937632098a6cda45859afa587a06fsewardj
37de4a1d01951937632098a6cda45859afa587a06fsewardj/*------------------------------------------------------------*/
38de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- Management of the LRU-based translation table+cache. ---*/
39de4a1d01951937632098a6cda45859afa587a06fsewardj/*------------------------------------------------------------*/
40de4a1d01951937632098a6cda45859afa587a06fsewardj
41de4a1d01951937632098a6cda45859afa587a06fsewardj/* These sizes were set up so as to be able to debug large KDE 3
42de4a1d01951937632098a6cda45859afa587a06fsewardj   applications (are there any small ones?) without excessive amounts
43de4a1d01951937632098a6cda45859afa587a06fsewardj   of code retranslation.  */
44de4a1d01951937632098a6cda45859afa587a06fsewardj
45de4a1d01951937632098a6cda45859afa587a06fsewardj/* Size of the translation cache, in bytes. */
4618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#define VG_TC_SIZE /*1000000*/ /*16000000*/ 32000000 /*40000000*/
47de4a1d01951937632098a6cda45859afa587a06fsewardj
48de4a1d01951937632098a6cda45859afa587a06fsewardj/* Do a LRU pass when the translation cache becomes this full. */
49ec05564e60750787ac4db9e9254f74be357f307csewardj#define VG_TC_LIMIT_PERCENT 98
50de4a1d01951937632098a6cda45859afa587a06fsewardj
51de4a1d01951937632098a6cda45859afa587a06fsewardj/* When doing an LRU pass, reduce TC fullness to this level. */
52de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TC_TARGET_PERCENT 85
53de4a1d01951937632098a6cda45859afa587a06fsewardj
54de4a1d01951937632098a6cda45859afa587a06fsewardj/* Number of entries in the translation table.  This must be a prime
55de4a1d01951937632098a6cda45859afa587a06fsewardj   number in order to make the hashing work properly. */
5618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#define VG_TT_SIZE /*5281*/ /*100129*/ 200191 /*250829*/
57de4a1d01951937632098a6cda45859afa587a06fsewardj
58de4a1d01951937632098a6cda45859afa587a06fsewardj/* Do an LRU pass when the translation table becomes this full. */
59de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TT_LIMIT_PERCENT /*67*/ 80
60de4a1d01951937632098a6cda45859afa587a06fsewardj
61de4a1d01951937632098a6cda45859afa587a06fsewardj/* When doing an LRU pass, reduce TT fullness to this level. */
62de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TT_TARGET_PERCENT /*60*/ 70
63de4a1d01951937632098a6cda45859afa587a06fsewardj
64de4a1d01951937632098a6cda45859afa587a06fsewardj/* The number of age steps we track.  0 means the current epoch,
65de4a1d01951937632098a6cda45859afa587a06fsewardj   N_EPOCHS-1 means used the epoch N_EPOCHS-1 or more ago.  */
66ac68028393aef2bf9a7d48c98f293d3106a44ae1sewardj#define VG_N_EPOCHS /*2000*/ /*4000*/ 20000
67de4a1d01951937632098a6cda45859afa587a06fsewardj
6818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* This TT entry is empty.  There is no associated TC storage. */
69de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TTE_EMPTY   ((Addr)1)
7018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* This TT entry has been deleted, in the sense that it does not
7118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   contribute to the orig->trans mapping.  However, the ex-translation
7218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   it points at still occupies space in TC.  This slot cannot be
7318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   re-used without doing an LRU pass. */
74de4a1d01951937632098a6cda45859afa587a06fsewardj#define VG_TTE_DELETED ((Addr)3)
75de4a1d01951937632098a6cda45859afa587a06fsewardj
76de4a1d01951937632098a6cda45859afa587a06fsewardj/* The TC.  This used to be statically allocated, but that forces many
77de4a1d01951937632098a6cda45859afa587a06fsewardj   SecMap arrays to be pointlessly allocated at startup, bloating the
78de4a1d01951937632098a6cda45859afa587a06fsewardj   process size by about 22M and making startup slow.  So now we
79de4a1d01951937632098a6cda45859afa587a06fsewardj   dynamically allocate it at startup time.
80de4a1d01951937632098a6cda45859afa587a06fsewardj   was: static UChar vg_tc[VG_TC_SIZE];
81de4a1d01951937632098a6cda45859afa587a06fsewardj*/
82de4a1d01951937632098a6cda45859afa587a06fsewardjstatic UChar* vg_tc = NULL;
83de4a1d01951937632098a6cda45859afa587a06fsewardj
8418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* Count of bytes used in the TC.  This includes those pointed to from
8518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   VG_TTE_DELETED entries. */
86de4a1d01951937632098a6cda45859afa587a06fsewardjstatic Int vg_tc_used = 0;
87de4a1d01951937632098a6cda45859afa587a06fsewardj
88de4a1d01951937632098a6cda45859afa587a06fsewardj/* The TT.  Like TC, for the same reason, is dynamically allocated at
89de4a1d01951937632098a6cda45859afa587a06fsewardj   startup.
90de4a1d01951937632098a6cda45859afa587a06fsewardj   was: static TTEntry vg_tt[VG_TT_SIZE];
91de4a1d01951937632098a6cda45859afa587a06fsewardj*/
92de4a1d01951937632098a6cda45859afa587a06fsewardjstatic TTEntry* vg_tt = NULL;
93de4a1d01951937632098a6cda45859afa587a06fsewardj
9418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* Count of non-empty TT entries.  This includes deleted ones. */
95de4a1d01951937632098a6cda45859afa587a06fsewardjstatic Int vg_tt_used = 0;
96de4a1d01951937632098a6cda45859afa587a06fsewardj
97de4a1d01951937632098a6cda45859afa587a06fsewardj/* Fast helper for the TT.  A direct-mapped cache which holds a
98de4a1d01951937632098a6cda45859afa587a06fsewardj   pointer to a TT entry which may or may not be the correct one, but
99de4a1d01951937632098a6cda45859afa587a06fsewardj   which we hope usually is.  This array is referred to directly from
100de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_dispatch.S. */
101de4a1d01951937632098a6cda45859afa587a06fsewardjAddr VG_(tt_fast)[VG_TT_FAST_SIZE];
102de4a1d01951937632098a6cda45859afa587a06fsewardj
103de4a1d01951937632098a6cda45859afa587a06fsewardj/* For reading/writing the misaligned TT-index word at immediately
104de4a1d01951937632098a6cda45859afa587a06fsewardj   preceding every translation in TC. */
1058aef1191a25d33b1173c2f05a27df7606f3ef535sewardj#if 0
1068aef1191a25d33b1173c2f05a27df7606f3ef535sewardj   /* Big sigh.  However reasonable this seems, there are those who
1078aef1191a25d33b1173c2f05a27df7606f3ef535sewardj      set AC in %EFLAGS (Alignment Check) to 1, causing bus errors.  A
1088aef1191a25d33b1173c2f05a27df7606f3ef535sewardj      proper solution is for valgrind to properly virtualise AC, like
1098aef1191a25d33b1173c2f05a27df7606f3ef535sewardj      the other flags (DOSZACP).  The current cheap hack simply avoids
1108aef1191a25d33b1173c2f05a27df7606f3ef535sewardj      all misaligned accesses, so valgrind doesn't fault even if AC is
1118aef1191a25d33b1173c2f05a27df7606f3ef535sewardj      set. */
1128aef1191a25d33b1173c2f05a27df7606f3ef535sewardj#  define VG_READ_MISALIGNED_WORD(aaa) (*((UInt*)(aaa)))
1138aef1191a25d33b1173c2f05a27df7606f3ef535sewardj#  define VG_WRITE_MISALIGNED_WORD(aaa,vvv) *((UInt*)(aaa)) = ((UInt)(vvv))
1148aef1191a25d33b1173c2f05a27df7606f3ef535sewardj#else
1158aef1191a25d33b1173c2f05a27df7606f3ef535sewardj  static __inline__
1168aef1191a25d33b1173c2f05a27df7606f3ef535sewardj  UInt VG_READ_MISALIGNED_WORD ( Addr aaa )
1178aef1191a25d33b1173c2f05a27df7606f3ef535sewardj  {
1188aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     UInt w = 0;
1198aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     UChar* p = (UChar*)aaa;
1208aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     w = 0xFF & ((UInt)(p[3]));
1218aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     w = (w << 8) | (0xFF & ((UInt)(p[2])));
1228aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     w = (w << 8) | (0xFF & ((UInt)(p[1])));
1238aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     w = (w << 8) | (0xFF & ((UInt)(p[0])));
1248aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     return w;
1258aef1191a25d33b1173c2f05a27df7606f3ef535sewardj  }
1268aef1191a25d33b1173c2f05a27df7606f3ef535sewardj
1278aef1191a25d33b1173c2f05a27df7606f3ef535sewardj  static __inline__
1288aef1191a25d33b1173c2f05a27df7606f3ef535sewardj  void VG_WRITE_MISALIGNED_WORD ( Addr aaa, UInt vvv )
1298aef1191a25d33b1173c2f05a27df7606f3ef535sewardj  {
1308aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     UChar* p = (UChar*)aaa;
1318aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     p[0] = vvv & 0xFF;
1328aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     p[1] = (vvv >> 8) & 0xFF;
1338aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     p[2] = (vvv >> 16) & 0xFF;
1348aef1191a25d33b1173c2f05a27df7606f3ef535sewardj     p[3] = (vvv >> 24) & 0xFF;
1358aef1191a25d33b1173c2f05a27df7606f3ef535sewardj  }
1368aef1191a25d33b1173c2f05a27df7606f3ef535sewardj#endif
1378aef1191a25d33b1173c2f05a27df7606f3ef535sewardj
138de4a1d01951937632098a6cda45859afa587a06fsewardj
139de4a1d01951937632098a6cda45859afa587a06fsewardj/* Used for figuring out an age threshold for translations. */
140de4a1d01951937632098a6cda45859afa587a06fsewardjstatic Int vg_bytes_in_epoch[VG_N_EPOCHS];
141de4a1d01951937632098a6cda45859afa587a06fsewardjstatic Int vg_entries_in_epoch[VG_N_EPOCHS];
142de4a1d01951937632098a6cda45859afa587a06fsewardj
143de4a1d01951937632098a6cda45859afa587a06fsewardj
144de4a1d01951937632098a6cda45859afa587a06fsewardj/* Just so these counts can be queried without making them globally
145de4a1d01951937632098a6cda45859afa587a06fsewardj   visible. */
146de4a1d01951937632098a6cda45859afa587a06fsewardjvoid VG_(get_tt_tc_used) ( UInt* tt_used, UInt* tc_used )
147de4a1d01951937632098a6cda45859afa587a06fsewardj{
148de4a1d01951937632098a6cda45859afa587a06fsewardj   *tt_used = vg_tt_used;
149de4a1d01951937632098a6cda45859afa587a06fsewardj   *tc_used = vg_tc_used;
150de4a1d01951937632098a6cda45859afa587a06fsewardj}
151de4a1d01951937632098a6cda45859afa587a06fsewardj
152de4a1d01951937632098a6cda45859afa587a06fsewardj
153de4a1d01951937632098a6cda45859afa587a06fsewardj/* Do the LRU thing on TT/TC, clearing them back to the target limits
154de4a1d01951937632098a6cda45859afa587a06fsewardj   if they are over the threshold limits.
155de4a1d01951937632098a6cda45859afa587a06fsewardj*/
156de4a1d01951937632098a6cda45859afa587a06fsewardjvoid VG_(maybe_do_lru_pass) ( void )
157de4a1d01951937632098a6cda45859afa587a06fsewardj{
158de4a1d01951937632098a6cda45859afa587a06fsewardj   Int i, j, r, w, thresh, ttno;
159de4a1d01951937632098a6cda45859afa587a06fsewardj   TTEntry* tte;
160de4a1d01951937632098a6cda45859afa587a06fsewardj
161215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj   const Int tc_limit  = (Int)(((double)VG_TC_SIZE * (double)VG_TC_LIMIT_PERCENT)
162215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj                                / (double)100.0);
163215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj   const Int tt_limit  = (Int)(((double)VG_TT_SIZE * (double)VG_TT_LIMIT_PERCENT)
164215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj                                / (double)100.0);
165215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj   const Int tc_target = (Int)(((double)VG_TC_SIZE * (double)VG_TC_TARGET_PERCENT)
166215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj                                / (double)100.0);
167215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj   const Int tt_target = (Int)(((double)VG_TT_SIZE * (double)VG_TT_TARGET_PERCENT)
168215e7f01dd2a1c1baa18e1ddec99697f83edd717sewardj                                / (double)100.0);
169de4a1d01951937632098a6cda45859afa587a06fsewardj
170de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Decide quickly if we need to do an LRU pass ? */
171de4a1d01951937632098a6cda45859afa587a06fsewardj   if (vg_tc_used <= tc_limit && vg_tt_used <= tt_limit)
172de4a1d01951937632098a6cda45859afa587a06fsewardj      return;
173de4a1d01951937632098a6cda45859afa587a06fsewardj
17418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#  ifdef DEBUG_TRANSTAB
17518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   VG_(sanity_check_tc_tt)();
17618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#  endif
17718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj
178de4a1d01951937632098a6cda45859afa587a06fsewardj   VGP_PUSHCC(VgpDoLRU);
179de4a1d01951937632098a6cda45859afa587a06fsewardj   /*
180de4a1d01951937632098a6cda45859afa587a06fsewardj   VG_(printf)(
181de4a1d01951937632098a6cda45859afa587a06fsewardj      "limits: tc_limit %d, tt_limit %d, tc_target %d, tt_target %d\n",
182de4a1d01951937632098a6cda45859afa587a06fsewardj      tc_limit, tt_limit, tc_target, tt_target);
183de4a1d01951937632098a6cda45859afa587a06fsewardj   */
184de4a1d01951937632098a6cda45859afa587a06fsewardj
185de4a1d01951937632098a6cda45859afa587a06fsewardj   if (VG_(clo_verbosity) > 2)
186de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(printf)(" pre-LRU: tc %d (target %d),  tt %d (target %d)\n",
187de4a1d01951937632098a6cda45859afa587a06fsewardj	          vg_tc_used, tc_target, vg_tt_used, tt_target);
188de4a1d01951937632098a6cda45859afa587a06fsewardj
189de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Yes we do.  Figure out what threshold age is required in order to
190de4a1d01951937632098a6cda45859afa587a06fsewardj      shrink both the TC and TT occupancy below TC_TARGET_PERCENT and
191de4a1d01951937632098a6cda45859afa587a06fsewardj      TT_TARGET_PERCENT respectively. */
192de4a1d01951937632098a6cda45859afa587a06fsewardj
193de4a1d01951937632098a6cda45859afa587a06fsewardj   VG_(number_of_lrus)++;
194de4a1d01951937632098a6cda45859afa587a06fsewardj
195de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Count the number of TC bytes and TT entries in each epoch. */
196de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 0; i < VG_N_EPOCHS; i++)
197de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_bytes_in_epoch[i] = vg_entries_in_epoch[i] = 0;
198de4a1d01951937632098a6cda45859afa587a06fsewardj
199de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 0; i < VG_TT_SIZE; i++) {
20018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      if (vg_tt[i].orig_addr == VG_TTE_EMPTY
20118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj          || vg_tt[i].orig_addr == VG_TTE_DELETED)
20218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj            continue;
203de4a1d01951937632098a6cda45859afa587a06fsewardj      j = vg_tt[i].mru_epoch;
204de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_assert(j <= VG_(current_epoch));
205de4a1d01951937632098a6cda45859afa587a06fsewardj      j = VG_(current_epoch) - j;
206de4a1d01951937632098a6cda45859afa587a06fsewardj      if (j >= VG_N_EPOCHS) j = VG_N_EPOCHS-1;
207de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_assert(0 <= j && j < VG_N_EPOCHS);
208de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Greater j now means older. */
209de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_entries_in_epoch[j]++;
210de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_bytes_in_epoch[j] += 4+vg_tt[i].trans_size;
211de4a1d01951937632098a6cda45859afa587a06fsewardj   }
212de4a1d01951937632098a6cda45859afa587a06fsewardj
213de4a1d01951937632098a6cda45859afa587a06fsewardj   /*
214de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 0; i < VG_N_EPOCHS; i++)
215de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(printf)("epoch %d: ents %d, bytes %d\n",
216de4a1d01951937632098a6cda45859afa587a06fsewardj                  i, vg_entries_in_epoch[i], vg_bytes_in_epoch[i]);
217de4a1d01951937632098a6cda45859afa587a06fsewardj   */
218de4a1d01951937632098a6cda45859afa587a06fsewardj
219de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Cumulatise.  Make vg_{bytes,entries}_in_epoch[n] contain the
220de4a1d01951937632098a6cda45859afa587a06fsewardj      counts for itself and all younger epochs. */
221de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 1; i < VG_N_EPOCHS; i++) {
222de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_entries_in_epoch[i] += vg_entries_in_epoch[i-1];
223de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_bytes_in_epoch[i] += vg_bytes_in_epoch[i-1];
224de4a1d01951937632098a6cda45859afa587a06fsewardj   }
225de4a1d01951937632098a6cda45859afa587a06fsewardj
226de4a1d01951937632098a6cda45859afa587a06fsewardj   for (thresh = 0; thresh < VG_N_EPOCHS; thresh++) {
227de4a1d01951937632098a6cda45859afa587a06fsewardj      if (vg_entries_in_epoch[thresh] > tt_target
228de4a1d01951937632098a6cda45859afa587a06fsewardj          || vg_bytes_in_epoch[thresh] >= tc_target)
229de4a1d01951937632098a6cda45859afa587a06fsewardj         break;
230de4a1d01951937632098a6cda45859afa587a06fsewardj   }
231de4a1d01951937632098a6cda45859afa587a06fsewardj
232de4a1d01951937632098a6cda45859afa587a06fsewardj   if (VG_(clo_verbosity) > 2)
233de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(printf)(
234de4a1d01951937632098a6cda45859afa587a06fsewardj         "     LRU: discard translations %d or more epochs since last use\n",
235de4a1d01951937632098a6cda45859afa587a06fsewardj         thresh
236de4a1d01951937632098a6cda45859afa587a06fsewardj      );
237de4a1d01951937632098a6cda45859afa587a06fsewardj
238de4a1d01951937632098a6cda45859afa587a06fsewardj   thresh = VG_(current_epoch) - thresh;
239de4a1d01951937632098a6cda45859afa587a06fsewardj
240de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Ok, so we will hit our targets if we retain all entries most
241de4a1d01951937632098a6cda45859afa587a06fsewardj      recently used at most thresh epochs ago.  Traverse the TT and
242de4a1d01951937632098a6cda45859afa587a06fsewardj      mark such entries as deleted. */
243de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 0; i < VG_TT_SIZE; i++) {
24418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      if (vg_tt[i].orig_addr == VG_TTE_EMPTY
24518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj          || vg_tt[i].orig_addr == VG_TTE_DELETED)
24618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         continue;
247de4a1d01951937632098a6cda45859afa587a06fsewardj      if (vg_tt[i].mru_epoch <= thresh) {
248de4a1d01951937632098a6cda45859afa587a06fsewardj         vg_tt[i].orig_addr = VG_TTE_DELETED;
249de4a1d01951937632098a6cda45859afa587a06fsewardj	 VG_(this_epoch_out_count) ++;
250de4a1d01951937632098a6cda45859afa587a06fsewardj	 VG_(this_epoch_out_osize) += vg_tt[i].orig_size;
251de4a1d01951937632098a6cda45859afa587a06fsewardj	 VG_(this_epoch_out_tsize) += vg_tt[i].trans_size;
252de4a1d01951937632098a6cda45859afa587a06fsewardj	 VG_(overall_out_count) ++;
253de4a1d01951937632098a6cda45859afa587a06fsewardj	 VG_(overall_out_osize) += vg_tt[i].orig_size;
254de4a1d01951937632098a6cda45859afa587a06fsewardj	 VG_(overall_out_tsize) += vg_tt[i].trans_size;
255de4a1d01951937632098a6cda45859afa587a06fsewardj      }
256de4a1d01951937632098a6cda45859afa587a06fsewardj   }
257de4a1d01951937632098a6cda45859afa587a06fsewardj
258de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Now compact the TC, sliding live entries downwards to fill spaces
259de4a1d01951937632098a6cda45859afa587a06fsewardj      left by deleted entries.  In this loop, r is the offset in TC of
260de4a1d01951937632098a6cda45859afa587a06fsewardj      the current translation under consideration, and w is the next
261de4a1d01951937632098a6cda45859afa587a06fsewardj      allocation point. */
262de4a1d01951937632098a6cda45859afa587a06fsewardj   r = w = 0;
263de4a1d01951937632098a6cda45859afa587a06fsewardj   while (True) {
264de4a1d01951937632098a6cda45859afa587a06fsewardj      if (r >= vg_tc_used) break;
265de4a1d01951937632098a6cda45859afa587a06fsewardj      /* The first four bytes of every translation contain the index
266de4a1d01951937632098a6cda45859afa587a06fsewardj         of its TT entry.  The TT entry's .trans_addr field points at
267de4a1d01951937632098a6cda45859afa587a06fsewardj         the start of the code proper, not at this 4-byte index, so
268de4a1d01951937632098a6cda45859afa587a06fsewardj         that we don't constantly have to keep adding 4 in the main
269de4a1d01951937632098a6cda45859afa587a06fsewardj         lookup/dispatch loop. */
2708aef1191a25d33b1173c2f05a27df7606f3ef535sewardj
2718aef1191a25d33b1173c2f05a27df7606f3ef535sewardj      ttno = VG_READ_MISALIGNED_WORD((Addr)(&vg_tc[r]));
272de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_assert(ttno >= 0 && ttno < VG_TT_SIZE);
273de4a1d01951937632098a6cda45859afa587a06fsewardj      tte = & vg_tt[ ttno ];
274de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_assert(tte->orig_addr != VG_TTE_EMPTY);
275de4a1d01951937632098a6cda45859afa587a06fsewardj      if (tte->orig_addr != VG_TTE_DELETED) {
276de4a1d01951937632098a6cda45859afa587a06fsewardj         /* We want to keep this one alive. */
277de4a1d01951937632098a6cda45859afa587a06fsewardj         /* Sanity check the pointer back to TC. */
278de4a1d01951937632098a6cda45859afa587a06fsewardj         vg_assert(tte->trans_addr == (Addr)&vg_tc[r+4]);
279de4a1d01951937632098a6cda45859afa587a06fsewardj         for (i = 0; i < 4+tte->trans_size; i++)
280de4a1d01951937632098a6cda45859afa587a06fsewardj            vg_tc[w+i] = vg_tc[r+i];
281de4a1d01951937632098a6cda45859afa587a06fsewardj         tte->trans_addr = (Addr)&vg_tc[w+4];
282de4a1d01951937632098a6cda45859afa587a06fsewardj         w += 4+tte->trans_size;
28318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      } else {
28418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         tte->orig_addr = VG_TTE_EMPTY;
28518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         vg_tt_used--;
286de4a1d01951937632098a6cda45859afa587a06fsewardj      }
287de4a1d01951937632098a6cda45859afa587a06fsewardj      r += 4+tte->trans_size;
288de4a1d01951937632098a6cda45859afa587a06fsewardj   }
289de4a1d01951937632098a6cda45859afa587a06fsewardj   /* should have traversed an exact number of translations, with no
290de4a1d01951937632098a6cda45859afa587a06fsewardj      slop at the end. */
291de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(w <= r);
292de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(r == vg_tc_used);
293de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(w <= r);
294de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(w <= tc_target);
295de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_tc_used = w;
296de4a1d01951937632098a6cda45859afa587a06fsewardj
29718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   vg_assert(vg_tt_used >= 0);
29818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   vg_assert(vg_tt_used <= tt_target);
29918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj
300de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Invalidate the fast cache, since it is now out of date.  It will get
301de4a1d01951937632098a6cda45859afa587a06fsewardj      reconstructed incrementally when the client resumes. */
302de4a1d01951937632098a6cda45859afa587a06fsewardj   VG_(invalidate_tt_fast)();
303de4a1d01951937632098a6cda45859afa587a06fsewardj
304de4a1d01951937632098a6cda45859afa587a06fsewardj   if (VG_(clo_verbosity) > 2)
305de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(printf)("post-LRU: tc %d (target %d),  tt %d (target %d)\n",
306de4a1d01951937632098a6cda45859afa587a06fsewardj	          vg_tc_used, tc_target, vg_tt_used, tt_target);
307de4a1d01951937632098a6cda45859afa587a06fsewardj
308de4a1d01951937632098a6cda45859afa587a06fsewardj   if (VG_(clo_verbosity) > 1)
309de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(message)(Vg_UserMsg,
310de4a1d01951937632098a6cda45859afa587a06fsewardj         "epoch %d (bb %luk): thresh %d, "
311de4a1d01951937632098a6cda45859afa587a06fsewardj         "out %d (%dk -> %dk), new TT %d, TC %dk",
312de4a1d01951937632098a6cda45859afa587a06fsewardj         VG_(current_epoch),
313de4a1d01951937632098a6cda45859afa587a06fsewardj         VG_(bbs_done) / 1000,
314de4a1d01951937632098a6cda45859afa587a06fsewardj         VG_(current_epoch) - thresh,
315de4a1d01951937632098a6cda45859afa587a06fsewardj         VG_(this_epoch_out_count),
316de4a1d01951937632098a6cda45859afa587a06fsewardj         VG_(this_epoch_out_osize) / 1000,
317de4a1d01951937632098a6cda45859afa587a06fsewardj         VG_(this_epoch_out_tsize) / 1000,
318de4a1d01951937632098a6cda45859afa587a06fsewardj         vg_tt_used, vg_tc_used / 1000
319de4a1d01951937632098a6cda45859afa587a06fsewardj      );
320de4a1d01951937632098a6cda45859afa587a06fsewardj
32118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#  ifdef DEBUG_TRANSTAB
32218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   for (i = 0; i < VG_TT_SIZE; i++)
32318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      vg_assert(vg_tt[i].orig_addr != VG_TTE_DELETED);
32418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#  endif
32518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   VG_(sanity_check_tc_tt)();
326de4a1d01951937632098a6cda45859afa587a06fsewardj
327e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn   VGP_POPCC(VgpDoLRU);
328de4a1d01951937632098a6cda45859afa587a06fsewardj}
329de4a1d01951937632098a6cda45859afa587a06fsewardj
330de4a1d01951937632098a6cda45859afa587a06fsewardj
331de4a1d01951937632098a6cda45859afa587a06fsewardj/* Do a sanity check on TT/TC.
332de4a1d01951937632098a6cda45859afa587a06fsewardj*/
333de4a1d01951937632098a6cda45859afa587a06fsewardjvoid VG_(sanity_check_tc_tt) ( void )
334de4a1d01951937632098a6cda45859afa587a06fsewardj{
335de4a1d01951937632098a6cda45859afa587a06fsewardj   Int      i, counted_entries, counted_bytes;
336de4a1d01951937632098a6cda45859afa587a06fsewardj   TTEntry* tte;
337de4a1d01951937632098a6cda45859afa587a06fsewardj   counted_entries = 0;
338de4a1d01951937632098a6cda45859afa587a06fsewardj   counted_bytes   = 0;
339de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 0; i < VG_TT_SIZE; i++) {
340de4a1d01951937632098a6cda45859afa587a06fsewardj      tte = &vg_tt[i];
341de4a1d01951937632098a6cda45859afa587a06fsewardj      if (tte->orig_addr == VG_TTE_EMPTY) continue;
342de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_assert(tte->mru_epoch >= 0);
343de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_assert(tte->mru_epoch <= VG_(current_epoch));
344de4a1d01951937632098a6cda45859afa587a06fsewardj      counted_entries++;
345de4a1d01951937632098a6cda45859afa587a06fsewardj      counted_bytes += 4+tte->trans_size;
346de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_assert(tte->trans_addr >= (Addr)&vg_tc[4]);
347de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_assert(tte->trans_addr < (Addr)&vg_tc[vg_tc_used]);
348de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_assert(VG_READ_MISALIGNED_WORD(tte->trans_addr-4) == i);
349de4a1d01951937632098a6cda45859afa587a06fsewardj   }
350de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(counted_entries == vg_tt_used);
351de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(counted_bytes == vg_tc_used);
352de4a1d01951937632098a6cda45859afa587a06fsewardj}
353de4a1d01951937632098a6cda45859afa587a06fsewardj
354de4a1d01951937632098a6cda45859afa587a06fsewardj
355de4a1d01951937632098a6cda45859afa587a06fsewardj/* Add this already-filled-in entry to the TT.  Assumes that the
356de4a1d01951937632098a6cda45859afa587a06fsewardj   relevant code chunk has been placed in TC, along with a dummy back
357de4a1d01951937632098a6cda45859afa587a06fsewardj   pointer, which is inserted here.
358de4a1d01951937632098a6cda45859afa587a06fsewardj*/
359de4a1d01951937632098a6cda45859afa587a06fsewardjextern void VG_(add_to_trans_tab) ( TTEntry* tte )
360de4a1d01951937632098a6cda45859afa587a06fsewardj{
361de4a1d01951937632098a6cda45859afa587a06fsewardj   Int i;
362de4a1d01951937632098a6cda45859afa587a06fsewardj   /*
363de4a1d01951937632098a6cda45859afa587a06fsewardj   VG_(printf)("add_to_trans_tab(%d) %x %d %x %d\n",
364de4a1d01951937632098a6cda45859afa587a06fsewardj               vg_tt_used, tte->orig_addr, tte->orig_size,
365de4a1d01951937632098a6cda45859afa587a06fsewardj               tte->trans_addr, tte->trans_size);
366de4a1d01951937632098a6cda45859afa587a06fsewardj   */
367de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(tte->orig_addr != VG_TTE_DELETED
368de4a1d01951937632098a6cda45859afa587a06fsewardj             && tte->orig_addr != VG_TTE_EMPTY);
369de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Hash to get initial probe point. */
370de4a1d01951937632098a6cda45859afa587a06fsewardj   i = ((UInt)(tte->orig_addr)) % VG_TT_SIZE;
371de4a1d01951937632098a6cda45859afa587a06fsewardj   while (True) {
372de4a1d01951937632098a6cda45859afa587a06fsewardj      if (vg_tt[i].orig_addr == tte->orig_addr)
373de4a1d01951937632098a6cda45859afa587a06fsewardj         VG_(panic)("add_to_trans_tab: duplicate");
37418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      if (vg_tt[i].orig_addr == VG_TTE_EMPTY) {
375de4a1d01951937632098a6cda45859afa587a06fsewardj         /* Put it here, and set the back pointer. */
376de4a1d01951937632098a6cda45859afa587a06fsewardj         vg_tt[i] = *tte;
377de4a1d01951937632098a6cda45859afa587a06fsewardj         VG_WRITE_MISALIGNED_WORD(tte->trans_addr-4, i);
378de4a1d01951937632098a6cda45859afa587a06fsewardj         vg_tt_used++;
379de4a1d01951937632098a6cda45859afa587a06fsewardj         return;
380de4a1d01951937632098a6cda45859afa587a06fsewardj      }
381de4a1d01951937632098a6cda45859afa587a06fsewardj      i++;
382de4a1d01951937632098a6cda45859afa587a06fsewardj      if (i == VG_TT_SIZE) i = 0;
383de4a1d01951937632098a6cda45859afa587a06fsewardj   }
384de4a1d01951937632098a6cda45859afa587a06fsewardj}
385de4a1d01951937632098a6cda45859afa587a06fsewardj
386de4a1d01951937632098a6cda45859afa587a06fsewardj
387de4a1d01951937632098a6cda45859afa587a06fsewardj/* Copy a new translation's code into TC, leaving a 4-byte hole for
388de4a1d01951937632098a6cda45859afa587a06fsewardj   the back pointer, and returning a pointer to the code proper (not
389de4a1d01951937632098a6cda45859afa587a06fsewardj   the hole) in TC.
390de4a1d01951937632098a6cda45859afa587a06fsewardj*/
391de4a1d01951937632098a6cda45859afa587a06fsewardjAddr VG_(copy_to_transcache) ( Addr trans_addr, Int trans_size )
392de4a1d01951937632098a6cda45859afa587a06fsewardj{
393de4a1d01951937632098a6cda45859afa587a06fsewardj   Int i;
394de4a1d01951937632098a6cda45859afa587a06fsewardj   Addr ret_addr;
395de4a1d01951937632098a6cda45859afa587a06fsewardj   if (4+trans_size > VG_TC_SIZE-vg_tc_used)
396de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(panic)("copy_to_transcache: not enough free space?!");
397de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Leave a hole for the back pointer to the TT entry. */
398de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_tc_used += 4;
399de4a1d01951937632098a6cda45859afa587a06fsewardj   ret_addr = (Addr)&vg_tc[vg_tc_used];
400de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 0; i < trans_size; i++)
401de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_tc[vg_tc_used+i] = ((UChar*)trans_addr)[i];
402de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_tc_used += trans_size;
403de4a1d01951937632098a6cda45859afa587a06fsewardj   return ret_addr;
404de4a1d01951937632098a6cda45859afa587a06fsewardj}
405de4a1d01951937632098a6cda45859afa587a06fsewardj
406de4a1d01951937632098a6cda45859afa587a06fsewardj
407de4a1d01951937632098a6cda45859afa587a06fsewardj/* Invalidate the tt_fast cache, for whatever reason.  Tricky.  We
408de4a1d01951937632098a6cda45859afa587a06fsewardj   have to find a TTE_EMPTY slot to point all entries at. */
409de4a1d01951937632098a6cda45859afa587a06fsewardjvoid VG_(invalidate_tt_fast)( void )
410de4a1d01951937632098a6cda45859afa587a06fsewardj{
411de4a1d01951937632098a6cda45859afa587a06fsewardj   Int i, j;
412de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 0; i < VG_TT_SIZE && vg_tt[i].orig_addr != VG_TTE_EMPTY; i++)
413de4a1d01951937632098a6cda45859afa587a06fsewardj      ;
414de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(i < VG_TT_SIZE
415de4a1d01951937632098a6cda45859afa587a06fsewardj             && vg_tt[i].orig_addr == VG_TTE_EMPTY);
416de4a1d01951937632098a6cda45859afa587a06fsewardj   for (j = 0; j < VG_TT_FAST_SIZE; j++)
417de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(tt_fast)[j] = (Addr)&vg_tt[i];
418de4a1d01951937632098a6cda45859afa587a06fsewardj}
419de4a1d01951937632098a6cda45859afa587a06fsewardj
420de4a1d01951937632098a6cda45859afa587a06fsewardj
421de4a1d01951937632098a6cda45859afa587a06fsewardj/* Search TT to find the translated address of the supplied original,
422de4a1d01951937632098a6cda45859afa587a06fsewardj   or NULL if not found.  This routine is used when we miss in
423de4a1d01951937632098a6cda45859afa587a06fsewardj   VG_(tt_fast).
424de4a1d01951937632098a6cda45859afa587a06fsewardj*/
425de4a1d01951937632098a6cda45859afa587a06fsewardjstatic __inline__ TTEntry* search_trans_table ( Addr orig_addr )
426de4a1d01951937632098a6cda45859afa587a06fsewardj{
42718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   //static Int queries = 0;
42818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   //static Int probes = 0;
429de4a1d01951937632098a6cda45859afa587a06fsewardj   Int i;
430de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Hash to get initial probe point. */
431de4a1d01951937632098a6cda45859afa587a06fsewardj   //   if (queries == 10000) {
432de4a1d01951937632098a6cda45859afa587a06fsewardj   //  VG_(printf)("%d queries, %d probes\n", queries, probes);
433de4a1d01951937632098a6cda45859afa587a06fsewardj   //  queries = probes = 0;
434de4a1d01951937632098a6cda45859afa587a06fsewardj   //}
435de4a1d01951937632098a6cda45859afa587a06fsewardj   //queries++;
436de4a1d01951937632098a6cda45859afa587a06fsewardj   i = ((UInt)orig_addr) % VG_TT_SIZE;
437de4a1d01951937632098a6cda45859afa587a06fsewardj   while (True) {
43818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      //probes++;
439de4a1d01951937632098a6cda45859afa587a06fsewardj      if (vg_tt[i].orig_addr == orig_addr)
440de4a1d01951937632098a6cda45859afa587a06fsewardj         return &vg_tt[i];
441de4a1d01951937632098a6cda45859afa587a06fsewardj      if (vg_tt[i].orig_addr == VG_TTE_EMPTY)
442de4a1d01951937632098a6cda45859afa587a06fsewardj         return NULL;
443de4a1d01951937632098a6cda45859afa587a06fsewardj      i++;
444de4a1d01951937632098a6cda45859afa587a06fsewardj      if (i == VG_TT_SIZE) i = 0;
445de4a1d01951937632098a6cda45859afa587a06fsewardj   }
446de4a1d01951937632098a6cda45859afa587a06fsewardj}
447de4a1d01951937632098a6cda45859afa587a06fsewardj
448de4a1d01951937632098a6cda45859afa587a06fsewardj
449de4a1d01951937632098a6cda45859afa587a06fsewardj/* Find the translation address for a given (original) code address.
450de4a1d01951937632098a6cda45859afa587a06fsewardj   If found, update VG_(tt_fast) so subsequent lookups are fast.  If
451de4a1d01951937632098a6cda45859afa587a06fsewardj   no translation can be found, return zero.  This routine is (the
452de4a1d01951937632098a6cda45859afa587a06fsewardj   only one) called from vg_run_innerloop.  */
453de4a1d01951937632098a6cda45859afa587a06fsewardjAddr VG_(search_transtab) ( Addr original_addr )
454de4a1d01951937632098a6cda45859afa587a06fsewardj{
455de4a1d01951937632098a6cda45859afa587a06fsewardj   TTEntry* tte;
456de4a1d01951937632098a6cda45859afa587a06fsewardj   VGP_PUSHCC(VgpSlowFindT);
457de4a1d01951937632098a6cda45859afa587a06fsewardj   tte = search_trans_table ( original_addr );
458de4a1d01951937632098a6cda45859afa587a06fsewardj   if (tte == NULL) {
459de4a1d01951937632098a6cda45859afa587a06fsewardj      /* We didn't find it.  vg_run_innerloop will have to request a
460de4a1d01951937632098a6cda45859afa587a06fsewardj         translation. */
461e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn      VGP_POPCC(VgpSlowFindT);
462de4a1d01951937632098a6cda45859afa587a06fsewardj      return (Addr)0;
463de4a1d01951937632098a6cda45859afa587a06fsewardj   } else {
464de4a1d01951937632098a6cda45859afa587a06fsewardj      /* Found it.  Put the search result into the fast cache now.
465de4a1d01951937632098a6cda45859afa587a06fsewardj         Also set the mru_epoch to mark this translation as used. */
466de4a1d01951937632098a6cda45859afa587a06fsewardj      UInt cno = (UInt)original_addr & VG_TT_FAST_MASK;
467de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(tt_fast)[cno] = (Addr)tte;
468de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(tt_fast_misses)++;
469de4a1d01951937632098a6cda45859afa587a06fsewardj      tte->mru_epoch = VG_(current_epoch);
470e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn      VGP_POPCC(VgpSlowFindT);
471de4a1d01951937632098a6cda45859afa587a06fsewardj      return tte->trans_addr;
472de4a1d01951937632098a6cda45859afa587a06fsewardj   }
473de4a1d01951937632098a6cda45859afa587a06fsewardj}
474de4a1d01951937632098a6cda45859afa587a06fsewardj
475de4a1d01951937632098a6cda45859afa587a06fsewardj
47618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* Invalidate translations of original code [start .. start + range - 1].
47718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   This is slow, so you *really* don't want to call it very often.
478de4a1d01951937632098a6cda45859afa587a06fsewardj*/
47918d7513cc08bf982711c8a22b70d56af6aa87b33sewardjvoid VG_(invalidate_translations) ( Addr start, UInt range )
480de4a1d01951937632098a6cda45859afa587a06fsewardj{
48118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   Addr  i_start, i_end, o_start, o_end;
48218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   UInt  out_count, out_osize, out_tsize;
48318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   Int   i;
484de4a1d01951937632098a6cda45859afa587a06fsewardj
48518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#  ifdef DEBUG_TRANSTAB
48618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   VG_(sanity_check_tc_tt)();
487de4a1d01951937632098a6cda45859afa587a06fsewardj#  endif
48818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   i_start = start;
48918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   i_end   = start + range - 1;
49018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   out_count = out_osize = out_tsize = 0;
491de4a1d01951937632098a6cda45859afa587a06fsewardj
49218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   for (i = 0; i < VG_TT_SIZE; i++) {
49318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      if (vg_tt[i].orig_addr == VG_TTE_EMPTY
49418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj          || vg_tt[i].orig_addr == VG_TTE_DELETED) continue;
49518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      o_start = vg_tt[i].orig_addr;
49618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      o_end = o_start + vg_tt[i].orig_size - 1;
49718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      if (o_end < i_start || o_start > i_end)
49818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         continue;
499e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn
500e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn      if (VG_(needs).basic_block_discards)
501e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn         SK_(discard_basic_block_info)( vg_tt[i].orig_addr,
502e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn                                         vg_tt[i].orig_size );
503e49d8e7dfd3a9c96feb9935b5920973dfc0b170anjn
50418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      vg_tt[i].orig_addr = VG_TTE_DELETED;
50518d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      VG_(this_epoch_out_count) ++;
50618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      VG_(this_epoch_out_osize) += vg_tt[i].orig_size;
50718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      VG_(this_epoch_out_tsize) += vg_tt[i].trans_size;
50818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      VG_(overall_out_count) ++;
50918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      VG_(overall_out_osize) += vg_tt[i].orig_size;
51018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      VG_(overall_out_tsize) += vg_tt[i].trans_size;
51118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      out_count ++;
51218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      out_osize += vg_tt[i].orig_size;
51318d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      out_tsize += vg_tt[i].trans_size;
514de4a1d01951937632098a6cda45859afa587a06fsewardj   }
515de4a1d01951937632098a6cda45859afa587a06fsewardj
51618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   if (out_count > 0) {
51718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      VG_(invalidate_tt_fast)();
51818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      VG_(sanity_check_tc_tt)();
51918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#     ifdef DEBUG_TRANSTAB
52018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      { Addr aa;
52118d7513cc08bf982711c8a22b70d56af6aa87b33sewardj        for (aa = i_start; aa <= i_end; aa++)
52218d7513cc08bf982711c8a22b70d56af6aa87b33sewardj           vg_assert(search_trans_table ( aa ) == NULL);
523de4a1d01951937632098a6cda45859afa587a06fsewardj      }
52418d7513cc08bf982711c8a22b70d56af6aa87b33sewardj#     endif
525de4a1d01951937632098a6cda45859afa587a06fsewardj   }
526de4a1d01951937632098a6cda45859afa587a06fsewardj
52718d7513cc08bf982711c8a22b70d56af6aa87b33sewardj   if (1|| VG_(clo_verbosity) > 1)
52818d7513cc08bf982711c8a22b70d56af6aa87b33sewardj      VG_(message)(Vg_UserMsg,
52918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         "discard %d (%d -> %d) translations in range %p .. %p",
53018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         out_count, out_osize, out_tsize, i_start, i_end );
531de4a1d01951937632098a6cda45859afa587a06fsewardj}
532de4a1d01951937632098a6cda45859afa587a06fsewardj
533de4a1d01951937632098a6cda45859afa587a06fsewardj
534de4a1d01951937632098a6cda45859afa587a06fsewardj/*------------------------------------------------------------*/
535de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- Initialisation.                                      ---*/
536de4a1d01951937632098a6cda45859afa587a06fsewardj/*------------------------------------------------------------*/
537de4a1d01951937632098a6cda45859afa587a06fsewardj
53818d7513cc08bf982711c8a22b70d56af6aa87b33sewardjvoid VG_(init_tt_tc) ( void )
539de4a1d01951937632098a6cda45859afa587a06fsewardj{
540de4a1d01951937632098a6cda45859afa587a06fsewardj   Int i;
541de4a1d01951937632098a6cda45859afa587a06fsewardj
542de4a1d01951937632098a6cda45859afa587a06fsewardj   /* Allocate the translation table and translation cache. */
543de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(vg_tc == NULL);
544e90479594359d19ca51884c7936073dd7bd7d9c6sewardj   vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar),
545e90479594359d19ca51884c7936073dd7bd7d9c6sewardj                                       "trans-cache" );
546de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(vg_tc != NULL);
547de4a1d01951937632098a6cda45859afa587a06fsewardj
548de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(vg_tt == NULL);
549e90479594359d19ca51884c7936073dd7bd7d9c6sewardj   vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry),
550e90479594359d19ca51884c7936073dd7bd7d9c6sewardj                                       "trans-table" );
551de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_assert(vg_tt != NULL);
552de4a1d01951937632098a6cda45859afa587a06fsewardj
553de4a1d01951937632098a6cda45859afa587a06fsewardj   /* The main translation table is empty. */
554de4a1d01951937632098a6cda45859afa587a06fsewardj   vg_tt_used = 0;
555de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 0; i < VG_TT_SIZE; i++) {
556de4a1d01951937632098a6cda45859afa587a06fsewardj      vg_tt[i].orig_addr = VG_TTE_EMPTY;
557de4a1d01951937632098a6cda45859afa587a06fsewardj   }
558de4a1d01951937632098a6cda45859afa587a06fsewardj
559de4a1d01951937632098a6cda45859afa587a06fsewardj   /* The translation table's fast cache is empty.  Point all entries
560de4a1d01951937632098a6cda45859afa587a06fsewardj      at the first TT entry, which is, of course, empty. */
561de4a1d01951937632098a6cda45859afa587a06fsewardj   for (i = 0; i < VG_TT_FAST_SIZE; i++)
562de4a1d01951937632098a6cda45859afa587a06fsewardj      VG_(tt_fast)[i] = (Addr)(&vg_tt[0]);
563de4a1d01951937632098a6cda45859afa587a06fsewardj}
564de4a1d01951937632098a6cda45859afa587a06fsewardj
565de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
566de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- end                                            vg_transtab.c ---*/
567de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
568