1 /* This file is part of the program psim.
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
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.
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.
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.
26 #include "sim-assert.h"
29 /* "core" module install handler.
31 This is called via sim_module_install to install the "core" subsystem
32 into the simulator. */
34 static MODULE_INIT_FN sim_core_init;
35 static MODULE_UNINSTALL_FN sim_core_uninstall;
39 sim_core_install (SIM_DESC sd)
41 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
42 sim_module_add_uninstall_fn (sd, sim_core_uninstall);
43 sim_module_add_init_fn (sd, sim_core_init);
48 /* Uninstall the "core" subsystem from the simulator. */
52 sim_core_uninstall (SIM_DESC sd)
54 /* FIXME: free buffers, etc. */
60 sim_core_init (SIM_DESC sd)
62 sim_core *memory = STATE_CORE(sd);
65 map < nr_sim_core_maps;
67 /* blow away old mappings */
68 sim_core_mapping *curr = memory->map[map].first;
69 while (curr != NULL) {
70 sim_core_mapping *tbd = curr;
72 if (tbd->free_buffer) {
73 SIM_ASSERT(tbd->buffer != NULL);
78 memory->map[map].first = NULL;
85 #ifndef SIM_CORE_SIGNAL
86 #define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \
87 sim_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ERROR))
91 sim_core_signal (SIM_DESC sd,
97 transfer_type transfer,
100 const char *copy = (transfer == read_transfer ? "read" : "write");
103 case sim_core_unmapped_signal:
104 sim_engine_abort (sd, cpu, cia, "sim-core: %d byte %s to unmaped address 0x%lx",
105 nr_bytes, copy, (unsigned long) addr);
107 case sim_core_unaligned_signal:
108 sim_engine_abort (sd, cpu, cia, "sim-core: %d byte misaligned %s to address 0x%lx",
109 nr_bytes, copy, (unsigned long) addr);
112 sim_engine_abort (sd, cpu, cia, "sim_core_signal - internal error - bad switch");
118 STATIC_INLINE_SIM_CORE\
120 sim_core_map_to_str (sim_core_maps map)
124 case sim_core_read_map: return "read";
125 case sim_core_write_map: return "write";
126 case sim_core_execute_map: return "exec";
127 default: return "(invalid-map)";
134 new_sim_core_mapping(SIM_DESC sd,
143 sim_core_mapping *new_mapping = ZALLOC(sim_core_mapping);
145 new_mapping->level = attach;
146 new_mapping->space = space;
147 new_mapping->base = addr;
148 new_mapping->nr_bytes = nr_bytes;
149 new_mapping->bound = addr + (nr_bytes - 1);
150 if (attach == attach_raw_memory) {
151 new_mapping->buffer = buffer;
152 new_mapping->free_buffer = free_buffer;
154 else if (attach >= attach_callback) {
155 new_mapping->device = device;
158 sim_io_error (sd, "new_sim_core_mapping - internal error - unknown attach type %d\n",
167 sim_core_map_attach(SIM_DESC sd,
168 sim_core_map *access_map,
172 unsigned nr_bytes, /* host limited */
173 device *client, /*callback/default*/
174 void *buffer, /*raw_memory*/
175 int free_buffer) /*raw_memory*/
177 /* find the insertion point for this additional mapping and then
179 sim_core_mapping *next_mapping;
180 sim_core_mapping **last_mapping;
182 SIM_ASSERT((attach >= attach_callback && client != NULL && buffer == NULL && !free_buffer)
183 || (attach == attach_raw_memory && client == NULL && buffer != NULL));
185 /* actually do occasionally get a zero size map */
188 device_error(client, "called on sim_core_map_attach with size zero");
190 sim_io_error (sd, "called on sim_core_map_attach with size zero");
194 /* find the insertion point (between last/next) */
195 next_mapping = access_map->first;
196 last_mapping = &access_map->first;
197 while(next_mapping != NULL
198 && (next_mapping->level < attach
199 || (next_mapping->level == attach
200 && next_mapping->bound < addr))) {
201 /* provided levels are the same */
202 /* assert: next_mapping->base > all bases before next_mapping */
203 /* assert: next_mapping->bound >= all bounds before next_mapping */
204 last_mapping = &next_mapping->next;
205 next_mapping = next_mapping->next;
208 /* check insertion point correct */
209 SIM_ASSERT(next_mapping == NULL || next_mapping->level >= attach);
210 if (next_mapping != NULL && next_mapping->level == attach
211 && next_mapping->base < (addr + (nr_bytes - 1))) {
213 device_error(client, "map overlap when attaching %d:0x%lx (%ld)",
214 space, (long)addr, (long)nr_bytes);
216 sim_io_error (sd, "map overlap when attaching %d:0x%lx (%ld)",
217 space, (long)addr, (long)nr_bytes);
221 /* create/insert the new mapping */
222 *last_mapping = new_sim_core_mapping(sd,
224 space, addr, nr_bytes,
225 client, buffer, free_buffer);
226 (*last_mapping)->next = next_mapping;
232 sim_core_attach(SIM_DESC sd,
238 unsigned nr_bytes, /* host limited */
240 void *optional_buffer)
242 sim_core *memory = STATE_CORE(sd);
248 /* check for for attempt to use unimplemented per-processor core map */
250 sim_io_error (sd, "sim_core_map_attach - processor specific memory map not yet supported");
252 if ((access & access_read_write_exec) == 0
253 || (access & ~access_read_write_exec) != 0) {
255 device_error(client, "invalid access for core attach");
257 sim_io_error (sd, "invalid access for core attach");
260 /* verify the attach type */
261 if (attach == attach_raw_memory) {
262 if (optional_buffer == NULL) {
263 buffer = zalloc(nr_bytes);
267 buffer = optional_buffer;
271 else if (attach >= attach_callback) {
277 device_error(client, "sim_core_attach - conflicting buffer and attach arguments");
279 sim_io_error (sd, "sim_core_attach - conflicting buffer and attach arguments");
284 /* attach the region to all applicable access maps */
286 map < nr_sim_core_maps;
289 case sim_core_read_map:
290 if (access & access_read)
291 sim_core_map_attach(sd, &memory->map[map],
293 space, addr, nr_bytes,
294 client, buffer, !buffer_freed);
297 case sim_core_write_map:
298 if (access & access_write)
299 sim_core_map_attach(sd, &memory->map[map],
301 space, addr, nr_bytes,
302 client, buffer, !buffer_freed);
305 case sim_core_execute_map:
306 if (access & access_exec)
307 sim_core_map_attach(sd, &memory->map[map],
309 space, addr, nr_bytes,
310 client, buffer, !buffer_freed);
313 case nr_sim_core_maps:
314 sim_io_error (sd, "sim_core_attach - internal error - bad switch");
319 /* Just copy this map to each of the processor specific data structures.
320 FIXME - later this will be replaced by true processor specific
322 for (i = 0; i < MAX_NR_PROCESSORS; i++)
324 CPU_CORE (STATE_CPU (sd, i))->common = *STATE_CORE (sd);
329 STATIC_INLINE_SIM_CORE\
331 sim_core_find_mapping(sim_core *core,
335 transfer_type transfer,
336 int abort, /*either 0 or 1 - hint to inline/-O */
337 sim_cpu *cpu, /* abort => cpu != NULL */
340 sim_core_mapping *mapping = core->map[map].first;
341 ASSERT ((addr & (nr_bytes - 1)) == 0); /* must be aligned */
342 ASSERT ((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
343 ASSERT (!abort || cpu != NULL); /* abort needs a non null CPU */
344 while (mapping != NULL)
346 if (addr >= mapping->base
347 && (addr + (nr_bytes - 1)) <= mapping->bound)
349 mapping = mapping->next;
353 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, nr_bytes, addr, transfer,
354 sim_core_unmapped_signal);
360 STATIC_INLINE_SIM_CORE\
362 sim_core_translate(sim_core_mapping *mapping,
365 return (void *)(((char *)mapping->buffer) + addr - mapping->base);
371 sim_core_read_buffer(SIM_DESC sd,
378 while (count < len) {
379 unsigned_word raddr = addr + count;
380 sim_core_mapping *mapping =
381 sim_core_find_mapping(STATE_CORE (sd), map,
382 raddr, /*nr-bytes*/1,
384 0, NULL, NULL_CIA); /*dont-abort*/
388 if (mapping->device != NULL) {
389 int nr_bytes = len - count;
390 if (raddr + nr_bytes - 1> mapping->bound)
391 nr_bytes = mapping->bound - raddr + 1;
392 if (device_io_read_buffer(mapping->device,
393 (unsigned_1*)buffer + count,
396 nr_bytes) != nr_bytes)
403 ((unsigned_1*)buffer)[count] =
404 *(unsigned_1*)sim_core_translate(mapping, raddr);
414 sim_core_write_buffer(SIM_DESC sd,
421 while (count < len) {
422 unsigned_word raddr = addr + count;
423 sim_core_mapping *mapping = sim_core_find_mapping(STATE_CORE (sd), map,
424 raddr, /*nr-bytes*/1,
426 0, NULL, NULL_CIA); /*dont-abort*/
430 if (WITH_CALLBACK_MEMORY
431 && mapping->device != NULL) {
432 int nr_bytes = len - count;
433 if (raddr + nr_bytes - 1 > mapping->bound)
434 nr_bytes = mapping->bound - raddr + 1;
435 if (device_io_write_buffer(mapping->device,
436 (unsigned_1*)buffer + count,
439 nr_bytes) != nr_bytes)
446 *(unsigned_1*)sim_core_translate(mapping, raddr) =
447 ((unsigned_1*)buffer)[count];
457 sim_core_set_xor (sim_cpu *cpu,
461 sim_cpu_core *cpu_core = CPU_CORE (cpu);
462 /* set up the XOR registers if required. */
463 if (WITH_XOR_ENDIAN) {
468 mask = WITH_XOR_ENDIAN - 1;
471 while (i - 1 < WITH_XOR_ENDIAN)
473 cpu_core->xor[i-1] = mask;
474 mask = (mask << 1) & (WITH_XOR_ENDIAN - 1);
481 sim_engine_abort (CPU_STATE (cpu), cpu, cia,
482 "Attempted to enable xor-endian mode when permenantly disabled.");
489 /* define the read/write 1/2/4/8/word functions */
492 #include "sim-n-core.h"
496 #include "sim-n-core.h"
500 #include "sim-n-core.h"
504 #include "sim-n-core.h"
508 #include "sim-n-core.h"