m_transtab.c revision 924c852b5883a7b42298dc8c7542116bd9a8a485
1de4a1d01951937632098a6cda45859afa587a06fsewardj
2de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
3de4a1d01951937632098a6cda45859afa587a06fsewardj/*--- Management of the translation table and cache.               ---*/
48bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*---                                                 m_transtab.c ---*/
5de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
6de4a1d01951937632098a6cda45859afa587a06fsewardj
7de4a1d01951937632098a6cda45859afa587a06fsewardj/*
8b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn   This file is part of Valgrind, a dynamic binary instrumentation
9b9c427c63a278cc612ae0ec573be7bb1abaa447fnjn   framework.
10de4a1d01951937632098a6cda45859afa587a06fsewardj
110f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj   Copyright (C) 2000-2013 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
32c7561b931e249acf3768ead77638545b0ccaa8f1njn#include "pub_core_basics.h"
3345f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_debuglog.h"
34291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_machine.h"    // For VG_(machine_get_VexArchInfo)
3597405b2d134b52880d6dbec3eb2929e2002c2542njn#include "pub_core_libcbase.h"
36291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_vki.h"        // to keep pub_core_libproc.h happy, sigh
37291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_libcproc.h"   // VG_(invalidate_icache)
38132bfccd21960e462352175f8553a5bdce8a210cnjn#include "pub_core_libcassert.h"
3936a20fa5f779a0a6fb7b4a90dcaa6376481f1faanjn#include "pub_core_libcprint.h"
402024234c590f408994b373abfb00bc2cd2a90c48njn#include "pub_core_options.h"
4110f08cf5b84882eebbb6712a7be890577650e8adsewardj#include "pub_core_tooliface.h"  // For VG_(details).avg_translation_sizeB
428bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn#include "pub_core_transtab.h"
4345f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_aspacemgr.h"
4445f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_core_mallocfree.h" // VG_(out_of_memory_NORETURN)
45291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_xarray.h"
46291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#include "pub_core_dispatch.h"   // For VG_(disp_cp*) addresses
4759570ffbe31930ab4d678754daaeec0715117a3dsewardj
4859570ffbe31930ab4d678754daaeec0715117a3dsewardj
493a5322057616d0da214b9e0f897866e203c03e40philippe#define DEBUG_TRANSTAB 0
5018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj
51de4a1d01951937632098a6cda45859afa587a06fsewardj
526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/
536c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*--- Management of the FIFO-based translation table+cache. ---*/
546c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/
55de4a1d01951937632098a6cda45859afa587a06fsewardj
568e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/* Nr of sectors provided via command line parameter. */
578e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippeUInt VG_(clo_num_transtab_sectors) = N_SECTORS_DEFAULT;
588e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/* Nr of sectors.
598e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   Will be set by VG_(init_tt_tc) to VG_(clo_num_transtab_sectors). */
60a11ec17946cdbafb336e9121b64961c0633af2e7sewardjstatic UInt n_sectors = 0;
61de4a1d01951937632098a6cda45859afa587a06fsewardj
62924c852b5883a7b42298dc8c7542116bd9a8a485philippe/* Average size of a transtab code entry. 0 means to use the tool
63924c852b5883a7b42298dc8c7542116bd9a8a485philippe   provided default. */
64924c852b5883a7b42298dc8c7542116bd9a8a485philippeUInt VG_(clo_avg_transtab_entry_size) = 0;
65924c852b5883a7b42298dc8c7542116bd9a8a485philippe
668e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe/*------------------ CONSTANTS ------------------*/
67fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of TC entries in each sector.  This needs to be a prime
686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   number to work properly, it must be <= 65535 (so that a TT index
696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   fits in a UShort, leaving room for 0xFFFF(EC2TTE_DELETED) to denote
706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   'deleted') and it is strongly recommended not to change this.
716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   65521 is the largest prime <= 65535. */
72e25053c5aaefc6a4039dcd557adf24d8bb23db69sewardj#define N_TTES_PER_SECTOR /*10007*/ /*30011*/ /*40009*/ 65521
73de4a1d01951937632098a6cda45859afa587a06fsewardj
74fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to
75fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   specify the maximum allowable loading, after which the sector is
76fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   deemed full. */
775d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj#define SECTOR_TT_LIMIT_PERCENT 65
78de4a1d01951937632098a6cda45859afa587a06fsewardj
79fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */
80fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR_USABLE \
81fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj           ((N_TTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100)
826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Equivalence classes for fast address range deletion.  There are 1 +
846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   2^ECLASS_WIDTH bins.  The highest one, ECLASS_MISC, describes an
856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range which does not fall cleanly within any specific bin.
866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Note that ECLASS_SHIFT + ECLASS_WIDTH must be < 32. */
876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_SHIFT 11
886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_WIDTH 8
896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_MISC  (1 << ECLASS_WIDTH)
906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_N     (1 + ECLASS_MISC)
916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define EC2TTE_DELETED  0xFFFF /* 16-bit special value */
936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
94de4a1d01951937632098a6cda45859afa587a06fsewardj
956c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/
96de4a1d01951937632098a6cda45859afa587a06fsewardj
97291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* In edges ("to-me") in the graph created by chaining. */
98291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
99291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
100291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_sNo;   /* sector number */
101291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_tteNo; /* TTE number in given sector */
102291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_offs;  /* code offset from TCEntry::tcptr where the patch is */
103291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Bool to_fastEP;  /* Is the patch to a fast or slow entry point? */
104291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
105291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge;
106291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
107291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
108291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Out edges ("from-me") in the graph created by chaining. */
109291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
110291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
111291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt to_sNo;    /* sector number */
112291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt to_tteNo;  /* TTE number in given sector */
113291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_offs; /* code offset in owning translation where patch is */
114291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
115291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge;
116291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
117291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
118291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_IN_EDGE_ARR 3
119291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
120291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
121291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt     n_fixed; /* 0 .. N_FIXED_IN_EDGE_ARR */
122291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdge   fixed[N_FIXED_IN_EDGE_ARR];
123291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray*  var; /* XArray* of InEdgeArr */
124291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
125291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr;
126291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
127291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_OUT_EDGE_ARR 2
128291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
129291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
130291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt    n_fixed; /* 0 .. N_FIXED_OUT_EDGE_ARR */
131291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdge fixed[N_FIXED_OUT_EDGE_ARR];
132291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* var; /* XArray* of OutEdgeArr */
133291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
134291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr;
135291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
136291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
137fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry.  This indicates precisely which areas of
138fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   guest code are included in the translation, and contains all other
139fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   auxiliary info too.  */
1406c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef
1416c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   struct {
142fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Profiling only: the count and weight (arbitrary meaning) for
143fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         this translation.  Weight is a property of the translation
144fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         itself and computed once when the translation is created.
145fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         Count is an entry count for the translation and is
146fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         incremented by 1 every time the translation is used, if we
147fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         are profiling. */
148291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      ULong    count;
149fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      UShort   weight;
150fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
151fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Status of the slot.  Note, we need to be able to do lazy
152fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         deletion, hence the Deleted state. */
153fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      enum { InUse, Deleted, Empty } status;
154fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1555f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      /* 64-bit aligned pointer to one or more 64-bit words containing
1565f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         the corresponding host code (must be in the same sector!)
1575f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         This is a pointer into the sector's tc (code) area. */
1585f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      ULong* tcptr;
159fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
160fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This is the original guest address that purportedly is the
161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         entry point of the translation.  You might think that .entry
162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         should be the same as .vge->base[0], and most of the time it
163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         is.  However, when doing redirections, that is not the case.
164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         .vge must always correctly describe the guest code sections
165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         from which this translation was made.  However, .entry may or
166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         may not be a lie, depending on whether or not we're doing
167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         redirection. */
168ddd61ff058f02059064e083a8accaefed23d5548florian      Addr entry;
169fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
170fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This structure describes precisely what ranges of guest code
171fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         the translation covers, so we can decide whether or not to
172fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         delete it when translations of a given address range are
173fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         invalidated. */
174fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VexGuestExtents vge;
1756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Address range summary info: these are pointers back to
1776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclass[] entries in the containing Sector.  Those entries in
1786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         turn point back here -- the two structures are mutually
1796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         redundant but both necessary to make fast deletions work.
1806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         The eclass info is similar to, and derived from, this entry's
1816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         'vge' field, but it is not the same */
1826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort n_tte2ec;      // # tte2ec pointers (1 to 3)
1836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort tte2ec_ec[3];  // for each, the eclass #
1846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UInt   tte2ec_ix[3];  // and the index within the eclass.
1856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // for i in 0 .. n_tte2ec-1
1866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      //    sec->ec2tte[ tte2ec_ec[i] ][ tte2ec_ix[i] ]
1876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // should be the index
1886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // of this TTEntry in the containing Sector's tt array.
189291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
190291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Admin information for chaining.  'in_edges' is a set of the
191291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         patch points which jump to this translation -- hence are
192291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         predecessors in the control flow graph.  'out_edges' points
193291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         to successors in the control flow graph -- translations to
194291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         which this one has a patched jump.  In short these are just
195291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         backwards and forwards edges in the graph of patched-together
196291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         blocks.  The 'in_edges' contain slightly more info, enough
197291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         that we can undo the chaining of each mentioned patch point.
198291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The 'out_edges' list exists only so that we can visit the
199291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         'in_edges' entries of all blocks we're patched through to, in
200291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         order to remove ourselves from then when we're deleted. */
201291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
202291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* A translation can disappear for two reasons:
203291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          1. erased (as part of the oldest sector cleanup) when the
204291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             youngest sector is full.
205291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          2. discarded due to calls to VG_(discard_translations).
206291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             VG_(discard_translations) sets the status of the
207291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             translation to 'Deleted'.
208291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             A.o., the gdbserver discards one or more translations
209291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             when a breakpoint is inserted or removed at an Addr,
210291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             or when single stepping mode is enabled/disabled
211291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             or when a translation is instrumented for gdbserver
212291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             (all the target jumps of this translation are
213291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj              invalidated).
214291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
215291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         So, it is possible that the translation A to be patched
216291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (to obtain a patched jump from A to B) is invalidated
217291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         after B is translated and before A is patched.
218291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         In case a translation is erased or discarded, the patching
219291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         cannot be done.  VG_(tt_tc_do_chaining) and find_TTEntry_from_hcode
220291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         are checking the 'from' translation still exists before
221291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         doing the patching.
222291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
223291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Is it safe to erase or discard the current translation E being
224291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         executed ? Amazing, but yes, it is safe.
225291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Here is the explanation:
226291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
227291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The translation E being executed can only be erased if a new
228291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation N is being done. A new translation is done only
229291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if the host addr is a not yet patched jump to another
230291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation. In such a case, the guest address of N is
231291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         assigned to the PC in the VEX state. Control is returned
232291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         to the scheduler. N will be translated. This can erase the
233291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation E (in case of sector full). VG_(tt_tc_do_chaining)
234291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         will not do the chaining to a non found translation E.
235291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The execution will continue at the current guest PC
236291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (i.e. the translation N).
237291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         => it is safe to erase the current translation being executed.
238291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
239291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The current translation E being executed can also be discarded
240291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (e.g. by gdbserver). VG_(discard_translations) will mark
241291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         this translation E as Deleted, but the translation itself
242291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         is not erased. In particular, its host code can only
243291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         be overwritten or erased in case a new translation is done.
244291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         A new translation will only be done if a not yet translated
245291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         jump is to be executed. The execution of the Deleted translation
246291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         E will continue till a non patched jump is encountered.
247291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         This situation is then similar to the 'erasing' case above :
248291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         the current translation E can be erased or overwritten, as the
249291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         execution will continue at the new translation N.
250291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
251291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      */
252291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
253291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* It is possible, although very unlikely, that a block A has
254291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         more than one patched jump to block B.  This could happen if
255291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (eg) A finishes "jcond B; jmp B".
256291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
257291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         This means in turn that B's in_edges set can list A more than
258291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         once (twice in this example).  However, each such entry must
259291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         have a different from_offs, since a patched jump can only
260291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         jump to one place at once (it's meaningless for it to have
261291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         multiple destinations.)  IOW, the successor and predecessor
262291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         edges in the graph are not uniquely determined by a
263291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         TTEntry --> TTEntry pair, but rather by a
264291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (TTEntry,offset) --> TTEntry triple.
265291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
266291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         If A has multiple edges to B then B will mention A multiple
267291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         times in its in_edges.  To make things simpler, we then
268291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         require that A mentions B exactly the same number of times in
269291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         its out_edges.  Furthermore, a matching out-in pair must have
270291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         the same offset (from_offs).  This facilitates sanity
271291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         checking, and it facilitates establishing the invariant that
272291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         a out_edges set may not have duplicates when using the
273291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         equality defined by (TTEntry,offset).  Hence the out_edges
274291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         and in_edges sets really do have both have set semantics.
275291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
276291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         eg if  A has been patched to B at offsets 42 and 87 (in A)
277291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         then   A.out_edges = { (B,42), (B,87) }   (in any order)
278291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         and    B.in_edges  = { (A,42), (A,87) }   (in any order)
279291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
280291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Hence for each node pair P->Q in the graph, there's a 1:1
281291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         mapping between P.out_edges and Q.in_edges.
282291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      */
283291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdgeArr  in_edges;
284291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdgeArr out_edges;
2856c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
2866c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   TTEntry;
2876c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
2884ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
289291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* A structure used for mapping host code addresses back to the
290291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   relevant TTEntry.  Used when doing chaining, for finding the
291291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry to which some arbitrary patch address belongs. */
292291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
293291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
294291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* start;
295291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt   len;
296291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt   tteNo;
297291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
298291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HostExtent;
299291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
300fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself.  Each sector contains an array of
301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   TCEntries, which hold code, and an array of TTEntries, containing
302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   all required administrative info.  Profiling is supported using the
303291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry .count and .weight fields, if required.
3044ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
305fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   If the sector is not in use, all three pointers are NULL and
306fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_n_inuse is zero.
307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef
309fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   struct {
310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TCEntry area.  Size of this depends on the average
311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         translation size.  We try and size it so it becomes full
312fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         precisely when this sector's translation table (tt) reaches
313fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         its load limit (SECTOR_TT_LIMIT_PERCENT). */
314fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc;
3154ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
316fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TTEntry array.  This is a fixed size, always containing
317fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         exactly N_TTES_PER_SECTOR entries. */
318fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      TTEntry* tt;
3196c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
320fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This points to the current allocation point in tc. */
321fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc_next;
322de4a1d01951937632098a6cda45859afa587a06fsewardj
323fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The count of tt entries with state InUse. */
324fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Int tt_n_inuse;
3256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Expandable arrays of tt indices for each of the ECLASS_N
3276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         address range equivalence classes.  These hold indices into
3286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         the containing sector's tt array, which in turn should point
3296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         back here. */
3306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_size[ECLASS_N];
3316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_used[ECLASS_N];
3326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort* ec2tte[ECLASS_N];
333291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
334291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* The host extents.  The [start, +len) ranges are constructed
335291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         in strictly non-overlapping order, so we can binary search
336291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         them at any time. */
337291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* host_extents; /* XArray* of HostExtent */
338fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
339fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Sector;
340de4a1d01951937632098a6cda45859afa587a06fsewardj
341de4a1d01951937632098a6cda45859afa587a06fsewardj
3426c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/
3436c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
344fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors.  The index of the
345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest sector is recorded, and new translations are put into that
346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.  When it fills up, we move along to the next sector and
347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   start to fill that up, wrapping around at the end of the array.
348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   That way, once all N_TC_SECTORS have been bought into use for the
349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   first time, and are full, we then re-use the oldest sector,
350fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   endlessly.
351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
352fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   When running, youngest sector should be between >= 0 and <
353fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   N_TC_SECTORS.  The initial -1 value indicates the TT/TC system is
354fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   not yet initialised.
355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
3568e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippestatic Sector sectors[MAX_N_SECTORS];
357fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int    youngest_sector = -1;
3586c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
359fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area.  This is computed once
360fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   at startup and does not change. */
361a11ec17946cdbafb336e9121b64961c0633af2e7sewardjstatic Int    tc_sector_szQ = 0;
3626c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3636c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3645d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj/* A list of sector numbers, in the order which they should be
3655d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   searched to find translations.  This is an optimisation to be used
3665d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   when searching for translations and should not affect
3675d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   correctness.  -1 denotes "no entry". */
3688e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippestatic Int sector_search_order[MAX_N_SECTORS];
3695d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
3705d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
3715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Fast helper for the TC.  A direct-mapped cache which holds a set of
3725f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   recently used (guest address, host address) pairs.  This array is
3735f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   referred to directly from m_dispatch/dispatch-<platform>.S.
3746c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3755f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   Entries in tt_fast may refer to any valid TC entry, regardless of
376fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   which sector it's in.  Consequently we must be very careful to
377fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidate this cache when TC entries are changed or disappear.
378c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
3795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be
3805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   pointed at to cause that cache entry to miss.  This relies on the
3815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   assumption that no guest code actually has that address, hence a
3825f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   value 0x1 seems good.  m_translate gives the client a synthetic
3835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   segfault if it tries to execute at this address.
3845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
3855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*
3865f76de086a6d643db51e50a4e623df7dfc9b6161sewardjtypedef
3875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   struct {
3885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr guest;
3895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr host;
3905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
3915f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   FastCacheEntry;
3925f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
3935f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*global*/ __attribute__((aligned(16)))
3945f76de086a6d643db51e50a4e623df7dfc9b6161sewardj           FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE];
395de4a1d01951937632098a6cda45859afa587a06fsewardj
396663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */
397663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False;
398663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
399663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
400fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/
401de4a1d01951937632098a6cda45859afa587a06fsewardj
402fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */
403291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_flushes = 0;
404291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_updates = 0;
40522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
406fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */
407291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_full_lookups = 0;
408291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_lookup_probes = 0;
40922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
41026412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of
41126412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   those for which self-checking was requested. */
412291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_count    = 0;
413291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_osize    = 0;
414291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_tsize    = 0;
415291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_sc_count = 0;
416de4a1d01951937632098a6cda45859afa587a06fsewardj
417fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */
418291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_count = 0;
419291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_osize = 0;
4205e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippestatic ULong n_sectors_recycled = 0;
421fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
422fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */
423291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_count = 0;
424291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_osize = 0;
425291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
426291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
427291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
428291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Misc                                                  ---*/
429291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
430291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
43154fe2021b87b9e5edb8ec8070f47b86d5cafb8aaflorianstatic void* ttaux_malloc ( const HChar* tag, SizeT n )
432291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
433291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return VG_(arena_malloc)(VG_AR_TTAUX, tag, n);
434291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
435291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
436291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void ttaux_free ( void* p )
437291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
438291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(arena_free)(VG_AR_TTAUX, p);
439291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
440291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
441291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
442291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
443291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Chaining support                                      ---*/
444291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
445291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
446291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic inline TTEntry* index_tte ( UInt sNo, UInt tteNo )
447291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
4488e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   vg_assert(sNo < n_sectors);
449291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(tteNo < N_TTES_PER_SECTOR);
450291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Sector* s = &sectors[sNo];
451291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(s->tt);
452291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* tte = &s->tt[tteNo];
453291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(tte->status == InUse);
454291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return tte;
455291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
456291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
457291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdge__init ( InEdge* ie )
458291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
459291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_sNo   = -1; /* invalid */
460291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_tteNo = 0;
461291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_offs  = 0;
462291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->to_fastEP  = False;
463291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
464291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
465291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdge__init ( OutEdge* oe )
466291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
467291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->to_sNo    = -1; /* invalid */
468291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->to_tteNo  = 0;
469291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->from_offs = 0;
470291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
471291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
472291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void TTEntry__init ( TTEntry* tte )
473291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
474291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(memset)(tte, 0, sizeof(*tte));
475291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
476291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
477518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UWord InEdgeArr__size ( const InEdgeArr* iea )
478291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
479291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
480291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
481291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return VG_(sizeXA)(iea->var);
482291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
483291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
484291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return iea->n_fixed;
485291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
486291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
487291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
488291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdgeArr__makeEmpty ( InEdgeArr* iea )
489291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
490291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
491291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
492291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(deleteXA)(iea->var);
493291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->var = NULL;
494291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
495291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
496291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->n_fixed = 0;
497291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
498291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
499291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
500291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
501291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjInEdge* InEdgeArr__index ( InEdgeArr* iea, UWord i )
502291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
503291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
504291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
505291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return (InEdge*)VG_(indexXA)(iea->var, i);
506291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
507291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < iea->n_fixed);
508291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return &iea->fixed[i];
509291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
510291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
511291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
512291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
513291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__deleteIndex ( InEdgeArr* iea, UWord i )
514291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
515291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
516291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
517291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(removeIndexXA)(iea->var, i);
518291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
519291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < iea->n_fixed);
520291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (; i+1 < iea->n_fixed; i++) {
521291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->fixed[i] = iea->fixed[i+1];
522291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
523291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->n_fixed--;
524291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
525291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
526291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
527291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
528291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__add ( InEdgeArr* iea, InEdge* ie )
529291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
530291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
531291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
532291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(addToXA)(iea->var, ie);
533291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
534291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
535291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (iea->n_fixed == N_FIXED_IN_EDGE_ARR) {
536291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* The fixed array is full, so we have to initialise an
537291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            XArray and copy the fixed array into it. */
538291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->var = VG_(newXA)(ttaux_malloc, "transtab.IEA__add",
539291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               ttaux_free,
540291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               sizeof(InEdge));
541291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UWord i;
542291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         for (i = 0; i < iea->n_fixed; i++) {
543291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            VG_(addToXA)(iea->var, &iea->fixed[i]);
544291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         }
545291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         VG_(addToXA)(iea->var, ie);
546291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->n_fixed = 0;
547291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      } else {
548291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Just add to the fixed array. */
549291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->fixed[iea->n_fixed++] = *ie;
550291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
551291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
552291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
553291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
554518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UWord OutEdgeArr__size ( const OutEdgeArr* oea )
555291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
556291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
557291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
558291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return VG_(sizeXA)(oea->var);
559291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
560291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
561291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return oea->n_fixed;
562291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
563291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdgeArr__makeEmpty ( OutEdgeArr* oea )
566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
568291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
569291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(deleteXA)(oea->var);
570291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->var = NULL;
571291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
572291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
573291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->n_fixed = 0;
574291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
575291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
576291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
577291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
578291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjOutEdge* OutEdgeArr__index ( OutEdgeArr* oea, UWord i )
579291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
580291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
582291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return (OutEdge*)VG_(indexXA)(oea->var, i);
583291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
584291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < oea->n_fixed);
585291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return &oea->fixed[i];
586291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
587291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
588291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
589291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
590291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__deleteIndex ( OutEdgeArr* oea, UWord i )
591291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
592291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
593291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
594291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(removeIndexXA)(oea->var, i);
595291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
596291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < oea->n_fixed);
597291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (; i+1 < oea->n_fixed; i++) {
598291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->fixed[i] = oea->fixed[i+1];
599291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
600291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->n_fixed--;
601291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
602291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
603291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
604291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
605291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__add ( OutEdgeArr* oea, OutEdge* oe )
606291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
607291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
608291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
609291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(addToXA)(oea->var, oe);
610291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
611291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
612291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (oea->n_fixed == N_FIXED_OUT_EDGE_ARR) {
613291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* The fixed array is full, so we have to initialise an
614291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            XArray and copy the fixed array into it. */
615291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->var = VG_(newXA)(ttaux_malloc, "transtab.OEA__add",
616291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               ttaux_free,
617291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               sizeof(OutEdge));
618291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UWord i;
619291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         for (i = 0; i < oea->n_fixed; i++) {
620291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            VG_(addToXA)(oea->var, &oea->fixed[i]);
621291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         }
622291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         VG_(addToXA)(oea->var, oe);
623291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->n_fixed = 0;
624291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      } else {
625291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Just add to the fixed array. */
626291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->fixed[oea->n_fixed++] = *oe;
627291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
628291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
629291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
630291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
631291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
6326bd9dc18c043927c1196caba20a327238a179c42florianInt HostExtent__cmpOrd ( const void* v1, const void* v2 )
633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
6346bd9dc18c043927c1196caba20a327238a179c42florian   const HostExtent* hx1 = v1;
6356bd9dc18c043927c1196caba20a327238a179c42florian   const HostExtent* hx2 = v2;
636291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (hx1->start + hx1->len <= hx2->start) return -1;
637291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (hx2->start + hx2->len <= hx1->start) return 1;
638291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return 0; /* partial overlap */
639291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
640291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
6413a5322057616d0da214b9e0f897866e203c03e40philippe/* True if hx is a dead host extent, i.e. corresponds to host code
6423a5322057616d0da214b9e0f897866e203c03e40philippe   of an entry that was invalidated. */
6433a5322057616d0da214b9e0f897866e203c03e40philippestatic
6443a5322057616d0da214b9e0f897866e203c03e40philippeBool HostExtent__is_dead (const HostExtent* hx, const Sector* sec)
6453a5322057616d0da214b9e0f897866e203c03e40philippe{
6463a5322057616d0da214b9e0f897866e203c03e40philippe   const UInt tteNo = hx->tteNo;
6473a5322057616d0da214b9e0f897866e203c03e40philippe#define LDEBUG(m) if (DEBUG_TRANSTAB)                           \
6483a5322057616d0da214b9e0f897866e203c03e40philippe      VG_(printf) (m                                            \
6493a5322057616d0da214b9e0f897866e203c03e40philippe                   " start 0x%p len %u sector %d ttslot %u"     \
650ddd61ff058f02059064e083a8accaefed23d5548florian                   " tt.entry 0x%lu tt.tcptr 0x%p\n",           \
6513a5322057616d0da214b9e0f897866e203c03e40philippe                   hx->start, hx->len, (int)(sec - sectors),    \
6523a5322057616d0da214b9e0f897866e203c03e40philippe                   hx->tteNo,                                   \
6533a5322057616d0da214b9e0f897866e203c03e40philippe                   sec->tt[tteNo].entry, sec->tt[tteNo].tcptr)
6543a5322057616d0da214b9e0f897866e203c03e40philippe
6553a5322057616d0da214b9e0f897866e203c03e40philippe   /* Entry might have been invalidated and not re-used yet.*/
6563a5322057616d0da214b9e0f897866e203c03e40philippe   if (sec->tt[tteNo].status == Deleted) {
6573a5322057616d0da214b9e0f897866e203c03e40philippe      LDEBUG("found deleted entry");
6583a5322057616d0da214b9e0f897866e203c03e40philippe      return True;
6593a5322057616d0da214b9e0f897866e203c03e40philippe   }
6603a5322057616d0da214b9e0f897866e203c03e40philippe   /* Maybe we found this entry via a host_extents which was
6613a5322057616d0da214b9e0f897866e203c03e40philippe      inserted for an entry which was changed to Deleted then
6623a5322057616d0da214b9e0f897866e203c03e40philippe      re-used after. If this entry was re-used, then its tcptr
6633a5322057616d0da214b9e0f897866e203c03e40philippe      is >= to host_extents start (i.e. the previous tcptr) + len.
6643a5322057616d0da214b9e0f897866e203c03e40philippe      This is the case as there is no re-use of host code: a new
6653a5322057616d0da214b9e0f897866e203c03e40philippe      entry or re-used entry always gets "higher value" host code. */
6663a5322057616d0da214b9e0f897866e203c03e40philippe   if ((UChar*) sec->tt[tteNo].tcptr >= hx->start + hx->len) {
6673a5322057616d0da214b9e0f897866e203c03e40philippe      LDEBUG("found re-used entry");
6683a5322057616d0da214b9e0f897866e203c03e40philippe      return True;
6693a5322057616d0da214b9e0f897866e203c03e40philippe   }
6703a5322057616d0da214b9e0f897866e203c03e40philippe
6713a5322057616d0da214b9e0f897866e203c03e40philippe   return False;
6723a5322057616d0da214b9e0f897866e203c03e40philippe#undef LDEBUG
6733a5322057616d0da214b9e0f897866e203c03e40philippe}
6743a5322057616d0da214b9e0f897866e203c03e40philippe
675291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic __attribute__((noinline))
676291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool find_TTEntry_from_hcode( /*OUT*/UInt* from_sNo,
677291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              /*OUT*/UInt* from_tteNo,
678291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              void* hcode )
679291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
680291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int i;
681291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
682291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Search order logic copied from VG_(search_transtab). */
6838e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
684291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Int sno = sector_search_order[i];
685291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (UNLIKELY(sno == -1))
686291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return False; /* run out of sectors to search */
687291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
688518850bf0da07ed3e2244e307268ae0fd80e93a8florian      const Sector* sec = &sectors[sno];
689518850bf0da07ed3e2244e307268ae0fd80e93a8florian      const XArray* /* of HostExtent */ host_extents = sec->host_extents;
690291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(host_extents);
691291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
692291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      HostExtent key;
693291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(memset)(&key, 0, sizeof(key));
694291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      key.start = hcode;
695291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      key.len = 1;
696291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Word firstW = -1, lastW = -1;
697291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Bool found  = VG_(lookupXA_UNSAFE)(
698291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       host_extents, &key, &firstW, &lastW,
6996bd9dc18c043927c1196caba20a327238a179c42florian                       HostExtent__cmpOrd );
700291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(firstW == lastW); // always true, even if not found
701291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (found) {
702291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         HostExtent* hx = VG_(indexXA)(host_extents, firstW);
703291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UInt tteNo = hx->tteNo;
704291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Do some additional sanity checks. */
705291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert(tteNo <= N_TTES_PER_SECTOR);
7063a5322057616d0da214b9e0f897866e203c03e40philippe
7073a5322057616d0da214b9e0f897866e203c03e40philippe         /* if this hx entry corresponds to dead host code, we must
7083a5322057616d0da214b9e0f897866e203c03e40philippe            tell this code has not been found, as it cannot be patched. */
7093a5322057616d0da214b9e0f897866e203c03e40philippe         if (HostExtent__is_dead (hx, sec))
710291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            return False;
7113a5322057616d0da214b9e0f897866e203c03e40philippe
712291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert(sec->tt[tteNo].status == InUse);
713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Can only half check that the found TTEntry contains hcode,
714291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            due to not having a length value for the hcode in the
715291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            TTEntry. */
716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert((UChar*)sec->tt[tteNo].tcptr <= (UChar*)hcode);
717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Looks plausible */
718291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         *from_sNo   = sno;
719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         *from_tteNo = (UInt)tteNo;
720291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return True;
721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
722291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
723291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return False;
724291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
725291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
726291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
727291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Figure out whether or not hcode is jitted code present in the main
728291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   code cache (but not in the no-redir cache).  Used for sanity
729291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   checking. */
730518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool is_in_the_main_TC ( const void* hcode )
731291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
732291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int i, sno;
7338e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
734291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sno = sector_search_order[i];
735291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (sno == -1)
736291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         break; /* run out of sectors to search */
737518850bf0da07ed3e2244e307268ae0fd80e93a8florian      if ((const UChar*)hcode >= (const UChar*)sectors[sno].tc
738518850bf0da07ed3e2244e307268ae0fd80e93a8florian          && (const UChar*)hcode <= (const UChar*)sectors[sno].tc_next
739291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              + sizeof(ULong) - 1)
740291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return True;
741291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
742291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return False;
743291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
744291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
745291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
746291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Fulfill a chaining request, and record admin info so we
747291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   can undo it later, if required.
748291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj*/
749291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid VG_(tt_tc_do_chaining) ( void* from__patch_addr,
750291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              UInt  to_sNo,
751291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              UInt  to_tteNo,
752291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              Bool  to_fastEP )
753291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
754291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Get the CPU info established at startup. */
755597314210494248b4fbefd45525a748439629218sewardj   VexArch     arch_host = VexArch_INVALID;
756597314210494248b4fbefd45525a748439629218sewardj   VexArchInfo archinfo_host;
757597314210494248b4fbefd45525a748439629218sewardj   VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host));
758597314210494248b4fbefd45525a748439629218sewardj   VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host );
759597314210494248b4fbefd45525a748439629218sewardj   VexEndness endness_host = archinfo_host.endness;
760291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
761291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // host_code is where we're patching to.  So it needs to
762291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // take into account, whether we're jumping to the slow
763291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // or fast entry point.  By definition, the fast entry point
764291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // is exactly one event check's worth of code along from
765291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // the slow (tcptr) entry point.
766291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* to_tte    = index_tte(to_sNo, to_tteNo);
767291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   void*    host_code = ((UChar*)to_tte->tcptr)
7685f8ced84fdd6ebd260cece49b51477c68437e8caflorian                        + (to_fastEP ? LibVEX_evCheckSzB(arch_host) : 0);
769291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
770291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // stay sane -- the patch point (dst) is in this sector's code cache
771291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( (UChar*)host_code >= (UChar*)sectors[to_sNo].tc );
772291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( (UChar*)host_code <= (UChar*)sectors[to_sNo].tc_next
773291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                   + sizeof(ULong) - 1 );
774291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
775291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Find the TTEntry for the from__ code.  This isn't simple since
776291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      we only know the patch address, which is going to be somewhere
777291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      inside the from_ block. */
778291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UInt from_sNo   = (UInt)-1;
779291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UInt from_tteNo = (UInt)-1;
780291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Bool from_found
781291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = find_TTEntry_from_hcode( &from_sNo, &from_tteNo,
782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                 from__patch_addr );
783291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (!from_found) {
784291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // The from code might have been discarded due to sector re-use
785291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // or marked Deleted due to translation invalidation.
786291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // In such a case, don't do the chaining.
787291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(debugLog)(1,"transtab",
788291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    "host code %p not found (discarded? sector recycled?)"
789291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    " => no chaining done\n",
790291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    from__patch_addr);
791291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return;
792291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
793291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
794291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* from_tte = index_tte(from_sNo, from_tteNo);
795291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
796291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Get VEX to do the patching itself.  We have to hand it off
797291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      since it is host-dependent. */
798291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexInvalRange vir
799291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = LibVEX_Chain(
800597314210494248b4fbefd45525a748439629218sewardj           arch_host, endness_host,
801291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           from__patch_addr,
802291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           VG_(fnptr_to_fnentry)(
803291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj              to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP)
804291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                        : &VG_(disp_cp_chain_me_to_slowEP)),
805291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           (void*)host_code
806291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        );
807291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( (void*)vir.start, vir.len );
808291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
809291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Now do the tricky bit -- update the ch_succs and ch_preds info
810291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for the two translations involved, so we can undo the chaining
811291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      later, which we will have to do if the to_ block gets removed
812291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for whatever reason. */
813291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
814291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* This is the new from_ -> to_ link to add. */
815291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge ie;
816291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge__init(&ie);
817291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_sNo   = from_sNo;
818291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_tteNo = from_tteNo;
819291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.to_fastEP  = to_fastEP;
820291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HWord from_offs = (HWord)( (UChar*)from__patch_addr
821291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              - (UChar*)from_tte->tcptr );
822291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(from_offs < 100000/* let's say */);
823291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_offs  = (UInt)from_offs;
824291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
825291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* This is the new to_ -> from_ backlink to add. */
826291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge oe;
827291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge__init(&oe);
828291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.to_sNo    = to_sNo;
829291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.to_tteNo  = to_tteNo;
830291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.from_offs = (UInt)from_offs;
831291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
832291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Add .. */
833291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr__add(&to_tte->in_edges, &ie);
834291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr__add(&from_tte->out_edges, &oe);
835291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
836291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
837291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
838291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Unchain one patch, as described by the specified InEdge.  For
839291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   sanity check purposes only (to check that the patched location is
840291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   as expected) it also requires the fast and slow entry point
841291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   addresses of the destination block (that is, the block that owns
842291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   this InEdge). */
843291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj__attribute__((noinline))
844597314210494248b4fbefd45525a748439629218sewardjstatic void unchain_one ( VexArch arch_host, VexEndness endness_host,
845291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          InEdge* ie,
846291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          void* to_fastEPaddr, void* to_slowEPaddr )
847291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
848291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(ie);
849291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* tte
850291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = index_tte(ie->from_sNo, ie->from_tteNo);
851291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* place_to_patch
85219f91bbaedb4caef8a60ce94b0f507193cc0bc10florian      = ((UChar*)tte->tcptr) + ie->from_offs;
853291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* disp_cp_chain_me
854291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = VG_(fnptr_to_fnentry)(
855291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           ie->to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP)
856291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         : &VG_(disp_cp_chain_me_to_slowEP)
857291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        );
858291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* place_to_jump_to_EXPECTED
859291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = ie->to_fastEP ? to_fastEPaddr : to_slowEPaddr;
860291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
861291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // stay sane: both src and dst for this unchaining are
862291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // in the main code cache
863291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( is_in_the_main_TC(place_to_patch) ); // src
864291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( is_in_the_main_TC(place_to_jump_to_EXPECTED) ); // dst
865291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // dst check is ok because LibVEX_UnChain checks that
866291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // place_to_jump_to_EXPECTED really is the current dst, and
867291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // asserts if it isn't.
868291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexInvalRange vir
869597314210494248b4fbefd45525a748439629218sewardj       = LibVEX_UnChain( arch_host, endness_host, place_to_patch,
870291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         place_to_jump_to_EXPECTED, disp_cp_chain_me );
871291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( (void*)vir.start, vir.len );
872291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
873291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
874291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
875291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* The specified block is about to be deleted.  Update the preds and
876291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   succs of its associated blocks accordingly.  This includes undoing
877291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   any chained jumps to this block. */
878291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
879597314210494248b4fbefd45525a748439629218sewardjvoid unchain_in_preparation_for_deletion ( VexArch arch_host,
880597314210494248b4fbefd45525a748439629218sewardj                                           VexEndness endness_host,
881291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                           UInt here_sNo, UInt here_tteNo )
882291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
8833a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB)
8843a5322057616d0da214b9e0f897866e203c03e40philippe      VG_(printf)("QQQ unchain_in_prep %u.%u...\n", here_sNo, here_tteNo);
885291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UWord    i, j, n, m;
8865f8ced84fdd6ebd260cece49b51477c68437e8caflorian   Int      evCheckSzB = LibVEX_evCheckSzB(arch_host);
887291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* here_tte   = index_tte(here_sNo, here_tteNo);
8883a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB)
889ddd61ff058f02059064e083a8accaefed23d5548florian      VG_(printf)("... QQQ tt.entry 0x%lu tt.tcptr 0x%p\n",
8903a5322057616d0da214b9e0f897866e203c03e40philippe                  here_tte->entry, here_tte->tcptr);
891291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(here_tte->status == InUse);
892291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
893291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Visit all InEdges owned by here_tte. */
894291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   n = InEdgeArr__size(&here_tte->in_edges);
895291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < n; i++) {
896291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdge* ie = InEdgeArr__index(&here_tte->in_edges, i);
897291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Undo the chaining.
898291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* here_slow_EP = (UChar*)here_tte->tcptr;
899291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* here_fast_EP = here_slow_EP + evCheckSzB;
900597314210494248b4fbefd45525a748439629218sewardj      unchain_one(arch_host, endness_host, ie, here_fast_EP, here_slow_EP);
901291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Find the corresponding entry in the "from" node's out_edges,
902291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // and remove it.
903291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      TTEntry* from_tte = index_tte(ie->from_sNo, ie->from_tteNo);
904291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      m = OutEdgeArr__size(&from_tte->out_edges);
905291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(m > 0); // it must have at least one entry
906291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (j = 0; j < m; j++) {
907291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         OutEdge* oe = OutEdgeArr__index(&from_tte->out_edges, j);
908291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (oe->to_sNo == here_sNo && oe->to_tteNo == here_tteNo
909291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             && oe->from_offs == ie->from_offs)
910291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           break;
911291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
912291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(j < m); // "oe must be findable"
913291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdgeArr__deleteIndex(&from_tte->out_edges, j);
914291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
915291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
916291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Visit all OutEdges owned by here_tte. */
917291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   n = OutEdgeArr__size(&here_tte->out_edges);
918291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < n; i++) {
919291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdge* oe = OutEdgeArr__index(&here_tte->out_edges, i);
920291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Find the corresponding entry in the "to" node's in_edges,
921291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // and remove it.
922291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      TTEntry* to_tte = index_tte(oe->to_sNo, oe->to_tteNo);
923291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      m = InEdgeArr__size(&to_tte->in_edges);
924291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(m > 0); // it must have at least one entry
925291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (j = 0; j < m; j++) {
926291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         InEdge* ie = InEdgeArr__index(&to_tte->in_edges, j);
927291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (ie->from_sNo == here_sNo && ie->from_tteNo == here_tteNo
928291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             && ie->from_offs == oe->from_offs)
929291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           break;
930291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
931291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(j < m); // "ie must be findable"
932291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdgeArr__deleteIndex(&to_tte->in_edges, j);
933291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
934291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
935291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr__makeEmpty(&here_tte->in_edges);
936291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr__makeEmpty(&here_tte->out_edges);
937291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
938fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
939fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
9406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
9416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Address-range equivalence class stuff                 ---*/
9426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
9436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Return equivalence class number for a range. */
9456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
946ddd61ff058f02059064e083a8accaefed23d5548florianstatic Int range_to_eclass ( Addr start, UInt len )
9476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
9486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt mask   = (1 << ECLASS_WIDTH) - 1;
9496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt lo     = (UInt)start;
9506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hi     = lo + len - 1;
9516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt loBits = (lo >> ECLASS_SHIFT) & mask;
9526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hiBits = (hi >> ECLASS_SHIFT) & mask;
9536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (loBits == hiBits) {
9546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(loBits < ECLASS_N-1);
9556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return loBits;
9566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
9576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return ECLASS_MISC;
9586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
9606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Calculates the equivalence class numbers for any VexGuestExtent.
9636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   These are written in *eclasses, which must be big enough to hold 3
9646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Ints.  The number written, between 1 and 3, is returned.  The
9656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses are presented in order, and any duplicates are removed.
9666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj*/
9676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
9696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjInt vexGuestExtents_to_eclasses ( /*OUT*/Int* eclasses,
970518850bf0da07ed3e2244e307268ae0fd80e93a8florian                                  const VexGuestExtents* vge )
9716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
972518850bf0da07ed3e2244e307268ae0fd80e93a8florian
9736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define SWAP(_lv1,_lv2) \
9746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      do { Int t = _lv1; _lv1 = _lv2; _lv2 = t; } while (0)
9756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, j, n_ec, r;
9776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
9796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_ec = 0;
9816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < vge->n_used; i++) {
982ddd61ff058f02059064e083a8accaefed23d5548florian      r = range_to_eclass( vge->base[i], vge->len[i] );
9836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (r == ECLASS_MISC)
9846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         goto bad;
9856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* only add if we haven't already seen it */
9866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < n_ec; j++)
9876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (eclasses[j] == r)
9886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            break;
9896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (j == n_ec)
9906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclasses[n_ec++] = r;
9916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 1)
9946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 1;
9956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 2) {
9976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
9986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
9996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
10006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 2;
10016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 3) {
10046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
10056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[2])
10066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[2]);
10076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
10086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
10096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[1] > eclasses[2])
10106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[1], eclasses[2]);
10116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 3;
10126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* NOTREACHED */
10156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(0);
10166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
10186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses[0] = ECLASS_MISC;
10196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return 1;
10206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef SWAP
10226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Add tteno to the set of entries listed for equivalence class ec in
10266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   this sector.  Returns used location in eclass array. */
10276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
10296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjUInt addEClassNo ( /*MOD*/Sector* sec, Int ec, UShort tteno )
10306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int    old_sz, new_sz, i, r;
10326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort *old_ar, *new_ar;
10336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
10356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno < N_TTES_PER_SECTOR);
10366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10373a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB) VG_(printf)("ec %d  gets %d\n", ec, (Int)tteno);
10386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->ec2tte_used[ec] >= sec->ec2tte_size[ec]) {
10406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->ec2tte_used[ec] == sec->ec2tte_size[ec]);
10426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_sz = sec->ec2tte_size[ec];
10446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_ar = sec->ec2tte[ec];
10456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      new_sz = old_sz==0 ? 8 : old_sz<64 ? 2*old_sz : (3*old_sz)/2;
1046291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      new_ar = ttaux_malloc("transtab.aECN.1",
1047291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                            new_sz * sizeof(UShort));
10486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < old_sz; i++)
10496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         new_ar[i] = old_ar[i];
10506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (old_ar)
1051291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         ttaux_free(old_ar);
10526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte_size[ec] = new_sz;
10536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec] = new_ar;
10546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10553a5322057616d0da214b9e0f897866e203c03e40philippe      if (DEBUG_TRANSTAB) VG_(printf)("expand ec %d to %d\n", ec, new_sz);
10566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Common case */
10596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = sec->ec2tte_used[ec]++;
10606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 0 && r < sec->ec2tte_size[ec]);
10616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->ec2tte[ec][r] = tteno;
10626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return (UInt)r;
10636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* 'vge' is being added to 'sec' at TT entry 'tteno'.  Add appropriate
10676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclass entries to 'sec'. */
10686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
10706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjvoid upd_eclasses_after_add ( /*MOD*/Sector* sec, Int tteno )
10716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, r, eclasses[3];
10736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
10746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
10756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
10776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = vexGuestExtents_to_eclasses( eclasses, &tte->vge );
10786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 1 && r <= 3);
10806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = r;
10816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < r; i++) {
10836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte->tte2ec_ec[i] = eclasses[i];
10846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte->tte2ec_ix[i] = addEClassNo( sec, eclasses[i], (UShort)tteno );
10856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Check the eclass info in 'sec' to ensure it is consistent.  Returns
10906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   True if OK, False if something's not right.  Expensive. */
10916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1092518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic Bool sanity_check_eclasses_in_sector ( const Sector* sec )
10936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define BAD(_str) do { whassup = (_str); goto bad; } while (0)
10956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10966bd9dc18c043927c1196caba20a327238a179c42florian   const HChar* whassup = NULL;
10976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, j, k, n, ec_num, ec_idx;
10986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
10996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort   tteno;
11006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ULong*   tce;
11016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Basic checks on this sector */
11036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->tt_n_inuse < 0 || sec->tt_n_inuse > N_TTES_PER_SECTOR_USABLE)
11046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("invalid sec->tt_n_inuse");
11056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tce = sec->tc_next;
11066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tce < &sec->tc[0] || tce > &sec->tc[tc_sector_szQ])
11076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("sec->tc_next points outside tc");
11086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* For each eclass ... */
11106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < ECLASS_N; i++) {
11116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] == 0 && sec->ec2tte[i] != NULL)
11126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(1)");
11136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] != 0 && sec->ec2tte[i] == NULL)
11146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(2)");
11156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] < 0
11166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          || sec->ec2tte_used[i] > sec->ec2tte_size[i])
11176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("implausible ec2tte_used");
11186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] == 0)
11196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
11206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* For each tt reference in each eclass .. ensure the reference
11226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         is to a valid tt entry, and that the entry's address ranges
11236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         really include this eclass. */
11246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < sec->ec2tte_used[i]; j++) {
11266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tteno = sec->ec2tte[i][j];
11276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno == EC2TTE_DELETED)
11286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
11296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno >= N_TTES_PER_SECTOR)
11306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("implausible tteno");
11316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tte = &sec->tt[tteno];
11326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->status != InUse)
11336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno points to non-inuse tte");
11346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
11356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_tte2ec out of range");
11366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* Exactly least one of tte->eclasses[0 .. tte->n_eclasses-1]
11376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            must equal i.  Inspect tte's eclass info. */
11386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         n = 0;
11396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (k = 0; k < tte->n_tte2ec; k++) {
11406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (k < tte->n_tte2ec-1
11416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                && tte->tte2ec_ec[k] >= tte->tte2ec_ec[k+1])
11426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of order");
11436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_num = tte->tte2ec_ec[k];
11446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num < 0 || ec_num >= ECLASS_N)
11456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of range");
11466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num != i)
11476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
11486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_idx = tte->tte2ec_ix[k];
11496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[i])
11506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ix[..] out of range");
11516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx == j)
11526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               n++;
11536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
11546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (n != 1)
11556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno does not point back at eclass");
11566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* That establishes that for each forward pointer from TTEntrys
11606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      there is a corresponding backward pointer from the eclass[]
11616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      arrays.  However, it doesn't rule out the possibility of other,
11626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      bogus pointers in the eclass[] arrays.  So do those similarly:
11636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      scan through them and check the TTEntryies they point at point
11646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      back. */
11656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < N_TTES_PER_SECTOR_USABLE; i++) {
11676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte = &sec->tt[i];
11696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->status == Empty || tte->status == Deleted) {
11706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec != 0)
11716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_eclasses nonzero for unused tte");
11726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
11736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
11766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
11786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("tte->n_eclasses out of range(2)");
11796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < tte->n_tte2ec; j++) {
11816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_num = tte->tte2ec_ec[j];
11826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_num < 0 || ec_num >= ECLASS_N)
11836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->eclass[..] out of range");
11846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_idx = tte->tte2ec_ix[j];
11856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[ec_num])
11866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->ec_idx[..] out of range(2)");
11876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->ec2tte[ec_num][ec_idx] != i)
11886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("ec2tte does not point back to tte");
11896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
11936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
11956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (whassup)
11966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(0, "transtab", "eclass sanity fail: %s\n", whassup);
11976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  if 0
11996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("eclass = %d\n", i);
12006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("tteno = %d\n", (Int)tteno);
12016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   switch (tte->status) {
12026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case InUse:   VG_(printf)("InUse\n"); break;
12036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Deleted: VG_(printf)("Deleted\n"); break;
12046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Empty:   VG_(printf)("Empty\n"); break;
12056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
12066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tte->status != Empty) {
12076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (k = 0; k < tte->vge.n_used; k++)
1208ddd61ff058f02059064e083a8accaefed23d5548florian         VG_(printf)("0x%lx %u\n", tte->vge.base[k], (UInt)tte->vge.len[k]);
12096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
12106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  endif
12116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return False;
12136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef BAD
12156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
12166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Sanity check absolutely everything.  True == check passed. */
12196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
12205f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* forwards */
12210ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void );
12220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
12235d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Bool sanity_check_sector_search_order ( void )
12245d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj{
12255d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   Int i, j, nListed;
12265d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* assert the array is the right size */
12278e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   vg_assert(MAX_N_SECTORS == (sizeof(sector_search_order)
12288e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe                               / sizeof(sector_search_order[0])));
12295d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check it's of the form  valid_sector_numbers ++ [-1, -1, ..] */
12308e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
12318e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      if (sector_search_order[i] < 0 || sector_search_order[i] >= n_sectors)
12325d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         break;
12335d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12345d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   nListed = i;
12358e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (/* */; i < n_sectors; i++) {
12365d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sector_search_order[i] != -1)
12375d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         break;
12385d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12398e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   if (i != n_sectors)
12405d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
12415d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check each sector number only appears once */
12428e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
12435d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sector_search_order[i] == -1)
12445d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         continue;
12458e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (j = i+1; j < n_sectors; j++) {
12465d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[j] == sector_search_order[i])
12475d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            return False;
12485d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
12495d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12505d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check that the number of listed sectors equals the number
12515d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      in use, by counting nListed back down. */
12528e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
12535d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sectors[i].tc != NULL)
12545d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         nListed--;
12555d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12565d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if (nListed != 0)
12575d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
12585d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   return True;
12595d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj}
12605d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
12616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_all_sectors ( void )
12626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
12636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int     sno;
12646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    sane;
12656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
12668e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (sno = 0; sno < n_sectors; sno++) {
12673a5322057616d0da214b9e0f897866e203c03e40philippe      Int i;
12683a5322057616d0da214b9e0f897866e203c03e40philippe      Int nr_not_dead_hx = 0;
12693a5322057616d0da214b9e0f897866e203c03e40philippe      Int szhxa;
12706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec = &sectors[sno];
12716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tc == NULL)
12726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
12736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sane = sanity_check_eclasses_in_sector( sec );
12746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (!sane)
12756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         return False;
12763a5322057616d0da214b9e0f897866e203c03e40philippe      szhxa = VG_(sizeXA)(sec->host_extents);
12773a5322057616d0da214b9e0f897866e203c03e40philippe      for (i = 0; i < szhxa; i++) {
12783a5322057616d0da214b9e0f897866e203c03e40philippe         const HostExtent* hx = VG_(indexXA)(sec->host_extents, i);
12793a5322057616d0da214b9e0f897866e203c03e40philippe         if (!HostExtent__is_dead (hx, sec))
12803a5322057616d0da214b9e0f897866e203c03e40philippe            nr_not_dead_hx++;
12813a5322057616d0da214b9e0f897866e203c03e40philippe      }
12823a5322057616d0da214b9e0f897866e203c03e40philippe      if (nr_not_dead_hx != sec->tt_n_inuse) {
12833a5322057616d0da214b9e0f897866e203c03e40philippe         VG_(debugLog)(0, "transtab",
12843a5322057616d0da214b9e0f897866e203c03e40philippe                       "nr_not_dead_hx %d sanity fail (expected == in use %d)\n",
12853a5322057616d0da214b9e0f897866e203c03e40philippe                       nr_not_dead_hx, sec->tt_n_inuse);
12863a5322057616d0da214b9e0f897866e203c03e40philippe         return False;
12873a5322057616d0da214b9e0f897866e203c03e40philippe      }
12886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
12893a5322057616d0da214b9e0f897866e203c03e40philippe
12905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if ( !sanity_check_redir_tt_tc() )
12915f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      return False;
12925d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if ( !sanity_check_sector_search_order() )
12935d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
12946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
12956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
12966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
12985d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1299fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
13006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Add/find translations                                 ---*/
1301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
1302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1303518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic UInt vge_osize ( const VexGuestExtents* vge )
1304c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{
1305fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt i, n = 0;
1306fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < vge->n_used; i++)
1307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n += (UInt)vge->len[i];
1308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n;
1309c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
1310c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
1311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool isValidSector ( Int sector )
13126c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
13138e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   if (sector < 0 || sector >= n_sectors)
1314fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1315fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
13166c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1317de4a1d01951937632098a6cda45859afa587a06fsewardj
1318ddd61ff058f02059064e083a8accaefed23d5548florianstatic inline UInt HASH_TT ( Addr key )
1319de4a1d01951937632098a6cda45859afa587a06fsewardj{
1320ddd61ff058f02059064e083a8accaefed23d5548florian   UInt kHi = sizeof(Addr) == 4 ? 0 : (key >> 32);
1321fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kLo = (UInt)key;
13226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt k32 = kHi ^ kLo;
13236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt ror = 7;
13246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ror > 0)
13256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      k32 = (k32 >> ror) | (k32 << (32-ror));
13266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return k32 % N_TTES_PER_SECTOR;
1327de4a1d01951937632098a6cda45859afa587a06fsewardj}
1328de4a1d01951937632098a6cda45859afa587a06fsewardj
1329ddd61ff058f02059064e083a8accaefed23d5548florianstatic void setFastCacheEntry ( Addr key, ULong* tcptr )
1330de4a1d01951937632098a6cda45859afa587a06fsewardj{
13313387dda4479102751d544c176a7bfc24f3766669sewardj   UInt cno = (UInt)VG_TT_FAST_HASH(key);
1332ddd61ff058f02059064e083a8accaefed23d5548florian   VG_(tt_fast)[cno].guest = key;
13335f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   VG_(tt_fast)[cno].host  = (Addr)tcptr;
1334fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_updates++;
13355f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This shouldn't fail.  It should be assured by m_translate
13365f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      which should reject any attempt to make translation of code
13375f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      starting at TRANSTAB_BOGUS_GUEST_ADDR. */
13385f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR);
13396c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1340de4a1d01951937632098a6cda45859afa587a06fsewardj
1341291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Invalidate the fast cache VG_(tt_fast). */
13425f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastCache ( void )
13435f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{
13445f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   UInt j;
13455f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This loop is popular enough to make it worth unrolling a
13465f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      bit, at least on ppc32. */
13475f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0);
13485f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   for (j = 0; j < VG_TT_FAST_SIZE; j += 4) {
13495f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR;
13505f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR;
13515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR;
13525f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR;
13535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
13545f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
13555f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(j == VG_TT_FAST_SIZE);
1356fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_flushes++;
13576c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1358de4a1d01951937632098a6cda45859afa587a06fsewardj
1359fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void initialiseSector ( Int sno )
13606c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1361291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int     i;
1362291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   SysRes  sres;
13636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
1364fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(sno));
1365fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
13665d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   { Bool sane = sanity_check_sector_search_order();
13675d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj     vg_assert(sane);
13685d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
13696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec = &sectors[sno];
13706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
13716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->tc == NULL) {
13726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1373fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Sector has never been used before.  Need to allocate tt and
1374fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         tc. */
13756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt == NULL);
13766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next == NULL);
13776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt_n_inuse == 0);
13786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
13796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_size[i] == 0);
13806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_used[i] == 0);
13816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte[i] == NULL);
13826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
1383291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(sec->host_extents == NULL);
138445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
13855e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe      if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1)
1386059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj         VG_(dmsg)("transtab: " "allocate sector %d\n", sno);
138745f4e7c91119c7d01a59f5e827c67841632c9314sewardj
138845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ );
1389cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
139045f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TC)",
139145f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     8 * tc_sector_szQ );
139245f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
139345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
139444bd4465581ff28cef83bb39e684a489297d7b71florian      sec->tc = (ULong*)(Addr)sr_Res(sres);
139545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
139645f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)
139745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                ( N_TTES_PER_SECTOR * sizeof(TTEntry) );
1398cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
139945f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TT)",
140045f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     N_TTES_PER_SECTOR * sizeof(TTEntry) );
140145f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
140245f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
140344bd4465581ff28cef83bb39e684a489297d7b71florian      sec->tt = (TTEntry*)(Addr)sr_Res(sres);
14046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
14056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
14066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].status   = Empty;
14076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].n_tte2ec = 0;
14086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
140945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1410291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Set up the host_extents array. */
1411291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sec->host_extents
1412291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         = VG_(newXA)(ttaux_malloc, "transtab.initialiseSector(host_extents)",
1413291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                      ttaux_free,
1414291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                      sizeof(HostExtent));
1415291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
14165d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      /* Add an entry in the sector_search_order */
14178e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (i = 0; i < n_sectors; i++) {
14185d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[i] == -1)
14195d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            break;
14205d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
14218e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      vg_assert(i >= 0 && i < n_sectors);
14225d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sector_search_order[i] = sno;
14235d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1424fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
1425738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d\n", sno);
14266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1427fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   } else {
14286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
14296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Sector has been used before.  Dump the old contents. */
14305e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe      if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1)
14311bb648db3172e70b73a8ca3a3f3c12ffc1dcd263sewardj         VG_(dmsg)("transtab: " "recycle  sector %d\n", sno);
14325e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe      n_sectors_recycled++;
1433059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj
14346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt != NULL);
14356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next != NULL);
14366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      n_dump_count += sec->tt_n_inuse;
14376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1438597314210494248b4fbefd45525a748439629218sewardj      VexArch     arch_host = VexArch_INVALID;
1439597314210494248b4fbefd45525a748439629218sewardj      VexArchInfo archinfo_host;
1440597314210494248b4fbefd45525a748439629218sewardj      VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host));
1441597314210494248b4fbefd45525a748439629218sewardj      VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host );
1442597314210494248b4fbefd45525a748439629218sewardj      VexEndness endness_host = archinfo_host.endness;
1443291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
14446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Visit each just-about-to-be-abandoned translation. */
14453a5322057616d0da214b9e0f897866e203c03e40philippe      if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d START\n",
14463a5322057616d0da214b9e0f897866e203c03e40philippe                                      sno);
1447fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
14486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tt[i].status == InUse) {
14496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec >= 1);
14506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec <= 3);
14516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            n_dump_osize += vge_osize(&sec->tt[i].vge);
14523786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            /* Tell the tool too. */
14530b9d74abd0a663b530d290b2b788ddeda46e5400sewardj            if (VG_(needs).superblock_discards) {
14540b9d74abd0a663b530d290b2b788ddeda46e5400sewardj               VG_TDICT_CALL( tool_discard_superblock_info,
14554ba057cce1d81a949f5a899b5abb99e90a731bccsewardj                              sec->tt[i].entry,
14566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                              sec->tt[i].vge );
14573786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            }
1458597314210494248b4fbefd45525a748439629218sewardj            unchain_in_preparation_for_deletion(arch_host,
1459597314210494248b4fbefd45525a748439629218sewardj                                                endness_host, sno, i);
14606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
14616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec == 0);
14626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
14636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].status   = Empty;
14646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].n_tte2ec = 0;
14656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
14663a5322057616d0da214b9e0f897866e203c03e40philippe      if (DEBUG_TRANSTAB) VG_(printf)("QQQ unlink-entire-sector: %d END\n",
14673a5322057616d0da214b9e0f897866e203c03e40philippe                                      sno);
14686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
14696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Free up the eclass structures. */
14706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
14716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->ec2tte_size[i] == 0) {
14726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte_used[i] == 0);
14736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] == NULL);
14746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
14756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] != NULL);
1476291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            ttaux_free(sec->ec2tte[i]);
14776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte[i] = NULL;
14786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_size[i] = 0;
14796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_used[i] = 0;
1480fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1481fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      }
14826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1483291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Empty out the host extents array. */
1484291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(sec->host_extents != NULL);
1485291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(dropTailXA)(sec->host_extents, VG_(sizeXA)(sec->host_extents));
1486291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(VG_(sizeXA)(sec->host_extents) == 0);
1487291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
14885d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      /* Sanity check: ensure it is already in
14895d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         sector_search_order[]. */
14908e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (i = 0; i < n_sectors; i++) {
14915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[i] == sno)
14925d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            break;
14935d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
14948e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      vg_assert(i >= 0 && i < n_sectors);
14955d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1496fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
1497738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d\n", sno);
14986c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
14994ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
15006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tc_next = sec->tc;
15016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse = 0;
1502fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1503fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
15045d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
15055d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   { Bool sane = sanity_check_sector_search_order();
15065d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj     vg_assert(sane);
15075d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
15086c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1509de4a1d01951937632098a6cda45859afa587a06fsewardj
1510de4a1d01951937632098a6cda45859afa587a06fsewardj
1511fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC.  The translation is temporarily
1512fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   in code[0 .. code_len-1].
1513de4a1d01951937632098a6cda45859afa587a06fsewardj
1514fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   pre: youngest_sector points to a valid (although possibly full)
1515fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.
1516fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
1517518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid VG_(add_to_transtab)( const VexGuestExtents* vge,
1518ddd61ff058f02059064e083a8accaefed23d5548florian                           Addr             entry,
151944bd4465581ff28cef83bb39e684a489297d7b71florian                           Addr             code,
152026412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                           UInt             code_len,
1521291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           Bool             is_self_checking,
1522291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           Int              offs_profInc,
1523597314210494248b4fbefd45525a748439629218sewardj                           UInt             n_guest_instrs )
152422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{
1525fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int    tcAvailQ, reqdQ, y, i;
15265f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   ULong  *tcptr, *tcptr2;
1527fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* srcP;
1528fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* dstP;
1529fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1530663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1531fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
1532e808930793aeddc4cfd3e7a94b665913bec2566csewardj
1533e808930793aeddc4cfd3e7a94b665913bec2566csewardj   /* 60000: should agree with N_TMPBUF in m_translate.c. */
1534e808930793aeddc4cfd3e7a94b665913bec2566csewardj   vg_assert(code_len > 0 && code_len < 60000);
1535fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1536b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj   /* Generally stay sane */
1537b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj   vg_assert(n_guest_instrs < 200); /* it can be zero, tho */
1538b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj
15393a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB)
1540ddd61ff058f02059064e083a8accaefed23d5548florian      VG_(printf)("add_to_transtab(entry = 0x%lx, len = %u) ...\n",
1541fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                  entry, code_len);
1542fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1543fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_count++;
1544fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_tsize += code_len;
1545fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_osize += vge_osize(vge);
154626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   if (is_self_checking)
154726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj      n_in_sc_count++;
1548fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1549fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   y = youngest_sector;
1550fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(y));
1551fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1552fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sectors[y].tc == NULL)
1553fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
1554fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1555fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Try putting the translation in this sector. */
15565f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   reqdQ = (code_len + 7) >> 3;
1557fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1558fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Will it fit in tc? */
1559fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
1560fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
1561fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
1562fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
1563fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1564fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (tcAvailQ < reqdQ
1565fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj       || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR_USABLE) {
1566fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* No.  So move on to the next sector.  Either it's never been
1567fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         used before, in which case it will get its tt/tc allocated
1568fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         now, or it has been used before, in which case it is set to be
1569fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         empty, hence throwing out the oldest sector. */
1570a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      vg_assert(tc_sector_szQ > 0);
1571059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj      Int tt_loading_pct = (100 * sectors[y].tt_n_inuse)
1572059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj                           / N_TTES_PER_SECTOR;
1573059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj      Int tc_loading_pct = (100 * (tc_sector_szQ - tcAvailQ))
1574059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj                           / tc_sector_szQ;
15755e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe      if (VG_(clo_stats) || VG_(debugLog_getLevel)() >= 1) {
1576059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj         VG_(dmsg)("transtab: "
15771bb648db3172e70b73a8ca3a3f3c12ffc1dcd263sewardj                   "declare  sector %d full "
15785e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                   "(TT loading %2d%%, TC loading %2d%%, avg tce size %d)\n",
15795e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                   y, tt_loading_pct, tc_loading_pct,
15805e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                   8 * (tc_sector_szQ - tcAvailQ)/sectors[y].tt_n_inuse);
1581059838bd94f9d06cd31648dc9bbf7da71c3db957sewardj      }
1582fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      youngest_sector++;
15838e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      if (youngest_sector >= n_sectors)
1584fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         youngest_sector = 0;
1585fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      y = youngest_sector;
1586fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
1587fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
158822854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
1589fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Be sure ... */
1590fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
1591fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
1592fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
1593fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
1594fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= reqdQ);
1595fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR_USABLE);
1596fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse >= 0);
1597fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1598fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Copy into tc. */
15995f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr = sectors[y].tc_next;
16005f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr >= &sectors[y].tc[0]);
16015f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr <= &sectors[y].tc[tc_sector_szQ]);
1602fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
16035f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   dstP = (UChar*)tcptr;
1604fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   srcP = (UChar*)code;
1605291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(memcpy)(dstP, srcP, code_len);
1606fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tc_next += reqdQ;
1607fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt_n_inuse++;
1608fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1609fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* more paranoia */
16105f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr2 = sectors[y].tc_next;
16115f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 >= &sectors[y].tc[0]);
16125f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 <= &sectors[y].tc[tc_sector_szQ]);
1613fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1614fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find an empty tt slot, and use it.  There must be such a slot
1615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      since tt is never allowed to get completely full. */
1616fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   i = HASH_TT(entry);
1617fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(i >= 0 && i < N_TTES_PER_SECTOR);
161822854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   while (True) {
1619fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[y].tt[i].status == Empty
1620fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          || sectors[y].tt[i].status == Deleted)
1621fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         break;
1622fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      i++;
1623fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (i >= N_TTES_PER_SECTOR)
1624fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         i = 0;
162522854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   }
1626fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1627291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry__init(&sectors[y].tt[i]);
1628fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].status = InUse;
16295f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   sectors[y].tt[i].tcptr  = tcptr;
1630fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].count  = 0;
1631b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj   sectors[y].tt[i].weight = n_guest_instrs == 0 ? 1 : n_guest_instrs;
1632fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].vge    = *vge;
1633fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].entry  = entry;
1634fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1635291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Patch in the profile counter location, if necessary. */
1636291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (offs_profInc != -1) {
1637291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(offs_profInc >= 0 && offs_profInc < code_len);
1638597314210494248b4fbefd45525a748439629218sewardj      VexArch     arch_host = VexArch_INVALID;
1639597314210494248b4fbefd45525a748439629218sewardj      VexArchInfo archinfo_host;
1640597314210494248b4fbefd45525a748439629218sewardj      VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host));
1641597314210494248b4fbefd45525a748439629218sewardj      VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host );
1642597314210494248b4fbefd45525a748439629218sewardj      VexEndness endness_host = archinfo_host.endness;
1643291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VexInvalRange vir
1644597314210494248b4fbefd45525a748439629218sewardj         = LibVEX_PatchProfInc( arch_host, endness_host,
1645291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                dstP + offs_profInc,
1646291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                &sectors[y].tt[i].count );
1647291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(invalidate_icache)( (void*)vir.start, vir.len );
1648291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
1649291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
1650291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( dstP, code_len );
1651291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
1652291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Add this entry to the host_extents map, checking that we're
1653291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      adding in order. */
1654291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   { HostExtent hx;
1655291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.start = (UChar*)tcptr;
1656291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.len   = code_len;
1657291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.tteNo = i;
1658291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     vg_assert(hx.len > 0); /* bsearch fails w/ zero length entries */
1659291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     XArray* hx_array = sectors[y].host_extents;
1660291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     vg_assert(hx_array);
1661291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     Word n = VG_(sizeXA)(hx_array);
1662291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     if (n > 0) {
1663291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        HostExtent* hx_prev = (HostExtent*)VG_(indexXA)(hx_array, n-1);
1664291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        vg_assert(hx_prev->start + hx_prev->len <= hx.start);
1665291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     }
1666291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     VG_(addToXA)(hx_array, &hx);
16673a5322057616d0da214b9e0f897866e203c03e40philippe     if (DEBUG_TRANSTAB)
16683a5322057616d0da214b9e0f897866e203c03e40philippe        VG_(printf)("... hx.start 0x%p hx.len %u sector %d ttslot %d\n",
16693a5322057616d0da214b9e0f897866e203c03e40philippe                    hx.start, hx.len, y, i);
1670291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
1671291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
16726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Update the fast-cache. */
1673291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   setFastCacheEntry( entry, tcptr );
16746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
16756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Note the eclass numbers for this translation. */
16766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   upd_eclasses_after_add( &sectors[y], i );
167722854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj}
167822854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
1679fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1680fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address.  If
1681fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   requested, a successful search can also cause the fast-caches to be
1682fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   updated.
1683fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
168444bd4465581ff28cef83bb39e684a489297d7b71florianBool VG_(search_transtab) ( /*OUT*/Addr*  res_hcode,
1685291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                            /*OUT*/UInt*  res_sNo,
1686291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                            /*OUT*/UInt*  res_tteNo,
1687ddd61ff058f02059064e083a8accaefed23d5548florian                            Addr          guest_addr,
1688fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Bool          upd_cache )
16896c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1690fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int i, j, k, kstart, sno;
1691663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1692663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1693fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find the initial probe point just once.  It will be the same in
1694fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      all sectors and avoids multiple expensive % operations. */
1695fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_full_lookups++;
1696fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   k      = -1;
1697fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   kstart = HASH_TT(guest_addr);
1698fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(kstart >= 0 && kstart < N_TTES_PER_SECTOR);
1699fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
17005d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Search in all the sectors,using sector_search_order[] as a
17015d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      heuristic guide as to what order to visit the sectors. */
17028e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (i = 0; i < n_sectors; i++) {
1703fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
17045d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sno = sector_search_order[i];
17055d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (UNLIKELY(sno == -1))
17065d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         return False; /* run out of sectors to search */
1707fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1708fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      k = kstart;
1709fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (j = 0; j < N_TTES_PER_SECTOR; j++) {
1710fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         n_lookup_probes++;
1711fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == InUse
1712fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             && sectors[sno].tt[k].entry == guest_addr) {
1713fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            /* found it */
1714fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (upd_cache)
1715fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               setFastCacheEntry(
1716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                  guest_addr, sectors[sno].tt[k].tcptr );
1717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_hcode)
171844bd4465581ff28cef83bb39e684a489297d7b71florian               *res_hcode = (Addr)sectors[sno].tt[k].tcptr;
1719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_sNo)
1720291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj               *res_sNo = sno;
1721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_tteNo)
1722291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj               *res_tteNo = k;
17235d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            /* pull this one one step closer to the front.  For large
17245d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               apps this more or less halves the number of required
17255d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               probes. */
17265d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            if (i > 0) {
17275d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               Int tmp = sector_search_order[i-1];
17285d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               sector_search_order[i-1] = sector_search_order[i];
17295d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               sector_search_order[i] = tmp;
17305d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            }
1731fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            return True;
1732fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1733fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == Empty)
1734fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            break; /* not found in this sector */
1735fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         k++;
1736fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (k == N_TTES_PER_SECTOR)
1737fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            k = 0;
17386c3769f487145a08c01b58d6e5db3ba274062ad4sewardj      }
1739fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1740fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* If we fall off the end, all entries are InUse and not
1741fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         matching, or Deleted.  In any case we did not find it in this
1742fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         sector. */
17436c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
1744fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1745fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Not found in any sector. */
1746fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
17476c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1748de4a1d01951937632098a6cda45859afa587a06fsewardj
1749de4a1d01951937632098a6cda45859afa587a06fsewardj
17506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
17516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Delete translations.                                  ---*/
17526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
17536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* forward */
1755ddd61ff058f02059064e083a8accaefed23d5548florianstatic void unredir_discard_translations( Addr, ULong );
17560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
17576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Stuff for deleting translations which intersect with a given
17586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range.  Unfortunately, to make this run at a reasonable
17596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   speed, it is complex. */
1760fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1761fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1762ddd61ff058f02059064e083a8accaefed23d5548florianBool overlap1 ( Addr s1, ULong r1, Addr s2, ULong r2 )
17636c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1764ddd61ff058f02059064e083a8accaefed23d5548florian   Addr e1 = s1 + r1 - 1;
1765ddd61ff058f02059064e083a8accaefed23d5548florian   Addr e2 = s2 + r2 - 1;
1766fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (e1 < s2 || e2 < s1)
1767fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1768fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
17696c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1770de4a1d01951937632098a6cda45859afa587a06fsewardj
1771fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1772ddd61ff058f02059064e083a8accaefed23d5548florianBool overlaps ( Addr start, ULong range, const VexGuestExtents* vge )
17736c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1774ddd61ff058f02059064e083a8accaefed23d5548florian   if (overlap1(start, range, vge->base[0], vge->len[0]))
1775fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1776fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 2)
1777fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1778ddd61ff058f02059064e083a8accaefed23d5548florian   if (overlap1(start, range, vge->base[1], vge->len[1]))
1779fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1780fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 3)
1781fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1782ddd61ff058f02059064e083a8accaefed23d5548florian   if (overlap1(start, range, vge->base[2], vge->len[2]))
1783fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1784fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
17856c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1786de4a1d01951937632098a6cda45859afa587a06fsewardj
1787de4a1d01951937632098a6cda45859afa587a06fsewardj
17886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete a tt entry, and update all the eclass data accordingly. */
17896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1790291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void delete_tte ( /*MOD*/Sector* sec, UInt secNo, Int tteno,
1791597314210494248b4fbefd45525a748439629218sewardj                         VexArch arch_host, VexEndness endness_host )
17926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
17936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, ec_num, ec_idx;
17946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
17956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1796291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* sec and secNo are mutually redundant; cross-check. */
1797291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(sec == &sectors[secNo]);
1798291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
17996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
18006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
18016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->status == InUse);
18026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->n_tte2ec >= 1 && tte->n_tte2ec <= 3);
18036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1804291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Unchain .. */
1805597314210494248b4fbefd45525a748439629218sewardj   unchain_in_preparation_for_deletion(arch_host, endness_host, secNo, tteno);
1806291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
18076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Deal with the ec-to-tte links first. */
18086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < tte->n_tte2ec; i++) {
18096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_num = (Int)tte->tte2ec_ec[i];
18106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_idx = tte->tte2ec_ix[i];
18116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_num >= 0 && ec_num < ECLASS_N);
18126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx >= 0);
18136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx < sec->ec2tte_used[ec_num]);
18146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Assert that the two links point at each other. */
18156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->ec2tte[ec_num][ec_idx] == (UShort)tteno);
18166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* "delete" the pointer back to here. */
18176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec_num][ec_idx] = EC2TTE_DELETED;
18186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
18196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Now fix up this TTEntry. */
18216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->status   = Deleted;
18226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = 0;
18236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Stats .. */
18256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse--;
18266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_count++;
18276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_osize += vge_osize(&tte->vge);
18286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Tell the tool too. */
18300b9d74abd0a663b530d290b2b788ddeda46e5400sewardj   if (VG_(needs).superblock_discards) {
18310b9d74abd0a663b530d290b2b788ddeda46e5400sewardj      VG_TDICT_CALL( tool_discard_superblock_info,
18324ba057cce1d81a949f5a899b5abb99e90a731bccsewardj                     tte->entry,
18336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                     tte->vge );
18346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
18356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
18366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, but
18396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   only consider translations in the specified eclass. */
18406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1842291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector_eclass ( /*MOD*/Sector* sec, UInt secNo,
1843ddd61ff058f02059064e083a8accaefed23d5548florian                                            Addr guest_start, ULong range,
1844291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                            Int ec,
1845597314210494248b4fbefd45525a748439629218sewardj                                            VexArch arch_host,
1846597314210494248b4fbefd45525a748439629218sewardj                                            VexEndness endness_host )
18476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
18486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i;
18496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort   tteno;
18506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool     anyDeld = False;
18516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
18526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
18546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < sec->ec2tte_used[ec]; i++) {
18566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tteno = sec->ec2tte[ec][i];
18586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tteno == EC2TTE_DELETED) {
18596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* already deleted */
18606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
18616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
18626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tteno < N_TTES_PER_SECTOR);
18646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte = &sec->tt[tteno];
18666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
18676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (overlaps( guest_start, range, &tte->vge )) {
18696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
1870597314210494248b4fbefd45525a748439629218sewardj         delete_tte( sec, secNo, (Int)tteno, arch_host, endness_host );
18716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
18726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
18746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
18766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
18776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, the
18806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   slow way, by inspecting all translations in sec. */
18816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1883291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector ( /*MOD*/Sector* sec, UInt secNo,
1884ddd61ff058f02059064e083a8accaefed23d5548florian                                     Addr guest_start, ULong range,
1885597314210494248b4fbefd45525a748439629218sewardj                                     VexArch arch_host,
1886597314210494248b4fbefd45525a748439629218sewardj                                     VexEndness endness_host )
18876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
18886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int  i;
18896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool anyDeld = False;
18906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < N_TTES_PER_SECTOR; i++) {
18926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tt[i].status == InUse
18936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          && overlaps( guest_start, range, &sec->tt[i].vge )) {
18946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
1895597314210494248b4fbefd45525a748439629218sewardj         delete_tte( sec, secNo, i, arch_host, endness_host );
18966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
18976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
18986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
19006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
19016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1903ddd61ff058f02059064e083a8accaefed23d5548florianvoid VG_(discard_translations) ( Addr guest_start, ULong range,
19041636d33c13958b9c0e7d3059cdd5005746418eb2florian                                 const HChar* who )
19056c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
19066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
19076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int     sno, ec;
19086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    anyDeleted = False;
19096c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1910663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1911663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1912a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj   VG_(debugLog)(2, "transtab",
1913ddd61ff058f02059064e083a8accaefed23d5548florian                    "discard_translations(0x%lx, %llu) req by %s\n",
191445f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    guest_start, range, who );
191545f4e7c91119c7d01a59f5e827c67841632c9314sewardj
19166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Pre-deletion sanity check */
19176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
19186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool sane = sanity_check_all_sectors();
19196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
19206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
19216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range == 0)
19236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return;
19246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1925597314210494248b4fbefd45525a748439629218sewardj   VexArch     arch_host = VexArch_INVALID;
1926597314210494248b4fbefd45525a748439629218sewardj   VexArchInfo archinfo_host;
1927597314210494248b4fbefd45525a748439629218sewardj   VG_(bzero_inline)(&archinfo_host, sizeof(archinfo_host));
1928597314210494248b4fbefd45525a748439629218sewardj   VG_(machine_get_VexArchInfo)( &arch_host, &archinfo_host );
1929597314210494248b4fbefd45525a748439629218sewardj   VexEndness endness_host = archinfo_host.endness;
1930291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
19316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* There are two different ways to do this.
19326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      If the range fits within a single address-range equivalence
19346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, as will be the case for a cache line sized invalidation,
19356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      then we only have to inspect the set of translations listed in
19366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      that equivalence class, and also in the "sin-bin" equivalence
19376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class ECLASS_MISC.
19386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Otherwise, the invalidation is of a larger range and probably
19406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      results from munmap.  In this case it's (probably!) faster just
19416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      to inspect all translations, dump those we don't want, and
19426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      regenerate the equivalence class information (since modifying it
19436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      in-situ is even more expensive).
19446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   */
19456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* First off, figure out if the range falls within a single class,
19476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      and if so which one. */
19486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ec = ECLASS_MISC;
19506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range < (1ULL << ECLASS_SHIFT))
19516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec = range_to_eclass( guest_start, (UInt)range );
19526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* if ec is ECLASS_MISC then we aren't looking at just a single
19546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, so use the slow scheme.  Else use the fast scheme,
19556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      examining 'ec' and ECLASS_MISC. */
19566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ec != ECLASS_MISC) {
19586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
19606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    FAST, ec = %d\n", ec);
19616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Fast scheme */
19636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec >= 0 && ec < ECLASS_MISC);
19646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19658e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (sno = 0; sno < n_sectors; sno++) {
19666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
19676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
19686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
19696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
1970291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, ec,
1971597314210494248b4fbefd45525a748439629218sewardj                          arch_host, endness_host
1972291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       );
19736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
1974291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, ECLASS_MISC,
1975597314210494248b4fbefd45525a748439629218sewardj                          arch_host, endness_host
1976291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       );
19776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
19786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
19806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* slow scheme */
19826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
19846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    SLOW, ec = %d\n", ec);
19856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19868e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (sno = 0; sno < n_sectors; sno++) {
19876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
19886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
19896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
19906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector(
1991597314210494248b4fbefd45525a748439629218sewardj                          sec, sno, guest_start, range,
1992597314210494248b4fbefd45525a748439629218sewardj                          arch_host, endness_host
1993597314210494248b4fbefd45525a748439629218sewardj                       );
19946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
19956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1996de4a1d01951937632098a6cda45859afa587a06fsewardj   }
1997de4a1d01951937632098a6cda45859afa587a06fsewardj
1998fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (anyDeleted)
1999fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      invalidateFastCache();
20006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
20010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* don't forget the no-redir cache */
20020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_discard_translations( guest_start, range );
20030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Post-deletion sanity check */
20056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
20066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int      i;
20076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      TTEntry* tte;
20086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool     sane = sanity_check_all_sectors();
20096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
20106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* But now, also check the requested address range isn't
20116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         present anywhere. */
20128e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      for (sno = 0; sno < n_sectors; sno++) {
20136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
20146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
20156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
20166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (i = 0; i < N_TTES_PER_SECTOR; i++) {
20176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            tte = &sec->tt[i];
20186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (tte->status != InUse)
20196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
20206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(!overlaps( guest_start, range, &tte->vge ));
20216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
20226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
20236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
2024fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
20256c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
20265f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian/* Whether or not tools may discard translations. */
20275f1aeb620eb5a3aab662f8b949b031a77a0d14feflorianBool  VG_(ok_to_discard_translations) = False;
20285f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian
20295f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian/* This function is exported to tools which can use it to discard
20305f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian   translations, provided it is safe to do so. */
20315f1aeb620eb5a3aab662f8b949b031a77a0d14feflorianvoid VG_(discard_translations_safely) ( Addr  start, SizeT len,
20325f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian                                        const HChar* who )
20335f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian{
20345f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian   vg_assert(VG_(ok_to_discard_translations));
20355f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian   VG_(discard_translations)(start, len, who);
20365f1aeb620eb5a3aab662f8b949b031a77a0d14feflorian}
20376c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
2038fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
20390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*--- AUXILIARY: the unredirected TT/TC                    ---*/
20400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
20410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* A very simple translation cache which holds a small number of
20430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredirected translations.  This is completely independent of the
20440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   main tt/tc structures.  When unredir_tc or unredir_tt becomes full,
20450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   both structures are simply dumped and we start over.
20460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Since these translations are unredirected, the search key is (by
20480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   definition) the first address entry in the .vge field. */
20490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Sized to hold 500 translations of average size 1000 bytes. */
20510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define UNREDIR_SZB   1000
20530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TT  500
20550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TCQ (N_UNREDIR_TT * UNREDIR_SZB / sizeof(ULong))
20560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20570ec07f32bbbb209d749b9974408e6f025ad40b31sewardjtypedef
20580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   struct {
20590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      VexGuestExtents vge;
20600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Addr            hcode;
20610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Bool            inUse;
20620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
20630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   UTCEntry;
20640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* We just allocate forwards in _tc, never deleting. */
206678c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic ULong    *unredir_tc;
206778c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic Int      unredir_tc_used = N_UNREDIR_TCQ;
20680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Slots in _tt can come into use and out again (.inUse).
20700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Nevertheless _tt_highwater is maintained so that invalidations
20710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   don't have to scan all the slots when only a few are in use.
20720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   _tt_highwater holds the index of the highest ever allocated
20730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   slot. */
20740ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic UTCEntry unredir_tt[N_UNREDIR_TT];
20750ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Int      unredir_tt_highwater;
20760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20780ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void init_unredir_tt_tc ( void )
20790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
20800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
208178c0c09d429c95115e826ef769ecaa6cff2ac338tom   if (unredir_tc == NULL) {
2082cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      SysRes sres = VG_(am_mmap_anon_float_valgrind)
2083cda2f0fbda4c4b2644babc830244be8aed95de1dnjn                       ( N_UNREDIR_TT * UNREDIR_SZB );
2084cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
2085cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         VG_(out_of_memory_NORETURN)("init_unredir_tt_tc",
2086cda2f0fbda4c4b2644babc830244be8aed95de1dnjn                                     N_UNREDIR_TT * UNREDIR_SZB);
208778c0c09d429c95115e826ef769ecaa6cff2ac338tom         /*NOTREACHED*/
208878c0c09d429c95115e826ef769ecaa6cff2ac338tom      }
208944bd4465581ff28cef83bb39e684a489297d7b71florian      unredir_tc = (ULong *)(Addr)sr_Res(sres);
209078c0c09d429c95115e826ef769ecaa6cff2ac338tom   }
20910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used = 0;
20920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
20930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt[i].inUse = False;
20940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt_highwater = -1;
20950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
20960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Do a sanity check; return False on failure. */
20980ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void )
20990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
21000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
21010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater < -1) return False;
21020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater >= N_UNREDIR_TT) return False;
21030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = unredir_tt_highwater+1; i < N_UNREDIR_TT; i++)
21050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse)
21060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return False;
21070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used < 0) return False;
21090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used > N_UNREDIR_TCQ) return False;
21100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return True;
21120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
21130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21150ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Add an UNREDIRECTED translation of vge to TT/TC.  The translation
21160ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   is temporarily in code[0 .. code_len-1].
21170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj*/
2118518850bf0da07ed3e2244e307268ae0fd80e93a8florianvoid VG_(add_to_unredir_transtab)( const VexGuestExtents* vge,
2119ddd61ff058f02059064e083a8accaefed23d5548florian                                   Addr             entry,
212044bd4465581ff28cef83bb39e684a489297d7b71florian                                   Addr             code,
21211dcee097db02f9ef3ba355162c4373d90d0e895cnjn                                   UInt             code_len )
21220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
21230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int   i, j, code_szQ;
21240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   HChar *srcP, *dstP;
21250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
21270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* This is the whole point: it's not redirected! */
21290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(entry == vge->base[0]);
21300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* How many unredir_tt slots are needed */
21320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   code_szQ = (code_len + 7) / 8;
21330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* Look for an empty unredir_tc slot */
21350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
21360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
21370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         break;
21380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i >= N_UNREDIR_TT || code_szQ > (N_UNREDIR_TCQ - unredir_tc_used)) {
21400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      /* It's full; dump everything we currently have */
21410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      init_unredir_tt_tc();
21420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      i = 0;
21430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
21440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
21460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
21470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ > 0);
21480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ + unredir_tc_used <= N_UNREDIR_TCQ);
21490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(i >= 0 && i < N_UNREDIR_TT);
21500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tt[i].inUse == False);
21510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i > unredir_tt_highwater)
21530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt_highwater = i;
21540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   dstP = (HChar*)&unredir_tc[unredir_tc_used];
21560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   srcP = (HChar*)code;
21570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (j = 0; j < code_len; j++)
21580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      dstP[j] = srcP[j];
21590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
2160291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( dstP, code_len );
2161c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj
21620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].inUse = True;
21630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].vge   = *vge;
21640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].hcode = (Addr)dstP;
21650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used += code_szQ;
21670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
21680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
21690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(&dstP[code_len] <= (HChar*)&unredir_tc[unredir_tc_used]);
21710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
21720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
217344bd4465581ff28cef83bb39e684a489297d7b71florianBool VG_(search_unredir_transtab) ( /*OUT*/Addr*  result,
2174ddd61ff058f02059064e083a8accaefed23d5548florian                                    Addr          guest_addr )
21750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
21760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
21770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++) {
21780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
21790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         continue;
21800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].vge.base[0] == guest_addr) {
2181ddd61ff058f02059064e083a8accaefed23d5548florian         *result = unredir_tt[i].hcode;
21820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return True;
21830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      }
21840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
21850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return False;
21860ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
21870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
2188ddd61ff058f02059064e083a8accaefed23d5548florianstatic void unredir_discard_translations( Addr guest_start, ULong range )
21890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
21900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
21910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
21930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i <= unredir_tt_highwater; i++) {
21950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse
21960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj          && overlaps( guest_start, range, &unredir_tt[i].vge))
21970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         unredir_tt[i].inUse = False;
21980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
21990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
22000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
2203fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation.                                      ---*/
2204fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2205fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2206fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void )
22076c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
2208a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   Int i, avg_codeszQ;
2209de4a1d01951937632098a6cda45859afa587a06fsewardj
2210663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(!init_done);
2211663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   init_done = True;
2212663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
2213fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Otherwise lots of things go wrong... */
2214fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(ULong) == 8);
22155f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries really are 2 words long */
22165f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(Addr) == sizeof(void*));
22175f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr));
22185f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries are packed back-to-back with no spaces */
22195f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof( VG_(tt_fast) ) == VG_TT_FAST_SIZE * sizeof(FastCacheEntry));
22205f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache is aligned as we requested.  Not fatal if it
22215f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      isn't, but we might as well make sure. */
22225f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) ));
2223de4a1d01951937632098a6cda45859afa587a06fsewardj
2224fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2)
2225fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2226fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                   "TT/TC: VG_(init_tt_tc) "
2227738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                   "(startup of code management)\n");
2228fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2229fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Figure out how big each tc area should be.  */
2230924c852b5883a7b42298dc8c7542116bd9a8a485philippe   if (VG_(clo_avg_transtab_entry_size) == 0)
2231924c852b5883a7b42298dc8c7542116bd9a8a485philippe      avg_codeszQ   = (VG_(details).avg_translation_sizeB + 7) / 8;
2232924c852b5883a7b42298dc8c7542116bd9a8a485philippe   else
2233924c852b5883a7b42298dc8c7542116bd9a8a485philippe      avg_codeszQ   = (VG_(clo_avg_transtab_entry_size) + 7) / 8;
223443b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ);
2235fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2236fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Ensure the calculated value is not way crazy. */
2237fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE);
22381e0fff690e9c571275e8025eb2dcff7bf29b53afsewardj   vg_assert(tc_sector_szQ <= 100 * N_TTES_PER_SECTOR_USABLE);
2239fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
22408e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   n_sectors = VG_(clo_num_transtab_sectors);
22418e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   vg_assert(n_sectors >= MIN_N_SECTORS);
22428e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   vg_assert(n_sectors <= MAX_N_SECTORS);
22438e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe
2244a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   /* Initialise the sectors, even the ones we aren't going to use.
2245a11ec17946cdbafb336e9121b64961c0633af2e7sewardj      Set all fields to zero. */
2246fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest_sector = 0;
2247a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   for (i = 0; i < MAX_N_SECTORS; i++)
2248a11ec17946cdbafb336e9121b64961c0633af2e7sewardj      VG_(memset)(&sectors[i], 0, sizeof(sectors[i]));
22494ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2250a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   /* Initialise the sector_search_order hint table, including the
2251a11ec17946cdbafb336e9121b64961c0633af2e7sewardj      entries we aren't going to use. */
2252a11ec17946cdbafb336e9121b64961c0633af2e7sewardj   for (i = 0; i < MAX_N_SECTORS; i++)
22535d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sector_search_order[i] = -1;
22545d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
2255291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Initialise the fast cache. */
2256fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
2257fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
22580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* and the unredir tt/tc */
22590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   init_unredir_tt_tc();
22600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
22618e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   if (VG_(clo_verbosity) > 2 || VG_(clo_stats)
22628e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe       || VG_(debugLog_getLevel) () >= 2) {
2263fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2264924c852b5883a7b42298dc8c7542116bd9a8a485philippe         "TT/TC: cache: %s--avg-transtab-entry-size=%d, "
2265924c852b5883a7b42298dc8c7542116bd9a8a485philippe         "%stool provided default %d\n",
2266924c852b5883a7b42298dc8c7542116bd9a8a485philippe         VG_(clo_avg_transtab_entry_size) == 0 ? "ignoring " : "using ",
2267924c852b5883a7b42298dc8c7542116bd9a8a485philippe         VG_(clo_avg_transtab_entry_size),
2268924c852b5883a7b42298dc8c7542116bd9a8a485philippe         VG_(clo_avg_transtab_entry_size) == 0 ? "using " : "ignoring ",
2269924c852b5883a7b42298dc8c7542116bd9a8a485philippe         VG_(details).avg_translation_sizeB);
2270924c852b5883a7b42298dc8c7542116bd9a8a485philippe      VG_(message)(Vg_DebugMsg,
2271738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         "TT/TC: cache: %d sectors of %d bytes each = %d total\n",
22728e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe          n_sectors, 8 * tc_sector_szQ,
22738e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe          n_sectors * 8 * tc_sector_szQ );
2274fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
22758e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe         "TT/TC: table: %d tables  of %d bytes each = %d total\n",
22768e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe          n_sectors, (int)(N_TTES_PER_SECTOR * sizeof(TTEntry)),
22778e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe          (int)(n_sectors * N_TTES_PER_SECTOR * sizeof(TTEntry)));
22788e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe      VG_(message)(Vg_DebugMsg,
22798e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe         "TT/TC: table: %d entries each = %d total entries"
22808e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe                       " max occupancy %d (%d%%)\n",
22818e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe         N_TTES_PER_SECTOR,
22828e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe         n_sectors * N_TTES_PER_SECTOR,
22838e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe         n_sectors * N_TTES_PER_SECTOR_USABLE,
2284fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         SECTOR_TT_LIMIT_PERCENT );
2285fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
2286de4a1d01951937632098a6cda45859afa587a06fsewardj}
2287de4a1d01951937632098a6cda45859afa587a06fsewardj
22884ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2289fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2290fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics.                             ---*/
2291fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2292fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2293fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b )
229492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
229592e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   return (b == 0 ? 0 : a / b);
229692e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
229792e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
2298fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void )
2299fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
2300fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n_in_count;
2301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
2302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2303fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void )
230492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
230592e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2306738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      "    tt/tc: %'llu tt lookups requiring %'llu probes\n",
2307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_full_lookups, n_lookup_probes );
230892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2309738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      "    tt/tc: %'llu fast-cache updates, %'llu flushes\n",
2310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_fast_updates, n_fast_flushes );
2311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
231292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2313a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                " transtab: new        %'lld "
23145e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                "(%'llu -> %'llu; ratio %'llu:10) [%'llu scs] "
23155e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                "avg tce size %d\n",
2316fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_in_count, n_in_osize, n_in_tsize,
231726412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                safe_idiv(10*n_in_tsize, n_in_osize),
23185e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                n_in_sc_count,
231987d15de937a7fda829d1916bda59b9bcf62a2fd3philippe                (int) (n_in_tsize / n_in_count));
232092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
23215e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                " transtab: dumped     %'llu (%'llu -> ?" "?) "
23225e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                "(sectors recycled %'llu)\n",
23235e47e3fae6c8bd8e3b669801a1edbc30ec10499cphilippe                n_dump_count, n_dump_osize, n_sectors_recycled );
2324fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   VG_(message)(Vg_DebugMsg,
2325738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                " transtab: discarded  %'llu (%'llu -> ?" "?)\n",
2326fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_disc_count, n_disc_osize );
23276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
23283a5322057616d0da214b9e0f897866e203c03e40philippe   if (DEBUG_TRANSTAB) {
23296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int i;
23306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n");
23316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
23326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         VG_(printf)(" %4d", sectors[0].ec2tte_used[i]);
23336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (i % 16 == 15)
23346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            VG_(printf)("\n");
23356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
23366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n\n");
23376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
233892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
2339de4a1d01951937632098a6cda45859afa587a06fsewardj
2340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results.                   ---*/
2342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
23434ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2344518850bf0da07ed3e2244e307268ae0fd80e93a8florianstatic ULong score ( const TTEntry* tte )
2345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
2346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return ((ULong)tte->weight) * ((ULong)tte->count);
2347de4a1d01951937632098a6cda45859afa587a06fsewardj}
2348de4a1d01951937632098a6cda45859afa587a06fsewardj
234917c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardjULong VG_(get_SB_profile) ( SBProfEntry tops[], UInt n_tops )
2350de4a1d01951937632098a6cda45859afa587a06fsewardj{
2351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int   sno, i, r, s;
23522025cf98a3210c175a90fc77cb599cca1643bd68njn   ULong score_total;
2353fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2354fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* First, compute the total weighted count, and find the top N
23552025cf98a3210c175a90fc77cb599cca1643bd68njn      ttes.  tops contains pointers to the most-used n_tops blocks, in
2356fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      descending order (viz, tops[0] is the highest scorer). */
23572025cf98a3210c175a90fc77cb599cca1643bd68njn   for (i = 0; i < n_tops; i++) {
23582025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].addr  = 0;
23592025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].score = 0;
23602025cf98a3210c175a90fc77cb599cca1643bd68njn   }
2361fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2362fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   score_total = 0;
2363fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
23648e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (sno = 0; sno < n_sectors; sno++) {
2365fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[sno].tc == NULL)
236618d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         continue;
2367fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
2368fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[i].status != InUse)
2369fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            continue;
2370fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         score_total += score(&sectors[sno].tt[i]);
2371fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* Find the rank for sectors[sno].tt[i]. */
23722025cf98a3210c175a90fc77cb599cca1643bd68njn         r = n_tops-1;
2373fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         while (True) {
2374fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (r == -1)
2375fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               break;
23762025cf98a3210c175a90fc77cb599cca1643bd68njn             if (tops[r].addr == 0) {
2377fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               r--;
2378fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               continue;
2379fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
23802025cf98a3210c175a90fc77cb599cca1643bd68njn             if ( score(&sectors[sno].tt[i]) > tops[r].score ) {
2381fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                r--;
2382fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                continue;
2383fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
2384fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             break;
2385fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
2386fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         r++;
23872025cf98a3210c175a90fc77cb599cca1643bd68njn         vg_assert(r >= 0 && r <= n_tops);
2388fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* This bb should be placed at r, and bbs above it shifted
2389fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            upwards one slot. */
23902025cf98a3210c175a90fc77cb599cca1643bd68njn         if (r < n_tops) {
23912025cf98a3210c175a90fc77cb599cca1643bd68njn            for (s = n_tops-1; s > r; s--)
2392fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               tops[s] = tops[s-1];
23932025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].addr  = sectors[sno].tt[i].entry;
23942025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].score = score( &sectors[sno].tt[i] );
2395fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
2396de4a1d01951937632098a6cda45859afa587a06fsewardj      }
2397de4a1d01951937632098a6cda45859afa587a06fsewardj   }
2398de4a1d01951937632098a6cda45859afa587a06fsewardj
239917c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj   /* Now zero out all the counter fields, so that we can make
240017c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      multiple calls here and just get the values since the last call,
240117c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      each time, rather than values accumulated for the whole run. */
24028e1bee406c191820bc3b22bf55cfa69ef5fdcd8bphilippe   for (sno = 0; sno < n_sectors; sno++) {
240317c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      if (sectors[sno].tc == NULL)
240417c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj         continue;
240517c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
240617c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj         if (sectors[sno].tt[i].status != InUse)
240717c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj            continue;
240817c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj         sectors[sno].tt[i].count = 0;
240917c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj      }
241017c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj   }
241117c5e2e3a2f48970063ea43a9abee3e11c72cb04sewardj
24122025cf98a3210c175a90fc77cb599cca1643bd68njn   return score_total;
2413c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
2414c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
2415de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
24168bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end                                                          ---*/
2417de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
2418