Actually remove definitions of DEFINE_NON_INLINE_P and DEFINE_INLINE_P
[deliverable/binutils-gdb.git] / sim / common / sim-arange.c
CommitLineData
c906108c 1/* Address ranges.
42a4f53d 2 Copyright (C) 1998-2019 Free Software Foundation, Inc.
c906108c
SS
3 Contributed by Cygnus Solutions.
4
5This file is part of the GNU Simulators.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4744ac1b
JB
9the Free Software Foundation; either version 3 of the License, or
10(at your option) any later version.
c906108c
SS
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
4744ac1b
JB
17You should have received a copy of the GNU General Public License
18along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
19
20/* Tell sim-arange.h it's us. */
21#define SIM_ARANGE_C
22
23#include "libiberty.h"
24#include "sim-basics.h"
25#include "sim-assert.h"
26
27#ifdef HAVE_STDLIB_H
28#include <stdlib.h>
29#endif
30
c4093a6a
JM
31#ifdef HAVE_STRING_H
32#include <string.h>
33#endif
34
7516c26f 35#ifdef SIM_ARANGE_C_INCLUDED
c906108c
SS
36
37/* Insert a range. */
38
39static void
40insert_range (ADDR_SUBRANGE **pos, ADDR_SUBRANGE *asr)
41{
42 asr->next = *pos;
43 *pos = asr;
44}
45
46/* Delete a range. */
47
48static void
49delete_range (ADDR_SUBRANGE **thisasrp)
50{
51 ADDR_SUBRANGE *thisasr;
52
53 thisasr = *thisasrp;
54 *thisasrp = thisasr->next;
55
56 free (thisasr);
57}
58
59/* Add or delete an address range.
60 This code was borrowed from linux's locks.c:posix_lock_file().
61 ??? Todo: Given our simpler needs this could be simplified
62 (split into two fns). */
63
64static void
65frob_range (ADDR_RANGE *ar, address_word start, address_word end, int delete_p)
66{
67 ADDR_SUBRANGE *asr;
68 ADDR_SUBRANGE *new_asr, *new_asr2;
69 ADDR_SUBRANGE *left = NULL;
70 ADDR_SUBRANGE *right = NULL;
71 ADDR_SUBRANGE **before;
72 ADDR_SUBRANGE init_caller;
73 ADDR_SUBRANGE *caller = &init_caller;
74 int added_p = 0;
75
76 memset (caller, 0, sizeof (ADDR_SUBRANGE));
77 new_asr = ZALLOC (ADDR_SUBRANGE);
78 new_asr2 = ZALLOC (ADDR_SUBRANGE);
79
80 caller->start = start;
81 caller->end = end;
82 before = &ar->ranges;
83
84 while ((asr = *before) != NULL)
85 {
86 if (! delete_p)
87 {
88 /* Try next range if current range preceeds new one and not
89 adjacent or overlapping. */
90 if (asr->end < caller->start - 1)
91 goto next_range;
92
93 /* Break out if new range preceeds current one and not
94 adjacent or overlapping. */
95 if (asr->start > caller->end + 1)
96 break;
97
98 /* If we come here, the new and current ranges are adjacent or
99 overlapping. Make one range yielding from the lower start address
100 of both ranges to the higher end address. */
101 if (asr->start > caller->start)
102 asr->start = caller->start;
103 else
104 caller->start = asr->start;
105 if (asr->end < caller->end)
106 asr->end = caller->end;
107 else
108 caller->end = asr->end;
109
110 if (added_p)
111 {
112 delete_range (before);
113 continue;
114 }
115 caller = asr;
116 added_p = 1;
117 }
118 else /* deleting a range */
119 {
120 /* Try next range if current range preceeds new one. */
121 if (asr->end < caller->start)
122 goto next_range;
123
124 /* Break out if new range preceeds current one. */
125 if (asr->start > caller->end)
126 break;
127
128 added_p = 1;
129
130 if (asr->start < caller->start)
131 left = asr;
132
133 /* If the next range in the list has a higher end
134 address than the new one, insert the new one here. */
135 if (asr->end > caller->end)
136 {
137 right = asr;
138 break;
139 }
140 if (asr->start >= caller->start)
141 {
142 /* The new range completely replaces an old
143 one (This may happen several times). */
144 if (added_p)
145 {
146 delete_range (before);
147 continue;
148 }
149
150 /* Replace the old range with the new one. */
151 asr->start = caller->start;
152 asr->end = caller->end;
153 caller = asr;
154 added_p = 1;
155 }
156 }
157
158 /* Go on to next range. */
159 next_range:
160 before = &asr->next;
161 }
162
163 if (!added_p)
164 {
165 if (delete_p)
166 goto out;
167 new_asr->start = caller->start;
168 new_asr->end = caller->end;
169 insert_range (before, new_asr);
170 new_asr = NULL;
171 }
172 if (right)
173 {
174 if (left == right)
175 {
176 /* The new range breaks the old one in two pieces,
177 so we have to use the second new range. */
178 new_asr2->start = right->start;
179 new_asr2->end = right->end;
180 left = new_asr2;
181 insert_range (before, left);
182 new_asr2 = NULL;
183 }
184 right->start = caller->end + 1;
185 }
186 if (left)
187 {
188 left->end = caller->start - 1;
189 }
190
191 out:
192 if (new_asr)
34b47c38 193 free (new_asr);
c906108c 194 if (new_asr2)
34b47c38 195 free (new_asr2);
c906108c
SS
196}
197
198/* Free T and all subtrees. */
199
200static void
201free_search_tree (ADDR_RANGE_TREE *t)
202{
203 if (t != NULL)
204 {
205 free_search_tree (t->lower);
206 free_search_tree (t->higher);
207 free (t);
208 }
209}
210
211/* Subroutine of build_search_tree to recursively build a balanced tree.
212 ??? It's not an optimum tree though. */
213
214static ADDR_RANGE_TREE *
215build_tree_1 (ADDR_SUBRANGE **asrtab, unsigned int n)
216{
217 unsigned int mid = n / 2;
218 ADDR_RANGE_TREE *t;
219
220 if (n == 0)
221 return NULL;
222 t = (ADDR_RANGE_TREE *) xmalloc (sizeof (ADDR_RANGE_TREE));
223 t->start = asrtab[mid]->start;
224 t->end = asrtab[mid]->end;
225 if (mid != 0)
226 t->lower = build_tree_1 (asrtab, mid);
227 else
228 t->lower = NULL;
229 if (n > mid + 1)
230 t->higher = build_tree_1 (asrtab + mid + 1, n - mid - 1);
231 else
232 t->higher = NULL;
233 return t;
234}
235
236/* Build a search tree for address range AR. */
237
238static void
239build_search_tree (ADDR_RANGE *ar)
240{
241 /* ??? Simple version for now. */
242 ADDR_SUBRANGE *asr,**asrtab;
243 unsigned int i, n;
244
245 for (n = 0, asr = ar->ranges; asr != NULL; ++n, asr = asr->next)
246 continue;
247 asrtab = (ADDR_SUBRANGE **) xmalloc (n * sizeof (ADDR_SUBRANGE *));
248 for (i = 0, asr = ar->ranges; i < n; ++i, asr = asr->next)
249 asrtab[i] = asr;
250 ar->range_tree = build_tree_1 (asrtab, n);
251 free (asrtab);
252}
253
254void
255sim_addr_range_add (ADDR_RANGE *ar, address_word start, address_word end)
256{
257 frob_range (ar, start, end, 0);
258
259 /* Rebuild the search tree. */
260 /* ??? Instead of rebuilding it here it could be done in a module resume
261 handler, say by first checking for a `changed' flag, assuming of course
262 this would never be done while the simulation is running. */
263 free_search_tree (ar->range_tree);
264 build_search_tree (ar);
265}
266
267void
268sim_addr_range_delete (ADDR_RANGE *ar, address_word start, address_word end)
269{
270 frob_range (ar, start, end, 1);
271
272 /* Rebuild the search tree. */
273 /* ??? Instead of rebuilding it here it could be done in a module resume
274 handler, say by first checking for a `changed' flag, assuming of course
275 this would never be done while the simulation is running. */
276 free_search_tree (ar->range_tree);
277 build_search_tree (ar);
278}
279
7516c26f 280#else /* SIM_ARANGE_C_INCLUDED */
c906108c
SS
281
282SIM_ARANGE_INLINE int
283sim_addr_range_hit_p (ADDR_RANGE *ar, address_word addr)
284{
285 ADDR_RANGE_TREE *t = ar->range_tree;
286
287 while (t != NULL)
288 {
289 if (addr < t->start)
290 t = t->lower;
291 else if (addr > t->end)
292 t = t->higher;
293 else
294 return 1;
295 }
296 return 0;
297}
298
7516c26f 299#endif /* SIM_ARANGE_C_INCLUDED */
This page took 0.797389 seconds and 4 git commands to generate.