xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/sim-core.c (revision 88241920d21b339bf319c0e979ffda80c49a2936)
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
854