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
sim_core_install(SIM_DESC sd)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
sim_core_uninstall(SIM_DESC sd)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
sim_core_init(SIM_DESC sd)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
sim_core_signal(SIM_DESC sd,sim_cpu * cpu,sim_cia cia,unsigned map,int nr_bytes,address_word addr,transfer_type transfer,sim_core_signals sig)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 *
new_sim_core_mapping(SIM_DESC sd,int level,int space,address_word addr,address_word nr_bytes,unsigned modulo,struct hw * device,void * buffer,void * free_buffer)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
sim_core_map_attach(SIM_DESC sd,sim_core_map * access_map,int level,int space,address_word addr,address_word nr_bytes,unsigned modulo,struct hw * client,void * buffer,void * free_buffer)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
sim_core_attach(SIM_DESC sd,sim_cpu * cpu,int level,unsigned mapmask,int space,address_word addr,address_word nr_bytes,unsigned modulo,struct hw * client,void * optional_buffer)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
sim_core_map_detach(SIM_DESC sd,sim_core_map * access_map,int level,int space,address_word addr)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
sim_core_detach(SIM_DESC sd,sim_cpu * cpu,int level,int address_space,address_word addr)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 *)
sim_core_find_mapping(sim_core_common * core,unsigned map,address_word addr,unsigned nr_bytes,transfer_type transfer,int abort,sim_cpu * cpu,sim_cia cia)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 *)
sim_core_translate(sim_core_mapping * mapping,address_word addr)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 *
sim_memory_map(SIM_DESC sd)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
sim_core_read_buffer(SIM_DESC sd,sim_cpu * cpu,unsigned map,void * buffer,address_word addr,unsigned len)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
sim_core_write_buffer(SIM_DESC sd,sim_cpu * cpu,unsigned map,const void * buffer,address_word addr,unsigned len)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
sim_core_set_xor(SIM_DESC sd,sim_cpu * cpu,int is_xor)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
reverse_n(unsigned_1 * dest,const unsigned_1 * src,int nr_bytes)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
sim_core_xor_read_buffer(SIM_DESC sd,sim_cpu * cpu,unsigned map,void * buffer,address_word addr,unsigned nr_bytes)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
sim_core_xor_write_buffer(SIM_DESC sd,sim_cpu * cpu,unsigned map,const void * buffer,address_word addr,unsigned nr_bytes)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 *
sim_core_trans_addr(SIM_DESC sd,sim_cpu * cpu,unsigned map,address_word addr)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