1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* -*- mode: C; c-basic-offset: 3; indent-tabs-mode: nil; -*- */
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This file is part of drd, a thread error detector.
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>.
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is free software; you can redistribute it and/or
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  modify it under the terms of the GNU General Public License as
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  published by the Free Software Foundation; either version 2 of the
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  License, or (at your option) any later version.
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is distributed in the hope that it will be useful, but
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WITHOUT ANY WARRANTY; without even the implied warranty of
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  General Public License for more details.
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  You should have received a copy of the GNU General Public License
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  along with this program; if not, write to the Free Software
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  02111-1307, USA.
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  The GNU General Public License is contained in the file COPYING.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_basics.h"           /* DRD_() */
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_bitmap.h"
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_error.h"
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "drd_suppression.h"
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_drd_bitmap.h"
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h"      /* Addr, SizeT */
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_debuginfo.h"   /* VG_(get_objname)() */
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h"  /* tl_assert() */
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h"    /* VG_(memset) */
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h"   /* VG_(printf) */
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_machine.h"     /* VG_(get_IP)() */
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h"  /* VG_(malloc), VG_(free) */
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local function declarations. */
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bm2_merge(struct bitmap2* const bm2l,
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      const struct bitmap2* const bm2r);
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bm2_print(const struct bitmap2* const bm2);
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Local variables. */
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong s_bitmap_creation_count;
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong s_bitmap_merge_count;
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong s_bitmap2_merge_count;
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Function definitions. */
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct bitmap* DRD_(bm_new)()
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap* bm;
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If this assert fails, fix the definition of BITS_PER_BITS_PER_UWORD */
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* in drd_bitmap.h.                                                    */
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert((1 << BITS_PER_BITS_PER_UWORD) == BITS_PER_UWORD);
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bm = VG_(malloc)("drd.bitmap.bn.1", sizeof(*bm));
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(bm_init)(bm);
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bm;
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_delete)(struct bitmap* const bm)
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(bm_cleanup)(bm);
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(free)(bm);
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Initialize *bm. */
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_init)(struct bitmap* const bm)
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned i;
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * Cache initialization. a1 is initialized with a value that never can
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * match any valid address: the upper (ADDR_LSB_BITS + ADDR_IGNORED_BITS)
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * bits of a1 are always zero for a valid cache entry.
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    */
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < DRD_BITMAP_N_CACHE_ELEM; i++)
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm->cache[i].a1  = ~(UWord)1;
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm->cache[i].bm2 = 0;
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bm->oset = VG_(OSetGen_Create)(0, 0, DRD_(bm2_alloc_node),
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  "drd.bitmap.bn.2", DRD_(bm2_free_node));
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_bitmap_creation_count++;
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Free the memory allocated by DRD_(bm_init)(). */
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_cleanup)(struct bitmap* const bm)
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_Destroy)(bm->oset);
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Record an access of type access_type at addresses a .. a + size - 1 in
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * bitmap bm.
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @note The current implementation of bm_access_range does not work for the
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * highest addresses in the address range. At least on Linux this is
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * not a problem since the upper part of the address space is reserved
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * for the kernel.
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_range)(struct bitmap* const bm,
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const Addr a1, const Addr a2,
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           const BmAccessTypeT access_type)
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(access_type == eLoad || access_type == eStore);
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (access_type == eLoad)
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_access_range_load)(bm, a1, a2);
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_access_range_store)(bm, a1, a2);
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_range_load)(struct bitmap* const bm, Addr a1, Addr a2)
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr b, b_next;
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 <= a2);
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a2 < first_address_with_higher_msb(a2));
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 == first_address_with_same_lsb(a1));
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a2 == first_address_with_same_lsb(a2));
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (b = a1; b < a2; b = b_next)
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr b_start;
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr b_end;
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct bitmap2* bm2;
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord b0;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b_next = first_address_with_higher_msb(b);
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b_next > a2)
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_next = a2;
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(b));
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(bm2);
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (make_address(bm2->addr, 0) < a1)
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_start = a1;
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr, 0) < a2)
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_start = make_address(bm2->addr, 0);
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (make_address(bm2->addr + 1, 0) < a2)
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_end = make_address(bm2->addr + 1, 0);
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_end = a2;
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b_start && b_start < b_end && b_end && b_end <= a2);
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(address_msb(b_start) == address_msb(b_end - 1));
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (address_lsb(b_start) == 0 && address_lsb(b_end) == 0)
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unsigned k;
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bm2->bm1.bm0_r[k] = ~(UWord)0;
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bm0_set(bm2->bm1.bm0_r, b0);
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_load_1)(struct bitmap* const bm, const Addr a1)
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bm_access_aligned_load(bm, a1, 1);
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_load_2)(struct bitmap* const bm, const Addr a1)
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 1) == 0)
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_load(bm, a1, 2);
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_access_range)(bm, a1, a1 + 2, eLoad);
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_load_4)(struct bitmap* const bm, const Addr a1)
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 3) == 0)
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_load(bm, a1, 4);
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_access_range)(bm, a1, a1 + 4, eLoad);
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_load_8)(struct bitmap* const bm, const Addr a1)
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 7) == 0)
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_load(bm, a1, 8);
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if ((a1 & 3) == 0)
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_load(bm, a1 + 0, 4);
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_load(bm, a1 + 4, 4);
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_access_range)(bm, a1, a1 + 8, eLoad);
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_range_store)(struct bitmap* const bm,
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 const Addr a1, const Addr a2)
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr b, b_next;
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 <= a2);
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a2 < first_address_with_higher_msb(a2));
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 == first_address_with_same_lsb(a1));
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a2 == first_address_with_same_lsb(a2));
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (b = a1; b < a2; b = b_next)
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr b_start;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr b_end;
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct bitmap2* bm2;
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord b0;
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b_next = first_address_with_higher_msb(b);
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b_next > a2)
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_next = a2;
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2 = bm2_lookup_or_insert_exclusive(bm, address_msb(b));
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(bm2);
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (make_address(bm2->addr, 0) < a1)
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_start = a1;
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr, 0) < a2)
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_start = make_address(bm2->addr, 0);
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (make_address(bm2->addr + 1, 0) < a2)
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_end = make_address(bm2->addr + 1, 0);
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_end = a2;
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b_start && b_start < b_end && b_end && b_end <= a2);
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(address_msb(b_start) == address_msb(b_end - 1));
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (address_lsb(b_start) == 0 && address_lsb(b_end) == 0)
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unsigned k;
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bm2->bm1.bm0_w[k] = ~(UWord)0;
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bm0_set(bm2->bm1.bm0_w, b0);
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_store_1)(struct bitmap* const bm, const Addr a1)
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bm_access_aligned_store(bm, a1, 1);
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_store_2)(struct bitmap* const bm, const Addr a1)
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 1) == 0)
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_store(bm, a1, 2);
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_access_range)(bm, a1, a1 + 2, eStore);
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_store_4)(struct bitmap* const bm, const Addr a1)
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 3) == 0)
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_store(bm, a1, 4);
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_access_range)(bm, a1, a1 + 4, eStore);
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_access_store_8)(struct bitmap* const bm, const Addr a1)
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 7) == 0)
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_store(bm, a1, 8);
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if ((a1 & 3) == 0)
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_store(bm, a1 + 0, 4);
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm_access_aligned_store(bm, a1 + 4, 4);
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DRD_(bm_access_range)(bm, a1, a1 + 8, eStore);
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_has)(struct bitmap* const bm, const Addr a1, const Addr a2,
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  const BmAccessTypeT access_type)
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(access_type == eLoad || access_type == eStore);
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (access_type == eLoad)
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_has_any_load)(bm, a1, a2);
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_has_any_store)(bm, a1, a2);
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDRD_(bm_has_any_load)(struct bitmap* const bm, const Addr a1, const Addr a2)
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr b, b_next;
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (b = a1; b < a2; b = b_next)
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const struct bitmap2* bm2 = bm2_lookup(bm, address_msb(b));
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b_next = first_address_with_higher_msb(b);
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b_next > a2)
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_next = a2;
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2)
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr b_start;
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr b_end;
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UWord b0;
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         const struct bitmap1* const p1 = &bm2->bm1;
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr, 0) < a1)
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_start = a1;
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (make_address(bm2->addr, 0) < a2)
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               b_start = make_address(bm2->addr, 0);
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b_start && b_start <= a2);
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr + 1, 0) < a2)
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_end = make_address(bm2->addr + 1, 0);
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_end = a2;
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b_end && b_end <= a2);
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(b_start < b_end);
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bm0_is_set(p1->bm0_r, b0))
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return True;
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_has_any_store)(struct bitmap* const bm,
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            const Addr a1, const Addr a2)
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr b, b_next;
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (b = a1; b < a2; b = b_next)
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const struct bitmap2* bm2 = bm2_lookup(bm, address_msb(b));
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b_next = first_address_with_higher_msb(b);
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b_next > a2)
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_next = a2;
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2)
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr b_start;
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr b_end;
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UWord b0;
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         const struct bitmap1* const p1 = &bm2->bm1;
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr, 0) < a1)
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_start = a1;
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (make_address(bm2->addr, 0) < a2)
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               b_start = make_address(bm2->addr, 0);
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b_start && b_start <= a2);
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr + 1, 0) < a2)
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_end = make_address(bm2->addr + 1, 0);
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_end = a2;
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b_end && b_end <= a2);
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(b_start < b_end);
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bm0_is_set(p1->bm0_w, b0))
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return True;
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return True if there is a read access, write access or both   */
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* to any of the addresses in the range [ a1, a2 [ in bitmap bm. */
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_has_any_access)(struct bitmap* const bm,
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             const Addr a1, const Addr a2)
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr b, b_next;
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (b = a1; b < a2; b = b_next)
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const struct bitmap2* bm2 = bm2_lookup(bm, address_msb(b));
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b_next = first_address_with_higher_msb(b);
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b_next > a2)
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_next = a2;
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2)
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr b_start;
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr b_end;
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UWord b0;
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         const struct bitmap1* const p1 = &bm2->bm1;
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr, 0) < a1)
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_start = a1;
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (make_address(bm2->addr, 0) < a2)
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               b_start = make_address(bm2->addr, 0);
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b_start && b_start <= a2);
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr + 1, 0) < a2)
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_end = make_address(bm2->addr + 1, 0);
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_end = a2;
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b_end && b_end <= a2);
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(b_start < b_end);
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * Note: the statement below uses a binary or instead of a logical
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             * or on purpose.
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             */
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (bm0_is_set(p1->bm0_r, b0) | bm0_is_set(p1->bm0_w, b0))
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return True;
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Report whether an access of type access_type at address a is recorded in
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * bitmap bm.
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_has_1)(struct bitmap* const bm,
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    const Addr a, const BmAccessTypeT access_type)
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const struct bitmap2* p2;
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const struct bitmap1* p1;
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const UWord* p0;
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const UWord a0 = address_lsb(a);
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   p2 = bm2_lookup(bm, address_msb(a));
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (p2)
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p1 = &p2->bm1;
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p0 = (access_type == eLoad) ? p1->bm0_r : p1->bm0_w;
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return bm0_is_set(p0, a0) ? True : False;
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_clear)(struct bitmap* const bm, Addr a1, Addr a2)
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr b, b_next;
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1);
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 <= a2);
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 == first_address_with_same_lsb(a1));
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a2 == first_address_with_same_lsb(a2));
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (b = a1; b < a2; b = b_next)
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct bitmap2* p2;
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr c;
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b < a2);
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p2 = bm2_lookup_exclusive(bm, address_msb(b));
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b_next = first_address_with_higher_msb(b);
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b_next > a2)
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_next = a2;
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (p2 == 0)
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c = b;
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the first address in the bitmap that must be cleared does not */
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* start on an UWord boundary, start clearing the first addresses.  */
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (uword_lsb(address_lsb(c)))
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr c_next = first_address_with_higher_uword_msb(c);
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c_next > b_next)
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c_next = b_next;
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b && b <= c && c <= c_next && c_next <= b_next
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   && b_next <= a2);
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm0_clear_range(p2->bm1.bm0_r, address_lsb(c), SCALED_SIZE(c_next - c));
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm0_clear_range(p2->bm1.bm0_w, address_lsb(c), SCALED_SIZE(c_next - c));
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         c = c_next;
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If some UWords have to be cleared entirely, do this now. */
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (uword_lsb(address_lsb(c)) == 0)
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr c_next = first_address_with_same_uword_lsb(b_next);
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(uword_lsb(address_lsb(c)) == 0);
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(uword_lsb(address_lsb(c_next)) == 0);
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(c_next <= b_next);
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c_next > c)
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UWord idx = uword_msb(address_lsb(c));
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memset)(&p2->bm1.bm0_r[idx], 0, SCALED_SIZE((c_next - c) / 8));
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memset)(&p2->bm1.bm0_w[idx], 0, SCALED_SIZE((c_next - c) / 8));
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = c_next;
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the last address in the bitmap that must be cleared does not */
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall on an UWord boundary, clear the last addresses.            */
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm0_clear_range(p2->bm1.bm0_r, address_lsb(c), SCALED_SIZE(b_next - c));
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm0_clear_range(p2->bm1.bm0_w, address_lsb(c), SCALED_SIZE(b_next - c));
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Clear all references to loads in bitmap bm starting at address a1 and
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * up to but not including address a2.
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_clear_load)(struct bitmap* const bm, Addr a1, Addr a2)
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr b, b_next;
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1);
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 <= a2);
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 == first_address_with_same_lsb(a1));
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a2 == first_address_with_same_lsb(a2));
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (b = a1; b < a2; b = b_next)
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct bitmap2* p2;
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr c;
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b < a2);
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p2 = bm2_lookup_exclusive(bm, address_msb(b));
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b_next = first_address_with_higher_msb(b);
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b_next > a2)
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_next = a2;
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (p2 == 0)
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c = b;
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the first address in the bitmap that must be cleared does not */
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* start on an UWord boundary, start clearing the first addresses.  */
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b <= c && c < b_next && b_next <= a2);
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (uword_lsb(address_lsb(c)))
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr c_next = first_address_with_higher_uword_msb(c);
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c_next > b_next)
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c_next = b_next;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b && b <= c && c < c_next && c_next <= b_next
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   && b_next <= a2);
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm0_clear_range(p2->bm1.bm0_r, address_lsb(c), SCALED_SIZE(c_next - c));
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         c = c_next;
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If some UWords have to be cleared entirely, do this now. */
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (uword_lsb(address_lsb(c)) == 0)
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr c_next = first_address_with_same_uword_lsb(b_next);
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(uword_lsb(address_lsb(c)) == 0);
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(uword_lsb(address_lsb(c_next)) == 0);
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b && b <= c && c <= c_next && c_next <= b_next
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   && b_next <= a2);
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c_next > c)
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UWord idx = uword_msb(address_lsb(c));
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memset)(&p2->bm1.bm0_r[idx], 0, SCALED_SIZE((c_next - c) / 8));
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = c_next;
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the last address in the bitmap that must be cleared does not */
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall on an UWord boundary, clear the last addresses.            */
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm0_clear_range(p2->bm1.bm0_r, address_lsb(c), SCALED_SIZE(b_next - c));
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Clear all references to stores in bitmap bm starting at address a1 and
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * up to but not including address a2.
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_clear_store)(struct bitmap* const bm,
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          const Addr a1, const Addr a2)
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr b, b_next;
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1);
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 <= a2);
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a1 == first_address_with_same_lsb(a1));
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(a2 == first_address_with_same_lsb(a2));
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (b = a1; b < a2; b = b_next)
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct bitmap2* p2;
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr c;
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b < a2);
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p2 = bm2_lookup_exclusive(bm, address_msb(b));
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b_next = first_address_with_higher_msb(b);
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b_next > a2)
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_next = a2;
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (p2 == 0)
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c = b;
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the first address in the bitmap that must be cleared does not */
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* start on an UWord boundary, start clearing the first addresses.  */
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b <= c && c < b_next && b_next <= a2);
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (uword_lsb(address_lsb(c)))
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr c_next = first_address_with_higher_uword_msb(c);
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c_next > b_next)
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c_next = b_next;
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b && b <= c && c < c_next && c_next <= b_next
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   && b_next <= a2);
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm0_clear_range(p2->bm1.bm0_w, address_lsb(c), SCALED_SIZE(c_next - c));
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         c = c_next;
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If some UWords have to be cleared entirely, do this now. */
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (uword_lsb(address_lsb(c)) == 0)
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr c_next = first_address_with_same_uword_lsb(b_next);
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(uword_lsb(address_lsb(c)) == 0);
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(uword_lsb(address_lsb(c_next)) == 0);
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b && b <= c && c <= c_next && c_next <= b_next
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   && b_next <= a2);
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c_next > c)
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UWord idx = uword_msb(address_lsb(c));
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memset)(&p2->bm1.bm0_w[idx], 0, SCALED_SIZE((c_next - c) / 8));
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            c = c_next;
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the last address in the bitmap that must be cleared does not */
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall on an UWord boundary, clear the last addresses.            */
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef ENABLE_DRD_CONSISTENCY_CHECKS
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(a1 <= b && b <= c && c <= b_next && b_next <= a2);
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm0_clear_range(p2->bm1.bm0_w, address_lsb(c), SCALED_SIZE(b_next - c));
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Clear bitmap bm starting at address a1 and up to but not including address
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * a2. Return True if and only if any of the addresses was set before
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * clearing.
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_test_and_clear)(struct bitmap* const bm,
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             const Addr a1, const Addr a2)
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool result;
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   result = DRD_(bm_has_any_access)(bm, a1, a2) != 0;
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DRD_(bm_clear)(bm, a1, a2);
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return result;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_has_conflict_with)(struct bitmap* const bm,
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                const Addr a1, const Addr a2,
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                const BmAccessTypeT access_type)
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr b, b_next;
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm);
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (b = a1; b < a2; b = b_next)
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const struct bitmap2* bm2 = bm2_lookup(bm, address_msb(b));
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b_next = first_address_with_higher_msb(b);
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b_next > a2)
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b_next = a2;
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2)
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr b_start;
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Addr b_end;
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UWord b0;
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         const struct bitmap1* const p1 = &bm2->bm1;
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr, 0) < a1)
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_start = a1;
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (make_address(bm2->addr, 0) < a2)
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               b_start = make_address(bm2->addr, 0);
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b_start && b_start <= a2);
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (make_address(bm2->addr + 1, 0) < a2)
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_end = make_address(bm2->addr + 1, 0);
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b_end = a2;
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(a1 <= b_end && b_end <= a2);
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(b_start < b_end);
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(address_lsb(b_start) <= address_lsb(b_end - 1));
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (b0 = address_lsb(b_start); b0 <= address_lsb(b_end - 1); b0++)
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (access_type == eLoad)
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (bm0_is_set(p1->bm0_w, b0))
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               {
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return True;
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               tl_assert(access_type == eStore);
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               if (bm0_is_set(p1->bm0_r, b0)
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   | bm0_is_set(p1->bm0_w, b0))
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               {
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  return True;
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_load_has_conflict_with)(struct bitmap* const bm,
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     const Addr a1, const Addr a2)
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(bm_has_conflict_with)(bm, a1, a2, eLoad);
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_load_1_has_conflict_with)(struct bitmap* const bm, const Addr a1)
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bm_aligned_load_has_conflict_with(bm, a1, 1);
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_load_2_has_conflict_with)(struct bitmap* const bm, const Addr a1)
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 1) == 0)
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return bm_aligned_load_has_conflict_with(bm, a1, 2);
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eLoad);
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_load_4_has_conflict_with)(struct bitmap* const bm, const Addr a1)
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 3) == 0)
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return bm_aligned_load_has_conflict_with(bm, a1, 4);
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eLoad);
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_load_8_has_conflict_with)(struct bitmap* const bm, const Addr a1)
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 7) == 0)
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return bm_aligned_load_has_conflict_with(bm, a1, 8);
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eLoad);
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_store_1_has_conflict_with)(struct bitmap* const bm, const Addr a1)
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bm_aligned_store_has_conflict_with(bm, a1, 1);
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_store_2_has_conflict_with)(struct bitmap* const bm, const Addr a1)
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 1) == 0)
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return bm_aligned_store_has_conflict_with(bm, a1, 2);
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 2, eStore);
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_store_4_has_conflict_with)(struct bitmap* const bm, const Addr a1)
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 3) == 0)
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return bm_aligned_store_has_conflict_with(bm, a1, 4);
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 4, eStore);
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_store_8_has_conflict_with)(struct bitmap* const bm, const Addr a1)
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((a1 & 7) == 0)
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return bm_aligned_store_has_conflict_with(bm, a1, 8);
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return DRD_(bm_has_conflict_with)(bm, a1, a1 + 8, eStore);
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_store_has_conflict_with)(struct bitmap* const bm,
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      const Addr a1, const Addr a2)
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return DRD_(bm_has_conflict_with)(bm, a1, a2, eStore);
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return True if the two bitmaps *lhs and *rhs are identical, and false
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * if not.
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_equal)(struct bitmap* const lhs, struct bitmap* const rhs)
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2l;
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2r;
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* It's not possible to have two independent iterators over the same OSet, */
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* so complain if lhs == rhs.                                              */
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(lhs != rhs);
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(lhs->oset);
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(rhs->oset);
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for ( ; (bm2l = VG_(OSetGen_Next)(lhs->oset)) != 0; )
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (bm2l
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && ! DRD_(bm_has_any_access)(lhs,
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          make_address(bm2l->addr, 0),
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          make_address(bm2l->addr + 1, 0)))
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm2l = VG_(OSetGen_Next)(lhs->oset);
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2l == 0)
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(bm2l);
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm2r = VG_(OSetGen_Next)(rhs->oset);
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bm2r == 0)
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (! DRD_(bm_has_any_access)(rhs,
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       make_address(bm2r->addr, 0),
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       make_address(bm2r->addr + 1, 0)));
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(bm2r);
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(DRD_(bm_has_any_access)(rhs,
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        make_address(bm2r->addr, 0),
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        make_address(bm2r->addr + 1, 0)));
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2l != bm2r
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && (bm2l->addr != bm2r->addr
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              || VG_(memcmp)(&bm2l->bm1, &bm2r->bm1, sizeof(bm2l->bm1)) != 0))
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   do
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2r = VG_(OSetGen_Next)(rhs->oset);
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } while (bm2r && ! DRD_(bm_has_any_access)(rhs,
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              make_address(bm2r->addr, 0),
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              make_address(bm2r->addr + 1, 0)));
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bm2r)
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(DRD_(bm_has_any_access)(rhs,
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        make_address(bm2r->addr, 0),
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        make_address(bm2r->addr + 1, 0)));
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_swap)(struct bitmap* const bm1, struct bitmap* const bm2)
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OSet* const tmp = bm1->oset;
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bm1->oset = bm2->oset;
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bm2->oset = tmp;
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Merge bitmaps *lhs and *rhs into *lhs. */
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_merge2)(struct bitmap* const lhs, struct bitmap* const rhs)
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2l;
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2r;
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * It's not possible to have two independent iterators over the same OSet,
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * so complain if lhs == rhs.
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    */
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(lhs != rhs);
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_bitmap_merge_count++;
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(rhs->oset);
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2l = VG_(OSetGen_Lookup)(lhs->oset, &bm2r->addr);
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2l)
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(bm2l != bm2r);
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm2_merge(bm2l, bm2r);
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm2_insert_copy(lhs, bm2r);
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Clear bitmap2::recalc. */
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_unmark)(struct bitmap* bm)
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2;
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (VG_(OSetGen_ResetIter)(bm->oset);
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0;
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        )
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2->recalc = False;
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Report whether bitmap2::recalc has been set for the second level bitmap
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * corresponding to address a.
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool DRD_(bm_is_marked)(struct bitmap* bm, const Addr a)
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const struct bitmap2* bm2;
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bm2 = bm2_lookup(bm, a);
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return bm2 && bm2->recalc;
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Set bitmap2::recalc in bml for each second level bitmap in bmr that contains
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * at least one access.
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @note Any new second-level bitmaps inserted in bml by this function are
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *       uninitialized.
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_mark)(struct bitmap* bml, struct bitmap* bmr)
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2l;
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2r;
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (VG_(OSetGen_ResetIter)(bmr->oset);
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (bm2r = VG_(OSetGen_Next)(bmr->oset)) != 0;
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        )
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      bm2l = bm2_lookup_or_insert(bml, bm2r->addr);
1055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      bm2l->recalc = True;
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Clear all second-level bitmaps for which bitmap2::recalc == True. */
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_clear_marked)(struct bitmap* bm)
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2;
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (VG_(OSetGen_ResetIter)(bm->oset);
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0;
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        )
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2->recalc)
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm2_clear(bm2);
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Merge the second level bitmaps from *rhs into *lhs for which recalc == True. */
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_merge2_marked)(struct bitmap* const lhs, struct bitmap* const rhs)
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2l;
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2r;
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * It's not possible to have two independent iterators over the same OSet,
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * so complain if lhs == rhs.
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    */
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(lhs != rhs);
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_bitmap_merge_count++;
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(rhs->oset);
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for ( ; (bm2r = VG_(OSetGen_Next)(rhs->oset)) != 0; )
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2l = VG_(OSetGen_Lookup)(lhs->oset, &bm2r->addr);
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2l && bm2l->recalc)
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(bm2l != bm2r);
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm2_merge(bm2l, bm2r);
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Remove all marked second-level bitmaps that do not contain any access. */
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_remove_cleared_marked)(struct bitmap* bm)
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2;
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(bm->oset);
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for ( ; (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0; )
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const UWord a1 = bm2->addr;
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2->recalc
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && ! DRD_(bm_has_any_access(bm, make_address(a1, 0),
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      make_address(a1 + 1, 0))))
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bm2_remove(bm, a1);
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(OSetGen_ResetIterAt)(bm->oset, &a1);
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/**
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Report whether there are any RW / WR / WW patterns in lhs and rhs.
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @param lhs First bitmap.
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @param rhs Bitmap to be compared with lhs.
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * @return !=0 if there are data races, == 0 if there are none.
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint DRD_(bm_has_races)(struct bitmap* const lhs, struct bitmap* const rhs)
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(lhs->oset);
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(OSetGen_ResetIter)(rhs->oset);
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (;;)
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const struct bitmap2* bm2l;
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const struct bitmap2* bm2r;
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const struct bitmap1* bm1l;
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const struct bitmap1* bm1r;
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned k;
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2l = VG_(OSetGen_Next)(lhs->oset);
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2r = VG_(OSetGen_Next)(rhs->oset);
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (bm2l && bm2r && bm2l->addr != bm2r->addr)
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (bm2l->addr < bm2r->addr)
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bm2l = VG_(OSetGen_Next)(lhs->oset);
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            bm2r = VG_(OSetGen_Next)(rhs->oset);
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (bm2l == 0 || bm2r == 0)
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm1l = &bm2l->bm1;
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm1r = &bm2r->bm1;
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unsigned b;
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (b = 0; b < BITS_PER_UWORD; b++)
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UWord const access_mask
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               = ((bm1l->bm0_r[k] & bm0_mask(b)) ? LHS_R : 0)
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               | ((bm1l->bm0_w[k] & bm0_mask(b)) ? LHS_W : 0)
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               | ((bm1r->bm0_r[k] & bm0_mask(b)) ? RHS_R : 0)
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               | ((bm1r->bm0_w[k] & bm0_mask(b)) ? RHS_W : 0);
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Addr const a = make_address(bm2l->addr, k * BITS_PER_UWORD | b);
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (HAS_RACE(access_mask) && ! DRD_(is_suppressed)(a, a + 1))
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            {
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return 1;
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DRD_(bm_print)(struct bitmap* const bm)
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct bitmap2* bm2;
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (VG_(OSetGen_ResetIter)(bm->oset);
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        (bm2 = VG_(OSetGen_Next)(bm->oset)) != 0;
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        )
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2_print(bm2);
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void bm2_print(const struct bitmap2* const bm2)
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const struct bitmap1* bm1;
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr a;
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm2);
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bm1 = &bm2->bm1;
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (a = make_address(bm2->addr, 0);
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        a <= make_address(bm2->addr + 1, 0) - 1;
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        a++)
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Bool r = bm0_is_set(bm1->bm0_r, address_lsb(a)) != 0;
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Bool w = bm0_is_set(bm1->bm0_w, address_lsb(a)) != 0;
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (r || w)
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      {
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("0x%08lx %c %c\n",
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     a,
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     w ? 'W' : ' ',
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     r ? 'R' : ' ');
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(bm_get_bitmap_creation_count)(void)
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_bitmap_creation_count;
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(bm_get_bitmap2_creation_count)(void)
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_bitmap2_creation_count;
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong DRD_(bm_get_bitmap2_merge_count)(void)
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return s_bitmap2_merge_count;
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** Compute *bm2l |= *bm2r. */
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid bm2_merge(struct bitmap2* const bm2l, const struct bitmap2* const bm2r)
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned k;
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm2l);
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm2r);
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(bm2l->addr == bm2r->addr);
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s_bitmap2_merge_count++;
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2l->bm1.bm0_r[k] |= bm2r->bm1.bm0_r[k];
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (k = 0; k < BITMAP1_UWORD_COUNT; k++)
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bm2l->bm1.bm0_w[k] |= bm2r->bm1.bm0_w[k];
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1246