Commit | Line | Data |
---|---|---|
f2de7dfd AC |
1 | /* This file is part of the program psim. |
2 | ||
3 | Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au> | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | ||
19 | */ | |
20 | ||
21 | ||
22 | #ifndef _SIM_CORE_C_ | |
23 | #define _SIM_CORE_C_ | |
24 | ||
c967f187 DE |
25 | #include "sim-main.h" |
26 | #include "sim-assert.h" | |
f2de7dfd AC |
27 | |
28 | ||
c967f187 DE |
29 | /* "core" module install handler. |
30 | This is called via sim_module_install to install the "core" subsystem | |
31 | into the simulator. */ | |
32 | ||
33 | EXTERN_SIM_CORE\ | |
34 | (SIM_RC) | |
35 | sim_core_install (SIM_DESC sd) | |
36 | { | |
37 | sim_module_add_uninstall_fn (sd, sim_core_uninstall); | |
38 | sim_module_add_init_fn (sd, sim_core_init); | |
39 | return SIM_RC_OK; | |
40 | } | |
41 | ||
42 | ||
43 | /* Uninstall the "core" subsystem from the simulator. */ | |
44 | ||
45 | EXTERN_SIM_CORE\ | |
f2de7dfd | 46 | (void) |
c967f187 DE |
47 | sim_core_uninstall (SIM_DESC sd) |
48 | { | |
49 | /* FIXME: free buffers, etc. */ | |
50 | } | |
51 | ||
52 | ||
53 | EXTERN_SIM_CORE\ | |
54 | (SIM_RC) | |
55 | sim_core_init (SIM_DESC sd) | |
f2de7dfd | 56 | { |
c967f187 DE |
57 | sim_core *memory = &sd->core; |
58 | sim_core_maps map; | |
f2de7dfd | 59 | for (map = 0; |
c967f187 | 60 | map < nr_sim_core_maps; |
f2de7dfd AC |
61 | map++) { |
62 | /* blow away old mappings */ | |
c967f187 | 63 | sim_core_mapping *curr = memory->map[map].first; |
f2de7dfd | 64 | while (curr != NULL) { |
c967f187 | 65 | sim_core_mapping *tbd = curr; |
f2de7dfd AC |
66 | curr = curr->next; |
67 | if (tbd->free_buffer) { | |
c967f187 | 68 | SIM_ASSERT(tbd->buffer != NULL); |
f2de7dfd AC |
69 | zfree(tbd->buffer); |
70 | } | |
71 | zfree(tbd); | |
72 | } | |
73 | memory->map[map].first = NULL; | |
74 | } | |
c967f187 | 75 | return SIM_RC_OK; |
f2de7dfd AC |
76 | } |
77 | ||
78 | ||
79 | ||
80 | STATIC_INLINE_SIM_CORE\ | |
c967f187 DE |
81 | (sim_core_mapping *) |
82 | new_sim_core_mapping(SIM_DESC sd, | |
f2de7dfd AC |
83 | attach_type attach, |
84 | int space, | |
85 | unsigned_word addr, | |
86 | unsigned nr_bytes, | |
87 | device *device, | |
88 | void *buffer, | |
89 | int free_buffer) | |
90 | { | |
c967f187 | 91 | sim_core_mapping *new_mapping = ZALLOC(sim_core_mapping); |
f2de7dfd AC |
92 | /* common */ |
93 | new_mapping->level = attach; | |
94 | new_mapping->space = space; | |
95 | new_mapping->base = addr; | |
96 | new_mapping->nr_bytes = nr_bytes; | |
97 | new_mapping->bound = addr + (nr_bytes - 1); | |
98 | if (attach == attach_raw_memory) { | |
99 | new_mapping->buffer = buffer; | |
100 | new_mapping->free_buffer = free_buffer; | |
101 | } | |
102 | else if (attach >= attach_callback) { | |
103 | new_mapping->device = device; | |
104 | } | |
105 | else { | |
c967f187 | 106 | sim_io_error (sd, "new_sim_core_mapping - internal error - unknown attach type %d\n", |
f2de7dfd AC |
107 | attach); |
108 | } | |
109 | return new_mapping; | |
110 | } | |
111 | ||
112 | ||
113 | STATIC_INLINE_SIM_CORE\ | |
114 | (void) | |
c967f187 DE |
115 | sim_core_map_attach(SIM_DESC sd, |
116 | sim_core_map *access_map, | |
f2de7dfd AC |
117 | attach_type attach, |
118 | int space, | |
119 | unsigned_word addr, | |
120 | unsigned nr_bytes, /* host limited */ | |
121 | device *client, /*callback/default*/ | |
122 | void *buffer, /*raw_memory*/ | |
123 | int free_buffer) /*raw_memory*/ | |
124 | { | |
125 | /* find the insertion point for this additional mapping and then | |
126 | insert */ | |
c967f187 DE |
127 | sim_core_mapping *next_mapping; |
128 | sim_core_mapping **last_mapping; | |
f2de7dfd | 129 | |
c967f187 | 130 | SIM_ASSERT((attach >= attach_callback && client != NULL && buffer == NULL && !free_buffer) |
f2de7dfd AC |
131 | || (attach == attach_raw_memory && client == NULL && buffer != NULL)); |
132 | ||
133 | /* actually do occasionally get a zero size map */ | |
134 | if (nr_bytes == 0) { | |
135 | #if (WITH_DEVICES) | |
c967f187 | 136 | device_error(client, "called on sim_core_map_attach with size zero"); |
f2de7dfd | 137 | #else |
c967f187 | 138 | sim_io_error (sd, "called on sim_core_map_attach with size zero"); |
f2de7dfd AC |
139 | #endif |
140 | } | |
141 | ||
142 | /* find the insertion point (between last/next) */ | |
143 | next_mapping = access_map->first; | |
144 | last_mapping = &access_map->first; | |
145 | while(next_mapping != NULL | |
146 | && (next_mapping->level < attach | |
147 | || (next_mapping->level == attach | |
148 | && next_mapping->bound < addr))) { | |
149 | /* provided levels are the same */ | |
150 | /* assert: next_mapping->base > all bases before next_mapping */ | |
151 | /* assert: next_mapping->bound >= all bounds before next_mapping */ | |
152 | last_mapping = &next_mapping->next; | |
153 | next_mapping = next_mapping->next; | |
154 | } | |
155 | ||
156 | /* check insertion point correct */ | |
c967f187 | 157 | SIM_ASSERT(next_mapping == NULL || next_mapping->level >= attach); |
f2de7dfd AC |
158 | if (next_mapping != NULL && next_mapping->level == attach |
159 | && next_mapping->base < (addr + (nr_bytes - 1))) { | |
160 | #if (WITH_DEVICES) | |
161 | device_error(client, "map overlap when attaching %d:0x%lx (%ld)", | |
162 | space, (long)addr, (long)nr_bytes); | |
163 | #else | |
c967f187 | 164 | sim_io_error (sd, "map overlap when attaching %d:0x%lx (%ld)", |
f2de7dfd AC |
165 | space, (long)addr, (long)nr_bytes); |
166 | #endif | |
167 | } | |
168 | ||
169 | /* create/insert the new mapping */ | |
c967f187 | 170 | *last_mapping = new_sim_core_mapping(sd, |
f2de7dfd AC |
171 | attach, |
172 | space, addr, nr_bytes, | |
173 | client, buffer, free_buffer); | |
174 | (*last_mapping)->next = next_mapping; | |
175 | } | |
176 | ||
177 | ||
178 | INLINE_SIM_CORE\ | |
179 | (void) | |
c967f187 | 180 | sim_core_attach(SIM_DESC sd, |
f2de7dfd AC |
181 | attach_type attach, |
182 | access_type access, | |
183 | int space, | |
184 | unsigned_word addr, | |
185 | unsigned nr_bytes, /* host limited */ | |
186 | device *client, | |
187 | void *optional_buffer) | |
188 | { | |
c967f187 DE |
189 | sim_core *memory = &sd->core; |
190 | sim_core_maps map; | |
f2de7dfd AC |
191 | void *buffer; |
192 | int buffer_freed; | |
193 | if ((access & access_read_write_exec) == 0 | |
194 | || (access & ~access_read_write_exec) != 0) { | |
195 | #if (WITH_DEVICES) | |
196 | device_error(client, "invalid access for core attach"); | |
197 | #else | |
c967f187 | 198 | sim_io_error (sd, "invalid access for core attach"); |
f2de7dfd AC |
199 | #endif |
200 | } | |
201 | /* verify the attach type */ | |
202 | if (attach == attach_raw_memory) { | |
203 | if (optional_buffer == NULL) { | |
204 | buffer = zalloc(nr_bytes); | |
205 | buffer_freed = 0; | |
206 | } | |
207 | else { | |
208 | buffer = optional_buffer; | |
209 | buffer_freed = 1; | |
210 | } | |
211 | } | |
212 | else if (attach >= attach_callback) { | |
213 | buffer = NULL; | |
214 | buffer_freed = 1; | |
215 | } | |
216 | else { | |
217 | #if (WITH_DEVICES) | |
c967f187 | 218 | device_error(client, "sim_core_attach - conflicting buffer and attach arguments"); |
f2de7dfd | 219 | #else |
c967f187 | 220 | sim_io_error (sd, "sim_core_attach - conflicting buffer and attach arguments"); |
f2de7dfd AC |
221 | #endif |
222 | buffer = NULL; | |
223 | buffer_freed = 1; | |
224 | } | |
225 | /* attach the region to all applicable access maps */ | |
226 | for (map = 0; | |
c967f187 | 227 | map < nr_sim_core_maps; |
f2de7dfd AC |
228 | map++) { |
229 | switch (map) { | |
c967f187 | 230 | case sim_core_read_map: |
f2de7dfd | 231 | if (access & access_read) |
c967f187 | 232 | sim_core_map_attach(sd, &memory->map[map], |
f2de7dfd AC |
233 | attach, |
234 | space, addr, nr_bytes, | |
235 | client, buffer, !buffer_freed); | |
236 | buffer_freed ++; | |
237 | break; | |
c967f187 | 238 | case sim_core_write_map: |
f2de7dfd | 239 | if (access & access_write) |
c967f187 | 240 | sim_core_map_attach(sd, &memory->map[map], |
f2de7dfd AC |
241 | attach, |
242 | space, addr, nr_bytes, | |
243 | client, buffer, !buffer_freed); | |
244 | buffer_freed ++; | |
245 | break; | |
c967f187 | 246 | case sim_core_execute_map: |
f2de7dfd | 247 | if (access & access_exec) |
c967f187 | 248 | sim_core_map_attach(sd, &memory->map[map], |
f2de7dfd AC |
249 | attach, |
250 | space, addr, nr_bytes, | |
251 | client, buffer, !buffer_freed); | |
252 | buffer_freed ++; | |
253 | break; | |
c967f187 DE |
254 | case nr_sim_core_maps: |
255 | sim_io_error (sd, "sim_core_attach - internal error - bad switch"); | |
f2de7dfd AC |
256 | break; |
257 | } | |
258 | } | |
259 | } | |
260 | ||
261 | ||
262 | STATIC_INLINE_SIM_CORE\ | |
c967f187 DE |
263 | (sim_core_mapping *) |
264 | sim_core_find_mapping(SIM_DESC sd, | |
265 | sim_core_maps map, | |
f2de7dfd AC |
266 | unsigned_word addr, |
267 | unsigned nr_bytes, | |
268 | int abort) /*either 0 or 1 - helps inline */ | |
269 | { | |
c967f187 DE |
270 | sim_core_mapping *mapping = sd->core.map[map].first; |
271 | SIM_ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */ | |
272 | SIM_ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */ | |
f2de7dfd AC |
273 | while (mapping != NULL) { |
274 | if (addr >= mapping->base | |
275 | && (addr + (nr_bytes - 1)) <= mapping->bound) | |
276 | return mapping; | |
277 | mapping = mapping->next; | |
278 | } | |
279 | if (abort) | |
c967f187 | 280 | sim_io_error (sd, "access to unmaped address 0x%x (%d bytes)\n", |
f2de7dfd AC |
281 | addr, nr_bytes); |
282 | return NULL; | |
283 | } | |
284 | ||
285 | ||
286 | STATIC_INLINE_SIM_CORE\ | |
287 | (void *) | |
c967f187 | 288 | sim_core_translate(sim_core_mapping *mapping, |
f2de7dfd AC |
289 | unsigned_word addr) |
290 | { | |
291 | return (void *)(((char *)mapping->buffer) + addr - mapping->base); | |
292 | } | |
293 | ||
294 | ||
295 | INLINE_SIM_CORE\ | |
296 | (unsigned) | |
c967f187 DE |
297 | sim_core_read_buffer(SIM_DESC sd, |
298 | sim_core_maps map, | |
f2de7dfd AC |
299 | void *buffer, |
300 | unsigned_word addr, | |
301 | unsigned len) | |
302 | { | |
303 | unsigned count = 0; | |
304 | while (count < len) { | |
305 | unsigned_word raddr = addr + count; | |
c967f187 DE |
306 | sim_core_mapping *mapping = |
307 | sim_core_find_mapping(sd, map, | |
f2de7dfd AC |
308 | raddr, 1, |
309 | 0); /*dont-abort*/ | |
310 | if (mapping == NULL) | |
311 | break; | |
312 | #if (WITH_DEVICES) | |
313 | if (mapping->device != NULL) { | |
314 | int nr_bytes = len - count; | |
315 | if (raddr + nr_bytes - 1> mapping->bound) | |
316 | nr_bytes = mapping->bound - raddr + 1; | |
317 | if (device_io_read_buffer(mapping->device, | |
318 | (unsigned_1*)buffer + count, | |
319 | mapping->space, | |
320 | raddr, | |
321 | nr_bytes) != nr_bytes) | |
322 | break; | |
323 | count += nr_bytes; | |
324 | } | |
325 | else | |
326 | #endif | |
327 | { | |
328 | ((unsigned_1*)buffer)[count] = | |
c967f187 | 329 | *(unsigned_1*)sim_core_translate(mapping, raddr); |
f2de7dfd AC |
330 | count += 1; |
331 | } | |
332 | } | |
333 | return count; | |
334 | } | |
335 | ||
336 | ||
337 | INLINE_SIM_CORE\ | |
338 | (unsigned) | |
c967f187 DE |
339 | sim_core_write_buffer(SIM_DESC sd, |
340 | sim_core_maps map, | |
f2de7dfd AC |
341 | const void *buffer, |
342 | unsigned_word addr, | |
343 | unsigned len) | |
344 | { | |
345 | unsigned count = 0; | |
346 | while (count < len) { | |
347 | unsigned_word raddr = addr + count; | |
c967f187 DE |
348 | sim_core_mapping *mapping = sim_core_find_mapping(sd, map, |
349 | raddr, 1, | |
350 | 0); /*dont-abort*/ | |
f2de7dfd AC |
351 | if (mapping == NULL) |
352 | break; | |
353 | #if (WITH_DEVICES) | |
354 | if (WITH_CALLBACK_MEMORY | |
355 | && mapping->device != NULL) { | |
356 | int nr_bytes = len - count; | |
357 | if (raddr + nr_bytes - 1 > mapping->bound) | |
358 | nr_bytes = mapping->bound - raddr + 1; | |
359 | if (device_io_write_buffer(mapping->device, | |
360 | (unsigned_1*)buffer + count, | |
361 | mapping->space, | |
362 | raddr, | |
363 | nr_bytes) != nr_bytes) | |
364 | break; | |
365 | count += nr_bytes; | |
366 | } | |
367 | else | |
368 | #endif | |
369 | { | |
c967f187 | 370 | *(unsigned_1*)sim_core_translate(mapping, raddr) = |
f2de7dfd AC |
371 | ((unsigned_1*)buffer)[count]; |
372 | count += 1; | |
373 | } | |
374 | } | |
375 | return count; | |
376 | } | |
377 | ||
378 | ||
379 | /* define the read/write 1/2/4/8/word functions */ | |
380 | ||
381 | #define N 1 | |
382 | #include "sim-n-core.h" | |
383 | #undef N | |
384 | ||
385 | #define N 2 | |
386 | #include "sim-n-core.h" | |
387 | #undef N | |
388 | ||
389 | #define N 4 | |
390 | #include "sim-n-core.h" | |
391 | #undef N | |
392 | ||
393 | #define N 8 | |
394 | #include "sim-n-core.h" | |
395 | #undef N | |
396 | ||
397 | #define N word | |
398 | #include "sim-n-core.h" | |
399 | #undef N | |
400 | ||
401 | #endif |