]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/sim-core.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / sim / common / sim-core.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3 Copyright 2002-2024 Free Software Foundation, Inc.
4
5 Contributed by Andrew Cagney and Red Hat.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22
23 #ifndef SIM_CORE_C
24 #define SIM_CORE_C
25
26 /* This must come before any other includes. */
27 #include "defs.h"
28
29 #include <stdlib.h>
30
31 #include "libiberty.h"
32
33 #include "sim-main.h"
34 #include "sim-assert.h"
35 #include "sim-signal.h"
36
37 #if (WITH_HW)
38 #include "sim-hw.h"
39 #endif
40
41 /* "core" module install handler.
42
43 This is called via sim_module_install to install the "core"
44 subsystem into the simulator. */
45
46 #if EXTERN_SIM_CORE_P
47 static MODULE_INIT_FN sim_core_init;
48 static MODULE_UNINSTALL_FN sim_core_uninstall;
49 #endif
50
51 #if EXTERN_SIM_CORE_P
52 SIM_RC
53 sim_core_install (SIM_DESC sd)
54 {
55 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
56
57 /* establish the other handlers */
58 sim_module_add_uninstall_fn (sd, sim_core_uninstall);
59 sim_module_add_init_fn (sd, sim_core_init);
60
61 /* establish any initial data structures - none */
62 return SIM_RC_OK;
63 }
64 #endif
65
66
67 /* Uninstall the "core" subsystem from the simulator. */
68
69 #if EXTERN_SIM_CORE_P
70 static void
71 sim_core_uninstall (SIM_DESC sd)
72 {
73 sim_core *core = STATE_CORE (sd);
74 unsigned map;
75 /* blow away any mappings */
76 for (map = 0; map < nr_maps; map++) {
77 sim_core_mapping *curr = core->common.map[map].first;
78 while (curr != NULL) {
79 sim_core_mapping *tbd = curr;
80 curr = curr->next;
81 if (tbd->free_buffer != NULL) {
82 SIM_ASSERT (tbd->buffer != NULL);
83 free (tbd->free_buffer);
84 }
85 free (tbd);
86 }
87 core->common.map[map].first = NULL;
88 }
89 }
90 #endif
91
92
93 #if EXTERN_SIM_CORE_P
94 static SIM_RC
95 sim_core_init (SIM_DESC sd)
96 {
97 /* Nothing to do */
98 return SIM_RC_OK;
99 }
100 #endif
101
102
103
104 #ifndef SIM_CORE_SIGNAL
105 #define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \
106 sim_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ERROR))
107 #endif
108
109 #if EXTERN_SIM_CORE_P
110 void
111 sim_core_signal (SIM_DESC sd,
112 sim_cpu *cpu,
113 sim_cia cia,
114 unsigned map,
115 int nr_bytes,
116 address_word addr,
117 transfer_type transfer,
118 sim_core_signals sig)
119 {
120 const char *copy = (transfer == read_transfer ? "read" : "write");
121 address_word ip = CIA_ADDR (cia);
122 switch (sig)
123 {
124 case sim_core_unmapped_signal:
125 sim_io_eprintf (sd, "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
126 nr_bytes, copy, (unsigned long) addr, (unsigned long) ip);
127 sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGSEGV);
128 break;
129 case sim_core_unaligned_signal:
130 sim_io_eprintf (sd, "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n",
131 nr_bytes, copy, (unsigned long) addr, (unsigned long) ip);
132 sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGBUS);
133 break;
134 default:
135 sim_engine_abort (sd, cpu, cia,
136 "sim_core_signal - internal error - bad switch");
137 }
138 }
139 #endif
140
141
142 #if EXTERN_SIM_CORE_P
143 static sim_core_mapping *
144 new_sim_core_mapping (SIM_DESC sd,
145 int level,
146 int space,
147 address_word addr,
148 address_word nr_bytes,
149 unsigned modulo,
150 struct hw *device,
151 void *buffer,
152 void *free_buffer)
153 {
154 sim_core_mapping *new_mapping = ZALLOC (sim_core_mapping);
155 /* common */
156 new_mapping->level = level;
157 new_mapping->space = space;
158 new_mapping->base = addr;
159 new_mapping->nr_bytes = nr_bytes;
160 new_mapping->bound = addr + (nr_bytes - 1);
161 new_mapping->mask = modulo - 1;
162 new_mapping->buffer = buffer;
163 new_mapping->free_buffer = free_buffer;
164 new_mapping->device = device;
165 return new_mapping;
166 }
167 #endif
168
169
170 #if EXTERN_SIM_CORE_P
171 static void
172 sim_core_map_attach (SIM_DESC sd,
173 sim_core_map *access_map,
174 int level,
175 int space,
176 address_word addr,
177 address_word nr_bytes,
178 unsigned modulo,
179 struct hw *client, /*callback/default*/
180 void *buffer, /*raw_memory*/
181 void *free_buffer) /*raw_memory*/
182 {
183 /* find the insertion point for this additional mapping and then
184 insert */
185 sim_core_mapping *next_mapping;
186 sim_core_mapping **last_mapping;
187
188 SIM_ASSERT ((client == NULL) != (buffer == NULL));
189 SIM_ASSERT ((client == NULL) >= (free_buffer != NULL));
190
191 /* actually do occasionally get a zero size map */
192 if (nr_bytes == 0)
193 {
194 #if (WITH_HW)
195 sim_hw_abort (sd, client, "called on sim_core_map_attach with size zero");
196 #endif
197 sim_io_error (sd, "called on sim_core_map_attach with size zero");
198 }
199
200 /* find the insertion point (between last/next) */
201 next_mapping = access_map->first;
202 last_mapping = &access_map->first;
203 while (next_mapping != NULL
204 && (next_mapping->level < level
205 || (next_mapping->level == level
206 && next_mapping->bound < addr)))
207 {
208 /* provided levels are the same */
209 /* assert: next_mapping->base > all bases before next_mapping */
210 /* assert: next_mapping->bound >= all bounds before next_mapping */
211 last_mapping = &next_mapping->next;
212 next_mapping = next_mapping->next;
213 }
214
215 /* check insertion point correct */
216 SIM_ASSERT (next_mapping == NULL || next_mapping->level >= level);
217 if (next_mapping != NULL && next_mapping->level == level
218 && next_mapping->base < (addr + (nr_bytes - 1)))
219 {
220 #if WITH_HW
221 sim_hw_abort (sd, client, "memory map %d:0x%lx..0x%lx (%ld bytes) overlaps %d:0x%lx..0x%lx (%ld bytes)",
222 space,
223 (long) addr,
224 (long) (addr + (nr_bytes - 1)),
225 (long) nr_bytes,
226 next_mapping->space,
227 (long) next_mapping->base,
228 (long) next_mapping->bound,
229 (long) next_mapping->nr_bytes);
230 #endif
231 sim_io_error (sd, "memory map %d:0x%lx..0x%lx (%ld bytes) overlaps %d:0x%lx..0x%lx (%ld bytes)",
232 space,
233 (long) addr,
234 (long) (addr + (nr_bytes - 1)),
235 (long) nr_bytes,
236 next_mapping->space,
237 (long) next_mapping->base,
238 (long) next_mapping->bound,
239 (long) next_mapping->nr_bytes);
240 }
241
242 /* create/insert the new mapping */
243 *last_mapping = new_sim_core_mapping (sd,
244 level,
245 space, addr, nr_bytes, modulo,
246 client, buffer, free_buffer);
247 (*last_mapping)->next = next_mapping;
248 }
249 #endif
250
251
252 /* Attach memory or a memory mapped device to the simulator.
253 See sim-core.h for a full description. */
254
255 #if EXTERN_SIM_CORE_P
256 void
257 sim_core_attach (SIM_DESC sd,
258 sim_cpu *cpu,
259 int level,
260 unsigned mapmask,
261 int space,
262 address_word addr,
263 address_word nr_bytes,
264 unsigned modulo,
265 struct hw *client,
266 void *optional_buffer)
267 {
268 sim_core *memory = STATE_CORE (sd);
269 unsigned map;
270 void *buffer;
271 void *free_buffer;
272
273 /* check for for attempt to use unimplemented per-processor core map */
274 if (cpu != NULL)
275 sim_io_error (sd, "sim_core_map_attach - processor specific memory map not yet supported");
276
277 if (client != NULL && modulo != 0)
278 {
279 #if (WITH_HW)
280 sim_hw_abort (sd, client, "sim_core_attach - internal error - modulo and callback memory conflict");
281 #endif
282 sim_io_error (sd, "sim_core_attach - internal error - modulo and callback memory conflict");
283 }
284 if (modulo != 0)
285 {
286 unsigned mask = modulo - 1;
287 /* any zero bits */
288 while (mask >= sizeof (uint64_t)) /* minimum modulo */
289 {
290 if ((mask & 1) == 0)
291 mask = 0;
292 else
293 mask >>= 1;
294 }
295 if (mask != sizeof (uint64_t) - 1)
296 {
297 #if (WITH_HW)
298 sim_hw_abort (sd, client, "sim_core_attach - internal error - modulo %lx not power of two", (long) modulo);
299 #endif
300 sim_io_error (sd, "sim_core_attach - internal error - modulo %lx not power of two", (long) modulo);
301 }
302 }
303
304 /* verify consistency between device and buffer */
305 if (client != NULL && optional_buffer != NULL)
306 {
307 #if (WITH_HW)
308 sim_hw_abort (sd, client, "sim_core_attach - internal error - conflicting buffer and attach arguments");
309 #endif
310 sim_io_error (sd, "sim_core_attach - internal error - conflicting buffer and attach arguments");
311 }
312 if (client == NULL)
313 {
314 if (optional_buffer == NULL)
315 {
316 int padding = (addr % sizeof (uint64_t));
317 unsigned long bytes = (modulo == 0 ? nr_bytes : modulo) + padding;
318 free_buffer = zalloc (bytes);
319 buffer = (char*) free_buffer + padding;
320 }
321 else
322 {
323 buffer = optional_buffer;
324 free_buffer = NULL;
325 }
326 }
327 else
328 {
329 /* a device */
330 buffer = NULL;
331 free_buffer = NULL;
332 }
333
334 /* attach the region to all applicable access maps */
335 for (map = 0;
336 map < nr_maps;
337 map++)
338 {
339 if (mapmask & (1 << map))
340 {
341 sim_core_map_attach (sd, &memory->common.map[map],
342 level, space, addr, nr_bytes, modulo,
343 client, buffer, free_buffer);
344 free_buffer = NULL;
345 }
346 }
347
348 /* Just copy this map to each of the processor specific data structures.
349 FIXME - later this will be replaced by true processor specific
350 maps. */
351 {
352 int i;
353 for (i = 0; i < MAX_NR_PROCESSORS; i++)
354 {
355 CPU_CORE (STATE_CPU (sd, i))->common = STATE_CORE (sd)->common;
356 }
357 }
358 }
359 #endif
360
361
362 /* Remove any memory reference related to this address */
363 #if EXTERN_SIM_CORE_P
364 static void
365 sim_core_map_detach (SIM_DESC sd,
366 sim_core_map *access_map,
367 int level,
368 int space,
369 address_word addr)
370 {
371 sim_core_mapping **entry;
372 for (entry = &access_map->first;
373 (*entry) != NULL;
374 entry = &(*entry)->next)
375 {
376 if ((*entry)->base == addr
377 && (*entry)->level == level
378 && (*entry)->space == space)
379 {
380 sim_core_mapping *dead = (*entry);
381 (*entry) = dead->next;
382 if (dead->free_buffer != NULL)
383 free (dead->free_buffer);
384 free (dead);
385 return;
386 }
387 }
388 }
389 #endif
390
391 #if EXTERN_SIM_CORE_P
392 void
393 sim_core_detach (SIM_DESC sd,
394 sim_cpu *cpu,
395 int level,
396 int address_space,
397 address_word addr)
398 {
399 sim_core *memory = STATE_CORE (sd);
400 unsigned map;
401 for (map = 0; map < nr_maps; map++)
402 {
403 sim_core_map_detach (sd, &memory->common.map[map],
404 level, address_space, addr);
405 }
406 /* Just copy this update to each of the processor specific data
407 structures. FIXME - later this will be replaced by true
408 processor specific maps. */
409 {
410 int i;
411 for (i = 0; i < MAX_NR_PROCESSORS; i++)
412 {
413 CPU_CORE (STATE_CPU (sd, i))->common = STATE_CORE (sd)->common;
414 }
415 }
416 }
417 #endif
418
419
420 STATIC_INLINE_SIM_CORE\
421 (sim_core_mapping *)
422 sim_core_find_mapping (sim_core_common *core,
423 unsigned map,
424 address_word addr,
425 unsigned nr_bytes,
426 transfer_type transfer,
427 int abort, /*either 0 or 1 - hint to inline/-O */
428 sim_cpu *cpu, /* abort => cpu != NULL */
429 sim_cia cia)
430 {
431 sim_core_mapping *mapping = core->map[map].first;
432 ASSERT ((addr & (nr_bytes - 1)) == 0); /* must be aligned */
433 ASSERT ((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
434 ASSERT (!abort || cpu != NULL); /* abort needs a non null CPU */
435 while (mapping != NULL)
436 {
437 if (addr >= mapping->base
438 && (addr + (nr_bytes - 1)) <= mapping->bound)
439 return mapping;
440 mapping = mapping->next;
441 }
442 if (abort)
443 {
444 SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, nr_bytes, addr, transfer,
445 sim_core_unmapped_signal);
446 }
447 return NULL;
448 }
449
450
451 STATIC_INLINE_SIM_CORE\
452 (void *)
453 sim_core_translate (sim_core_mapping *mapping,
454 address_word addr)
455 {
456 return (void *)((uint8_t *) mapping->buffer
457 + ((addr - mapping->base) & mapping->mask));
458 }
459
460
461 #if EXTERN_SIM_CORE_P
462 /* See include/sim/sim.h. */
463 char *
464 sim_memory_map (SIM_DESC sd)
465 {
466 sim_core *core = STATE_CORE (sd);
467 unsigned map;
468 char *s1, *s2, *entry;
469
470 s1 = xstrdup (
471 "<?xml version='1.0'?>\n"
472 "<!DOCTYPE memory-map PUBLIC '+//IDN gnu.org//DTD GDB Memory Map V1.0//EN'"
473 " 'http://sourceware.org/gdb/gdb-memory-map.dtd'>\n"
474 "<memory-map>\n");
475
476 for (map = 0; map < nr_maps; ++map)
477 {
478 sim_core_mapping *mapping;
479
480 for (mapping = core->common.map[map].first;
481 mapping != NULL;
482 mapping = mapping->next)
483 {
484 /* GDB can only handle a single address space. */
485 if (mapping->level != 0)
486 continue;
487
488 entry = xasprintf ("<memory type='ram' start='%#" PRIxTW "' "
489 "length='%#" PRIxTW "'/>\n",
490 mapping->base, mapping->nr_bytes);
491 /* The sim memory map is organized by access, not by addresses.
492 So a RWX memory map will have three independent mappings.
493 GDB's format cannot support overlapping regions, so we have
494 to filter those out.
495
496 Further, GDB can only handle RX ("rom") or RWX ("ram") mappings.
497 We just emit "ram" everywhere to keep it simple. If GDB ever
498 gains support for more stuff, we can expand this.
499
500 Using strstr is kind of hacky, but as long as the map is not huge
501 (we're talking <10K), should be fine. */
502 if (strstr (s1, entry) == NULL)
503 {
504 s2 = concat (s1, entry, NULL);
505 free (s1);
506 s1 = s2;
507 }
508 free (entry);
509 }
510 }
511
512 s2 = concat (s1, "</memory-map>", NULL);
513 free (s1);
514 return s2;
515 }
516 #endif
517
518
519 #if EXTERN_SIM_CORE_P
520 unsigned
521 sim_core_read_buffer (SIM_DESC sd,
522 sim_cpu *cpu,
523 unsigned map,
524 void *buffer,
525 address_word addr,
526 unsigned len)
527 {
528 sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common);
529 unsigned count = 0;
530 while (count < len)
531 {
532 address_word raddr = addr + count;
533 sim_core_mapping *mapping =
534 sim_core_find_mapping (core, map,
535 raddr, /*nr-bytes*/1,
536 read_transfer,
537 0 /*dont-abort*/, NULL, NULL_CIA);
538 if (mapping == NULL)
539 break;
540 #if (WITH_HW)
541 if (mapping->device != NULL)
542 {
543 int nr_bytes = len - count;
544 if (raddr + nr_bytes - 1> mapping->bound)
545 nr_bytes = mapping->bound - raddr + 1;
546 /* If the access was initiated by a cpu, pass it down so errors can
547 be propagated properly. For other sources (e.g. GDB or DMA), we
548 can only signal errors via the return value. */
549 if (cpu)
550 {
551 sim_cia cia = cpu ? CPU_PC_GET (cpu) : NULL_CIA;
552 sim_cpu_hw_io_read_buffer (cpu, cia, mapping->device,
553 (unsigned_1*)buffer + count,
554 mapping->space,
555 raddr,
556 nr_bytes);
557 }
558 else if (sim_hw_io_read_buffer (sd, mapping->device,
559 (unsigned_1*)buffer + count,
560 mapping->space,
561 raddr,
562 nr_bytes) != nr_bytes)
563 break;
564 count += nr_bytes;
565 continue;
566 }
567 #endif
568 ((unsigned_1*)buffer)[count] =
569 *(unsigned_1*)sim_core_translate (mapping, raddr);
570 count += 1;
571 }
572 return count;
573 }
574 #endif
575
576
577 #if EXTERN_SIM_CORE_P
578 unsigned
579 sim_core_write_buffer (SIM_DESC sd,
580 sim_cpu *cpu,
581 unsigned map,
582 const void *buffer,
583 address_word addr,
584 unsigned len)
585 {
586 sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common);
587 unsigned count = 0;
588 while (count < len)
589 {
590 address_word raddr = addr + count;
591 sim_core_mapping *mapping =
592 sim_core_find_mapping (core, map,
593 raddr, /*nr-bytes*/1,
594 write_transfer,
595 0 /*dont-abort*/, NULL, NULL_CIA);
596 if (mapping == NULL)
597 break;
598 #if (WITH_HW)
599 if (mapping->device != NULL)
600 {
601 int nr_bytes = len - count;
602 if (raddr + nr_bytes - 1 > mapping->bound)
603 nr_bytes = mapping->bound - raddr + 1;
604 /* If the access was initiated by a cpu, pass it down so errors can
605 be propagated properly. For other sources (e.g. GDB or DMA), we
606 can only signal errors via the return value. */
607 if (cpu)
608 {
609 sim_cia cia = cpu ? CPU_PC_GET (cpu) : NULL_CIA;
610 sim_cpu_hw_io_write_buffer (cpu, cia, mapping->device,
611 (unsigned_1*)buffer + count,
612 mapping->space,
613 raddr,
614 nr_bytes);
615 }
616 else if (sim_hw_io_write_buffer (sd, mapping->device,
617 (unsigned_1*)buffer + count,
618 mapping->space,
619 raddr,
620 nr_bytes) != nr_bytes)
621 break;
622 count += nr_bytes;
623 continue;
624 }
625 #endif
626 *(unsigned_1*)sim_core_translate (mapping, raddr) =
627 ((unsigned_1*)buffer)[count];
628 count += 1;
629 }
630 return count;
631 }
632 #endif
633
634
635 #if EXTERN_SIM_CORE_P
636 void
637 sim_core_set_xor (SIM_DESC sd,
638 sim_cpu *cpu,
639 int is_xor)
640 {
641 /* set up the XOR map if required. */
642 if (WITH_XOR_ENDIAN) {
643 {
644 sim_core *core = STATE_CORE (sd);
645 sim_cpu_core *cpu_core = (cpu != NULL ? CPU_CORE (cpu) : NULL);
646 if (cpu_core != NULL)
647 {
648 int i = 1;
649 unsigned mask;
650 if (is_xor)
651 mask = WITH_XOR_ENDIAN - 1;
652 else
653 mask = 0;
654 while (i - 1 < WITH_XOR_ENDIAN)
655 {
656 cpu_core->byte_xor[i-1] = mask;
657 mask = (mask << 1) & (WITH_XOR_ENDIAN - 1);
658 i = (i << 1);
659 }
660 }
661 else
662 {
663 if (is_xor)
664 core->byte_xor = WITH_XOR_ENDIAN - 1;
665 else
666 core->byte_xor = 0;
667 }
668 }
669 }
670 else {
671 if (is_xor)
672 sim_engine_abort (sd, NULL, NULL_CIA,
673 "Attempted to enable xor-endian mode when permanently disabled.");
674 }
675 }
676 #endif
677
678
679 #if EXTERN_SIM_CORE_P
680 static void
681 reverse_n (unsigned_1 *dest,
682 const unsigned_1 *src,
683 int nr_bytes)
684 {
685 int i;
686 for (i = 0; i < nr_bytes; i++)
687 {
688 dest [nr_bytes - i - 1] = src [i];
689 }
690 }
691 #endif
692
693
694 #if EXTERN_SIM_CORE_P
695 unsigned
696 sim_core_xor_read_buffer (SIM_DESC sd,
697 sim_cpu *cpu,
698 unsigned map,
699 void *buffer,
700 address_word addr,
701 unsigned nr_bytes)
702 {
703 address_word byte_xor
704 = (cpu == NULL ? STATE_CORE (sd)->byte_xor : CPU_CORE (cpu)->byte_xor[0]);
705 if (!WITH_XOR_ENDIAN || !byte_xor)
706 return sim_core_read_buffer (sd, cpu, map, buffer, addr, nr_bytes);
707 else
708 /* only break up transfers when xor-endian is both selected and enabled */
709 {
710 unsigned_1 x[WITH_XOR_ENDIAN + 1]; /* +1 to avoid zero-sized array */
711 unsigned nr_transfered = 0;
712 address_word start = addr;
713 unsigned nr_this_transfer = (WITH_XOR_ENDIAN - (addr & ~(WITH_XOR_ENDIAN - 1)));
714 address_word stop;
715 /* initial and intermediate transfers are broken when they cross
716 an XOR endian boundary */
717 while (nr_transfered + nr_this_transfer < nr_bytes)
718 /* initial/intermediate transfers */
719 {
720 /* since xor-endian is enabled stop^xor defines the start
721 address of the transfer */
722 stop = start + nr_this_transfer - 1;
723 SIM_ASSERT (start <= stop);
724 SIM_ASSERT ((stop ^ byte_xor) <= (start ^ byte_xor));
725 if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer)
726 != nr_this_transfer)
727 return nr_transfered;
728 reverse_n (&((unsigned_1*)buffer)[nr_transfered], x, nr_this_transfer);
729 nr_transfered += nr_this_transfer;
730 nr_this_transfer = WITH_XOR_ENDIAN;
731 start = stop + 1;
732 }
733 /* final transfer */
734 nr_this_transfer = nr_bytes - nr_transfered;
735 stop = start + nr_this_transfer - 1;
736 SIM_ASSERT (stop == (addr + nr_bytes - 1));
737 if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer)
738 != nr_this_transfer)
739 return nr_transfered;
740 reverse_n (&((unsigned_1*)buffer)[nr_transfered], x, nr_this_transfer);
741 return nr_bytes;
742 }
743 }
744 #endif
745
746
747 #if EXTERN_SIM_CORE_P
748 unsigned
749 sim_core_xor_write_buffer (SIM_DESC sd,
750 sim_cpu *cpu,
751 unsigned map,
752 const void *buffer,
753 address_word addr,
754 unsigned nr_bytes)
755 {
756 address_word byte_xor
757 = (cpu == NULL ? STATE_CORE (sd)->byte_xor : CPU_CORE (cpu)->byte_xor[0]);
758 if (!WITH_XOR_ENDIAN || !byte_xor)
759 return sim_core_write_buffer (sd, cpu, map, buffer, addr, nr_bytes);
760 else
761 /* only break up transfers when xor-endian is both selected and enabled */
762 {
763 unsigned_1 x[WITH_XOR_ENDIAN + 1]; /* +1 to avoid zero sized array */
764 unsigned nr_transfered = 0;
765 address_word start = addr;
766 unsigned nr_this_transfer = (WITH_XOR_ENDIAN - (addr & ~(WITH_XOR_ENDIAN - 1)));
767 address_word stop;
768 /* initial and intermediate transfers are broken when they cross
769 an XOR endian boundary */
770 while (nr_transfered + nr_this_transfer < nr_bytes)
771 /* initial/intermediate transfers */
772 {
773 /* since xor-endian is enabled stop^xor defines the start
774 address of the transfer */
775 stop = start + nr_this_transfer - 1;
776 SIM_ASSERT (start <= stop);
777 SIM_ASSERT ((stop ^ byte_xor) <= (start ^ byte_xor));
778 reverse_n (x, &((unsigned_1*)buffer)[nr_transfered], nr_this_transfer);
779 if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer)
780 != nr_this_transfer)
781 return nr_transfered;
782 nr_transfered += nr_this_transfer;
783 nr_this_transfer = WITH_XOR_ENDIAN;
784 start = stop + 1;
785 }
786 /* final transfer */
787 nr_this_transfer = nr_bytes - nr_transfered;
788 stop = start + nr_this_transfer - 1;
789 SIM_ASSERT (stop == (addr + nr_bytes - 1));
790 reverse_n (x, &((unsigned_1*)buffer)[nr_transfered], nr_this_transfer);
791 if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer)
792 != nr_this_transfer)
793 return nr_transfered;
794 return nr_bytes;
795 }
796 }
797 #endif
798
799 #if EXTERN_SIM_CORE_P
800 void *
801 sim_core_trans_addr (SIM_DESC sd,
802 sim_cpu *cpu,
803 unsigned map,
804 address_word addr)
805 {
806 sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common);
807 sim_core_mapping *mapping =
808 sim_core_find_mapping (core, map,
809 addr, /*nr-bytes*/1,
810 write_transfer,
811 0 /*dont-abort*/, NULL, NULL_CIA);
812 if (mapping == NULL)
813 return NULL;
814 return sim_core_translate (mapping, addr);
815 }
816 #endif
817
818
819
820 /* define the read/write 1/2/4/8/16/word functions */
821
822 #define N 16
823 #include "sim-n-core.h"
824
825 #define N 8
826 #include "sim-n-core.h"
827
828 #define N 7
829 #define M 8
830 #include "sim-n-core.h"
831
832 #define N 6
833 #define M 8
834 #include "sim-n-core.h"
835
836 #define N 5
837 #define M 8
838 #include "sim-n-core.h"
839
840 #define N 4
841 #include "sim-n-core.h"
842
843 #define N 3
844 #define M 4
845 #include "sim-n-core.h"
846
847 #define N 2
848 #include "sim-n-core.h"
849
850 #define N 1
851 #include "sim-n-core.h"
852
853 #endif