m_transtab.c revision b7301c690606964dd1ece81ce2fd2b6fd90ab012
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
11ec062e8d96a361af9905b5447027819dfbfee01asewardj   Copyright (C) 2000-2011 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
4918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj/* #define DEBUG_TRANSTAB */
5018d7513cc08bf982711c8a22b70d56af6aa87b33sewardj
51de4a1d01951937632098a6cda45859afa587a06fsewardj
526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/
536c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*--- Management of the FIFO-based translation table+cache. ---*/
546c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*-------------------------------------------------------------*/
55de4a1d01951937632098a6cda45859afa587a06fsewardj
566c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ CONSTANTS ------------------*/
57de4a1d01951937632098a6cda45859afa587a06fsewardj
58fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of sectors the TC is divided into.  If you need a larger
59fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   overall translation cache, increase this value. */
60fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_SECTORS 8
61de4a1d01951937632098a6cda45859afa587a06fsewardj
62fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of TC entries in each sector.  This needs to be a prime
636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   number to work properly, it must be <= 65535 (so that a TT index
646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   fits in a UShort, leaving room for 0xFFFF(EC2TTE_DELETED) to denote
656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   'deleted') and it is strongly recommended not to change this.
666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   65521 is the largest prime <= 65535. */
67e25053c5aaefc6a4039dcd557adf24d8bb23db69sewardj#define N_TTES_PER_SECTOR /*10007*/ /*30011*/ /*40009*/ 65521
68de4a1d01951937632098a6cda45859afa587a06fsewardj
69fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Because each sector contains a hash table of TTEntries, we need to
70fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   specify the maximum allowable loading, after which the sector is
71fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   deemed full. */
725d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj#define SECTOR_TT_LIMIT_PERCENT 65
73de4a1d01951937632098a6cda45859afa587a06fsewardj
74fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The sector is deemed full when this many entries are in it. */
75fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj#define N_TTES_PER_SECTOR_USABLE \
76fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj           ((N_TTES_PER_SECTOR * SECTOR_TT_LIMIT_PERCENT) / 100)
776c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Equivalence classes for fast address range deletion.  There are 1 +
796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   2^ECLASS_WIDTH bins.  The highest one, ECLASS_MISC, describes an
806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range which does not fall cleanly within any specific bin.
816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Note that ECLASS_SHIFT + ECLASS_WIDTH must be < 32. */
826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_SHIFT 11
836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_WIDTH 8
846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_MISC  (1 << ECLASS_WIDTH)
856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define ECLASS_N     (1 + ECLASS_MISC)
866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#define EC2TTE_DELETED  0xFFFF /* 16-bit special value */
886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
89de4a1d01951937632098a6cda45859afa587a06fsewardj
906c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ TYPES ------------------*/
91de4a1d01951937632098a6cda45859afa587a06fsewardj
92291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* In edges ("to-me") in the graph created by chaining. */
93291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
94291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
95291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_sNo;   /* sector number */
96291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_tteNo; /* TTE number in given sector */
97291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_offs;  /* code offset from TCEntry::tcptr where the patch is */
98291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Bool to_fastEP;  /* Is the patch to a fast or slow entry point? */
99291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
100291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge;
101291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
102291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
103291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Out edges ("from-me") in the graph created by chaining. */
104291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
105291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
106291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt to_sNo;    /* sector number */
107291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt to_tteNo;  /* TTE number in given sector */
108291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt from_offs; /* code offset in owning translation where patch is */
109291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
110291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge;
111291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
112291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
113291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_IN_EDGE_ARR 3
114291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
115291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
116291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt     n_fixed; /* 0 .. N_FIXED_IN_EDGE_ARR */
117291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdge   fixed[N_FIXED_IN_EDGE_ARR];
118291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray*  var; /* XArray* of InEdgeArr */
119291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
120291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr;
121291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
122291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj#define N_FIXED_OUT_EDGE_ARR 2
123291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
124291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
125291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt    n_fixed; /* 0 .. N_FIXED_OUT_EDGE_ARR */
126291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdge fixed[N_FIXED_OUT_EDGE_ARR];
127291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* var; /* XArray* of OutEdgeArr */
128291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
129291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr;
130291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
131291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
132fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* A translation-table entry.  This indicates precisely which areas of
133fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   guest code are included in the translation, and contains all other
134fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   auxiliary info too.  */
1356c3769f487145a08c01b58d6e5db3ba274062ad4sewardjtypedef
1366c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   struct {
137fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Profiling only: the count and weight (arbitrary meaning) for
138fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         this translation.  Weight is a property of the translation
139fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         itself and computed once when the translation is created.
140fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         Count is an entry count for the translation and is
141fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         incremented by 1 every time the translation is used, if we
142fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         are profiling. */
143291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      ULong    count;
144fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      UShort   weight;
145fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
146fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Status of the slot.  Note, we need to be able to do lazy
147fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         deletion, hence the Deleted state. */
148fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      enum { InUse, Deleted, Empty } status;
149fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1505f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      /* 64-bit aligned pointer to one or more 64-bit words containing
1515f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         the corresponding host code (must be in the same sector!)
1525f76de086a6d643db51e50a4e623df7dfc9b6161sewardj         This is a pointer into the sector's tc (code) area. */
1535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      ULong* tcptr;
154fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
155fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This is the original guest address that purportedly is the
156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         entry point of the translation.  You might think that .entry
157fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         should be the same as .vge->base[0], and most of the time it
158fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         is.  However, when doing redirections, that is not the case.
159fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         .vge must always correctly describe the guest code sections
160fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         from which this translation was made.  However, .entry may or
161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         may not be a lie, depending on whether or not we're doing
162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         redirection. */
163fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Addr64 entry;
164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This structure describes precisely what ranges of guest code
166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         the translation covers, so we can decide whether or not to
167fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         delete it when translations of a given address range are
168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         invalidated. */
169fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VexGuestExtents vge;
1706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Address range summary info: these are pointers back to
1726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclass[] entries in the containing Sector.  Those entries in
1736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         turn point back here -- the two structures are mutually
1746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         redundant but both necessary to make fast deletions work.
1756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         The eclass info is similar to, and derived from, this entry's
1766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         'vge' field, but it is not the same */
1776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort n_tte2ec;      // # tte2ec pointers (1 to 3)
1786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort tte2ec_ec[3];  // for each, the eclass #
1796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UInt   tte2ec_ix[3];  // and the index within the eclass.
1806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // for i in 0 .. n_tte2ec-1
1816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      //    sec->ec2tte[ tte2ec_ec[i] ][ tte2ec_ix[i] ]
1826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // should be the index
1836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      // of this TTEntry in the containing Sector's tt array.
184291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
185291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Admin information for chaining.  'in_edges' is a set of the
186291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         patch points which jump to this translation -- hence are
187291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         predecessors in the control flow graph.  'out_edges' points
188291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         to successors in the control flow graph -- translations to
189291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         which this one has a patched jump.  In short these are just
190291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         backwards and forwards edges in the graph of patched-together
191291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         blocks.  The 'in_edges' contain slightly more info, enough
192291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         that we can undo the chaining of each mentioned patch point.
193291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The 'out_edges' list exists only so that we can visit the
194291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         'in_edges' entries of all blocks we're patched through to, in
195291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         order to remove ourselves from then when we're deleted. */
196291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
197291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* A translation can disappear for two reasons:
198291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          1. erased (as part of the oldest sector cleanup) when the
199291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             youngest sector is full.
200291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          2. discarded due to calls to VG_(discard_translations).
201291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             VG_(discard_translations) sets the status of the
202291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             translation to 'Deleted'.
203291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             A.o., the gdbserver discards one or more translations
204291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             when a breakpoint is inserted or removed at an Addr,
205291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             or when single stepping mode is enabled/disabled
206291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             or when a translation is instrumented for gdbserver
207291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             (all the target jumps of this translation are
208291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj              invalidated).
209291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
210291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         So, it is possible that the translation A to be patched
211291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (to obtain a patched jump from A to B) is invalidated
212291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         after B is translated and before A is patched.
213291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         In case a translation is erased or discarded, the patching
214291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         cannot be done.  VG_(tt_tc_do_chaining) and find_TTEntry_from_hcode
215291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         are checking the 'from' translation still exists before
216291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         doing the patching.
217291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
218291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Is it safe to erase or discard the current translation E being
219291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         executed ? Amazing, but yes, it is safe.
220291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Here is the explanation:
221291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
222291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The translation E being executed can only be erased if a new
223291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation N is being done. A new translation is done only
224291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if the host addr is a not yet patched jump to another
225291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation. In such a case, the guest address of N is
226291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         assigned to the PC in the VEX state. Control is returned
227291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         to the scheduler. N will be translated. This can erase the
228291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         translation E (in case of sector full). VG_(tt_tc_do_chaining)
229291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         will not do the chaining to a non found translation E.
230291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The execution will continue at the current guest PC
231291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (i.e. the translation N).
232291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         => it is safe to erase the current translation being executed.
233291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
234291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         The current translation E being executed can also be discarded
235291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (e.g. by gdbserver). VG_(discard_translations) will mark
236291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         this translation E as Deleted, but the translation itself
237291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         is not erased. In particular, its host code can only
238291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         be overwritten or erased in case a new translation is done.
239291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         A new translation will only be done if a not yet translated
240291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         jump is to be executed. The execution of the Deleted translation
241291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         E will continue till a non patched jump is encountered.
242291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         This situation is then similar to the 'erasing' case above :
243291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         the current translation E can be erased or overwritten, as the
244291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         execution will continue at the new translation N.
245291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
246291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      */
247291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
248291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* It is possible, although very unlikely, that a block A has
249291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         more than one patched jump to block B.  This could happen if
250291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (eg) A finishes "jcond B; jmp B".
251291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
252291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         This means in turn that B's in_edges set can list A more than
253291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         once (twice in this example).  However, each such entry must
254291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         have a different from_offs, since a patched jump can only
255291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         jump to one place at once (it's meaningless for it to have
256291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         multiple destinations.)  IOW, the successor and predecessor
257291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         edges in the graph are not uniquely determined by a
258291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         TTEntry --> TTEntry pair, but rather by a
259291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         (TTEntry,offset) --> TTEntry triple.
260291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
261291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         If A has multiple edges to B then B will mention A multiple
262291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         times in its in_edges.  To make things simpler, we then
263291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         require that A mentions B exactly the same number of times in
264291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         its out_edges.  Furthermore, a matching out-in pair must have
265291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         the same offset (from_offs).  This facilitates sanity
266291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         checking, and it facilitates establishing the invariant that
267291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         a out_edges set may not have duplicates when using the
268291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         equality defined by (TTEntry,offset).  Hence the out_edges
269291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         and in_edges sets really do have both have set semantics.
270291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
271291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         eg if  A has been patched to B at offsets 42 and 87 (in A)
272291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         then   A.out_edges = { (B,42), (B,87) }   (in any order)
273291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         and    B.in_edges  = { (A,42), (A,87) }   (in any order)
274291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
275291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         Hence for each node pair P->Q in the graph, there's a 1:1
276291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         mapping between P.out_edges and Q.in_edges.
277291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      */
278291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdgeArr  in_edges;
279291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdgeArr out_edges;
2806c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
2816c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   TTEntry;
2826c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
2834ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
284291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* A structure used for mapping host code addresses back to the
285291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   relevant TTEntry.  Used when doing chaining, for finding the
286291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry to which some arbitrary patch address belongs. */
287291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjtypedef
288291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   struct {
289291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* start;
290291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt   len;
291291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UInt   tteNo;
292291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
293291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HostExtent;
294291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
295fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Finally, a sector itself.  Each sector contains an array of
296fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   TCEntries, which hold code, and an array of TTEntries, containing
297fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   all required administrative info.  Profiling is supported using the
298291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry .count and .weight fields, if required.
2994ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
300fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   If the sector is not in use, all three pointers are NULL and
301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tt_n_inuse is zero.
302fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
303fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjtypedef
304fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   struct {
305fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TCEntry area.  Size of this depends on the average
306fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         translation size.  We try and size it so it becomes full
307fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         precisely when this sector's translation table (tt) reaches
308fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         its load limit (SECTOR_TT_LIMIT_PERCENT). */
309fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc;
3104ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
311fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The TTEntry array.  This is a fixed size, always containing
312fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         exactly N_TTES_PER_SECTOR entries. */
313fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      TTEntry* tt;
3146c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
315fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* This points to the current allocation point in tc. */
316fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      ULong* tc_next;
317de4a1d01951937632098a6cda45859afa587a06fsewardj
318fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* The count of tt entries with state InUse. */
319fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      Int tt_n_inuse;
3206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
3216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Expandable arrays of tt indices for each of the ECLASS_N
3226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         address range equivalence classes.  These hold indices into
3236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         the containing sector's tt array, which in turn should point
3246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         back here. */
3256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_size[ECLASS_N];
3266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int     ec2tte_used[ECLASS_N];
3276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      UShort* ec2tte[ECLASS_N];
328291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
329291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* The host extents.  The [start, +len) ranges are constructed
330291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         in strictly non-overlapping order, so we can binary search
331291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         them at any time. */
332291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* host_extents; /* XArray* of HostExtent */
333fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
334fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Sector;
335de4a1d01951937632098a6cda45859afa587a06fsewardj
336de4a1d01951937632098a6cda45859afa587a06fsewardj
3376c3769f487145a08c01b58d6e5db3ba274062ad4sewardj/*------------------ DECLS ------------------*/
3386c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
339fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The root data structure is an array of sectors.  The index of the
340fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest sector is recorded, and new translations are put into that
341fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.  When it fills up, we move along to the next sector and
342fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   start to fill that up, wrapping around at the end of the array.
343fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   That way, once all N_TC_SECTORS have been bought into use for the
344fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   first time, and are full, we then re-use the oldest sector,
345fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   endlessly.
346fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
347fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   When running, youngest sector should be between >= 0 and <
348fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   N_TC_SECTORS.  The initial -1 value indicates the TT/TC system is
349fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   not yet initialised.
350fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
351fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Sector sectors[N_SECTORS];
352fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int    youngest_sector = -1;
3536c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
354fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* The number of ULongs in each TCEntry area.  This is computed once
355fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   at startup and does not change. */
356fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Int    tc_sector_szQ;
3576c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3586c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3595d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj/* A list of sector numbers, in the order which they should be
3605d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   searched to find translations.  This is an optimisation to be used
3615d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   when searching for translations and should not affect
3625d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   correctness.  -1 denotes "no entry". */
3635d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Int sector_search_order[N_SECTORS];
3645d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
3655d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
3665f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* Fast helper for the TC.  A direct-mapped cache which holds a set of
3675f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   recently used (guest address, host address) pairs.  This array is
3685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   referred to directly from m_dispatch/dispatch-<platform>.S.
3696c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
3705f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   Entries in tt_fast may refer to any valid TC entry, regardless of
371fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   which sector it's in.  Consequently we must be very careful to
372fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidate this cache when TC entries are changed or disappear.
373c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
3745f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   A special .guest address - TRANSTAB_BOGUS_GUEST_ADDR -- must be
3755f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   pointed at to cause that cache entry to miss.  This relies on the
3765f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   assumption that no guest code actually has that address, hence a
3775f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   value 0x1 seems good.  m_translate gives the client a synthetic
3785f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   segfault if it tries to execute at this address.
3795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
3805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*
3815f76de086a6d643db51e50a4e623df7dfc9b6161sewardjtypedef
3825f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   struct {
3835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr guest;
3845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      Addr host;
3855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
3865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   FastCacheEntry;
3875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj*/
3885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/*global*/ __attribute__((aligned(16)))
3895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj           FastCacheEntry VG_(tt_fast)[VG_TT_FAST_SIZE];
390de4a1d01951937632098a6cda45859afa587a06fsewardj
391663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj/* Make sure we're not used before initialisation. */
392663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardjstatic Bool init_done = False;
393663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
394663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
395fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------ STATS DECLS ------------------*/
396de4a1d01951937632098a6cda45859afa587a06fsewardj
397fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of fast-cache updates and flushes done. */
398291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_flushes = 0;
399291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_fast_updates = 0;
40022854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
401fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number of full lookups done. */
402291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_full_lookups = 0;
403291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_lookup_probes = 0;
40422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
40526412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj/* Number/osize/tsize of translations entered; also the number of
40626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   those for which self-checking was requested. */
407291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_count    = 0;
408291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_osize    = 0;
409291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_tsize    = 0;
410291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_in_sc_count = 0;
411de4a1d01951937632098a6cda45859afa587a06fsewardj
412fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to lack of space. */
413291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_count = 0;
414291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_dump_osize = 0;
415fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
416fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Number/osize of translations discarded due to requests to do so. */
417291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_count = 0;
418291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic ULong n_disc_osize = 0;
419291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
420291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
421291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
422291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Misc                                                  ---*/
423291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
424291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
425291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void* ttaux_malloc ( HChar* tag, SizeT n )
426291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
427291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return VG_(arena_malloc)(VG_AR_TTAUX, tag, n);
428291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
429291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
430291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void ttaux_free ( void* p )
431291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
432291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(arena_free)(VG_AR_TTAUX, p);
433291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
434291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
435291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
436291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
437291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*--- Chaining support                                      ---*/
438291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/*-------------------------------------------------------------*/
439291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
440291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic inline TTEntry* index_tte ( UInt sNo, UInt tteNo )
441291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
442291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(sNo < N_SECTORS);
443291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(tteNo < N_TTES_PER_SECTOR);
444291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Sector* s = &sectors[sNo];
445291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(s->tt);
446291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* tte = &s->tt[tteNo];
447291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(tte->status == InUse);
448291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return tte;
449291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
450291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
451291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdge__init ( InEdge* ie )
452291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
453291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_sNo   = -1; /* invalid */
454291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_tteNo = 0;
455291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->from_offs  = 0;
456291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie->to_fastEP  = False;
457291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
458291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
459291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdge__init ( OutEdge* oe )
460291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
461291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->to_sNo    = -1; /* invalid */
462291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->to_tteNo  = 0;
463291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe->from_offs = 0;
464291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
465291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
466291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void TTEntry__init ( TTEntry* tte )
467291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
468291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(memset)(tte, 0, sizeof(*tte));
469291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
470291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
471291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic UWord InEdgeArr__size ( InEdgeArr* iea )
472291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
473291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
474291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
475291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return VG_(sizeXA)(iea->var);
476291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
477291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
478291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return iea->n_fixed;
479291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
480291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
481291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
482291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void InEdgeArr__makeEmpty ( InEdgeArr* iea )
483291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
484291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
485291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
486291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(deleteXA)(iea->var);
487291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->var = NULL;
488291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
489291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
490291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->n_fixed = 0;
491291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
492291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
493291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
494291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
495291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjInEdge* InEdgeArr__index ( InEdgeArr* iea, UWord i )
496291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
497291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
498291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
499291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return (InEdge*)VG_(indexXA)(iea->var, i);
500291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
501291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < iea->n_fixed);
502291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return &iea->fixed[i];
503291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
504291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
505291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
506291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
507291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__deleteIndex ( InEdgeArr* iea, UWord i )
508291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
509291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
510291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
511291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(removeIndexXA)(iea->var, i);
512291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
513291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < iea->n_fixed);
514291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (; i+1 < iea->n_fixed; i++) {
515291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->fixed[i] = iea->fixed[i+1];
516291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
517291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      iea->n_fixed--;
518291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
519291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
520291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
521291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
522291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid InEdgeArr__add ( InEdgeArr* iea, InEdge* ie )
523291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
524291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (iea->var) {
525291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed == 0);
526291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(addToXA)(iea->var, ie);
527291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
528291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(iea->n_fixed <= N_FIXED_IN_EDGE_ARR);
529291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (iea->n_fixed == N_FIXED_IN_EDGE_ARR) {
530291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* The fixed array is full, so we have to initialise an
531291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            XArray and copy the fixed array into it. */
532291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->var = VG_(newXA)(ttaux_malloc, "transtab.IEA__add",
533291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               ttaux_free,
534291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               sizeof(InEdge));
535291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UWord i;
536291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         for (i = 0; i < iea->n_fixed; i++) {
537291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            VG_(addToXA)(iea->var, &iea->fixed[i]);
538291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         }
539291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         VG_(addToXA)(iea->var, ie);
540291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->n_fixed = 0;
541291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      } else {
542291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Just add to the fixed array. */
543291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         iea->fixed[iea->n_fixed++] = *ie;
544291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
545291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
546291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
547291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
548291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic UWord OutEdgeArr__size ( OutEdgeArr* oea )
549291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
550291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
551291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
552291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return VG_(sizeXA)(oea->var);
553291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
554291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
555291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return oea->n_fixed;
556291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
557291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
558291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
559291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void OutEdgeArr__makeEmpty ( OutEdgeArr* oea )
560291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
561291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
562291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
563291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(deleteXA)(oea->var);
564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->var = NULL;
565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->n_fixed = 0;
568291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
569291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
570291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
571291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
572291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjOutEdge* OutEdgeArr__index ( OutEdgeArr* oea, UWord i )
573291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
574291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
575291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
576291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return (OutEdge*)VG_(indexXA)(oea->var, i);
577291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
578291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < oea->n_fixed);
579291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return &oea->fixed[i];
580291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
582291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
583291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
584291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__deleteIndex ( OutEdgeArr* oea, UWord i )
585291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
586291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
587291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
588291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(removeIndexXA)(oea->var, i);
589291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
590291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(i < oea->n_fixed);
591291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (; i+1 < oea->n_fixed; i++) {
592291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->fixed[i] = oea->fixed[i+1];
593291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
594291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      oea->n_fixed--;
595291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
596291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
597291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
598291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
599291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid OutEdgeArr__add ( OutEdgeArr* oea, OutEdge* oe )
600291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
601291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (oea->var) {
602291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed == 0);
603291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(addToXA)(oea->var, oe);
604291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   } else {
605291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(oea->n_fixed <= N_FIXED_OUT_EDGE_ARR);
606291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (oea->n_fixed == N_FIXED_OUT_EDGE_ARR) {
607291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* The fixed array is full, so we have to initialise an
608291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            XArray and copy the fixed array into it. */
609291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->var = VG_(newXA)(ttaux_malloc, "transtab.OEA__add",
610291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               ttaux_free,
611291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                               sizeof(OutEdge));
612291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UWord i;
613291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         for (i = 0; i < oea->n_fixed; i++) {
614291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            VG_(addToXA)(oea->var, &oea->fixed[i]);
615291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         }
616291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         VG_(addToXA)(oea->var, oe);
617291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->n_fixed = 0;
618291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      } else {
619291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Just add to the fixed array. */
620291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         oea->fixed[oea->n_fixed++] = *oe;
621291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
622291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
623291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
624291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
625291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
626291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjInt HostExtent__cmpOrd ( void* v1, void* v2 )
627291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
628291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HostExtent* hx1 = (HostExtent*)v1;
629291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HostExtent* hx2 = (HostExtent*)v2;
630291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (hx1->start + hx1->len <= hx2->start) return -1;
631291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (hx2->start + hx2->len <= hx1->start) return 1;
632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return 0; /* partial overlap */
633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
634291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
635291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic __attribute__((noinline))
636291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool find_TTEntry_from_hcode( /*OUT*/UInt* from_sNo,
637291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              /*OUT*/UInt* from_tteNo,
638291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              void* hcode )
639291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
640291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int i;
641291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
642291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Search order logic copied from VG_(search_transtab). */
643291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < N_SECTORS; i++) {
644291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Int sno = sector_search_order[i];
645291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (UNLIKELY(sno == -1))
646291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return False; /* run out of sectors to search */
647291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
648291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Sector* sec = &sectors[sno];
649291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      XArray* /* of HostExtent */ host_extents = sec->host_extents;
650291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(host_extents);
651291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
652291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      HostExtent key;
653291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(memset)(&key, 0, sizeof(key));
654291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      key.start = hcode;
655291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      key.len = 1;
656291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Word firstW = -1, lastW = -1;
657291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      Bool found  = VG_(lookupXA_UNSAFE)(
658291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       host_extents, &key, &firstW, &lastW,
659291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       (Int(*)(void*,void*))HostExtent__cmpOrd
660291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    );
661291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(firstW == lastW); // always true, even if not found
662291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (found) {
663291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         HostExtent* hx = VG_(indexXA)(host_extents, firstW);
664291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         UInt tteNo = hx->tteNo;
665291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Do some additional sanity checks. */
666291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert(tteNo <= N_TTES_PER_SECTOR);
667291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Entry might have been invalidated. Consider this
668291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            as not found. */
669291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (sec->tt[tteNo].status == Deleted)
670291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            return False;
671291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert(sec->tt[tteNo].status == InUse);
672291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Can only half check that the found TTEntry contains hcode,
673291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            due to not having a length value for the hcode in the
674291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            TTEntry. */
675291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         vg_assert((UChar*)sec->tt[tteNo].tcptr <= (UChar*)hcode);
676291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         /* Looks plausible */
677291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         *from_sNo   = sno;
678291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         *from_tteNo = (UInt)tteNo;
679291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return True;
680291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
681291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
682291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return False;
683291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
684291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
685291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
686291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Figure out whether or not hcode is jitted code present in the main
687291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   code cache (but not in the no-redir cache).  Used for sanity
688291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   checking. */
689291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic Bool is_in_the_main_TC ( void* hcode )
690291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
691291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int i, sno;
692291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < N_SECTORS; i++) {
693291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sno = sector_search_order[i];
694291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if (sno == -1)
695291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         break; /* run out of sectors to search */
696291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      if ((UChar*)hcode >= (UChar*)sectors[sno].tc
697291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj          && (UChar*)hcode <= (UChar*)sectors[sno].tc_next
698291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              + sizeof(ULong) - 1)
699291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         return True;
700291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
701291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   return False;
702291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
703291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
704291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
705291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Fulfill a chaining request, and record admin info so we
706291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   can undo it later, if required.
707291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj*/
708291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid VG_(tt_tc_do_chaining) ( void* from__patch_addr,
709291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              UInt  to_sNo,
710291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              UInt  to_tteNo,
711291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              Bool  to_fastEP )
712291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Get the CPU info established at startup. */
714291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexArch vex_arch = VexArch_INVALID;
715291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(machine_get_VexArchInfo)( &vex_arch, NULL );
716291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
717291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // host_code is where we're patching to.  So it needs to
718291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // take into account, whether we're jumping to the slow
719291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // or fast entry point.  By definition, the fast entry point
720291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // is exactly one event check's worth of code along from
721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // the slow (tcptr) entry point.
722291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* to_tte    = index_tte(to_sNo, to_tteNo);
723291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   void*    host_code = ((UChar*)to_tte->tcptr)
724291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                        + (to_fastEP ? LibVEX_evCheckSzB(vex_arch) : 0);
725291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
726291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // stay sane -- the patch point (dst) is in this sector's code cache
727291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( (UChar*)host_code >= (UChar*)sectors[to_sNo].tc );
728291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( (UChar*)host_code <= (UChar*)sectors[to_sNo].tc_next
729291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                   + sizeof(ULong) - 1 );
730291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
731291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Find the TTEntry for the from__ code.  This isn't simple since
732291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      we only know the patch address, which is going to be somewhere
733291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      inside the from_ block. */
734291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UInt from_sNo   = (UInt)-1;
735291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UInt from_tteNo = (UInt)-1;
736291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Bool from_found
737291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = find_TTEntry_from_hcode( &from_sNo, &from_tteNo,
738291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                 from__patch_addr );
739291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (!from_found) {
740291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // The from code might have been discarded due to sector re-use
741291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // or marked Deleted due to translation invalidation.
742291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // In such a case, don't do the chaining.
743291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(debugLog)(1,"transtab",
744291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    "host code %p not found (discarded? sector recycled?)"
745291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    " => no chaining done\n",
746291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                    from__patch_addr);
747291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      return;
748291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
749291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
750291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* from_tte = index_tte(from_sNo, from_tteNo);
751291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
752291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Get VEX to do the patching itself.  We have to hand it off
753291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      since it is host-dependent. */
754291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexInvalRange vir
755291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = LibVEX_Chain(
756291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           vex_arch,
757291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           from__patch_addr,
758291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           VG_(fnptr_to_fnentry)(
759291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj              to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP)
760291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                        : &VG_(disp_cp_chain_me_to_slowEP)),
761291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           (void*)host_code
762291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        );
763291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( (void*)vir.start, vir.len );
764291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
765291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Now do the tricky bit -- update the ch_succs and ch_preds info
766291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for the two translations involved, so we can undo the chaining
767291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      later, which we will have to do if the to_ block gets removed
768291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for whatever reason. */
769291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
770291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* This is the new from_ -> to_ link to add. */
771291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge ie;
772291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdge__init(&ie);
773291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_sNo   = from_sNo;
774291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_tteNo = from_tteNo;
775291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.to_fastEP  = to_fastEP;
776291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   HWord from_offs = (HWord)( (UChar*)from__patch_addr
777291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                              - (UChar*)from_tte->tcptr );
778291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(from_offs < 100000/* let's say */);
779291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   ie.from_offs  = (UInt)from_offs;
780291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
781291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* This is the new to_ -> from_ backlink to add. */
782291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge oe;
783291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdge__init(&oe);
784291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.to_sNo    = to_sNo;
785291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.to_tteNo  = to_tteNo;
786291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   oe.from_offs = (UInt)from_offs;
787291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
788291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Add .. */
789291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr__add(&to_tte->in_edges, &ie);
790291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr__add(&from_tte->out_edges, &oe);
791291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
792291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
793291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
794291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Unchain one patch, as described by the specified InEdge.  For
795291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   sanity check purposes only (to check that the patched location is
796291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   as expected) it also requires the fast and slow entry point
797291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   addresses of the destination block (that is, the block that owns
798291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   this InEdge). */
799291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj__attribute__((noinline))
800291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void unchain_one ( VexArch vex_arch,
801291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          InEdge* ie,
802291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          void* to_fastEPaddr, void* to_slowEPaddr )
803291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
804291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(ie);
805291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* tte
806291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = index_tte(ie->from_sNo, ie->from_tteNo);
807291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* place_to_patch
808291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = ((HChar*)tte->tcptr) + ie->from_offs;
809291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* disp_cp_chain_me
810291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = VG_(fnptr_to_fnentry)(
811291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           ie->to_fastEP ? &VG_(disp_cp_chain_me_to_fastEP)
812291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         : &VG_(disp_cp_chain_me_to_slowEP)
813291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        );
814291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UChar* place_to_jump_to_EXPECTED
815291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      = ie->to_fastEP ? to_fastEPaddr : to_slowEPaddr;
816291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
817291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // stay sane: both src and dst for this unchaining are
818291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // in the main code cache
819291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( is_in_the_main_TC(place_to_patch) ); // src
820291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert( is_in_the_main_TC(place_to_jump_to_EXPECTED) ); // dst
821291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // dst check is ok because LibVEX_UnChain checks that
822291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // place_to_jump_to_EXPECTED really is the current dst, and
823291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   // asserts if it isn't.
824291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexInvalRange vir
825291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj       = LibVEX_UnChain( vex_arch, place_to_patch,
826291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         place_to_jump_to_EXPECTED, disp_cp_chain_me );
827291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( (void*)vir.start, vir.len );
828291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
829291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
830291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
831291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* The specified block is about to be deleted.  Update the preds and
832291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   succs of its associated blocks accordingly.  This includes undoing
833291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   any chained jumps to this block. */
834291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic
835291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjvoid unchain_in_preparation_for_deletion ( VexArch vex_arch,
836291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                           UInt here_sNo, UInt here_tteNo )
837291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj{
838291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (0)
839291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(printf)("QQQ unchain_in_prep %u.%u\n", here_sNo, here_tteNo);
840291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   UWord    i, j, n, m;
841291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int      evCheckSzB = LibVEX_evCheckSzB(vex_arch);
842291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry* here_tte   = index_tte(here_sNo, here_tteNo);
843291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(here_tte->status == InUse);
844291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
845291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Visit all InEdges owned by here_tte. */
846291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   n = InEdgeArr__size(&here_tte->in_edges);
847291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < n; i++) {
848291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdge* ie = InEdgeArr__index(&here_tte->in_edges, i);
849291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Undo the chaining.
850291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* here_slow_EP = (UChar*)here_tte->tcptr;
851291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      UChar* here_fast_EP = here_slow_EP + evCheckSzB;
852291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      unchain_one(vex_arch, ie, here_fast_EP, here_slow_EP);
853291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Find the corresponding entry in the "from" node's out_edges,
854291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // and remove it.
855291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      TTEntry* from_tte = index_tte(ie->from_sNo, ie->from_tteNo);
856291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      m = OutEdgeArr__size(&from_tte->out_edges);
857291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(m > 0); // it must have at least one entry
858291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (j = 0; j < m; j++) {
859291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         OutEdge* oe = OutEdgeArr__index(&from_tte->out_edges, j);
860291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (oe->to_sNo == here_sNo && oe->to_tteNo == here_tteNo
861291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             && oe->from_offs == ie->from_offs)
862291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           break;
863291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
864291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(j < m); // "oe must be findable"
865291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdgeArr__deleteIndex(&from_tte->out_edges, j);
866291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
867291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
868291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Visit all OutEdges owned by here_tte. */
869291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   n = OutEdgeArr__size(&here_tte->out_edges);
870291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   for (i = 0; i < n; i++) {
871291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      OutEdge* oe = OutEdgeArr__index(&here_tte->out_edges, i);
872291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // Find the corresponding entry in the "to" node's in_edges,
873291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      // and remove it.
874291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      TTEntry* to_tte = index_tte(oe->to_sNo, oe->to_tteNo);
875291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      m = InEdgeArr__size(&to_tte->in_edges);
876291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(m > 0); // it must have at least one entry
877291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      for (j = 0; j < m; j++) {
878291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         InEdge* ie = InEdgeArr__index(&to_tte->in_edges, j);
879291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         if (ie->from_sNo == here_sNo && ie->from_tteNo == here_tteNo
880291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj             && ie->from_offs == oe->from_offs)
881291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj           break;
882291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      }
883291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(j < m); // "ie must be findable"
884291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      InEdgeArr__deleteIndex(&to_tte->in_edges, j);
885291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
886291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
887291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   InEdgeArr__makeEmpty(&here_tte->in_edges);
888291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   OutEdgeArr__makeEmpty(&here_tte->out_edges);
889291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj}
890fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
891fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
8926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
8936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Address-range equivalence class stuff                 ---*/
8946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
8956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
8966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Return equivalence class number for a range. */
8976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
8986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Int range_to_eclass ( Addr64 start, UInt len )
8996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
9006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt mask   = (1 << ECLASS_WIDTH) - 1;
9016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt lo     = (UInt)start;
9026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hi     = lo + len - 1;
9036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt loBits = (lo >> ECLASS_SHIFT) & mask;
9046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt hiBits = (hi >> ECLASS_SHIFT) & mask;
9056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (loBits == hiBits) {
9066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(loBits < ECLASS_N-1);
9076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return loBits;
9086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
9096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return ECLASS_MISC;
9106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
9126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Calculates the equivalence class numbers for any VexGuestExtent.
9156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   These are written in *eclasses, which must be big enough to hold 3
9166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Ints.  The number written, between 1 and 3, is returned.  The
9176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses are presented in order, and any duplicates are removed.
9186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj*/
9196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
9216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjInt vexGuestExtents_to_eclasses ( /*OUT*/Int* eclasses,
9226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                  VexGuestExtents* vge )
9236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
9246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define SWAP(_lv1,_lv2) \
9256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      do { Int t = _lv1; _lv1 = _lv2; _lv2 = t; } while (0)
9266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, j, n_ec, r;
9286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
9306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_ec = 0;
9326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < vge->n_used; i++) {
9336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      r = range_to_eclass( vge->base[i], (UInt)vge->len[i] );
9346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (r == ECLASS_MISC)
9356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         goto bad;
9366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* only add if we haven't already seen it */
9376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < n_ec; j++)
9386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (eclasses[j] == r)
9396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            break;
9406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (j == n_ec)
9416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         eclasses[n_ec++] = r;
9426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 1)
9456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 1;
9466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 2) {
9486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
9496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
9506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
9516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 2;
9526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (n_ec == 3) {
9556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* sort */
9566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[2])
9576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[2]);
9586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[0] > eclasses[1])
9596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[0], eclasses[1]);
9606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (eclasses[1] > eclasses[2])
9616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         SWAP(eclasses[1], eclasses[2]);
9626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return 3;
9636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
9646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* NOTREACHED */
9666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(0);
9676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
9696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclasses[0] = ECLASS_MISC;
9706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return 1;
9716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef SWAP
9736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
9746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Add tteno to the set of entries listed for equivalence class ec in
9776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   this sector.  Returns used location in eclass array. */
9786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
9806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjUInt addEClassNo ( /*MOD*/Sector* sec, Int ec, UShort tteno )
9816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
9826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int    old_sz, new_sz, i, r;
9836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort *old_ar, *new_ar;
9846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
9866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno < N_TTES_PER_SECTOR);
9876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (0) VG_(printf)("ec %d  gets %d\n", ec, (Int)tteno);
9896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->ec2tte_used[ec] >= sec->ec2tte_size[ec]) {
9916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->ec2tte_used[ec] == sec->ec2tte_size[ec]);
9936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
9946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_sz = sec->ec2tte_size[ec];
9956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      old_ar = sec->ec2tte[ec];
9966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      new_sz = old_sz==0 ? 8 : old_sz<64 ? 2*old_sz : (3*old_sz)/2;
997291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      new_ar = ttaux_malloc("transtab.aECN.1",
998291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                            new_sz * sizeof(UShort));
9996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < old_sz; i++)
10006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         new_ar[i] = old_ar[i];
10016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (old_ar)
1002291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         ttaux_free(old_ar);
10036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte_size[ec] = new_sz;
10046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec] = new_ar;
10056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (0) VG_(printf)("expand ec %d to %d\n", ec, new_sz);
10076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Common case */
10106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = sec->ec2tte_used[ec]++;
10116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 0 && r < sec->ec2tte_size[ec]);
10126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->ec2tte[ec][r] = tteno;
10136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return (UInt)r;
10146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* 'vge' is being added to 'sec' at TT entry 'tteno'.  Add appropriate
10186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   eclass entries to 'sec'. */
10196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
10216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjvoid upd_eclasses_after_add ( /*MOD*/Sector* sec, Int tteno )
10226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, r, eclasses[3];
10246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
10256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
10266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
10286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   r = vexGuestExtents_to_eclasses( eclasses, &tte->vge );
10296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(r >= 1 && r <= 3);
10316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = r;
10326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < r; i++) {
10346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte->tte2ec_ec[i] = eclasses[i];
10356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte->tte2ec_ix[i] = addEClassNo( sec, eclasses[i], (UShort)tteno );
10366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
10376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
10386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Check the eclass info in 'sec' to ensure it is consistent.  Returns
10416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   True if OK, False if something's not right.  Expensive. */
10426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_eclasses_in_sector ( Sector* sec )
10446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
10456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  define BAD(_str) do { whassup = (_str); goto bad; } while (0)
10466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   HChar*   whassup = NULL;
10486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, j, k, n, ec_num, ec_idx;
10496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
10506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort   tteno;
10516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ULong*   tce;
10526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Basic checks on this sector */
10546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->tt_n_inuse < 0 || sec->tt_n_inuse > N_TTES_PER_SECTOR_USABLE)
10556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("invalid sec->tt_n_inuse");
10566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tce = sec->tc_next;
10576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tce < &sec->tc[0] || tce > &sec->tc[tc_sector_szQ])
10586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      BAD("sec->tc_next points outside tc");
10596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* For each eclass ... */
10616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < ECLASS_N; i++) {
10626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] == 0 && sec->ec2tte[i] != NULL)
10636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(1)");
10646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_size[i] != 0 && sec->ec2tte[i] == NULL)
10656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("ec2tte_size/ec2tte mismatch(2)");
10666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] < 0
10676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          || sec->ec2tte_used[i] > sec->ec2tte_size[i])
10686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("implausible ec2tte_used");
10696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->ec2tte_used[i] == 0)
10706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
10716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* For each tt reference in each eclass .. ensure the reference
10736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         is to a valid tt entry, and that the entry's address ranges
10746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         really include this eclass. */
10756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
10766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < sec->ec2tte_used[i]; j++) {
10776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tteno = sec->ec2tte[i][j];
10786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno == EC2TTE_DELETED)
10796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
10806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tteno >= N_TTES_PER_SECTOR)
10816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("implausible tteno");
10826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         tte = &sec->tt[tteno];
10836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->status != InUse)
10846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno points to non-inuse tte");
10856c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
10866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_tte2ec out of range");
10876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* Exactly least one of tte->eclasses[0 .. tte->n_eclasses-1]
10886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            must equal i.  Inspect tte's eclass info. */
10896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         n = 0;
10906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (k = 0; k < tte->n_tte2ec; k++) {
10916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (k < tte->n_tte2ec-1
10926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                && tte->tte2ec_ec[k] >= tte->tte2ec_ec[k+1])
10936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of order");
10946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_num = tte->tte2ec_ec[k];
10956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num < 0 || ec_num >= ECLASS_N)
10966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ec[..] out of range");
10976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_num != i)
10986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
10996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            ec_idx = tte->tte2ec_ix[k];
11006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[i])
11016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               BAD("tte->tte2ec_ix[..] out of range");
11026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (ec_idx == j)
11036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               n++;
11046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
11056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (n != 1)
11066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tteno does not point back at eclass");
11076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* That establishes that for each forward pointer from TTEntrys
11116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      there is a corresponding backward pointer from the eclass[]
11126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      arrays.  However, it doesn't rule out the possibility of other,
11136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      bogus pointers in the eclass[] arrays.  So do those similarly:
11146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      scan through them and check the TTEntryies they point at point
11156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      back. */
11166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < N_TTES_PER_SECTOR_USABLE; i++) {
11186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte = &sec->tt[i];
11206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->status == Empty || tte->status == Deleted) {
11216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (tte->n_tte2ec != 0)
11226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->n_eclasses nonzero for unused tte");
11236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
11246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
11276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tte->n_tte2ec < 1 || tte->n_tte2ec > 3)
11296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         BAD("tte->n_eclasses out of range(2)");
11306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < tte->n_tte2ec; j++) {
11326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_num = tte->tte2ec_ec[j];
11336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_num < 0 || ec_num >= ECLASS_N)
11346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->eclass[..] out of range");
11356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         ec_idx = tte->tte2ec_ix[j];
11366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (ec_idx < 0 || ec_idx >= sec->ec2tte_used[ec_num])
11376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("tte->ec_idx[..] out of range(2)");
11386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->ec2tte[ec_num][ec_idx] != i)
11396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            BAD("ec2tte does not point back to tte");
11406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
11416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
11446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj  bad:
11466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (whassup)
11476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(0, "transtab", "eclass sanity fail: %s\n", whassup);
11486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  if 0
11506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("eclass = %d\n", i);
11516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   VG_(printf)("tteno = %d\n", (Int)tteno);
11526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   switch (tte->status) {
11536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case InUse:   VG_(printf)("InUse\n"); break;
11546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Deleted: VG_(printf)("Deleted\n"); break;
11556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      case Empty:   VG_(printf)("Empty\n"); break;
11566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (tte->status != Empty) {
11586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (k = 0; k < tte->vge.n_used; k++)
11596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         VG_(printf)("0x%llx %d\n", tte->vge.base[k],
11606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                    (Int)tte->vge.len[k]);
11616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
11626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  endif
11636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return False;
11656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj#  undef BAD
11676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
11686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Sanity check absolutely everything.  True == check passed. */
11716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
11725f76de086a6d643db51e50a4e623df7dfc9b6161sewardj/* forwards */
11730ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void );
11740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
11755d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardjstatic Bool sanity_check_sector_search_order ( void )
11765d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj{
11775d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   Int i, j, nListed;
11785d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* assert the array is the right size */
11795d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   vg_assert(N_SECTORS == (sizeof(sector_search_order)
11805d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj                           / sizeof(sector_search_order[0])));
11815d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check it's of the form  valid_sector_numbers ++ [-1, -1, ..] */
11825d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (i = 0; i < N_SECTORS; i++) {
11835d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sector_search_order[i] < 0 || sector_search_order[i] >= N_SECTORS)
11845d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         break;
11855d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
11865d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   nListed = i;
11875d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (/* */; i < N_SECTORS; i++) {
11885d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sector_search_order[i] != -1)
11895d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         break;
11905d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
11915d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if (i != N_SECTORS)
11925d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
11935d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check each sector number only appears once */
11945d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (i = 0; i < N_SECTORS; i++) {
11955d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sector_search_order[i] == -1)
11965d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         continue;
11975d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      for (j = i+1; j < N_SECTORS; j++) {
11985d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[j] == sector_search_order[i])
11995d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            return False;
12005d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
12015d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12025d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Check that the number of listed sectors equals the number
12035d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      in use, by counting nListed back down. */
12045d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (i = 0; i < N_SECTORS; i++) {
12055d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (sectors[i].tc != NULL)
12065d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         nListed--;
12075d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
12085d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if (nListed != 0)
12095d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
12105d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   return True;
12115d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj}
12125d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
12136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic Bool sanity_check_all_sectors ( void )
12146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
12156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int     sno;
12166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    sane;
12176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
12186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (sno = 0; sno < N_SECTORS; sno++) {
12196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec = &sectors[sno];
12206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tc == NULL)
12216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
12226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sane = sanity_check_eclasses_in_sector( sec );
12236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (!sane)
12246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         return False;
12256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
12265f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   if ( !sanity_check_redir_tt_tc() )
12275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      return False;
12285d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   if ( !sanity_check_sector_search_order() )
12295d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      return False;
12306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return True;
12316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
12326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1233fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
12345d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1235fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
12366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Add/find translations                                 ---*/
1237fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*-------------------------------------------------------------*/
1238fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1239fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic UInt vge_osize ( VexGuestExtents* vge )
1240c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj{
1241fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt i, n = 0;
1242fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < vge->n_used; i++)
1243fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n += (UInt)vge->len[i];
1244fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n;
1245c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
1246c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
1247fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic Bool isValidSector ( Int sector )
12486c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1249fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sector < 0 || sector >= N_SECTORS)
1250fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1251fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
12526c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1253de4a1d01951937632098a6cda45859afa587a06fsewardj
1254fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline UInt HASH_TT ( Addr64 key )
1255de4a1d01951937632098a6cda45859afa587a06fsewardj{
1256fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kHi = (UInt)(key >> 32);
1257fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UInt kLo = (UInt)key;
12586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt k32 = kHi ^ kLo;
12596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UInt ror = 7;
12606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ror > 0)
12616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      k32 = (k32 >> ror) | (k32 << (32-ror));
12626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return k32 % N_TTES_PER_SECTOR;
1263de4a1d01951937632098a6cda45859afa587a06fsewardj}
1264de4a1d01951937632098a6cda45859afa587a06fsewardj
1265291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void setFastCacheEntry ( Addr64 key, ULong* tcptr )
1266de4a1d01951937632098a6cda45859afa587a06fsewardj{
12673387dda4479102751d544c176a7bfc24f3766669sewardj   UInt cno = (UInt)VG_TT_FAST_HASH(key);
12685f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   VG_(tt_fast)[cno].guest = (Addr)key;
12695f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   VG_(tt_fast)[cno].host  = (Addr)tcptr;
1270fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_updates++;
12715f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This shouldn't fail.  It should be assured by m_translate
12725f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      which should reject any attempt to make translation of code
12735f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      starting at TRANSTAB_BOGUS_GUEST_ADDR. */
12745f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_(tt_fast)[cno].guest != TRANSTAB_BOGUS_GUEST_ADDR);
12756c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1276de4a1d01951937632098a6cda45859afa587a06fsewardj
1277291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj/* Invalidate the fast cache VG_(tt_fast). */
12785f76de086a6d643db51e50a4e623df7dfc9b6161sewardjstatic void invalidateFastCache ( void )
12795f76de086a6d643db51e50a4e623df7dfc9b6161sewardj{
12805f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   UInt j;
12815f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* This loop is popular enough to make it worth unrolling a
12825f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      bit, at least on ppc32. */
12835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_TT_FAST_SIZE > 0 && (VG_TT_FAST_SIZE % 4) == 0);
12845f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   for (j = 0; j < VG_TT_FAST_SIZE; j += 4) {
12855f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+0].guest = TRANSTAB_BOGUS_GUEST_ADDR;
12865f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+1].guest = TRANSTAB_BOGUS_GUEST_ADDR;
12875f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+2].guest = TRANSTAB_BOGUS_GUEST_ADDR;
12885f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      VG_(tt_fast)[j+3].guest = TRANSTAB_BOGUS_GUEST_ADDR;
12895f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   }
12905f76de086a6d643db51e50a4e623df7dfc9b6161sewardj
12915f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(j == VG_TT_FAST_SIZE);
1292fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_fast_flushes++;
12936c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1294de4a1d01951937632098a6cda45859afa587a06fsewardj
1295fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic void initialiseSector ( Int sno )
12966c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1297291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   Int     i;
1298291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   SysRes  sres;
12996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
1300fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(sno));
1301fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
13025d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   { Bool sane = sanity_check_sector_search_order();
13035d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj     vg_assert(sane);
13045d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
13056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec = &sectors[sno];
13066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
13076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (sec->tc == NULL) {
13086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1309fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* Sector has never been used before.  Need to allocate tt and
1310fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         tc. */
13116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt == NULL);
13126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next == NULL);
13136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt_n_inuse == 0);
13146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
13156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_size[i] == 0);
13166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte_used[i] == 0);
13176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         vg_assert(sec->ec2tte[i] == NULL);
13186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
1319291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(sec->host_extents == NULL);
132045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
132145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(1,"transtab", "allocate sector %d\n", sno);
132245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
132345f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)( 8 * tc_sector_szQ );
1324cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
132545f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TC)",
132645f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     8 * tc_sector_szQ );
132745f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
132845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
1329cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      sec->tc = (ULong*)(AddrH)sr_Res(sres);
133045f4e7c91119c7d01a59f5e827c67841632c9314sewardj
133145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      sres = VG_(am_mmap_anon_float_valgrind)
133245f4e7c91119c7d01a59f5e827c67841632c9314sewardj                ( N_TTES_PER_SECTOR * sizeof(TTEntry) );
1333cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
133445f4e7c91119c7d01a59f5e827c67841632c9314sewardj         VG_(out_of_memory_NORETURN)("initialiseSector(TT)",
133545f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                     N_TTES_PER_SECTOR * sizeof(TTEntry) );
133645f4e7c91119c7d01a59f5e827c67841632c9314sewardj	 /*NOTREACHED*/
133745f4e7c91119c7d01a59f5e827c67841632c9314sewardj      }
1338cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      sec->tt = (TTEntry*)(AddrH)sr_Res(sres);
13396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
13406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
13416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].status   = Empty;
13426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].n_tte2ec = 0;
13436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
134445f4e7c91119c7d01a59f5e827c67841632c9314sewardj
1345291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Set up the host_extents array. */
1346291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sec->host_extents
1347291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         = VG_(newXA)(ttaux_malloc, "transtab.initialiseSector(host_extents)",
1348291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                      ttaux_free,
1349291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                      sizeof(HostExtent));
1350291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
13515d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      /* Add an entry in the sector_search_order */
13525d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      for (i = 0; i < N_SECTORS; i++) {
13535d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[i] == -1)
13545d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            break;
13555d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
13565d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      vg_assert(i >= 0 && i < N_SECTORS);
13575d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sector_search_order[i] = sno;
13585d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1359fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
1360738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "TT/TC: initialise sector %d\n", sno);
13616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1362fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   } else {
13636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
13646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Sector has been used before.  Dump the old contents. */
136545f4e7c91119c7d01a59f5e827c67841632c9314sewardj      VG_(debugLog)(1,"transtab", "recycle sector %d\n", sno);
13666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tt != NULL);
13676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->tc_next != NULL);
13686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      n_dump_count += sec->tt_n_inuse;
13696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1370291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VexArch vex_arch = VexArch_INVALID;
1371291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(machine_get_VexArchInfo)( &vex_arch, NULL );
1372291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
13736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Visit each just-about-to-be-abandoned translation. */
1374e25053c5aaefc6a4039dcd557adf24d8bb23db69sewardj      if (0) VG_(printf)("QQQ unlink-entire-sector: %d START\n", sno);
1375fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
13766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tt[i].status == InUse) {
13776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec >= 1);
13786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec <= 3);
13796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            n_dump_osize += vge_osize(&sec->tt[i].vge);
13803786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            /* Tell the tool too. */
13810b9d74abd0a663b530d290b2b788ddeda46e5400sewardj            if (VG_(needs).superblock_discards) {
13820b9d74abd0a663b530d290b2b788ddeda46e5400sewardj               VG_TDICT_CALL( tool_discard_superblock_info,
13834ba057cce1d81a949f5a899b5abb99e90a731bccsewardj                              sec->tt[i].entry,
13846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                              sec->tt[i].vge );
13853786772222c5b31fd6cc5586bcd1ce0da58f1dbesewardj            }
1386291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            unchain_in_preparation_for_deletion(vex_arch, sno, i);
13876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
13886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->tt[i].n_tte2ec == 0);
13896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
13906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].status   = Empty;
13916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec->tt[i].n_tte2ec = 0;
13926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
1393e25053c5aaefc6a4039dcd557adf24d8bb23db69sewardj      if (0) VG_(printf)("QQQ unlink-entire-sector: %d END\n", sno);
13946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
13956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Free up the eclass structures. */
13966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
13976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->ec2tte_size[i] == 0) {
13986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte_used[i] == 0);
13996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] == NULL);
14006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         } else {
14016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(sec->ec2tte[i] != NULL);
1402291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            ttaux_free(sec->ec2tte[i]);
14036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte[i] = NULL;
14046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_size[i] = 0;
14056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            sec->ec2tte_used[i] = 0;
1406fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1407fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      }
14086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1409291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      /* Empty out the host extents array. */
1410291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(sec->host_extents != NULL);
1411291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(dropTailXA)(sec->host_extents, VG_(sizeXA)(sec->host_extents));
1412291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(VG_(sizeXA)(sec->host_extents) == 0);
1413291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
14145d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      /* Sanity check: ensure it is already in
14155d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         sector_search_order[]. */
14165d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      for (i = 0; i < N_SECTORS; i++) {
14175d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         if (sector_search_order[i] == sno)
14185d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            break;
14195d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      }
14205d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      vg_assert(i >= 0 && i < N_SECTORS);
14215d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
1422fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (VG_(clo_verbosity) > 2)
1423738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         VG_(message)(Vg_DebugMsg, "TT/TC: recycle sector %d\n", sno);
14246c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
14254ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
14266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tc_next = sec->tc;
14276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse = 0;
1428fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1429fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
14305d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
14315d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   { Bool sane = sanity_check_sector_search_order();
14325d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj     vg_assert(sane);
14335d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   }
14346c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1435de4a1d01951937632098a6cda45859afa587a06fsewardj
1436de4a1d01951937632098a6cda45859afa587a06fsewardj
1437fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Add a translation of vge to TT/TC.  The translation is temporarily
1438fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   in code[0 .. code_len-1].
1439de4a1d01951937632098a6cda45859afa587a06fsewardj
1440fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   pre: youngest_sector points to a valid (although possibly full)
1441fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sector.
1442fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
14438bddf58af8cc7342d4bde6712c5a6a33bf2850d4njnvoid VG_(add_to_transtab)( VexGuestExtents* vge,
14448bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn                           Addr64           entry,
14458bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn                           AddrH            code,
144626412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                           UInt             code_len,
1447291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           Bool             is_self_checking,
1448291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           Int              offs_profInc,
1449b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj                           UInt             n_guest_instrs,
1450291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                           VexArch          arch_host )
145122854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj{
1452fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int    tcAvailQ, reqdQ, y, i;
14535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   ULong  *tcptr, *tcptr2;
1454fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* srcP;
1455fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   UChar* dstP;
1456fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1457663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1458fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(vge->n_used >= 1 && vge->n_used <= 3);
1459e808930793aeddc4cfd3e7a94b665913bec2566csewardj
1460e808930793aeddc4cfd3e7a94b665913bec2566csewardj   /* 60000: should agree with N_TMPBUF in m_translate.c. */
1461e808930793aeddc4cfd3e7a94b665913bec2566csewardj   vg_assert(code_len > 0 && code_len < 60000);
1462fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1463b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj   /* Generally stay sane */
1464b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj   vg_assert(n_guest_instrs < 200); /* it can be zero, tho */
1465b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj
1466fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (0)
14678bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn      VG_(printf)("add_to_transtab(entry = 0x%llx, len = %d)\n",
1468fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                  entry, code_len);
1469fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1470fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_count++;
1471fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_tsize += code_len;
1472fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_in_osize += vge_osize(vge);
147326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj   if (is_self_checking)
147426412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj      n_in_sc_count++;
1475fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1476fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   y = youngest_sector;
1477fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(isValidSector(y));
1478fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1479fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (sectors[y].tc == NULL)
1480fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
1481fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1482fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Try putting the translation in this sector. */
14835f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   reqdQ = (code_len + 7) >> 3;
1484fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1485fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Will it fit in tc? */
1486fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
1487fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
1488fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
1489fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
1490fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1491fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (tcAvailQ < reqdQ
1492fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj       || sectors[y].tt_n_inuse >= N_TTES_PER_SECTOR_USABLE) {
1493fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* No.  So move on to the next sector.  Either it's never been
1494fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         used before, in which case it will get its tt/tc allocated
1495fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         now, or it has been used before, in which case it is set to be
1496fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         empty, hence throwing out the oldest sector. */
1497a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      vg_assert(tc_sector_szQ > 0);
1498a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj      VG_(debugLog)(1,"transtab",
1499a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      "declare sector %d full "
1500a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      "(TT loading %2d%%, TC loading %2d%%)\n",
1501a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      y,
1502a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      (100 * sectors[y].tt_n_inuse)
1503a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                         / N_TTES_PER_SECTOR,
1504a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                      (100 * (tc_sector_szQ - tcAvailQ))
1505a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj                         / tc_sector_szQ);
1506fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      youngest_sector++;
1507fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (youngest_sector >= N_SECTORS)
1508fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         youngest_sector = 0;
1509fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      y = youngest_sector;
1510fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      initialiseSector(y);
1511fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
151222854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
1513fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Be sure ... */
1514fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   tcAvailQ = ((ULong*)(&sectors[y].tc[tc_sector_szQ]))
1515fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj              - ((ULong*)(sectors[y].tc_next));
1516fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= 0);
1517fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ <= tc_sector_szQ);
1518fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tcAvailQ >= reqdQ);
1519fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse < N_TTES_PER_SECTOR_USABLE);
1520fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sectors[y].tt_n_inuse >= 0);
1521fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1522fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Copy into tc. */
15235f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr = sectors[y].tc_next;
15245f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr >= &sectors[y].tc[0]);
15255f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr <= &sectors[y].tc[tc_sector_szQ]);
1526fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
15275f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   dstP = (UChar*)tcptr;
1528fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   srcP = (UChar*)code;
1529291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(memcpy)(dstP, srcP, code_len);
1530fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tc_next += reqdQ;
1531fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt_n_inuse++;
1532fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1533fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* more paranoia */
15345f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   tcptr2 = sectors[y].tc_next;
15355f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 >= &sectors[y].tc[0]);
15365f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(tcptr2 <= &sectors[y].tc[tc_sector_szQ]);
1537fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1538fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find an empty tt slot, and use it.  There must be such a slot
1539fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      since tt is never allowed to get completely full. */
1540fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   i = HASH_TT(entry);
1541fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(i >= 0 && i < N_TTES_PER_SECTOR);
154222854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   while (True) {
1543fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[y].tt[i].status == Empty
1544fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          || sectors[y].tt[i].status == Deleted)
1545fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         break;
1546fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      i++;
1547fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (i >= N_TTES_PER_SECTOR)
1548fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         i = 0;
154922854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj   }
1550fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1551291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   TTEntry__init(&sectors[y].tt[i]);
1552fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].status = InUse;
15535f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   sectors[y].tt[i].tcptr  = tcptr;
1554fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].count  = 0;
1555b7301c690606964dd1ece81ce2fd2b6fd90ab012sewardj   sectors[y].tt[i].weight = n_guest_instrs == 0 ? 1 : n_guest_instrs;
1556fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].vge    = *vge;
1557fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   sectors[y].tt[i].entry  = entry;
1558fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1559291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Patch in the profile counter location, if necessary. */
1560291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   if (offs_profInc != -1) {
1561291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      vg_assert(offs_profInc >= 0 && offs_profInc < code_len);
1562291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VexInvalRange vir
1563291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         = LibVEX_PatchProfInc( arch_host,
1564291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                dstP + offs_profInc,
1565291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                &sectors[y].tt[i].count );
1566291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      VG_(invalidate_icache)( (void*)vir.start, vir.len );
1567291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
1568291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
1569291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( dstP, code_len );
1570291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
1571291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Add this entry to the host_extents map, checking that we're
1572291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      adding in order. */
1573291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   { HostExtent hx;
1574291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.start = (UChar*)tcptr;
1575291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.len   = code_len;
1576291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     hx.tteNo = i;
1577291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     vg_assert(hx.len > 0); /* bsearch fails w/ zero length entries */
1578291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     XArray* hx_array = sectors[y].host_extents;
1579291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     vg_assert(hx_array);
1580291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     Word n = VG_(sizeXA)(hx_array);
1581291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     if (n > 0) {
1582291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        HostExtent* hx_prev = (HostExtent*)VG_(indexXA)(hx_array, n-1);
1583291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj        vg_assert(hx_prev->start + hx_prev->len <= hx.start);
1584291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     }
1585291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj     VG_(addToXA)(hx_array, &hx);
1586291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   }
1587291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
15886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Update the fast-cache. */
1589291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   setFastCacheEntry( entry, tcptr );
15906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
15916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Note the eclass numbers for this translation. */
15926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   upd_eclasses_after_add( &sectors[y], i );
159322854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj}
159422854b907c1925a9af97ad20ca3dacb5e300d6f9sewardj
1595fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1596fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/* Search for the translation of the given guest address.  If
1597fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   requested, a successful search can also cause the fast-caches to be
1598fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   updated.
1599fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj*/
1600291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool VG_(search_transtab) ( /*OUT*/AddrH* res_hcode,
1601291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                            /*OUT*/UInt*  res_sNo,
1602291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                            /*OUT*/UInt*  res_tteNo,
1603fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Addr64        guest_addr,
1604fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                            Bool          upd_cache )
16056c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1606fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int i, j, k, kstart, sno;
1607663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1608663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1609fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Find the initial probe point just once.  It will be the same in
1610fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      all sectors and avoids multiple expensive % operations. */
1611fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   n_full_lookups++;
1612fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   k      = -1;
1613fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   kstart = HASH_TT(guest_addr);
1614fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(kstart >= 0 && kstart < N_TTES_PER_SECTOR);
1615fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
16165d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Search in all the sectors,using sector_search_order[] as a
16175d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      heuristic guide as to what order to visit the sectors. */
1618fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < N_SECTORS; i++) {
1619fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
16205d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sno = sector_search_order[i];
16215d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      if (UNLIKELY(sno == -1))
16225d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj         return False; /* run out of sectors to search */
1623fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1624fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      k = kstart;
1625fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (j = 0; j < N_TTES_PER_SECTOR; j++) {
1626fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         n_lookup_probes++;
1627fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == InUse
1628fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             && sectors[sno].tt[k].entry == guest_addr) {
1629fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            /* found it */
1630fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (upd_cache)
1631fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               setFastCacheEntry(
1632291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                  guest_addr, sectors[sno].tt[k].tcptr );
1633291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_hcode)
1634291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj               *res_hcode = (AddrH)sectors[sno].tt[k].tcptr;
1635291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_sNo)
1636291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj               *res_sNo = sno;
1637291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj            if (res_tteNo)
1638291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj               *res_tteNo = k;
16395d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            /* pull this one one step closer to the front.  For large
16405d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               apps this more or less halves the number of required
16415d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               probes. */
16425d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            if (i > 0) {
16435d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               Int tmp = sector_search_order[i-1];
16445d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               sector_search_order[i-1] = sector_search_order[i];
16455d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj               sector_search_order[i] = tmp;
16465d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj            }
1647fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            return True;
1648fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
1649fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[k].status == Empty)
1650fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            break; /* not found in this sector */
1651fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         k++;
1652fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (k == N_TTES_PER_SECTOR)
1653fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            k = 0;
16546c3769f487145a08c01b58d6e5db3ba274062ad4sewardj      }
1655fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1656fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      /* If we fall off the end, all entries are InUse and not
1657fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         matching, or Deleted.  In any case we did not find it in this
1658fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         sector. */
16596c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
1660fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1661fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Not found in any sector. */
1662fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
16636c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1664de4a1d01951937632098a6cda45859afa587a06fsewardj
1665de4a1d01951937632098a6cda45859afa587a06fsewardj
16666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
16676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*--- Delete translations.                                  ---*/
16686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/*-------------------------------------------------------------*/
16696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
16700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* forward */
16710ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64, ULong );
16720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
16736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Stuff for deleting translations which intersect with a given
16746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   address range.  Unfortunately, to make this run at a reasonable
16756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   speed, it is complex. */
1676fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
1677fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1678a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlap1 ( Addr64 s1, ULong r1, Addr64 s2, ULong r2 )
16796c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1680a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj   Addr64 e1 = s1 + r1 - 1ULL;
1681a30545069556d3dca4ca3feb7c621bdcb7b34107sewardj   Addr64 e2 = s2 + r2 - 1ULL;
1682fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (e1 < s2 || e2 < s1)
1683fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1684fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return True;
16856c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1686de4a1d01951937632098a6cda45859afa587a06fsewardj
1687fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic inline
1688a30545069556d3dca4ca3feb7c621bdcb7b34107sewardjBool overlaps ( Addr64 start, ULong range, VexGuestExtents* vge )
16896c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
1690fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[0], (UInt)vge->len[0]))
1691fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1692fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 2)
1693fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1694fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[1], (UInt)vge->len[1]))
1695fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1696fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (vge->n_used < 3)
1697fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return False;
1698fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (overlap1(start, range, vge->base[2], (UInt)vge->len[2]))
1699fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      return True;
1700fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return False;
17016c3769f487145a08c01b58d6e5db3ba274062ad4sewardj}
1702de4a1d01951937632098a6cda45859afa587a06fsewardj
1703de4a1d01951937632098a6cda45859afa587a06fsewardj
17046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete a tt entry, and update all the eclass data accordingly. */
17056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1706291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjstatic void delete_tte ( /*MOD*/Sector* sec, UInt secNo, Int tteno,
1707291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                         VexArch vex_arch )
17086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
17096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i, ec_num, ec_idx;
17106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
17116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1712291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* sec and secNo are mutually redundant; cross-check. */
1713291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   vg_assert(sec == &sectors[secNo]);
1714291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
17156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tteno >= 0 && tteno < N_TTES_PER_SECTOR);
17166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte = &sec->tt[tteno];
17176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->status == InUse);
17186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(tte->n_tte2ec >= 1 && tte->n_tte2ec <= 3);
17196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1720291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Unchain .. */
1721291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   unchain_in_preparation_for_deletion(vex_arch, secNo, tteno);
1722291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
17236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Deal with the ec-to-tte links first. */
17246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < tte->n_tte2ec; i++) {
17256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_num = (Int)tte->tte2ec_ec[i];
17266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec_idx = tte->tte2ec_ix[i];
17276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_num >= 0 && ec_num < ECLASS_N);
17286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx >= 0);
17296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec_idx < sec->ec2tte_used[ec_num]);
17306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Assert that the two links point at each other. */
17316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sec->ec2tte[ec_num][ec_idx] == (UShort)tteno);
17326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* "delete" the pointer back to here. */
17336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      sec->ec2tte[ec_num][ec_idx] = EC2TTE_DELETED;
17346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
17356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Now fix up this TTEntry. */
17376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->status   = Deleted;
17386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   tte->n_tte2ec = 0;
17396c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17406c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Stats .. */
17416c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   sec->tt_n_inuse--;
17426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_count++;
17436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   n_disc_osize += vge_osize(&tte->vge);
17446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Tell the tool too. */
17460b9d74abd0a663b530d290b2b788ddeda46e5400sewardj   if (VG_(needs).superblock_discards) {
17470b9d74abd0a663b530d290b2b788ddeda46e5400sewardj      VG_TDICT_CALL( tool_discard_superblock_info,
17484ba057cce1d81a949f5a899b5abb99e90a731bccsewardj                     tte->entry,
17496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                     tte->vge );
17506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
17516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
17526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, but
17556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   only consider translations in the specified eclass. */
17566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1758291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector_eclass ( /*MOD*/Sector* sec, UInt secNo,
17596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                                            Addr64 guest_start, ULong range,
1760291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                            Int ec,
1761291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                            VexArch vex_arch )
17626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
17636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int      i;
17646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   UShort   tteno;
17656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool     anyDeld = False;
17666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   TTEntry* tte;
17676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   vg_assert(ec >= 0 && ec < ECLASS_N);
17696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < sec->ec2tte_used[ec]; i++) {
17716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tteno = sec->ec2tte[ec][i];
17736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (tteno == EC2TTE_DELETED) {
17746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         /* already deleted */
17756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         continue;
17766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
17776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tteno < N_TTES_PER_SECTOR);
17796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      tte = &sec->tt[tteno];
17816c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(tte->status == InUse);
17826c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17836c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (overlaps( guest_start, range, &tte->vge )) {
17846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
1785291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         delete_tte( sec, secNo, (Int)tteno, vex_arch );
17866c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
17876c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
17896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
17916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
17926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj/* Delete translations from sec which intersect specified range, the
17956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   slow way, by inspecting all translations in sec. */
17966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
17976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardjstatic
1798291849fb0285e0998b4c9e33eb153eb3373c4a88sewardjBool delete_translations_in_sector ( /*MOD*/Sector* sec, UInt secNo,
1799291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                     Addr64 guest_start, ULong range,
1800291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                                     VexArch vex_arch )
18016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj{
18026c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int  i;
18036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool anyDeld = False;
18046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18056c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   for (i = 0; i < N_TTES_PER_SECTOR; i++) {
18066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      if (sec->tt[i].status == InUse
18076c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj          && overlaps( guest_start, range, &sec->tt[i].vge )) {
18086c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeld = True;
1809291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj         delete_tte( sec, secNo, i, vex_arch );
18106c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
18116c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
18126c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   return anyDeld;
18146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj}
18156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
181745f4e7c91119c7d01a59f5e827c67841632c9314sewardjvoid VG_(discard_translations) ( Addr64 guest_start, ULong range,
181845f4e7c91119c7d01a59f5e827c67841632c9314sewardj                                 HChar* who )
18196c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
18206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Sector* sec;
18216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int     sno, ec;
18226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Bool    anyDeleted = False;
18236c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1824663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(init_done);
1825663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
1826a16ea0a5fa05dac343e63feddf63f51cb0c340bdsewardj   VG_(debugLog)(2, "transtab",
182745f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    "discard_translations(0x%llx, %lld) req by %s\n",
182845f4e7c91119c7d01a59f5e827c67841632c9314sewardj                    guest_start, range, who );
182945f4e7c91119c7d01a59f5e827c67841632c9314sewardj
18306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Pre-deletion sanity check */
18316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
18326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool sane = sanity_check_all_sectors();
18336c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
18346c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
18356c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18366c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range == 0)
18376c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      return;
18386c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1839291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VexArch vex_arch = VexArch_INVALID;
1840291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(machine_get_VexArchInfo)( &vex_arch, NULL );
1841291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj
18426c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* There are two different ways to do this.
18436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      If the range fits within a single address-range equivalence
18456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, as will be the case for a cache line sized invalidation,
18466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      then we only have to inspect the set of translations listed in
18476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      that equivalence class, and also in the "sin-bin" equivalence
18486c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class ECLASS_MISC.
18496c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18506c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Otherwise, the invalidation is of a larger range and probably
18516c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      results from munmap.  In this case it's (probably!) faster just
18526c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      to inspect all translations, dump those we don't want, and
18536c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      regenerate the equivalence class information (since modifying it
18546c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      in-situ is even more expensive).
18556c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   */
18566c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18576c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* First off, figure out if the range falls within a single class,
18586c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      and if so which one. */
18596c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18606c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   ec = ECLASS_MISC;
18616c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (range < (1ULL << ECLASS_SHIFT))
18626c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      ec = range_to_eclass( guest_start, (UInt)range );
18636c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18646c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* if ec is ECLASS_MISC then we aren't looking at just a single
18656c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      class, so use the slow scheme.  Else use the fast scheme,
18666c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      examining 'ec' and ECLASS_MISC. */
18676c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18686c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (ec != ECLASS_MISC) {
18696c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18706c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
18716c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    FAST, ec = %d\n", ec);
18726c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18736c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* Fast scheme */
18746c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(ec >= 0 && ec < ECLASS_MISC);
18756c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18766c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (sno = 0; sno < N_SECTORS; sno++) {
18776c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
18786c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
18796c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
18806c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
1881291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, ec,
1882291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          vex_arch
1883291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       );
18846c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector_eclass(
1885291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, ECLASS_MISC,
1886291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          vex_arch
1887291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                       );
18886c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
18896c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18906c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   } else {
18916c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18926c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* slow scheme */
18936c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18946c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(debugLog)(2, "transtab",
18956c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj                       "                    SLOW, ec = %d\n", ec);
18966c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
18976c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (sno = 0; sno < N_SECTORS; sno++) {
18986c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
18996c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
19006c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
19016c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         anyDeleted |= delete_translations_in_sector(
1902291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj                          sec, sno, guest_start, range, vex_arch );
19036c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
19046c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
1905de4a1d01951937632098a6cda45859afa587a06fsewardj   }
1906de4a1d01951937632098a6cda45859afa587a06fsewardj
1907fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (anyDeleted)
1908fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      invalidateFastCache();
19096c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
19100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* don't forget the no-redir cache */
19110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_discard_translations( guest_start, range );
19120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19136c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   /* Post-deletion sanity check */
19146c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (VG_(clo_sanity_level >= 4)) {
19156c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int      i;
19166c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      TTEntry* tte;
19176c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Bool     sane = sanity_check_all_sectors();
19186c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      vg_assert(sane);
19196c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      /* But now, also check the requested address range isn't
19206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         present anywhere. */
19216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (sno = 0; sno < N_SECTORS; sno++) {
19226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sec = &sectors[sno];
19236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (sec->tc == NULL)
19246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            continue;
19256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         for (i = 0; i < N_TTES_PER_SECTOR; i++) {
19266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            tte = &sec->tt[i];
19276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            if (tte->status != InUse)
19286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj               continue;
19296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            vg_assert(!overlaps( guest_start, range, &tte->vge ));
19306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         }
19316c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
19326c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
1933fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
19346c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
19356c3769f487145a08c01b58d6e5db3ba274062ad4sewardj
1936fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
19370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*--- AUXILIARY: the unredirected TT/TC                    ---*/
19380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
19390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* A very simple translation cache which holds a small number of
19410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredirected translations.  This is completely independent of the
19420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   main tt/tc structures.  When unredir_tc or unredir_tt becomes full,
19430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   both structures are simply dumped and we start over.
19440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Since these translations are unredirected, the search key is (by
19460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   definition) the first address entry in the .vge field. */
19470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Sized to hold 500 translations of average size 1000 bytes. */
19490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define UNREDIR_SZB   1000
19510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TT  500
19530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj#define N_UNREDIR_TCQ (N_UNREDIR_TT * UNREDIR_SZB / sizeof(ULong))
19540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19550ec07f32bbbb209d749b9974408e6f025ad40b31sewardjtypedef
19560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   struct {
19570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      VexGuestExtents vge;
19580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Addr            hcode;
19590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      Bool            inUse;
19600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
19610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   UTCEntry;
19620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* We just allocate forwards in _tc, never deleting. */
196478c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic ULong    *unredir_tc;
196578c0c09d429c95115e826ef769ecaa6cff2ac338tomstatic Int      unredir_tc_used = N_UNREDIR_TCQ;
19660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Slots in _tt can come into use and out again (.inUse).
19680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Nevertheless _tt_highwater is maintained so that invalidations
19690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   don't have to scan all the slots when only a few are in use.
19700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   _tt_highwater holds the index of the highest ever allocated
19710ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   slot. */
19720ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic UTCEntry unredir_tt[N_UNREDIR_TT];
19730ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Int      unredir_tt_highwater;
19740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19760ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void init_unredir_tt_tc ( void )
19770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
19780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
197978c0c09d429c95115e826ef769ecaa6cff2ac338tom   if (unredir_tc == NULL) {
1980cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      SysRes sres = VG_(am_mmap_anon_float_valgrind)
1981cda2f0fbda4c4b2644babc830244be8aed95de1dnjn                       ( N_UNREDIR_TT * UNREDIR_SZB );
1982cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      if (sr_isError(sres)) {
1983cda2f0fbda4c4b2644babc830244be8aed95de1dnjn         VG_(out_of_memory_NORETURN)("init_unredir_tt_tc",
1984cda2f0fbda4c4b2644babc830244be8aed95de1dnjn                                     N_UNREDIR_TT * UNREDIR_SZB);
198578c0c09d429c95115e826ef769ecaa6cff2ac338tom         /*NOTREACHED*/
198678c0c09d429c95115e826ef769ecaa6cff2ac338tom      }
1987cda2f0fbda4c4b2644babc830244be8aed95de1dnjn      unredir_tc = (ULong *)(AddrH)sr_Res(sres);
198878c0c09d429c95115e826ef769ecaa6cff2ac338tom   }
19890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used = 0;
19900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
19910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt[i].inUse = False;
19920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt_highwater = -1;
19930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
19940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
19950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Do a sanity check; return False on failure. */
19960ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic Bool sanity_check_redir_tt_tc ( void )
19970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
19980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
19990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater < -1) return False;
20000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tt_highwater >= N_UNREDIR_TT) return False;
20010ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20020ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = unredir_tt_highwater+1; i < N_UNREDIR_TT; i++)
20030ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse)
20040ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return False;
20050ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20060ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used < 0) return False;
20070ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (unredir_tc_used > N_UNREDIR_TCQ) return False;
20080ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20090ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return True;
20100ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
20110ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20120ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20130ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/* Add an UNREDIRECTED translation of vge to TT/TC.  The translation
20140ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   is temporarily in code[0 .. code_len-1].
20150ec07f32bbbb209d749b9974408e6f025ad40b31sewardj*/
20160ec07f32bbbb209d749b9974408e6f025ad40b31sewardjvoid VG_(add_to_unredir_transtab)( VexGuestExtents* vge,
20170ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                   Addr64           entry,
20180ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                   AddrH            code,
20191dcee097db02f9ef3ba355162c4373d90d0e895cnjn                                   UInt             code_len )
20200ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
20210ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int   i, j, code_szQ;
20220ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   HChar *srcP, *dstP;
20230ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20240ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
20250ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20260ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* This is the whole point: it's not redirected! */
20270ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(entry == vge->base[0]);
20280ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20290ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* How many unredir_tt slots are needed */
20300ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   code_szQ = (code_len + 7) / 8;
20310ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20320ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* Look for an empty unredir_tc slot */
20330ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++)
20340ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
20350ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         break;
20360ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20370ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i >= N_UNREDIR_TT || code_szQ > (N_UNREDIR_TCQ - unredir_tc_used)) {
20380ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      /* It's full; dump everything we currently have */
20390ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      init_unredir_tt_tc();
20400ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      i = 0;
20410ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
20420ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20430ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
20440ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
20450ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ > 0);
20460ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(code_szQ + unredir_tc_used <= N_UNREDIR_TCQ);
20470ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(i >= 0 && i < N_UNREDIR_TT);
20480ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tt[i].inUse == False);
20490ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20500ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   if (i > unredir_tt_highwater)
20510ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      unredir_tt_highwater = i;
20520ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20530ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   dstP = (HChar*)&unredir_tc[unredir_tc_used];
20540ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   srcP = (HChar*)code;
20550ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (j = 0; j < code_len; j++)
20560ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      dstP[j] = srcP[j];
20570ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
2058291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   VG_(invalidate_icache)( dstP, code_len );
2059c0a02f88a9b5ca7cebebf67e1f2f5ebcadb1e238sewardj
20600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].inUse = True;
20610ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].vge   = *vge;
20620ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tt[i].hcode = (Addr)dstP;
20630ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20640ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   unredir_tc_used += code_szQ;
20650ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used >= 0);
20660ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(unredir_tc_used <= N_UNREDIR_TCQ);
20670ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20680ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(&dstP[code_len] <= (HChar*)&unredir_tc[unredir_tc_used]);
20690ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
20700ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20710ec07f32bbbb209d749b9974408e6f025ad40b31sewardjBool VG_(search_unredir_transtab) ( /*OUT*/AddrH* result,
20720ec07f32bbbb209d749b9974408e6f025ad40b31sewardj                                    Addr64        guest_addr )
20730ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
20740ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
20750ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i < N_UNREDIR_TT; i++) {
20760ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (!unredir_tt[i].inUse)
20770ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         continue;
20780ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].vge.base[0] == guest_addr) {
20790ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         *result = (AddrH)unredir_tt[i].hcode;
20800ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         return True;
20810ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      }
20820ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
20830ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   return False;
20840ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
20850ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20860ec07f32bbbb209d749b9974408e6f025ad40b31sewardjstatic void unredir_discard_translations( Addr64 guest_start, ULong range )
20870ec07f32bbbb209d749b9974408e6f025ad40b31sewardj{
20880ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   Int i;
20890ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20900ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   vg_assert(sanity_check_redir_tt_tc());
20910ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20920ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   for (i = 0; i <= unredir_tt_highwater; i++) {
20930ec07f32bbbb209d749b9974408e6f025ad40b31sewardj      if (unredir_tt[i].inUse
20940ec07f32bbbb209d749b9974408e6f025ad40b31sewardj          && overlaps( guest_start, range, &unredir_tt[i].vge))
20950ec07f32bbbb209d749b9974408e6f025ad40b31sewardj         unredir_tt[i].inUse = False;
20960ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   }
20970ec07f32bbbb209d749b9974408e6f025ad40b31sewardj}
20980ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
20990ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
21000ec07f32bbbb209d749b9974408e6f025ad40b31sewardj/*------------------------------------------------------------*/
2101fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Initialisation.                                      ---*/
2102fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2103fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2104fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(init_tt_tc) ( void )
21056c3769f487145a08c01b58d6e5db3ba274062ad4sewardj{
21066c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   Int i, j, avg_codeszQ;
2107de4a1d01951937632098a6cda45859afa587a06fsewardj
2108663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   vg_assert(!init_done);
2109663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj   init_done = True;
2110663a1bd7a8def9d4ef4a10615732a15cc9b09171sewardj
2111fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Otherwise lots of things go wrong... */
2112fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(ULong) == 8);
2113fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(sizeof(Addr64) == 8);
21145f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries really are 2 words long */
21155f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(Addr) == sizeof(void*));
21165f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof(FastCacheEntry) == 2 * sizeof(Addr));
21175f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache entries are packed back-to-back with no spaces */
21185f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(sizeof( VG_(tt_fast) ) == VG_TT_FAST_SIZE * sizeof(FastCacheEntry));
21195f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   /* check fast cache is aligned as we requested.  Not fatal if it
21205f76de086a6d643db51e50a4e623df7dfc9b6161sewardj      isn't, but we might as well make sure. */
21215f76de086a6d643db51e50a4e623df7dfc9b6161sewardj   vg_assert(VG_IS_16_ALIGNED( ((Addr) & VG_(tt_fast)[0]) ));
2122de4a1d01951937632098a6cda45859afa587a06fsewardj
2123fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2)
2124fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2125fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                   "TT/TC: VG_(init_tt_tc) "
2126738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                   "(startup of code management)\n");
2127fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2128fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Figure out how big each tc area should be.  */
212943b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   avg_codeszQ   = (VG_(details).avg_translation_sizeB + 7) / 8;
213043b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn   tc_sector_szQ = N_TTES_PER_SECTOR_USABLE * (1 + avg_codeszQ);
2131fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2132fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Ensure the calculated value is not way crazy. */
2133fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   vg_assert(tc_sector_szQ >= 2 * N_TTES_PER_SECTOR_USABLE);
21341e0fff690e9c571275e8025eb2dcff7bf29b53afsewardj   vg_assert(tc_sector_szQ <= 100 * N_TTES_PER_SECTOR_USABLE);
2135fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2136fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* Initialise the sectors */
2137fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   youngest_sector = 0;
2138fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (i = 0; i < N_SECTORS; i++) {
2139fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tc = NULL;
2140fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tt = NULL;
2141fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tc_next = NULL;
2142fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      sectors[i].tt_n_inuse = 0;
21436c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (j = 0; j < ECLASS_N; j++) {
21446c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sectors[i].ec2tte_size[j] = 0;
21456c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sectors[i].ec2tte_used[j] = 0;
21466c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         sectors[i].ec2tte[j] = NULL;
21476c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
2148291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj      sectors[i].host_extents = NULL;
21496c3769f487145a08c01b58d6e5db3ba274062ad4sewardj   }
21504ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
21515d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   /* Initialise the sector_search_order hint table. */
21525d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj   for (i = 0; i < N_SECTORS; i++)
21535d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj      sector_search_order[i] = -1;
21545d0d1f3a78d6c5c765360982a08d87a068ce7f1csewardj
2155291849fb0285e0998b4c9e33eb153eb3373c4a88sewardj   /* Initialise the fast cache. */
2156fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   invalidateFastCache();
2157fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
21580ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   /* and the unredir tt/tc */
21590ec07f32bbbb209d749b9974408e6f025ad40b31sewardj   init_unredir_tt_tc();
21600ec07f32bbbb209d749b9974408e6f025ad40b31sewardj
2161fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   if (VG_(clo_verbosity) > 2) {
2162fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2163738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         "TT/TC: cache: %d sectors of %d bytes each = %d total\n",
2164fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          N_SECTORS, 8 * tc_sector_szQ,
2165fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj          N_SECTORS * 8 * tc_sector_szQ );
2166fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      VG_(message)(Vg_DebugMsg,
2167738856f99eea33d86ce91dcb1d6cd5b151e307casewardj         "TT/TC: table: %d total entries, max occupancy %d (%d%%)\n",
2168fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         N_SECTORS * N_TTES_PER_SECTOR,
2169fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         N_SECTORS * N_TTES_PER_SECTOR_USABLE,
2170fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         SECTOR_TT_LIMIT_PERCENT );
2171fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   }
217245f4e7c91119c7d01a59f5e827c67841632c9314sewardj
217345f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "transtab",
217445f4e7c91119c7d01a59f5e827c67841632c9314sewardj      "cache: %d sectors of %d bytes each = %d total\n",
217545f4e7c91119c7d01a59f5e827c67841632c9314sewardj       N_SECTORS, 8 * tc_sector_szQ,
217645f4e7c91119c7d01a59f5e827c67841632c9314sewardj       N_SECTORS * 8 * tc_sector_szQ );
217745f4e7c91119c7d01a59f5e827c67841632c9314sewardj   VG_(debugLog)(2, "transtab",
217845f4e7c91119c7d01a59f5e827c67841632c9314sewardj      "table: %d total entries, max occupancy %d (%d%%)\n",
217945f4e7c91119c7d01a59f5e827c67841632c9314sewardj      N_SECTORS * N_TTES_PER_SECTOR,
218045f4e7c91119c7d01a59f5e827c67841632c9314sewardj      N_SECTORS * N_TTES_PER_SECTOR_USABLE,
218145f4e7c91119c7d01a59f5e827c67841632c9314sewardj      SECTOR_TT_LIMIT_PERCENT );
2182de4a1d01951937632098a6cda45859afa587a06fsewardj}
2183de4a1d01951937632098a6cda45859afa587a06fsewardj
21844ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2185fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2186fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out statistics.                             ---*/
2187fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2188fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2189fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong safe_idiv( ULong a, ULong b )
219092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
219192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   return (b == 0 ? 0 : a / b);
219292e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
219392e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote
2194fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjUInt VG_(get_bbs_translated) ( void )
2195fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
2196fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return n_in_count;
2197fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj}
2198fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2199fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjvoid VG_(print_tt_tc_stats) ( void )
220092e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote{
220192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2202738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      "    tt/tc: %'llu tt lookups requiring %'llu probes\n",
2203fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_full_lookups, n_lookup_probes );
220492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2205738856f99eea33d86ce91dcb1d6cd5b151e307casewardj      "    tt/tc: %'llu fast-cache updates, %'llu flushes\n",
2206fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      n_fast_updates, n_fast_flushes );
2207fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
220892e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2209a0b6b2cf9abc7b0d87be1215a245eaccc0452af9bart                " transtab: new        %'lld "
2210738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                "(%'llu -> %'llu; ratio %'llu:10) [%'llu scs]\n",
2211fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_in_count, n_in_osize, n_in_tsize,
221226412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                safe_idiv(10*n_in_tsize, n_in_osize),
221326412bd2c4ef3e55683141f132ebd1eb32d8530bsewardj                n_in_sc_count);
221492e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote   VG_(message)(Vg_DebugMsg,
2215738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                " transtab: dumped     %'llu (%'llu -> ?" "?)\n",
2216fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_dump_count, n_dump_osize );
2217fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   VG_(message)(Vg_DebugMsg,
2218738856f99eea33d86ce91dcb1d6cd5b151e307casewardj                " transtab: discarded  %'llu (%'llu -> ?" "?)\n",
2219fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                n_disc_count, n_disc_osize );
22206c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj
22216c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   if (0) {
22226c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      Int i;
22236c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n");
22246c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      for (i = 0; i < ECLASS_N; i++) {
22256c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         VG_(printf)(" %4d", sectors[0].ec2tte_used[i]);
22266c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj         if (i % 16 == 15)
22276c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj            VG_(printf)("\n");
22286c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      }
22296c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj      VG_(printf)("\n\n");
22306c1bbbb1799cc34d05e2c1bae06f5533151eaaa3sewardj   }
223192e7b7f3d93564e293483fcf0f52f2d6f6c6dcc0nethercote}
2232de4a1d01951937632098a6cda45859afa587a06fsewardj
2233fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
2234fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*--- Printing out of profiling results.                   ---*/
2235fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj/*------------------------------------------------------------*/
22364ccf707a1b52898b878fc90dc0054a0c23cc9fccsewardj
2237fa8ec113ecff891bdefb13dd361b40a503a992f8sewardjstatic ULong score ( TTEntry* tte )
2238fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj{
2239fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   return ((ULong)tte->weight) * ((ULong)tte->count);
2240de4a1d01951937632098a6cda45859afa587a06fsewardj}
2241de4a1d01951937632098a6cda45859afa587a06fsewardj
22422025cf98a3210c175a90fc77cb599cca1643bd68njnULong VG_(get_BB_profile) ( BBProfEntry tops[], UInt n_tops )
2243de4a1d01951937632098a6cda45859afa587a06fsewardj{
2244fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   Int   sno, i, r, s;
22452025cf98a3210c175a90fc77cb599cca1643bd68njn   ULong score_total;
2246fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2247fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   /* First, compute the total weighted count, and find the top N
22482025cf98a3210c175a90fc77cb599cca1643bd68njn      ttes.  tops contains pointers to the most-used n_tops blocks, in
2249fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      descending order (viz, tops[0] is the highest scorer). */
22502025cf98a3210c175a90fc77cb599cca1643bd68njn   for (i = 0; i < n_tops; i++) {
22512025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].addr  = 0;
22522025cf98a3210c175a90fc77cb599cca1643bd68njn      tops[i].score = 0;
22532025cf98a3210c175a90fc77cb599cca1643bd68njn   }
2254fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2255fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   score_total = 0;
2256fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj
2257fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj   for (sno = 0; sno < N_SECTORS; sno++) {
2258fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      if (sectors[sno].tc == NULL)
225918d7513cc08bf982711c8a22b70d56af6aa87b33sewardj         continue;
2260fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj      for (i = 0; i < N_TTES_PER_SECTOR; i++) {
2261fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         if (sectors[sno].tt[i].status != InUse)
2262fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            continue;
2263fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         score_total += score(&sectors[sno].tt[i]);
2264fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* Find the rank for sectors[sno].tt[i]. */
22652025cf98a3210c175a90fc77cb599cca1643bd68njn         r = n_tops-1;
2266fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         while (True) {
2267fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            if (r == -1)
2268fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               break;
22692025cf98a3210c175a90fc77cb599cca1643bd68njn             if (tops[r].addr == 0) {
2270fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               r--;
2271fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               continue;
2272fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
22732025cf98a3210c175a90fc77cb599cca1643bd68njn             if ( score(&sectors[sno].tt[i]) > tops[r].score ) {
2274fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                r--;
2275fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj                continue;
2276fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             }
2277fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj             break;
2278fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
2279fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         r++;
22802025cf98a3210c175a90fc77cb599cca1643bd68njn         vg_assert(r >= 0 && r <= n_tops);
2281fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         /* This bb should be placed at r, and bbs above it shifted
2282fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj            upwards one slot. */
22832025cf98a3210c175a90fc77cb599cca1643bd68njn         if (r < n_tops) {
22842025cf98a3210c175a90fc77cb599cca1643bd68njn            for (s = n_tops-1; s > r; s--)
2285fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj               tops[s] = tops[s-1];
22862025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].addr  = sectors[sno].tt[i].entry;
22872025cf98a3210c175a90fc77cb599cca1643bd68njn            tops[r].score = score( &sectors[sno].tt[i] );
2288fa8ec113ecff891bdefb13dd361b40a503a992f8sewardj         }
2289de4a1d01951937632098a6cda45859afa587a06fsewardj      }
2290de4a1d01951937632098a6cda45859afa587a06fsewardj   }
2291de4a1d01951937632098a6cda45859afa587a06fsewardj
22922025cf98a3210c175a90fc77cb599cca1643bd68njn   return score_total;
2293c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj}
2294c0d8f68810eb79a5a6cb6049d6a4ab1de7dc4e18sewardj
2295de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
22968bddf58af8cc7342d4bde6712c5a6a33bf2850d4njn/*--- end                                                          ---*/
2297de4a1d01951937632098a6cda45859afa587a06fsewardj/*--------------------------------------------------------------------*/
2298