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