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 | { |
1fe05280 | 57 | sim_core *memory = STATE_CORE(sd); |
c967f187 | 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 | ||
1fe05280 AC |
80 | STATIC_INLINE_SIM_CORE\ |
81 | (const char *) | |
82 | sim_core_map_to_str (sim_core_maps map) | |
83 | { | |
84 | switch (map) | |
85 | { | |
86 | case sim_core_read_map: return "read"; | |
87 | case sim_core_write_map: return "write"; | |
88 | case sim_core_execute_map: return "exec"; | |
89 | default: return "(invalid-map)"; | |
90 | } | |
91 | } | |
92 | ||
93 | ||
f2de7dfd | 94 | STATIC_INLINE_SIM_CORE\ |
c967f187 DE |
95 | (sim_core_mapping *) |
96 | new_sim_core_mapping(SIM_DESC sd, | |
f2de7dfd AC |
97 | attach_type attach, |
98 | int space, | |
99 | unsigned_word addr, | |
100 | unsigned nr_bytes, | |
101 | device *device, | |
102 | void *buffer, | |
103 | int free_buffer) | |
104 | { | |
c967f187 | 105 | sim_core_mapping *new_mapping = ZALLOC(sim_core_mapping); |
f2de7dfd AC |
106 | /* common */ |
107 | new_mapping->level = attach; | |
108 | new_mapping->space = space; | |
109 | new_mapping->base = addr; | |
110 | new_mapping->nr_bytes = nr_bytes; | |
111 | new_mapping->bound = addr + (nr_bytes - 1); | |
112 | if (attach == attach_raw_memory) { | |
113 | new_mapping->buffer = buffer; | |
114 | new_mapping->free_buffer = free_buffer; | |
115 | } | |
116 | else if (attach >= attach_callback) { | |
117 | new_mapping->device = device; | |
118 | } | |
119 | else { | |
c967f187 | 120 | sim_io_error (sd, "new_sim_core_mapping - internal error - unknown attach type %d\n", |
f2de7dfd AC |
121 | attach); |
122 | } | |
123 | return new_mapping; | |
124 | } | |
125 | ||
126 | ||
127 | STATIC_INLINE_SIM_CORE\ | |
128 | (void) | |
c967f187 DE |
129 | sim_core_map_attach(SIM_DESC sd, |
130 | sim_core_map *access_map, | |
f2de7dfd AC |
131 | attach_type attach, |
132 | int space, | |
133 | unsigned_word addr, | |
134 | unsigned nr_bytes, /* host limited */ | |
135 | device *client, /*callback/default*/ | |
136 | void *buffer, /*raw_memory*/ | |
137 | int free_buffer) /*raw_memory*/ | |
138 | { | |
139 | /* find the insertion point for this additional mapping and then | |
140 | insert */ | |
c967f187 DE |
141 | sim_core_mapping *next_mapping; |
142 | sim_core_mapping **last_mapping; | |
f2de7dfd | 143 | |
c967f187 | 144 | SIM_ASSERT((attach >= attach_callback && client != NULL && buffer == NULL && !free_buffer) |
f2de7dfd AC |
145 | || (attach == attach_raw_memory && client == NULL && buffer != NULL)); |
146 | ||
147 | /* actually do occasionally get a zero size map */ | |
148 | if (nr_bytes == 0) { | |
149 | #if (WITH_DEVICES) | |
c967f187 | 150 | device_error(client, "called on sim_core_map_attach with size zero"); |
f2de7dfd | 151 | #else |
c967f187 | 152 | sim_io_error (sd, "called on sim_core_map_attach with size zero"); |
f2de7dfd AC |
153 | #endif |
154 | } | |
155 | ||
156 | /* find the insertion point (between last/next) */ | |
157 | next_mapping = access_map->first; | |
158 | last_mapping = &access_map->first; | |
159 | while(next_mapping != NULL | |
160 | && (next_mapping->level < attach | |
161 | || (next_mapping->level == attach | |
162 | && next_mapping->bound < addr))) { | |
163 | /* provided levels are the same */ | |
164 | /* assert: next_mapping->base > all bases before next_mapping */ | |
165 | /* assert: next_mapping->bound >= all bounds before next_mapping */ | |
166 | last_mapping = &next_mapping->next; | |
167 | next_mapping = next_mapping->next; | |
168 | } | |
169 | ||
170 | /* check insertion point correct */ | |
c967f187 | 171 | SIM_ASSERT(next_mapping == NULL || next_mapping->level >= attach); |
f2de7dfd AC |
172 | if (next_mapping != NULL && next_mapping->level == attach |
173 | && next_mapping->base < (addr + (nr_bytes - 1))) { | |
174 | #if (WITH_DEVICES) | |
175 | device_error(client, "map overlap when attaching %d:0x%lx (%ld)", | |
176 | space, (long)addr, (long)nr_bytes); | |
177 | #else | |
c967f187 | 178 | sim_io_error (sd, "map overlap when attaching %d:0x%lx (%ld)", |
f2de7dfd AC |
179 | space, (long)addr, (long)nr_bytes); |
180 | #endif | |
181 | } | |
182 | ||
183 | /* create/insert the new mapping */ | |
c967f187 | 184 | *last_mapping = new_sim_core_mapping(sd, |
f2de7dfd AC |
185 | attach, |
186 | space, addr, nr_bytes, | |
187 | client, buffer, free_buffer); | |
188 | (*last_mapping)->next = next_mapping; | |
189 | } | |
190 | ||
191 | ||
192 | INLINE_SIM_CORE\ | |
193 | (void) | |
c967f187 | 194 | sim_core_attach(SIM_DESC sd, |
f2de7dfd AC |
195 | attach_type attach, |
196 | access_type access, | |
197 | int space, | |
198 | unsigned_word addr, | |
199 | unsigned nr_bytes, /* host limited */ | |
200 | device *client, | |
201 | void *optional_buffer) | |
202 | { | |
1fe05280 | 203 | sim_core *memory = STATE_CORE(sd); |
c967f187 | 204 | sim_core_maps map; |
f2de7dfd AC |
205 | void *buffer; |
206 | int buffer_freed; | |
207 | if ((access & access_read_write_exec) == 0 | |
208 | || (access & ~access_read_write_exec) != 0) { | |
209 | #if (WITH_DEVICES) | |
210 | device_error(client, "invalid access for core attach"); | |
211 | #else | |
c967f187 | 212 | sim_io_error (sd, "invalid access for core attach"); |
f2de7dfd AC |
213 | #endif |
214 | } | |
215 | /* verify the attach type */ | |
216 | if (attach == attach_raw_memory) { | |
217 | if (optional_buffer == NULL) { | |
218 | buffer = zalloc(nr_bytes); | |
219 | buffer_freed = 0; | |
220 | } | |
221 | else { | |
222 | buffer = optional_buffer; | |
223 | buffer_freed = 1; | |
224 | } | |
225 | } | |
226 | else if (attach >= attach_callback) { | |
227 | buffer = NULL; | |
228 | buffer_freed = 1; | |
229 | } | |
230 | else { | |
231 | #if (WITH_DEVICES) | |
c967f187 | 232 | device_error(client, "sim_core_attach - conflicting buffer and attach arguments"); |
f2de7dfd | 233 | #else |
c967f187 | 234 | sim_io_error (sd, "sim_core_attach - conflicting buffer and attach arguments"); |
f2de7dfd AC |
235 | #endif |
236 | buffer = NULL; | |
237 | buffer_freed = 1; | |
238 | } | |
239 | /* attach the region to all applicable access maps */ | |
240 | for (map = 0; | |
c967f187 | 241 | map < nr_sim_core_maps; |
f2de7dfd AC |
242 | map++) { |
243 | switch (map) { | |
c967f187 | 244 | case sim_core_read_map: |
f2de7dfd | 245 | if (access & access_read) |
c967f187 | 246 | sim_core_map_attach(sd, &memory->map[map], |
f2de7dfd AC |
247 | attach, |
248 | space, addr, nr_bytes, | |
249 | client, buffer, !buffer_freed); | |
250 | buffer_freed ++; | |
251 | break; | |
c967f187 | 252 | case sim_core_write_map: |
f2de7dfd | 253 | if (access & access_write) |
c967f187 | 254 | sim_core_map_attach(sd, &memory->map[map], |
f2de7dfd AC |
255 | attach, |
256 | space, addr, nr_bytes, | |
257 | client, buffer, !buffer_freed); | |
258 | buffer_freed ++; | |
259 | break; | |
c967f187 | 260 | case sim_core_execute_map: |
f2de7dfd | 261 | if (access & access_exec) |
c967f187 | 262 | sim_core_map_attach(sd, &memory->map[map], |
f2de7dfd AC |
263 | attach, |
264 | space, addr, nr_bytes, | |
265 | client, buffer, !buffer_freed); | |
266 | buffer_freed ++; | |
267 | break; | |
c967f187 DE |
268 | case nr_sim_core_maps: |
269 | sim_io_error (sd, "sim_core_attach - internal error - bad switch"); | |
f2de7dfd AC |
270 | break; |
271 | } | |
272 | } | |
273 | } | |
274 | ||
275 | ||
276 | STATIC_INLINE_SIM_CORE\ | |
c967f187 DE |
277 | (sim_core_mapping *) |
278 | sim_core_find_mapping(SIM_DESC sd, | |
279 | sim_core_maps map, | |
f2de7dfd AC |
280 | unsigned_word addr, |
281 | unsigned nr_bytes, | |
1fe05280 AC |
282 | int abort, /*either 0 or 1 - helps inline */ |
283 | sim_cpu *cpu, | |
284 | sim_cia cia) | |
f2de7dfd | 285 | { |
1fe05280 | 286 | sim_core_mapping *mapping = STATE_CORE (sd)->map[map].first; |
c967f187 DE |
287 | SIM_ASSERT((addr & (nr_bytes - 1)) == 0); /* must be aligned */ |
288 | SIM_ASSERT((addr + (nr_bytes - 1)) >= addr); /* must not wrap */ | |
f2de7dfd AC |
289 | while (mapping != NULL) { |
290 | if (addr >= mapping->base | |
291 | && (addr + (nr_bytes - 1)) <= mapping->bound) | |
292 | return mapping; | |
293 | mapping = mapping->next; | |
294 | } | |
295 | if (abort) | |
1fe05280 AC |
296 | sim_io_error (sd, "access to unmaped address 0x%lx (%d bytes)\n", |
297 | (unsigned long) addr, nr_bytes); | |
f2de7dfd AC |
298 | return NULL; |
299 | } | |
300 | ||
301 | ||
302 | STATIC_INLINE_SIM_CORE\ | |
303 | (void *) | |
c967f187 | 304 | sim_core_translate(sim_core_mapping *mapping, |
f2de7dfd AC |
305 | unsigned_word addr) |
306 | { | |
307 | return (void *)(((char *)mapping->buffer) + addr - mapping->base); | |
308 | } | |
309 | ||
310 | ||
311 | INLINE_SIM_CORE\ | |
312 | (unsigned) | |
c967f187 DE |
313 | sim_core_read_buffer(SIM_DESC sd, |
314 | sim_core_maps map, | |
f2de7dfd AC |
315 | void *buffer, |
316 | unsigned_word addr, | |
317 | unsigned len) | |
318 | { | |
319 | unsigned count = 0; | |
320 | while (count < len) { | |
321 | unsigned_word raddr = addr + count; | |
c967f187 DE |
322 | sim_core_mapping *mapping = |
323 | sim_core_find_mapping(sd, map, | |
f2de7dfd | 324 | raddr, 1, |
1fe05280 | 325 | 0, NULL, NULL_CIA); /*dont-abort*/ |
f2de7dfd AC |
326 | if (mapping == NULL) |
327 | break; | |
328 | #if (WITH_DEVICES) | |
329 | if (mapping->device != NULL) { | |
330 | int nr_bytes = len - count; | |
331 | if (raddr + nr_bytes - 1> mapping->bound) | |
332 | nr_bytes = mapping->bound - raddr + 1; | |
333 | if (device_io_read_buffer(mapping->device, | |
334 | (unsigned_1*)buffer + count, | |
335 | mapping->space, | |
336 | raddr, | |
337 | nr_bytes) != nr_bytes) | |
338 | break; | |
339 | count += nr_bytes; | |
340 | } | |
341 | else | |
342 | #endif | |
343 | { | |
344 | ((unsigned_1*)buffer)[count] = | |
c967f187 | 345 | *(unsigned_1*)sim_core_translate(mapping, raddr); |
f2de7dfd AC |
346 | count += 1; |
347 | } | |
348 | } | |
349 | return count; | |
350 | } | |
351 | ||
352 | ||
353 | INLINE_SIM_CORE\ | |
354 | (unsigned) | |
c967f187 DE |
355 | sim_core_write_buffer(SIM_DESC sd, |
356 | sim_core_maps map, | |
f2de7dfd AC |
357 | const void *buffer, |
358 | unsigned_word addr, | |
359 | unsigned len) | |
360 | { | |
361 | unsigned count = 0; | |
362 | while (count < len) { | |
363 | unsigned_word raddr = addr + count; | |
c967f187 DE |
364 | sim_core_mapping *mapping = sim_core_find_mapping(sd, map, |
365 | raddr, 1, | |
1fe05280 | 366 | 0, NULL, NULL_CIA); /*dont-abort*/ |
f2de7dfd AC |
367 | if (mapping == NULL) |
368 | break; | |
369 | #if (WITH_DEVICES) | |
370 | if (WITH_CALLBACK_MEMORY | |
371 | && mapping->device != NULL) { | |
372 | int nr_bytes = len - count; | |
373 | if (raddr + nr_bytes - 1 > mapping->bound) | |
374 | nr_bytes = mapping->bound - raddr + 1; | |
375 | if (device_io_write_buffer(mapping->device, | |
376 | (unsigned_1*)buffer + count, | |
377 | mapping->space, | |
378 | raddr, | |
379 | nr_bytes) != nr_bytes) | |
380 | break; | |
381 | count += nr_bytes; | |
382 | } | |
383 | else | |
384 | #endif | |
385 | { | |
c967f187 | 386 | *(unsigned_1*)sim_core_translate(mapping, raddr) = |
f2de7dfd AC |
387 | ((unsigned_1*)buffer)[count]; |
388 | count += 1; | |
389 | } | |
390 | } | |
391 | return count; | |
392 | } | |
393 | ||
394 | ||
395 | /* define the read/write 1/2/4/8/word functions */ | |
396 | ||
397 | #define N 1 | |
398 | #include "sim-n-core.h" | |
399 | #undef N | |
400 | ||
401 | #define N 2 | |
402 | #include "sim-n-core.h" | |
403 | #undef N | |
404 | ||
405 | #define N 4 | |
406 | #include "sim-n-core.h" | |
407 | #undef N | |
408 | ||
409 | #define N 8 | |
410 | #include "sim-n-core.h" | |
411 | #undef N | |
412 | ||
413 | #define N word | |
414 | #include "sim-n-core.h" | |
415 | #undef N | |
416 | ||
417 | #endif |