xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/sim-core.c (revision 88241920d21b339bf319c0e979ffda80c49a2936)
14e98e3e1Schristos /* The common simulator framework for GDB, the GNU Debugger.
24e98e3e1Schristos 
3*88241920Schristos    Copyright 2002-2024 Free Software Foundation, Inc.
44e98e3e1Schristos 
54e98e3e1Schristos    Contributed by Andrew Cagney and Red Hat.
64e98e3e1Schristos 
74e98e3e1Schristos    This file is part of GDB.
84e98e3e1Schristos 
94e98e3e1Schristos    This program is free software; you can redistribute it and/or modify
104e98e3e1Schristos    it under the terms of the GNU General Public License as published by
114e98e3e1Schristos    the Free Software Foundation; either version 3 of the License, or
124e98e3e1Schristos    (at your option) any later version.
134e98e3e1Schristos 
144e98e3e1Schristos    This program is distributed in the hope that it will be useful,
154e98e3e1Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
164e98e3e1Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
174e98e3e1Schristos    GNU General Public License for more details.
184e98e3e1Schristos 
194e98e3e1Schristos    You should have received a copy of the GNU General Public License
204e98e3e1Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
214e98e3e1Schristos 
224e98e3e1Schristos 
234e98e3e1Schristos #ifndef SIM_CORE_C
244e98e3e1Schristos #define SIM_CORE_C
254e98e3e1Schristos 
264b169a6bSchristos /* This must come before any other includes.  */
274b169a6bSchristos #include "defs.h"
284b169a6bSchristos 
294b169a6bSchristos #include <stdlib.h>
304b169a6bSchristos 
314b169a6bSchristos #include "libiberty.h"
324b169a6bSchristos 
334e98e3e1Schristos #include "sim-main.h"
344e98e3e1Schristos #include "sim-assert.h"
354b169a6bSchristos #include "sim-signal.h"
364e98e3e1Schristos 
374e98e3e1Schristos #if (WITH_HW)
384e98e3e1Schristos #include "sim-hw.h"
394e98e3e1Schristos #endif
404e98e3e1Schristos 
414e98e3e1Schristos /* "core" module install handler.
424e98e3e1Schristos 
434e98e3e1Schristos    This is called via sim_module_install to install the "core"
444e98e3e1Schristos    subsystem into the simulator.  */
454e98e3e1Schristos 
464e98e3e1Schristos #if EXTERN_SIM_CORE_P
474e98e3e1Schristos static MODULE_INIT_FN sim_core_init;
484e98e3e1Schristos static MODULE_UNINSTALL_FN sim_core_uninstall;
494e98e3e1Schristos #endif
504e98e3e1Schristos 
514e98e3e1Schristos #if EXTERN_SIM_CORE_P
524e98e3e1Schristos SIM_RC
534e98e3e1Schristos sim_core_install (SIM_DESC sd)
544e98e3e1Schristos {
554e98e3e1Schristos   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
564e98e3e1Schristos 
574e98e3e1Schristos   /* establish the other handlers */
584e98e3e1Schristos   sim_module_add_uninstall_fn (sd, sim_core_uninstall);
594e98e3e1Schristos   sim_module_add_init_fn (sd, sim_core_init);
604e98e3e1Schristos 
614e98e3e1Schristos   /* establish any initial data structures - none */
624e98e3e1Schristos   return SIM_RC_OK;
634e98e3e1Schristos }
644e98e3e1Schristos #endif
654e98e3e1Schristos 
664e98e3e1Schristos 
674e98e3e1Schristos /* Uninstall the "core" subsystem from the simulator.  */
684e98e3e1Schristos 
694e98e3e1Schristos #if EXTERN_SIM_CORE_P
704e98e3e1Schristos static void
714e98e3e1Schristos sim_core_uninstall (SIM_DESC sd)
724e98e3e1Schristos {
734e98e3e1Schristos   sim_core *core = STATE_CORE (sd);
744e98e3e1Schristos   unsigned map;
754e98e3e1Schristos   /* blow away any mappings */
764e98e3e1Schristos   for (map = 0; map < nr_maps; map++) {
774e98e3e1Schristos     sim_core_mapping *curr = core->common.map[map].first;
784e98e3e1Schristos     while (curr != NULL) {
794e98e3e1Schristos       sim_core_mapping *tbd = curr;
804e98e3e1Schristos       curr = curr->next;
814e98e3e1Schristos       if (tbd->free_buffer != NULL) {
824e98e3e1Schristos 	SIM_ASSERT (tbd->buffer != NULL);
834e98e3e1Schristos 	free (tbd->free_buffer);
844e98e3e1Schristos       }
854e98e3e1Schristos       free (tbd);
864e98e3e1Schristos     }
874e98e3e1Schristos     core->common.map[map].first = NULL;
884e98e3e1Schristos   }
894e98e3e1Schristos }
904e98e3e1Schristos #endif
914e98e3e1Schristos 
924e98e3e1Schristos 
934e98e3e1Schristos #if EXTERN_SIM_CORE_P
944e98e3e1Schristos static SIM_RC
954e98e3e1Schristos sim_core_init (SIM_DESC sd)
964e98e3e1Schristos {
974e98e3e1Schristos   /* Nothing to do */
984e98e3e1Schristos   return SIM_RC_OK;
994e98e3e1Schristos }
1004e98e3e1Schristos #endif
1014e98e3e1Schristos 
1024e98e3e1Schristos 
1034e98e3e1Schristos 
1044e98e3e1Schristos #ifndef SIM_CORE_SIGNAL
1054e98e3e1Schristos #define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \
1064e98e3e1Schristos sim_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ERROR))
1074e98e3e1Schristos #endif
1084e98e3e1Schristos 
1094e98e3e1Schristos #if EXTERN_SIM_CORE_P
1104e98e3e1Schristos void
1114e98e3e1Schristos sim_core_signal (SIM_DESC sd,
1124e98e3e1Schristos 		 sim_cpu *cpu,
1134e98e3e1Schristos 		 sim_cia cia,
1144e98e3e1Schristos 		 unsigned map,
1154e98e3e1Schristos 		 int nr_bytes,
1164e98e3e1Schristos 		 address_word addr,
1174e98e3e1Schristos 		 transfer_type transfer,
1184e98e3e1Schristos 		 sim_core_signals sig)
1194e98e3e1Schristos {
1204e98e3e1Schristos   const char *copy = (transfer == read_transfer ? "read" : "write");
1214e98e3e1Schristos   address_word ip = CIA_ADDR (cia);
1224e98e3e1Schristos   switch (sig)
1234e98e3e1Schristos     {
1244e98e3e1Schristos     case sim_core_unmapped_signal:
1254e98e3e1Schristos       sim_io_eprintf (sd, "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
1264e98e3e1Schristos 		      nr_bytes, copy, (unsigned long) addr, (unsigned long) ip);
1274e98e3e1Schristos       sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGSEGV);
1284e98e3e1Schristos       break;
1294e98e3e1Schristos     case sim_core_unaligned_signal:
1304e98e3e1Schristos       sim_io_eprintf (sd, "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n",
1314e98e3e1Schristos 		      nr_bytes, copy, (unsigned long) addr, (unsigned long) ip);
1324e98e3e1Schristos       sim_engine_halt (sd, cpu, NULL, cia, sim_stopped, SIM_SIGBUS);
1334e98e3e1Schristos       break;
1344e98e3e1Schristos     default:
1354e98e3e1Schristos       sim_engine_abort (sd, cpu, cia,
1364e98e3e1Schristos 			"sim_core_signal - internal error - bad switch");
1374e98e3e1Schristos     }
1384e98e3e1Schristos }
1394e98e3e1Schristos #endif
1404e98e3e1Schristos 
1414e98e3e1Schristos 
1424e98e3e1Schristos #if EXTERN_SIM_CORE_P
1434e98e3e1Schristos static sim_core_mapping *
1444e98e3e1Schristos new_sim_core_mapping (SIM_DESC sd,
1454e98e3e1Schristos 		      int level,
1464e98e3e1Schristos 		      int space,
1474e98e3e1Schristos 		      address_word addr,
1484e98e3e1Schristos 		      address_word nr_bytes,
1494e98e3e1Schristos 		      unsigned modulo,
1504e98e3e1Schristos 		      struct hw *device,
1514e98e3e1Schristos 		      void *buffer,
1524e98e3e1Schristos 		      void *free_buffer)
1534e98e3e1Schristos {
1544e98e3e1Schristos   sim_core_mapping *new_mapping = ZALLOC (sim_core_mapping);
1554e98e3e1Schristos   /* common */
1564e98e3e1Schristos   new_mapping->level = level;
1574e98e3e1Schristos   new_mapping->space = space;
1584e98e3e1Schristos   new_mapping->base = addr;
1594e98e3e1Schristos   new_mapping->nr_bytes = nr_bytes;
1604e98e3e1Schristos   new_mapping->bound = addr + (nr_bytes - 1);
1614e98e3e1Schristos   new_mapping->mask = modulo - 1;
1624e98e3e1Schristos   new_mapping->buffer = buffer;
1634e98e3e1Schristos   new_mapping->free_buffer = free_buffer;
1644e98e3e1Schristos   new_mapping->device = device;
1654e98e3e1Schristos   return new_mapping;
1664e98e3e1Schristos }
1674e98e3e1Schristos #endif
1684e98e3e1Schristos 
1694e98e3e1Schristos 
1704e98e3e1Schristos #if EXTERN_SIM_CORE_P
1714e98e3e1Schristos static void
1724e98e3e1Schristos sim_core_map_attach (SIM_DESC sd,
1734e98e3e1Schristos 		     sim_core_map *access_map,
1744e98e3e1Schristos 		     int level,
1754e98e3e1Schristos 		     int space,
1764e98e3e1Schristos 		     address_word addr,
1774e98e3e1Schristos 		     address_word nr_bytes,
1784e98e3e1Schristos 		     unsigned modulo,
1794e98e3e1Schristos 		     struct hw *client, /*callback/default*/
1804e98e3e1Schristos 		     void *buffer, /*raw_memory*/
1814e98e3e1Schristos 		     void *free_buffer) /*raw_memory*/
1824e98e3e1Schristos {
1834e98e3e1Schristos   /* find the insertion point for this additional mapping and then
1844e98e3e1Schristos      insert */
1854e98e3e1Schristos   sim_core_mapping *next_mapping;
1864e98e3e1Schristos   sim_core_mapping **last_mapping;
1874e98e3e1Schristos 
1884e98e3e1Schristos   SIM_ASSERT ((client == NULL) != (buffer == NULL));
1894e98e3e1Schristos   SIM_ASSERT ((client == NULL) >= (free_buffer != NULL));
1904e98e3e1Schristos 
1914e98e3e1Schristos   /* actually do occasionally get a zero size map */
1924e98e3e1Schristos   if (nr_bytes == 0)
1934e98e3e1Schristos     {
1944e98e3e1Schristos #if (WITH_HW)
1954e98e3e1Schristos       sim_hw_abort (sd, client, "called on sim_core_map_attach with size zero");
1964e98e3e1Schristos #endif
1974e98e3e1Schristos       sim_io_error (sd, "called on sim_core_map_attach with size zero");
1984e98e3e1Schristos     }
1994e98e3e1Schristos 
2004e98e3e1Schristos   /* find the insertion point (between last/next) */
2014e98e3e1Schristos   next_mapping = access_map->first;
2024e98e3e1Schristos   last_mapping = &access_map->first;
2034e98e3e1Schristos   while (next_mapping != NULL
2044e98e3e1Schristos 	&& (next_mapping->level < level
2054e98e3e1Schristos 	    || (next_mapping->level == level
2064e98e3e1Schristos 		&& next_mapping->bound < addr)))
2074e98e3e1Schristos     {
2084e98e3e1Schristos       /* provided levels are the same */
2094e98e3e1Schristos       /* assert: next_mapping->base > all bases before next_mapping */
2104e98e3e1Schristos       /* assert: next_mapping->bound >= all bounds before next_mapping */
2114e98e3e1Schristos       last_mapping = &next_mapping->next;
2124e98e3e1Schristos       next_mapping = next_mapping->next;
2134e98e3e1Schristos     }
2144e98e3e1Schristos 
2154e98e3e1Schristos   /* check insertion point correct */
2164e98e3e1Schristos   SIM_ASSERT (next_mapping == NULL || next_mapping->level >= level);
2174e98e3e1Schristos   if (next_mapping != NULL && next_mapping->level == level
2184e98e3e1Schristos       && next_mapping->base < (addr + (nr_bytes - 1)))
2194e98e3e1Schristos     {
2204e98e3e1Schristos #if WITH_HW
2214e98e3e1Schristos       sim_hw_abort (sd, client, "memory map %d:0x%lx..0x%lx (%ld bytes) overlaps %d:0x%lx..0x%lx (%ld bytes)",
2224e98e3e1Schristos 		    space,
2234e98e3e1Schristos 		    (long) addr,
2244e98e3e1Schristos 		    (long) (addr + (nr_bytes - 1)),
2254e98e3e1Schristos 		    (long) nr_bytes,
2264e98e3e1Schristos 		    next_mapping->space,
2274e98e3e1Schristos 		    (long) next_mapping->base,
2284e98e3e1Schristos 		    (long) next_mapping->bound,
2294e98e3e1Schristos 		    (long) next_mapping->nr_bytes);
2304e98e3e1Schristos #endif
2314e98e3e1Schristos       sim_io_error (sd, "memory map %d:0x%lx..0x%lx (%ld bytes) overlaps %d:0x%lx..0x%lx (%ld bytes)",
2324e98e3e1Schristos 		    space,
2334e98e3e1Schristos 		    (long) addr,
2344e98e3e1Schristos 		    (long) (addr + (nr_bytes - 1)),
2354e98e3e1Schristos 		    (long) nr_bytes,
2364e98e3e1Schristos 		    next_mapping->space,
2374e98e3e1Schristos 		    (long) next_mapping->base,
2384e98e3e1Schristos 		    (long) next_mapping->bound,
2394e98e3e1Schristos 		    (long) next_mapping->nr_bytes);
2404e98e3e1Schristos   }
2414e98e3e1Schristos 
2424e98e3e1Schristos   /* create/insert the new mapping */
2434e98e3e1Schristos   *last_mapping = new_sim_core_mapping (sd,
2444e98e3e1Schristos 					level,
2454e98e3e1Schristos 					space, addr, nr_bytes, modulo,
2464e98e3e1Schristos 					client, buffer, free_buffer);
2474e98e3e1Schristos   (*last_mapping)->next = next_mapping;
2484e98e3e1Schristos }
2494e98e3e1Schristos #endif
2504e98e3e1Schristos 
2514e98e3e1Schristos 
2524e98e3e1Schristos /* Attach memory or a memory mapped device to the simulator.
2534e98e3e1Schristos    See sim-core.h for a full description.  */
2544e98e3e1Schristos 
2554e98e3e1Schristos #if EXTERN_SIM_CORE_P
2564e98e3e1Schristos void
2574e98e3e1Schristos sim_core_attach (SIM_DESC sd,
2584e98e3e1Schristos 		 sim_cpu *cpu,
2594e98e3e1Schristos 		 int level,
2604e98e3e1Schristos 		 unsigned mapmask,
2614e98e3e1Schristos 		 int space,
2624e98e3e1Schristos 		 address_word addr,
2634e98e3e1Schristos 		 address_word nr_bytes,
2644e98e3e1Schristos 		 unsigned modulo,
2654e98e3e1Schristos 		 struct hw *client,
2664e98e3e1Schristos 		 void *optional_buffer)
2674e98e3e1Schristos {
2684e98e3e1Schristos   sim_core *memory = STATE_CORE (sd);
2694e98e3e1Schristos   unsigned map;
2704e98e3e1Schristos   void *buffer;
2714e98e3e1Schristos   void *free_buffer;
2724e98e3e1Schristos 
2734e98e3e1Schristos   /* check for for attempt to use unimplemented per-processor core map */
2744e98e3e1Schristos   if (cpu != NULL)
2754e98e3e1Schristos     sim_io_error (sd, "sim_core_map_attach - processor specific memory map not yet supported");
2764e98e3e1Schristos 
2774e98e3e1Schristos   if (client != NULL && modulo != 0)
2784e98e3e1Schristos     {
2794e98e3e1Schristos #if (WITH_HW)
2804e98e3e1Schristos       sim_hw_abort (sd, client, "sim_core_attach - internal error - modulo and callback memory conflict");
2814e98e3e1Schristos #endif
2824e98e3e1Schristos       sim_io_error (sd, "sim_core_attach - internal error - modulo and callback memory conflict");
2834e98e3e1Schristos     }
2844e98e3e1Schristos   if (modulo != 0)
2854e98e3e1Schristos     {
2864e98e3e1Schristos       unsigned mask = modulo - 1;
2874e98e3e1Schristos       /* any zero bits */
2884b169a6bSchristos       while (mask >= sizeof (uint64_t)) /* minimum modulo */
2894e98e3e1Schristos 	{
2904e98e3e1Schristos 	  if ((mask & 1) == 0)
2914e98e3e1Schristos 	    mask = 0;
2924e98e3e1Schristos 	  else
2934e98e3e1Schristos 	    mask >>= 1;
2944e98e3e1Schristos 	}
2954b169a6bSchristos       if (mask != sizeof (uint64_t) - 1)
2964e98e3e1Schristos 	{
2974e98e3e1Schristos #if (WITH_HW)
2984e98e3e1Schristos 	  sim_hw_abort (sd, client, "sim_core_attach - internal error - modulo %lx not power of two", (long) modulo);
2994e98e3e1Schristos #endif
3004e98e3e1Schristos 	  sim_io_error (sd, "sim_core_attach - internal error - modulo %lx not power of two", (long) modulo);
3014e98e3e1Schristos 	}
3024e98e3e1Schristos     }
3034e98e3e1Schristos 
3044e98e3e1Schristos   /* verify consistency between device and buffer */
3054e98e3e1Schristos   if (client != NULL && optional_buffer != NULL)
3064e98e3e1Schristos     {
3074e98e3e1Schristos #if (WITH_HW)
3084e98e3e1Schristos       sim_hw_abort (sd, client, "sim_core_attach - internal error - conflicting buffer and attach arguments");
3094e98e3e1Schristos #endif
3104e98e3e1Schristos       sim_io_error (sd, "sim_core_attach - internal error - conflicting buffer and attach arguments");
3114e98e3e1Schristos     }
3124e98e3e1Schristos   if (client == NULL)
3134e98e3e1Schristos     {
3144e98e3e1Schristos       if (optional_buffer == NULL)
3154e98e3e1Schristos 	{
3164b169a6bSchristos 	  int padding = (addr % sizeof (uint64_t));
3174e98e3e1Schristos 	  unsigned long bytes = (modulo == 0 ? nr_bytes : modulo) + padding;
3184e98e3e1Schristos 	  free_buffer = zalloc (bytes);
3194e98e3e1Schristos 	  buffer = (char*) free_buffer + padding;
3204e98e3e1Schristos 	}
3214e98e3e1Schristos       else
3224e98e3e1Schristos 	{
3234e98e3e1Schristos 	  buffer = optional_buffer;
3244e98e3e1Schristos 	  free_buffer = NULL;
3254e98e3e1Schristos 	}
3264e98e3e1Schristos     }
3274e98e3e1Schristos   else
3284e98e3e1Schristos     {
3294e98e3e1Schristos       /* a device */
3304e98e3e1Schristos       buffer = NULL;
3314e98e3e1Schristos       free_buffer = NULL;
3324e98e3e1Schristos     }
3334e98e3e1Schristos 
3344e98e3e1Schristos   /* attach the region to all applicable access maps */
3354e98e3e1Schristos   for (map = 0;
3364e98e3e1Schristos        map < nr_maps;
3374e98e3e1Schristos        map++)
3384e98e3e1Schristos     {
3394e98e3e1Schristos       if (mapmask & (1 << map))
3404e98e3e1Schristos 	{
3414e98e3e1Schristos 	  sim_core_map_attach (sd, &memory->common.map[map],
3424e98e3e1Schristos 			       level, space, addr, nr_bytes, modulo,
3434e98e3e1Schristos 			       client, buffer, free_buffer);
3444e98e3e1Schristos 	  free_buffer = NULL;
3454e98e3e1Schristos 	}
3464e98e3e1Schristos     }
3474e98e3e1Schristos 
3484e98e3e1Schristos   /* Just copy this map to each of the processor specific data structures.
3494e98e3e1Schristos      FIXME - later this will be replaced by true processor specific
3504e98e3e1Schristos      maps. */
3514e98e3e1Schristos   {
3524e98e3e1Schristos     int i;
3534e98e3e1Schristos     for (i = 0; i < MAX_NR_PROCESSORS; i++)
3544e98e3e1Schristos       {
3554e98e3e1Schristos 	CPU_CORE (STATE_CPU (sd, i))->common = STATE_CORE (sd)->common;
3564e98e3e1Schristos       }
3574e98e3e1Schristos   }
3584e98e3e1Schristos }
3594e98e3e1Schristos #endif
3604e98e3e1Schristos 
3614e98e3e1Schristos 
3624e98e3e1Schristos /* Remove any memory reference related to this address */
3634e98e3e1Schristos #if EXTERN_SIM_CORE_P
3644e98e3e1Schristos static void
3654e98e3e1Schristos sim_core_map_detach (SIM_DESC sd,
3664e98e3e1Schristos 		     sim_core_map *access_map,
3674e98e3e1Schristos 		     int level,
3684e98e3e1Schristos 		     int space,
3694e98e3e1Schristos 		     address_word addr)
3704e98e3e1Schristos {
3714e98e3e1Schristos   sim_core_mapping **entry;
3724e98e3e1Schristos   for (entry = &access_map->first;
3734e98e3e1Schristos        (*entry) != NULL;
3744e98e3e1Schristos        entry = &(*entry)->next)
3754e98e3e1Schristos     {
3764e98e3e1Schristos       if ((*entry)->base == addr
3774e98e3e1Schristos 	  && (*entry)->level == level
3784e98e3e1Schristos 	  && (*entry)->space == space)
3794e98e3e1Schristos 	{
3804e98e3e1Schristos 	  sim_core_mapping *dead = (*entry);
3814e98e3e1Schristos 	  (*entry) = dead->next;
3824e98e3e1Schristos 	  if (dead->free_buffer != NULL)
3834e98e3e1Schristos 	    free (dead->free_buffer);
3844e98e3e1Schristos 	  free (dead);
3854e98e3e1Schristos 	  return;
3864e98e3e1Schristos 	}
3874e98e3e1Schristos     }
3884e98e3e1Schristos }
3894e98e3e1Schristos #endif
3904e98e3e1Schristos 
3914e98e3e1Schristos #if EXTERN_SIM_CORE_P
3924e98e3e1Schristos void
3934e98e3e1Schristos sim_core_detach (SIM_DESC sd,
3944e98e3e1Schristos 		 sim_cpu *cpu,
3954e98e3e1Schristos 		 int level,
3964e98e3e1Schristos 		 int address_space,
3974e98e3e1Schristos 		 address_word addr)
3984e98e3e1Schristos {
3994e98e3e1Schristos   sim_core *memory = STATE_CORE (sd);
4004e98e3e1Schristos   unsigned map;
4014e98e3e1Schristos   for (map = 0; map < nr_maps; map++)
4024e98e3e1Schristos     {
4034e98e3e1Schristos       sim_core_map_detach (sd, &memory->common.map[map],
4044e98e3e1Schristos 			   level, address_space, addr);
4054e98e3e1Schristos     }
4064e98e3e1Schristos   /* Just copy this update to each of the processor specific data
4074e98e3e1Schristos      structures.  FIXME - later this will be replaced by true
4084e98e3e1Schristos      processor specific maps. */
4094e98e3e1Schristos   {
4104e98e3e1Schristos     int i;
4114e98e3e1Schristos     for (i = 0; i < MAX_NR_PROCESSORS; i++)
4124e98e3e1Schristos       {
4134e98e3e1Schristos 	CPU_CORE (STATE_CPU (sd, i))->common = STATE_CORE (sd)->common;
4144e98e3e1Schristos       }
4154e98e3e1Schristos   }
4164e98e3e1Schristos }
4174e98e3e1Schristos #endif
4184e98e3e1Schristos 
4194e98e3e1Schristos 
4204e98e3e1Schristos STATIC_INLINE_SIM_CORE\
4214e98e3e1Schristos (sim_core_mapping *)
4224e98e3e1Schristos sim_core_find_mapping (sim_core_common *core,
4234e98e3e1Schristos 		       unsigned map,
4244e98e3e1Schristos 		       address_word addr,
4254e98e3e1Schristos 		       unsigned nr_bytes,
4264e98e3e1Schristos 		       transfer_type transfer,
4274e98e3e1Schristos 		       int abort, /*either 0 or 1 - hint to inline/-O */
4284e98e3e1Schristos 		       sim_cpu *cpu, /* abort => cpu != NULL */
4294e98e3e1Schristos 		       sim_cia cia)
4304e98e3e1Schristos {
4314e98e3e1Schristos   sim_core_mapping *mapping = core->map[map].first;
4324e98e3e1Schristos   ASSERT ((addr & (nr_bytes - 1)) == 0); /* must be aligned */
4334e98e3e1Schristos   ASSERT ((addr + (nr_bytes - 1)) >= addr); /* must not wrap */
4344e98e3e1Schristos   ASSERT (!abort || cpu != NULL); /* abort needs a non null CPU */
4354e98e3e1Schristos   while (mapping != NULL)
4364e98e3e1Schristos     {
4374e98e3e1Schristos       if (addr >= mapping->base
4384e98e3e1Schristos 	  && (addr + (nr_bytes - 1)) <= mapping->bound)
4394e98e3e1Schristos 	return mapping;
4404e98e3e1Schristos       mapping = mapping->next;
4414e98e3e1Schristos     }
4424e98e3e1Schristos   if (abort)
4434e98e3e1Schristos     {
4444e98e3e1Schristos       SIM_CORE_SIGNAL (CPU_STATE (cpu), cpu, cia, map, nr_bytes, addr, transfer,
4454e98e3e1Schristos 		       sim_core_unmapped_signal);
4464e98e3e1Schristos     }
4474e98e3e1Schristos   return NULL;
4484e98e3e1Schristos }
4494e98e3e1Schristos 
4504e98e3e1Schristos 
4514e98e3e1Schristos STATIC_INLINE_SIM_CORE\
4524e98e3e1Schristos (void *)
4534e98e3e1Schristos sim_core_translate (sim_core_mapping *mapping,
4544e98e3e1Schristos 		    address_word addr)
4554e98e3e1Schristos {
4564b169a6bSchristos   return (void *)((uint8_t *) mapping->buffer
4574e98e3e1Schristos 		  + ((addr - mapping->base) & mapping->mask));
4584e98e3e1Schristos }
4594e98e3e1Schristos 
4604e98e3e1Schristos 
4614e98e3e1Schristos #if EXTERN_SIM_CORE_P
4624b169a6bSchristos /* See include/sim/sim.h.  */
4634b169a6bSchristos char *
4644b169a6bSchristos sim_memory_map (SIM_DESC sd)
4654b169a6bSchristos {
4664b169a6bSchristos   sim_core *core = STATE_CORE (sd);
4674b169a6bSchristos   unsigned map;
4684b169a6bSchristos   char *s1, *s2, *entry;
4694b169a6bSchristos 
4704b169a6bSchristos   s1 = xstrdup (
4714b169a6bSchristos     "<?xml version='1.0'?>\n"
4724b169a6bSchristos     "<!DOCTYPE memory-map PUBLIC '+//IDN gnu.org//DTD GDB Memory Map V1.0//EN'"
4734b169a6bSchristos     " 'http://sourceware.org/gdb/gdb-memory-map.dtd'>\n"
4744b169a6bSchristos     "<memory-map>\n");
4754b169a6bSchristos 
4764b169a6bSchristos   for (map = 0; map < nr_maps; ++map)
4774b169a6bSchristos     {
4784b169a6bSchristos       sim_core_mapping *mapping;
4794b169a6bSchristos 
4804b169a6bSchristos       for (mapping = core->common.map[map].first;
4814b169a6bSchristos 	   mapping != NULL;
4824b169a6bSchristos 	   mapping = mapping->next)
4834b169a6bSchristos 	{
4844b169a6bSchristos 	  /* GDB can only handle a single address space.  */
4854b169a6bSchristos 	  if (mapping->level != 0)
4864b169a6bSchristos 	    continue;
4874b169a6bSchristos 
4884b169a6bSchristos 	  entry = xasprintf ("<memory type='ram' start='%#" PRIxTW "' "
4894b169a6bSchristos 			     "length='%#" PRIxTW "'/>\n",
4904b169a6bSchristos 			     mapping->base, mapping->nr_bytes);
4914b169a6bSchristos 	  /* The sim memory map is organized by access, not by addresses.
4924b169a6bSchristos 	     So a RWX memory map will have three independent mappings.
4934b169a6bSchristos 	     GDB's format cannot support overlapping regions, so we have
4944b169a6bSchristos 	     to filter those out.
4954b169a6bSchristos 
4964b169a6bSchristos 	     Further, GDB can only handle RX ("rom") or RWX ("ram") mappings.
4974b169a6bSchristos 	     We just emit "ram" everywhere to keep it simple.  If GDB ever
4984b169a6bSchristos 	     gains support for more stuff, we can expand this.
4994b169a6bSchristos 
5004b169a6bSchristos 	     Using strstr is kind of hacky, but as long as the map is not huge
5014b169a6bSchristos 	     (we're talking <10K), should be fine.  */
5024b169a6bSchristos 	  if (strstr (s1, entry) == NULL)
5034b169a6bSchristos 	    {
5044b169a6bSchristos 	      s2 = concat (s1, entry, NULL);
5054b169a6bSchristos 	      free (s1);
5064b169a6bSchristos 	      s1 = s2;
5074b169a6bSchristos 	    }
5084b169a6bSchristos 	  free (entry);
5094b169a6bSchristos 	}
5104b169a6bSchristos     }
5114b169a6bSchristos 
5124b169a6bSchristos   s2 = concat (s1, "</memory-map>", NULL);
5134b169a6bSchristos   free (s1);
5144b169a6bSchristos   return s2;
5154b169a6bSchristos }
5164b169a6bSchristos #endif
5174b169a6bSchristos 
5184b169a6bSchristos 
5194b169a6bSchristos #if EXTERN_SIM_CORE_P
5204e98e3e1Schristos unsigned
5214e98e3e1Schristos sim_core_read_buffer (SIM_DESC sd,
5224e98e3e1Schristos 		      sim_cpu *cpu,
5234e98e3e1Schristos 		      unsigned map,
5244e98e3e1Schristos 		      void *buffer,
5254e98e3e1Schristos 		      address_word addr,
5264e98e3e1Schristos 		      unsigned len)
5274e98e3e1Schristos {
5284e98e3e1Schristos   sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common);
5294e98e3e1Schristos   unsigned count = 0;
5304e98e3e1Schristos   while (count < len)
5314e98e3e1Schristos  {
5324e98e3e1Schristos     address_word raddr = addr + count;
5334e98e3e1Schristos     sim_core_mapping *mapping =
5344e98e3e1Schristos       sim_core_find_mapping (core, map,
5354e98e3e1Schristos 			    raddr, /*nr-bytes*/1,
5364e98e3e1Schristos 			    read_transfer,
5374e98e3e1Schristos 			    0 /*dont-abort*/, NULL, NULL_CIA);
5384e98e3e1Schristos     if (mapping == NULL)
5394e98e3e1Schristos       break;
5404e98e3e1Schristos #if (WITH_HW)
5414e98e3e1Schristos     if (mapping->device != NULL)
5424e98e3e1Schristos       {
5434e98e3e1Schristos 	int nr_bytes = len - count;
5444e98e3e1Schristos 	if (raddr + nr_bytes - 1> mapping->bound)
5454e98e3e1Schristos 	  nr_bytes = mapping->bound - raddr + 1;
546ba340e45Schristos 	/* If the access was initiated by a cpu, pass it down so errors can
547ba340e45Schristos 	   be propagated properly.  For other sources (e.g. GDB or DMA), we
548ba340e45Schristos 	   can only signal errors via the return value.  */
549ba340e45Schristos 	if (cpu)
550ba340e45Schristos 	  {
551ba340e45Schristos 	    sim_cia cia = cpu ? CPU_PC_GET (cpu) : NULL_CIA;
552ba340e45Schristos 	    sim_cpu_hw_io_read_buffer (cpu, cia, mapping->device,
553ba340e45Schristos 				       (unsigned_1*)buffer + count,
554ba340e45Schristos 				       mapping->space,
555ba340e45Schristos 				       raddr,
556ba340e45Schristos 				       nr_bytes);
557ba340e45Schristos 	  }
558ba340e45Schristos 	else if (sim_hw_io_read_buffer (sd, mapping->device,
5594e98e3e1Schristos 					(unsigned_1*)buffer + count,
5604e98e3e1Schristos 					mapping->space,
5614e98e3e1Schristos 					raddr,
5624e98e3e1Schristos 					nr_bytes) != nr_bytes)
5634e98e3e1Schristos 	  break;
5644e98e3e1Schristos 	count += nr_bytes;
5654e98e3e1Schristos 	continue;
5664e98e3e1Schristos       }
5674e98e3e1Schristos #endif
5684e98e3e1Schristos     ((unsigned_1*)buffer)[count] =
5694e98e3e1Schristos       *(unsigned_1*)sim_core_translate (mapping, raddr);
5704e98e3e1Schristos     count += 1;
5714e98e3e1Schristos  }
5724e98e3e1Schristos   return count;
5734e98e3e1Schristos }
5744e98e3e1Schristos #endif
5754e98e3e1Schristos 
5764e98e3e1Schristos 
5774e98e3e1Schristos #if EXTERN_SIM_CORE_P
5784e98e3e1Schristos unsigned
5794e98e3e1Schristos sim_core_write_buffer (SIM_DESC sd,
5804e98e3e1Schristos 		       sim_cpu *cpu,
5814e98e3e1Schristos 		       unsigned map,
5824e98e3e1Schristos 		       const void *buffer,
5834e98e3e1Schristos 		       address_word addr,
5844e98e3e1Schristos 		       unsigned len)
5854e98e3e1Schristos {
5864e98e3e1Schristos   sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common);
5874e98e3e1Schristos   unsigned count = 0;
5884e98e3e1Schristos   while (count < len)
5894e98e3e1Schristos     {
5904e98e3e1Schristos       address_word raddr = addr + count;
5914e98e3e1Schristos       sim_core_mapping *mapping =
5924e98e3e1Schristos 	sim_core_find_mapping (core, map,
5934e98e3e1Schristos 			       raddr, /*nr-bytes*/1,
5944e98e3e1Schristos 			       write_transfer,
5954e98e3e1Schristos 			       0 /*dont-abort*/, NULL, NULL_CIA);
5964e98e3e1Schristos       if (mapping == NULL)
5974e98e3e1Schristos 	break;
598ba340e45Schristos #if (WITH_HW)
599ba340e45Schristos       if (mapping->device != NULL)
6004e98e3e1Schristos 	{
6014e98e3e1Schristos 	  int nr_bytes = len - count;
6024e98e3e1Schristos 	  if (raddr + nr_bytes - 1 > mapping->bound)
6034e98e3e1Schristos 	    nr_bytes = mapping->bound - raddr + 1;
604ba340e45Schristos 	  /* If the access was initiated by a cpu, pass it down so errors can
605ba340e45Schristos 	     be propagated properly.  For other sources (e.g. GDB or DMA), we
606ba340e45Schristos 	     can only signal errors via the return value.  */
607ba340e45Schristos 	  if (cpu)
608ba340e45Schristos 	    {
609ba340e45Schristos 	      sim_cia cia = cpu ? CPU_PC_GET (cpu) : NULL_CIA;
610ba340e45Schristos 	      sim_cpu_hw_io_write_buffer (cpu, cia, mapping->device,
6114e98e3e1Schristos 					  (unsigned_1*)buffer + count,
6124e98e3e1Schristos 					  mapping->space,
6134e98e3e1Schristos 					  raddr,
614ba340e45Schristos 					  nr_bytes);
6154e98e3e1Schristos 	    }
616ba340e45Schristos 	  else if (sim_hw_io_write_buffer (sd, mapping->device,
6174e98e3e1Schristos 					  (unsigned_1*)buffer + count,
6184e98e3e1Schristos 					  mapping->space,
6194e98e3e1Schristos 					  raddr,
6204e98e3e1Schristos 					  nr_bytes) != nr_bytes)
6214e98e3e1Schristos 	    break;
6224e98e3e1Schristos 	  count += nr_bytes;
6234e98e3e1Schristos 	  continue;
6244e98e3e1Schristos 	}
6254e98e3e1Schristos #endif
6264e98e3e1Schristos       *(unsigned_1*)sim_core_translate (mapping, raddr) =
6274e98e3e1Schristos 	((unsigned_1*)buffer)[count];
6284e98e3e1Schristos       count += 1;
6294e98e3e1Schristos     }
6304e98e3e1Schristos   return count;
6314e98e3e1Schristos }
6324e98e3e1Schristos #endif
6334e98e3e1Schristos 
6344e98e3e1Schristos 
6354e98e3e1Schristos #if EXTERN_SIM_CORE_P
6364e98e3e1Schristos void
6374e98e3e1Schristos sim_core_set_xor (SIM_DESC sd,
6384e98e3e1Schristos 		  sim_cpu *cpu,
6394e98e3e1Schristos 		  int is_xor)
6404e98e3e1Schristos {
6414e98e3e1Schristos   /* set up the XOR map if required. */
6424e98e3e1Schristos   if (WITH_XOR_ENDIAN) {
6434e98e3e1Schristos     {
6444e98e3e1Schristos       sim_core *core = STATE_CORE (sd);
6454e98e3e1Schristos       sim_cpu_core *cpu_core = (cpu != NULL ? CPU_CORE (cpu) : NULL);
6464e98e3e1Schristos       if (cpu_core != NULL)
6474e98e3e1Schristos 	{
6484e98e3e1Schristos 	  int i = 1;
6494e98e3e1Schristos 	  unsigned mask;
6504e98e3e1Schristos 	  if (is_xor)
6514e98e3e1Schristos 	    mask = WITH_XOR_ENDIAN - 1;
6524e98e3e1Schristos 	  else
6534e98e3e1Schristos 	    mask = 0;
6544e98e3e1Schristos 	  while (i - 1 < WITH_XOR_ENDIAN)
6554e98e3e1Schristos 	    {
6564559860eSchristos 	      cpu_core->byte_xor[i-1] = mask;
6574e98e3e1Schristos 	      mask = (mask << 1) & (WITH_XOR_ENDIAN - 1);
6584e98e3e1Schristos 	      i = (i << 1);
6594e98e3e1Schristos 	    }
6604e98e3e1Schristos 	}
6614e98e3e1Schristos       else
6624e98e3e1Schristos 	{
6634e98e3e1Schristos 	  if (is_xor)
6644e98e3e1Schristos 	    core->byte_xor = WITH_XOR_ENDIAN - 1;
6654e98e3e1Schristos 	  else
6664e98e3e1Schristos 	    core->byte_xor = 0;
6674e98e3e1Schristos 	}
6684e98e3e1Schristos     }
6694e98e3e1Schristos   }
6704e98e3e1Schristos   else {
6714e98e3e1Schristos     if (is_xor)
6724e98e3e1Schristos       sim_engine_abort (sd, NULL, NULL_CIA,
673*88241920Schristos 			"Attempted to enable xor-endian mode when permanently disabled.");
6744e98e3e1Schristos   }
6754e98e3e1Schristos }
6764e98e3e1Schristos #endif
6774e98e3e1Schristos 
6784e98e3e1Schristos 
6794e98e3e1Schristos #if EXTERN_SIM_CORE_P
6804e98e3e1Schristos static void
6814e98e3e1Schristos reverse_n (unsigned_1 *dest,
6824e98e3e1Schristos 	   const unsigned_1 *src,
6834e98e3e1Schristos 	   int nr_bytes)
6844e98e3e1Schristos {
6854e98e3e1Schristos   int i;
6864e98e3e1Schristos   for (i = 0; i < nr_bytes; i++)
6874e98e3e1Schristos     {
6884e98e3e1Schristos       dest [nr_bytes - i - 1] = src [i];
6894e98e3e1Schristos     }
6904e98e3e1Schristos }
6914e98e3e1Schristos #endif
6924e98e3e1Schristos 
6934e98e3e1Schristos 
6944e98e3e1Schristos #if EXTERN_SIM_CORE_P
6954e98e3e1Schristos unsigned
6964e98e3e1Schristos sim_core_xor_read_buffer (SIM_DESC sd,
6974e98e3e1Schristos 			  sim_cpu *cpu,
6984e98e3e1Schristos 			  unsigned map,
6994e98e3e1Schristos 			  void *buffer,
7004e98e3e1Schristos 			  address_word addr,
7014e98e3e1Schristos 			  unsigned nr_bytes)
7024e98e3e1Schristos {
7034559860eSchristos   address_word byte_xor
7044559860eSchristos     = (cpu == NULL ? STATE_CORE (sd)->byte_xor : CPU_CORE (cpu)->byte_xor[0]);
7054e98e3e1Schristos   if (!WITH_XOR_ENDIAN || !byte_xor)
7064e98e3e1Schristos     return sim_core_read_buffer (sd, cpu, map, buffer, addr, nr_bytes);
7074e98e3e1Schristos   else
7084e98e3e1Schristos     /* only break up transfers when xor-endian is both selected and enabled */
7094e98e3e1Schristos     {
7104e98e3e1Schristos       unsigned_1 x[WITH_XOR_ENDIAN + 1]; /* +1 to avoid zero-sized array */
7114e98e3e1Schristos       unsigned nr_transfered = 0;
7124e98e3e1Schristos       address_word start = addr;
7134e98e3e1Schristos       unsigned nr_this_transfer = (WITH_XOR_ENDIAN - (addr & ~(WITH_XOR_ENDIAN - 1)));
7144e98e3e1Schristos       address_word stop;
7154e98e3e1Schristos       /* initial and intermediate transfers are broken when they cross
7164e98e3e1Schristos          an XOR endian boundary */
7174e98e3e1Schristos       while (nr_transfered + nr_this_transfer < nr_bytes)
7184e98e3e1Schristos 	/* initial/intermediate transfers */
7194e98e3e1Schristos 	{
7204e98e3e1Schristos 	  /* since xor-endian is enabled stop^xor defines the start
7214e98e3e1Schristos              address of the transfer */
7224e98e3e1Schristos 	  stop = start + nr_this_transfer - 1;
7234e98e3e1Schristos 	  SIM_ASSERT (start <= stop);
7244e98e3e1Schristos 	  SIM_ASSERT ((stop ^ byte_xor) <= (start ^ byte_xor));
7254e98e3e1Schristos 	  if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer)
7264e98e3e1Schristos 	      != nr_this_transfer)
7274e98e3e1Schristos 	    return nr_transfered;
7284e98e3e1Schristos 	  reverse_n (&((unsigned_1*)buffer)[nr_transfered], x, nr_this_transfer);
7294e98e3e1Schristos 	  nr_transfered += nr_this_transfer;
7304e98e3e1Schristos 	  nr_this_transfer = WITH_XOR_ENDIAN;
7314e98e3e1Schristos 	  start = stop + 1;
7324e98e3e1Schristos 	}
7334e98e3e1Schristos       /* final transfer */
7344e98e3e1Schristos       nr_this_transfer = nr_bytes - nr_transfered;
7354e98e3e1Schristos       stop = start + nr_this_transfer - 1;
7364e98e3e1Schristos       SIM_ASSERT (stop == (addr + nr_bytes - 1));
7374e98e3e1Schristos       if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer)
7384e98e3e1Schristos 	  != nr_this_transfer)
7394e98e3e1Schristos 	return nr_transfered;
7404e98e3e1Schristos       reverse_n (&((unsigned_1*)buffer)[nr_transfered], x, nr_this_transfer);
7414e98e3e1Schristos       return nr_bytes;
7424e98e3e1Schristos     }
7434e98e3e1Schristos }
7444e98e3e1Schristos #endif
7454e98e3e1Schristos 
7464e98e3e1Schristos 
7474e98e3e1Schristos #if EXTERN_SIM_CORE_P
7484e98e3e1Schristos unsigned
7494e98e3e1Schristos sim_core_xor_write_buffer (SIM_DESC sd,
7504e98e3e1Schristos 			   sim_cpu *cpu,
7514e98e3e1Schristos 			   unsigned map,
7524e98e3e1Schristos 			   const void *buffer,
7534e98e3e1Schristos 			   address_word addr,
7544e98e3e1Schristos 			   unsigned nr_bytes)
7554e98e3e1Schristos {
7564559860eSchristos   address_word byte_xor
7574559860eSchristos     = (cpu == NULL ? STATE_CORE (sd)->byte_xor : CPU_CORE (cpu)->byte_xor[0]);
7584e98e3e1Schristos   if (!WITH_XOR_ENDIAN || !byte_xor)
7594e98e3e1Schristos     return sim_core_write_buffer (sd, cpu, map, buffer, addr, nr_bytes);
7604e98e3e1Schristos   else
7614e98e3e1Schristos     /* only break up transfers when xor-endian is both selected and enabled */
7624e98e3e1Schristos     {
7634e98e3e1Schristos       unsigned_1 x[WITH_XOR_ENDIAN + 1]; /* +1 to avoid zero sized array */
7644e98e3e1Schristos       unsigned nr_transfered = 0;
7654e98e3e1Schristos       address_word start = addr;
7664e98e3e1Schristos       unsigned nr_this_transfer = (WITH_XOR_ENDIAN - (addr & ~(WITH_XOR_ENDIAN - 1)));
7674e98e3e1Schristos       address_word stop;
7684e98e3e1Schristos       /* initial and intermediate transfers are broken when they cross
7694e98e3e1Schristos          an XOR endian boundary */
7704e98e3e1Schristos       while (nr_transfered + nr_this_transfer < nr_bytes)
7714e98e3e1Schristos 	/* initial/intermediate transfers */
7724e98e3e1Schristos 	{
7734e98e3e1Schristos 	  /* since xor-endian is enabled stop^xor defines the start
7744e98e3e1Schristos              address of the transfer */
7754e98e3e1Schristos 	  stop = start + nr_this_transfer - 1;
7764e98e3e1Schristos 	  SIM_ASSERT (start <= stop);
7774e98e3e1Schristos 	  SIM_ASSERT ((stop ^ byte_xor) <= (start ^ byte_xor));
7784e98e3e1Schristos 	  reverse_n (x, &((unsigned_1*)buffer)[nr_transfered], nr_this_transfer);
7794e98e3e1Schristos 	  if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer)
7804e98e3e1Schristos 	      != nr_this_transfer)
7814e98e3e1Schristos 	    return nr_transfered;
7824e98e3e1Schristos 	  nr_transfered += nr_this_transfer;
7834e98e3e1Schristos 	  nr_this_transfer = WITH_XOR_ENDIAN;
7844e98e3e1Schristos 	  start = stop + 1;
7854e98e3e1Schristos 	}
7864e98e3e1Schristos       /* final transfer */
7874e98e3e1Schristos       nr_this_transfer = nr_bytes - nr_transfered;
7884e98e3e1Schristos       stop = start + nr_this_transfer - 1;
7894e98e3e1Schristos       SIM_ASSERT (stop == (addr + nr_bytes - 1));
7904e98e3e1Schristos       reverse_n (x, &((unsigned_1*)buffer)[nr_transfered], nr_this_transfer);
7914e98e3e1Schristos       if (sim_core_read_buffer (sd, cpu, map, x, stop ^ byte_xor, nr_this_transfer)
7924e98e3e1Schristos 	  != nr_this_transfer)
7934e98e3e1Schristos 	return nr_transfered;
7944e98e3e1Schristos       return nr_bytes;
7954e98e3e1Schristos     }
7964e98e3e1Schristos }
7974e98e3e1Schristos #endif
7984e98e3e1Schristos 
7994e98e3e1Schristos #if EXTERN_SIM_CORE_P
8004e98e3e1Schristos void *
8014e98e3e1Schristos sim_core_trans_addr (SIM_DESC sd,
8024e98e3e1Schristos                      sim_cpu *cpu,
8034e98e3e1Schristos                      unsigned map,
8044e98e3e1Schristos                      address_word addr)
8054e98e3e1Schristos {
8064e98e3e1Schristos   sim_core_common *core = (cpu == NULL ? &STATE_CORE (sd)->common : &CPU_CORE (cpu)->common);
8074e98e3e1Schristos   sim_core_mapping *mapping =
8084e98e3e1Schristos     sim_core_find_mapping (core, map,
8094e98e3e1Schristos                            addr, /*nr-bytes*/1,
8104e98e3e1Schristos                            write_transfer,
8114e98e3e1Schristos                            0 /*dont-abort*/, NULL, NULL_CIA);
8124e98e3e1Schristos   if (mapping == NULL)
8134e98e3e1Schristos     return NULL;
8144e98e3e1Schristos   return sim_core_translate (mapping, addr);
8154e98e3e1Schristos }
8164e98e3e1Schristos #endif
8174e98e3e1Schristos 
8184e98e3e1Schristos 
8194e98e3e1Schristos 
8204e98e3e1Schristos /* define the read/write 1/2/4/8/16/word functions */
8214e98e3e1Schristos 
8224e98e3e1Schristos #define N 16
8234e98e3e1Schristos #include "sim-n-core.h"
8244e98e3e1Schristos 
8254e98e3e1Schristos #define N 8
8264e98e3e1Schristos #include "sim-n-core.h"
8274e98e3e1Schristos 
8284e98e3e1Schristos #define N 7
8294e98e3e1Schristos #define M 8
8304e98e3e1Schristos #include "sim-n-core.h"
8314e98e3e1Schristos 
8324e98e3e1Schristos #define N 6
8334e98e3e1Schristos #define M 8
8344e98e3e1Schristos #include "sim-n-core.h"
8354e98e3e1Schristos 
8364e98e3e1Schristos #define N 5
8374e98e3e1Schristos #define M 8
8384e98e3e1Schristos #include "sim-n-core.h"
8394e98e3e1Schristos 
8404e98e3e1Schristos #define N 4
8414e98e3e1Schristos #include "sim-n-core.h"
8424e98e3e1Schristos 
8434e98e3e1Schristos #define N 3
8444e98e3e1Schristos #define M 4
8454e98e3e1Schristos #include "sim-n-core.h"
8464e98e3e1Schristos 
8474e98e3e1Schristos #define N 2
8484e98e3e1Schristos #include "sim-n-core.h"
8494e98e3e1Schristos 
8504e98e3e1Schristos #define N 1
8514e98e3e1Schristos #include "sim-n-core.h"
8524e98e3e1Schristos 
8534e98e3e1Schristos #endif
854