Preliminary suport for xor-endian suport in core module.
[deliverable/binutils-gdb.git] / sim / common / sim-core.c
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
25 #include "sim-main.h"
26 #include "sim-assert.h"
27
28
29 /* "core" module install handler.
30
31 This is called via sim_module_install to install the "core" subsystem
32 into the simulator. */
33
34 static MODULE_INIT_FN sim_core_init;
35 static MODULE_UNINSTALL_FN sim_core_uninstall;
36
37 EXTERN_SIM_CORE\
38 (SIM_RC)
39 sim_core_install (SIM_DESC sd)
40 {
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);
44 return SIM_RC_OK;
45 }
46
47
48 /* Uninstall the "core" subsystem from the simulator. */
49
50 STATIC_SIM_CORE\
51 (void)
52 sim_core_uninstall (SIM_DESC sd)
53 {
54 /* FIXME: free buffers, etc. */
55 }
56
57
58 STATIC_SIM_CORE\
59 (SIM_RC)
60 sim_core_init (SIM_DESC sd)
61 {
62 sim_core *memory = STATE_CORE(sd);
63 sim_core_maps map;
64 for (map = 0;
65 map < nr_sim_core_maps;
66 map++) {
67 /* blow away old mappings */
68 sim_core_mapping *curr = memory->map[map].first;
69 while (curr != NULL) {
70 sim_core_mapping *tbd = curr;
71 curr = curr->next;
72 if (tbd->free_buffer) {
73 SIM_ASSERT(tbd->buffer != NULL);
74 zfree(tbd->buffer);
75 }
76 zfree(tbd);
77 }
78 memory->map[map].first = NULL;
79 }
80 return SIM_RC_OK;
81 }
82
83
84
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))
88
89 STATIC_SIM_CORE\
90 (void)
91 sim_core_signal (SIM_DESC sd,
92 sim_cpu *cpu,
93 sim_cia cia,
94 sim_core_maps map,
95 int nr_bytes,
96 address_word addr,
97 transfer_type transfer,
98 sim_core_signals sig)
99 {
100 const char *copy = (transfer == read_transfer ? "read" : "write");
101 switch (sig)
102 {
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);
106 break;
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);
110 break;
111 default:
112 sim_engine_abort (sd, cpu, cia, "sim_core_signal - internal error - bad switch");
113 }
114 }
115 #endif
116
117
118 STATIC_INLINE_SIM_CORE\
119 (const char *)
120 sim_core_map_to_str (sim_core_maps map)
121 {
122 switch (map)
123 {
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)";
128 }
129 }
130
131
132 STATIC_SIM_CORE\
133 (sim_core_mapping *)
134 new_sim_core_mapping(SIM_DESC sd,
135 attach_type attach,
136 int space,
137 address_word addr,
138 unsigned nr_bytes,
139 device *device,
140 void *buffer,
141 int free_buffer)
142 {
143 sim_core_mapping *new_mapping = ZALLOC(sim_core_mapping);
144 /* common */
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;
153 }
154 else if (attach >= attach_callback) {
155 new_mapping->device = device;
156 }
157 else {
158 sim_io_error (sd, "new_sim_core_mapping - internal error - unknown attach type %d\n",
159 attach);
160 }
161 return new_mapping;
162 }
163
164
165 STATIC_SIM_CORE\
166 (void)
167 sim_core_map_attach(SIM_DESC sd,
168 sim_core_map *access_map,
169 attach_type attach,
170 int space,
171 address_word addr,
172 unsigned nr_bytes, /* host limited */
173 device *client, /*callback/default*/
174 void *buffer, /*raw_memory*/
175 int free_buffer) /*raw_memory*/
176 {
177 /* find the insertion point for this additional mapping and then
178 insert */
179 sim_core_mapping *next_mapping;
180 sim_core_mapping **last_mapping;
181
182 SIM_ASSERT((attach >= attach_callback && client != NULL && buffer == NULL && !free_buffer)
183 || (attach == attach_raw_memory && client == NULL && buffer != NULL));
184
185 /* actually do occasionally get a zero size map */
186 if (nr_bytes == 0) {
187 #if (WITH_DEVICES)
188 device_error(client, "called on sim_core_map_attach with size zero");
189 #else
190 sim_io_error (sd, "called on sim_core_map_attach with size zero");
191 #endif
192 }
193
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;
206 }
207
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))) {
212 #if (WITH_DEVICES)
213 device_error(client, "map overlap when attaching %d:0x%lx (%ld)",
214 space, (long)addr, (long)nr_bytes);
215 #else
216 sim_io_error (sd, "map overlap when attaching %d:0x%lx (%ld)",
217 space, (long)addr, (long)nr_bytes);
218 #endif
219 }
220
221 /* create/insert the new mapping */
222 *last_mapping = new_sim_core_mapping(sd,
223 attach,
224 space, addr, nr_bytes,
225 client, buffer, free_buffer);
226 (*last_mapping)->next = next_mapping;
227 }
228
229
230 EXTERN_SIM_CORE\
231 (void)
232 sim_core_attach(SIM_DESC sd,
233 sim_cpu *cpu,
234 attach_type attach,
235 access_type access,
236 int space,
237 address_word addr,
238 unsigned nr_bytes, /* host limited */
239 device *client,
240 void *optional_buffer)
241 {
242 sim_core *memory = STATE_CORE(sd);
243 sim_core_maps map;
244 void *buffer;
245 int buffer_freed;
246 int i;
247
248 /* check for for attempt to use unimplemented per-processor core map */
249 if (cpu != NULL)
250 sim_io_error (sd, "sim_core_map_attach - processor specific memory map not yet supported");
251
252 if ((access & access_read_write_exec) == 0
253 || (access & ~access_read_write_exec) != 0) {
254 #if (WITH_DEVICES)
255 device_error(client, "invalid access for core attach");
256 #else
257 sim_io_error (sd, "invalid access for core attach");
258 #endif
259 }
260 /* verify the attach type */
261 if (attach == attach_raw_memory) {
262 if (optional_buffer == NULL) {
263 buffer = zalloc(nr_bytes);
264 buffer_freed = 0;
265 }
266 else {
267 buffer = optional_buffer;
268 buffer_freed = 1;
269 }
270 }
271 else if (attach >= attach_callback) {
272 buffer = NULL;
273 buffer_freed = 1;
274 }
275 else {
276 #if (WITH_DEVICES)
277 device_error(client, "sim_core_attach - conflicting buffer and attach arguments");
278 #else
279 sim_io_error (sd, "sim_core_attach - conflicting buffer and attach arguments");
280 #endif
281 buffer = NULL;
282 buffer_freed = 1;
283 }
284 /* attach the region to all applicable access maps */
285 for (map = 0;
286 map < nr_sim_core_maps;
287 map++) {
288 switch (map) {
289 case sim_core_read_map:
290 if (access & access_read)
291 sim_core_map_attach(sd, &memory->map[map],
292 attach,
293 space, addr, nr_bytes,
294 client, buffer, !buffer_freed);
295 buffer_freed ++;
296 break;
297 case sim_core_write_map:
298 if (access & access_write)
299 sim_core_map_attach(sd, &memory->map[map],
300 attach,
301 space, addr, nr_bytes,
302 client, buffer, !buffer_freed);
303 buffer_freed ++;
304 break;
305 case sim_core_execute_map:
306 if (access & access_exec)
307 sim_core_map_attach(sd, &memory->map[map],
308 attach,
309 space, addr, nr_bytes,
310 client, buffer, !buffer_freed);
311 buffer_freed ++;
312 break;
313 case nr_sim_core_maps:
314 sim_io_error (sd, "sim_core_attach - internal error - bad switch");
315 break;
316 }
317 }
318
319 /* Just copy this map to each of the processor specific data structures.
320 FIXME - later this will be replaced by true processor specific
321 maps. */
322 for (i = 0; i < MAX_NR_PROCESSORS; i++)
323 {
324 CPU_CORE (STATE_CPU (sd, i))->common = *STATE_CORE (sd);
325 }
326 }
327
328
329 STATIC_INLINE_SIM_CORE\
330 (sim_core_mapping *)
331 sim_core_find_mapping(sim_core *core,
332 sim_core_maps map,
333 address_word addr,
334 unsigned nr_bytes,
335 transfer_type transfer,
336 int abort, /*either 0 or 1 - hint to inline/-O */
337 sim_cpu *cpu, /* abort => cpu != NULL */
338 sim_cia cia)
339 {
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)
345 {
346 if (addr >= mapping->base
347 && (addr + (nr_bytes - 1)) <= mapping->bound)
348 return mapping;
349 mapping = mapping->next;
350 }
351 if (abort)
352 {
353 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, nr_bytes, addr, transfer,
354 sim_core_unmapped_signal);
355 }
356 return NULL;
357 }
358
359
360 STATIC_INLINE_SIM_CORE\
361 (void *)
362 sim_core_translate(sim_core_mapping *mapping,
363 address_word addr)
364 {
365 return (void *)(((char *)mapping->buffer) + addr - mapping->base);
366 }
367
368
369 EXTERN_SIM_CORE\
370 (unsigned)
371 sim_core_read_buffer(SIM_DESC sd,
372 sim_core_maps map,
373 void *buffer,
374 address_word addr,
375 unsigned len)
376 {
377 unsigned count = 0;
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,
383 read_transfer,
384 0, NULL, NULL_CIA); /*dont-abort*/
385 if (mapping == NULL)
386 break;
387 #if (WITH_DEVICES)
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,
394 mapping->space,
395 raddr,
396 nr_bytes) != nr_bytes)
397 break;
398 count += nr_bytes;
399 }
400 else
401 #endif
402 {
403 ((unsigned_1*)buffer)[count] =
404 *(unsigned_1*)sim_core_translate(mapping, raddr);
405 count += 1;
406 }
407 }
408 return count;
409 }
410
411
412 EXTERN_SIM_CORE\
413 (unsigned)
414 sim_core_write_buffer(SIM_DESC sd,
415 sim_core_maps map,
416 const void *buffer,
417 address_word addr,
418 unsigned len)
419 {
420 unsigned count = 0;
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,
425 write_transfer,
426 0, NULL, NULL_CIA); /*dont-abort*/
427 if (mapping == NULL)
428 break;
429 #if (WITH_DEVICES)
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,
437 mapping->space,
438 raddr,
439 nr_bytes) != nr_bytes)
440 break;
441 count += nr_bytes;
442 }
443 else
444 #endif
445 {
446 *(unsigned_1*)sim_core_translate(mapping, raddr) =
447 ((unsigned_1*)buffer)[count];
448 count += 1;
449 }
450 }
451 return count;
452 }
453
454
455 EXTERN_SIM_CORE\
456 (void)
457 sim_core_set_xor (sim_cpu *cpu,
458 sim_cia cia,
459 int is_xor)
460 {
461 sim_cpu_core *cpu_core = CPU_CORE (cpu);
462 /* set up the XOR registers if required. */
463 if (WITH_XOR_ENDIAN) {
464 {
465 int i = 1;
466 unsigned mask;
467 if (is_xor)
468 mask = WITH_XOR_ENDIAN - 1;
469 else
470 mask = 0;
471 while (i - 1 < WITH_XOR_ENDIAN)
472 {
473 cpu_core->xor[i-1] = mask;
474 mask = (mask << 1) & (WITH_XOR_ENDIAN - 1);
475 i = (i << 1);
476 }
477 }
478 }
479 else {
480 if (is_xor)
481 sim_engine_abort (CPU_STATE (cpu), cpu, cia,
482 "Attempted to enable xor-endian mode when permenantly disabled.");
483 }
484 }
485
486
487
488
489 /* define the read/write 1/2/4/8/word functions */
490
491 #define N 1
492 #include "sim-n-core.h"
493 #undef N
494
495 #define N 2
496 #include "sim-n-core.h"
497 #undef N
498
499 #define N 4
500 #include "sim-n-core.h"
501 #undef N
502
503 #define N 8
504 #include "sim-n-core.h"
505 #undef N
506
507 #define N word
508 #include "sim-n-core.h"
509 #undef N
510
511 #endif
This page took 0.042456 seconds and 5 git commands to generate.