/[gxemul]/trunk/src/memory.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/memory.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: memory.c,v 1.176 2005/08/28 20:16:23 debug Exp $   *  $Id: memory.c,v 1.190 2006/06/16 18:31:25 debug Exp $
29   *   *
30   *  Functions for handling the memory of an emulated machine.   *  Functions for handling the memory of an emulated machine.
31   */   */
# Line 36  Line 36 
36  #include <sys/types.h>  #include <sys/types.h>
37  #include <sys/mman.h>  #include <sys/mman.h>
38    
 #include "bintrans.h"  
 #include "cop0.h"  
39  #include "cpu.h"  #include "cpu.h"
40  #include "machine.h"  #include "machine.h"
41  #include "memory.h"  #include "memory.h"
 #include "mips_cpu_types.h"  
42  #include "misc.h"  #include "misc.h"
43    
44    
45  extern int quiet_mode;  extern int verbose;
 extern volatile int single_step;  
46    
47    
48  /*  /*
# Line 59  extern volatile int single_step; Line 55  extern volatile int single_step;
55   */   */
56  uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)  uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
57  {  {
58          int i;          int i, byte_order = cpu->byte_order;
59          uint64_t x = 0;          uint64_t x = 0;
60    
61            if (len & MEM_PCI_LITTLE_ENDIAN) {
62                    len &= ~MEM_PCI_LITTLE_ENDIAN;
63                    byte_order = EMUL_LITTLE_ENDIAN;
64            }
65    
66          /*  Switch byte order for incoming data, if necessary:  */          /*  Switch byte order for incoming data, if necessary:  */
67          if (cpu->byte_order == EMUL_BIG_ENDIAN)          if (byte_order == EMUL_BIG_ENDIAN)
68                  for (i=0; i<len; i++) {                  for (i=0; i<len; i++) {
69                          x <<= 8;                          x <<= 8;
70                          x |= buf[i];                          x |= buf[i];
# Line 89  uint64_t memory_readmax64(struct cpu *cp Line 90  uint64_t memory_readmax64(struct cpu *cp
90  void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len,  void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len,
91          uint64_t data)          uint64_t data)
92  {  {
93          int i;          int i, byte_order = cpu->byte_order;
94    
95            if (len & MEM_PCI_LITTLE_ENDIAN) {
96                    len &= ~MEM_PCI_LITTLE_ENDIAN;
97                    byte_order = EMUL_LITTLE_ENDIAN;
98            }
99    
100          if (cpu->byte_order == EMUL_LITTLE_ENDIAN)          if (byte_order == EMUL_LITTLE_ENDIAN)
101                  for (i=0; i<len; i++) {                  for (i=0; i<len; i++) {
102                          buf[i] = data & 255;                          buf[i] = data & 255;
103                          data >>= 8;                          data >>= 8;
# Line 184  struct memory *memory_new(uint64_t physi Line 190  struct memory *memory_new(uint64_t physi
190  /*  /*
191   *  memory_points_to_string():   *  memory_points_to_string():
192   *   *
193   *  Returns 1 if there's something string-like at addr, otherwise 0.   *  Returns 1 if there's something string-like in emulated memory at address
194     *  addr, otherwise 0.
195   */   */
196  int memory_points_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,  int memory_points_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,
197          int min_string_length)          int min_string_length)
# Line 213  int memory_points_to_string(struct cpu * Line 220  int memory_points_to_string(struct cpu *
220  /*  /*
221   *  memory_conv_to_string():   *  memory_conv_to_string():
222   *   *
223   *  Convert virtual memory contents to a string, placing it in a   *  Convert emulated memory contents to a string, placing it in a buffer
224   *  buffer provided by the caller.   *  provided by the caller.
225   */   */
226  char *memory_conv_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,  char *memory_conv_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,
227          char *buf, int bufsize)          char *buf, int bufsize)
# Line 258  char *memory_conv_to_string(struct cpu * Line 265  char *memory_conv_to_string(struct cpu *
265  /*  /*
266   *  memory_device_dyntrans_access():   *  memory_device_dyntrans_access():
267   *   *
268   *  Get the lowest and highest dyntrans (or bintrans) access since last time.   *  Get the lowest and highest dyntrans access since last time.
269   */   */
270  void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem,  void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem,
271          void *extra, uint64_t *low, uint64_t *high)          void *extra, uint64_t *low, uint64_t *high)
272  {  {
         int i, j;  
273          size_t s;          size_t s;
274          int need_inval = 0;          int i, need_inval = 0;
275    
276          /*  TODO: This is O(n), so it might be good to rewrite it some day.          /*  TODO: This is O(n), so it might be good to rewrite it some day.
277              For now, it will be enough, as long as this function is not              For now, it will be enough, as long as this function is not
# Line 273  void memory_device_dyntrans_access(struc Line 279  void memory_device_dyntrans_access(struc
279    
280          for (i=0; i<mem->n_mmapped_devices; i++) {          for (i=0; i<mem->n_mmapped_devices; i++) {
281                  if (mem->dev_extra[i] == extra &&                  if (mem->dev_extra[i] == extra &&
282                        mem->dev_flags[i] & DM_DYNTRANS_WRITE_OK &&
283                      mem->dev_dyntrans_data[i] != NULL) {                      mem->dev_dyntrans_data[i] != NULL) {
284                          if (mem->dev_dyntrans_write_low[i] != (uint64_t) -1)                          if (mem->dev_dyntrans_write_low[i] != (uint64_t) -1)
285                                  need_inval = 1;                                  need_inval = 1;
# Line 290  void memory_device_dyntrans_access(struc Line 297  void memory_device_dyntrans_access(struc
297                          /*  Invalidate any pages of this device that might                          /*  Invalidate any pages of this device that might
298                              be in the dyntrans load/store cache, by marking                              be in the dyntrans load/store cache, by marking
299                              the pages read-only.  */                              the pages read-only.  */
300                          if (cpu->invalidate_translation_caches_paddr != NULL) {                          if (cpu->invalidate_translation_caches != NULL) {
301                                  for (s=0; s<mem->dev_length[i];                                  for (s=0; s<mem->dev_length[i];
302                                      s+=cpu->machine->arch_pagesize)                                      s+=cpu->machine->arch_pagesize)
303                                          cpu->invalidate_translation_caches_paddr                                          cpu->invalidate_translation_caches
304                                              (cpu, mem->dev_baseaddr[i] + s,                                              (cpu, mem->dev_baseaddr[i] + s,
305                                              JUST_MARK_AS_NON_WRITABLE);                                              JUST_MARK_AS_NON_WRITABLE
306                                                | INVALIDATE_PADDR);
307                          }                          }
308    
                         if (cpu->machine->arch == ARCH_MIPS) {  
                                 /*  
                                  *  ... and invalidate the "fast_vaddr_to_  
                                  *  hostaddr" cache entries that contain  
                                  *  pointers to this device:  (NOTE: Device i,  
                                  *  cache entry j)  
                                  */  
                                 for (j=0; j<N_BINTRANS_VADDR_TO_HOST; j++) {  
                                         if (cpu->cd.  
                                             mips.bintrans_data_hostpage[j] >=  
                                             mem->dev_dyntrans_data[i] &&  
                                             cpu->cd.mips.  
                                             bintrans_data_hostpage[j] <  
                                             mem->dev_dyntrans_data[i] +  
                                             mem->dev_length[i])  
                                                 cpu->cd.mips.  
                                                     bintrans_data_hostpage[j]  
                                                     = NULL;  
                                 }  
                         }  
309                          return;                          return;
310                  }                  }
311          }          }
# Line 325  void memory_device_dyntrans_access(struc Line 313  void memory_device_dyntrans_access(struc
313    
314    
315  /*  /*
  *  memory_device_register_statefunction():  
  *  
  *  TODO: Hm. This is semi-ugly. Should probably be rewritten/redesigned  
  *  some day.  
  */  
 void memory_device_register_statefunction(  
         struct memory *mem, void *extra,  
         int (*dev_f_state)(struct cpu *,  
             struct memory *, void *extra, int wf, int nr,  
             int *type, char **namep, void **data, size_t *len))  
 {  
         int i;  
   
         for (i=0; i<mem->n_mmapped_devices; i++)  
                 if (mem->dev_extra[i] == extra) {  
                         mem->dev_f_state[i] = dev_f_state;  
                         return;  
                 }  
   
         printf("memory_device_register_statefunction(): "  
             "couldn't find the device\n");  
         exit(1);  
 }  
   
   
 /*  
316   *  memory_device_register():   *  memory_device_register():
317   *   *
318   *  Register a (memory mapped) device by adding it to the dev_* fields of a   *  Register a (memory mapped) device by adding it to the dev_* fields of a
# Line 362  void memory_device_register(struct memor Line 324  void memory_device_register(struct memor
324                  size_t,int,void *),                  size_t,int,void *),
325          void *extra, int flags, unsigned char *dyntrans_data)          void *extra, int flags, unsigned char *dyntrans_data)
326  {  {
327          int i;          int i, newi = 0;
328    
329          if (mem->n_mmapped_devices >= MAX_DEVICES) {          if (mem->n_mmapped_devices >= MAX_DEVICES) {
330                  fprintf(stderr, "memory_device_register(): too many "                  fprintf(stderr, "memory_device_register(): too many "
# Line 370  void memory_device_register(struct memor Line 332  void memory_device_register(struct memor
332                  exit(1);                  exit(1);
333          }          }
334    
335          /*  Check for collisions:  */          /*
336             *  Figure out at which index to insert this device, and simultaneously
337             *  check for collisions:
338             */
339            newi = -1;
340          for (i=0; i<mem->n_mmapped_devices; i++) {          for (i=0; i<mem->n_mmapped_devices; i++) {
341                    if (i == 0 && baseaddr + len <= mem->dev_baseaddr[i])
342                            newi = i;
343                    if (i > 0 && baseaddr + len <= mem->dev_baseaddr[i] &&
344                        baseaddr >= mem->dev_endaddr[i-1])
345                            newi = i;
346                    if (i == mem->n_mmapped_devices - 1 &&
347                        baseaddr >= mem->dev_endaddr[i])
348                            newi = i + 1;
349    
350                  /*  If we are not colliding with device i, then continue:  */                  /*  If we are not colliding with device i, then continue:  */
351                  if (baseaddr + len <= mem->dev_baseaddr[i])                  if (baseaddr + len <= mem->dev_baseaddr[i])
352                          continue;                          continue;
353                  if (baseaddr >= mem->dev_baseaddr[i] + mem->dev_length[i])                  if (baseaddr >= mem->dev_endaddr[i])
354                          continue;                          continue;
355    
356                  fatal("\nWARNING! \"%s\" collides with device %i (\"%s\")!\n"                  fatal("\nERROR! \"%s\" collides with device %i (\"%s\")!\n",
                     "         Run-time behaviour will be undefined!\n\n",  
357                      device_name, i, mem->dev_name[i]);                      device_name, i, mem->dev_name[i]);
358                    exit(1);
359            }
360            if (mem->n_mmapped_devices == 0)
361                    newi = 0;
362            if (newi == -1) {
363                    fatal("INTERNAL ERROR\n");
364                    exit(1);
365          }          }
366    
367          /*  (40 bits of physical address is displayed)  */          if (verbose >= 2) {
368          debug("device %2i at 0x%010llx: %s",                  /*  (40 bits of physical address is displayed)  */
369              mem->n_mmapped_devices, (long long)baseaddr, device_name);                  debug("device at 0x%010"PRIx64": %s", (uint64_t) baseaddr,
370                        device_name);
371          if (flags & (MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK)  
372              && (baseaddr & mem->dev_dyntrans_alignment) != 0) {                  if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
373                  fatal("\nWARNING: Device dyntrans access, but unaligned"                      && (baseaddr & mem->dev_dyntrans_alignment) != 0) {
374                      " baseaddr 0x%llx.\n", (long long)baseaddr);                          fatal("\nWARNING: Device dyntrans access, but unaligned"
375                                " baseaddr 0x%"PRIx64".\n", (uint64_t) baseaddr);
376                    }
377    
378                    if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
379                            debug(" (dyntrans %s)",
380                                (flags & DM_DYNTRANS_WRITE_OK)? "R/W" : "R");
381                    }
382                    debug("\n");
383          }          }
384    
385          if (flags & (MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK)) {          for (i=0; i<mem->n_mmapped_devices; i++) {
386                  debug(" (dyntrans %s)",                  if (dyntrans_data == mem->dev_dyntrans_data[i] &&
387                      (flags & MEM_DYNTRANS_WRITE_OK)? "R/W" : "R");                      mem->dev_flags[i] & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
388                        && flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
389                            fatal("ERROR: the data pointer used for dyntrans "
390                                "accesses must only be used once!\n");
391                            fatal("(%p cannot be used by '%s'; already in use by '"
392                                "%s')\n", dyntrans_data, device_name,
393                                mem->dev_name[i]);
394                            exit(1);
395                    }
396          }          }
         debug("\n");  
397    
398          mem->dev_name[mem->n_mmapped_devices] = strdup(device_name);          mem->n_mmapped_devices++;
         mem->dev_baseaddr[mem->n_mmapped_devices] = baseaddr;  
         mem->dev_length[mem->n_mmapped_devices] = len;  
         mem->dev_flags[mem->n_mmapped_devices] = flags;  
         mem->dev_dyntrans_data[mem->n_mmapped_devices] = dyntrans_data;  
399    
400          if (mem->dev_name[mem->n_mmapped_devices] == NULL) {          /*
401             *  YUCK! This is ugly. TODO: fix
402             */
403            /*  Make space for the new entry:  */
404            memmove(&mem->dev_name[newi+1], &mem->dev_name[newi], sizeof(char *) *
405                (MAX_DEVICES - newi - 1));
406            memmove(&mem->dev_baseaddr[newi+1], &mem->dev_baseaddr[newi],
407                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
408            memmove(&mem->dev_endaddr[newi+1], &mem->dev_endaddr[newi],
409                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
410            memmove(&mem->dev_length[newi+1], &mem->dev_length[newi],
411                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
412            memmove(&mem->dev_flags[newi+1], &mem->dev_flags[newi], sizeof(int) *
413                (MAX_DEVICES - newi - 1));
414            memmove(&mem->dev_extra[newi+1], &mem->dev_extra[newi], sizeof(void *) *
415                (MAX_DEVICES - newi - 1));
416            memmove(&mem->dev_f[newi+1], &mem->dev_f[newi], sizeof(void *) *
417                (MAX_DEVICES - newi - 1));
418            memmove(&mem->dev_dyntrans_data[newi+1], &mem->dev_dyntrans_data[newi],
419                sizeof(void *) * (MAX_DEVICES - newi - 1));
420            memmove(&mem->dev_dyntrans_write_low[newi+1],
421                &mem->dev_dyntrans_write_low[newi],
422                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
423            memmove(&mem->dev_dyntrans_write_high[newi+1],
424                &mem->dev_dyntrans_write_high[newi],
425                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
426    
427    
428            mem->dev_name[newi] = strdup(device_name);
429            mem->dev_baseaddr[newi] = baseaddr;
430            mem->dev_endaddr[newi] = baseaddr + len;
431            mem->dev_length[newi] = len;
432            mem->dev_flags[newi] = flags;
433            mem->dev_dyntrans_data[newi] = dyntrans_data;
434    
435            if (mem->dev_name[newi] == NULL) {
436                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
437                  exit(1);                  exit(1);
438          }          }
439    
440          if (flags & (MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK)          if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
441              && dyntrans_data == NULL) {              && !(flags & DM_EMULATED_RAM) && dyntrans_data == NULL) {
442                  fatal("\nERROR: Device dyntrans access, but dyntrans_data"                  fatal("\nERROR: Device dyntrans access, but dyntrans_data"
443                      " = NULL!\n");                      " = NULL!\n");
444                  exit(1);                  exit(1);
445          }          }
446    
447          if ((size_t)dyntrans_data & 7) {          if ((size_t)dyntrans_data & (sizeof(void *) - 1)) {
448                  fprintf(stderr, "memory_device_register():"                  fprintf(stderr, "memory_device_register():"
449                      " dyntrans_data not aligned correctly (%p)\n",                      " dyntrans_data not aligned correctly (%p)\n",
450                      dyntrans_data);                      dyntrans_data);
451                  exit(1);                  exit(1);
452          }          }
453    
454          mem->dev_dyntrans_write_low[mem->n_mmapped_devices] = (uint64_t)-1;          mem->dev_dyntrans_write_low[newi] = (uint64_t)-1;
455          mem->dev_dyntrans_write_high[mem->n_mmapped_devices] = 0;          mem->dev_dyntrans_write_high[newi] = 0;
456          mem->dev_f[mem->n_mmapped_devices] = f;          mem->dev_f[newi] = f;
457          mem->dev_extra[mem->n_mmapped_devices] = extra;          mem->dev_extra[newi] = extra;
         mem->n_mmapped_devices++;  
458    
459          if (baseaddr < mem->mmap_dev_minaddr)          if (baseaddr < mem->mmap_dev_minaddr)
460                  mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;                  mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;
# Line 463  void memory_device_remove(struct memory Line 489  void memory_device_remove(struct memory
489              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
490          memmove(&mem->dev_baseaddr[i], &mem->dev_baseaddr[i+1],          memmove(&mem->dev_baseaddr[i], &mem->dev_baseaddr[i+1],
491              sizeof(uint64_t) * (MAX_DEVICES - i - 1));              sizeof(uint64_t) * (MAX_DEVICES - i - 1));
492            memmove(&mem->dev_endaddr[i], &mem->dev_endaddr[i+1],
493                sizeof(uint64_t) * (MAX_DEVICES - i - 1));
494          memmove(&mem->dev_length[i], &mem->dev_length[i+1], sizeof(uint64_t) *          memmove(&mem->dev_length[i], &mem->dev_length[i+1], sizeof(uint64_t) *
495              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
496          memmove(&mem->dev_flags[i], &mem->dev_flags[i+1], sizeof(int) *          memmove(&mem->dev_flags[i], &mem->dev_flags[i+1], sizeof(int) *
# Line 471  void memory_device_remove(struct memory Line 499  void memory_device_remove(struct memory
499              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
500          memmove(&mem->dev_f[i], &mem->dev_f[i+1], sizeof(void *) *          memmove(&mem->dev_f[i], &mem->dev_f[i+1], sizeof(void *) *
501              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
         memmove(&mem->dev_f_state[i], &mem->dev_f_state[i+1], sizeof(void *) *  
             (MAX_DEVICES - i - 1));  
502          memmove(&mem->dev_dyntrans_data[i], &mem->dev_dyntrans_data[i+1],          memmove(&mem->dev_dyntrans_data[i], &mem->dev_dyntrans_data[i+1],
503              sizeof(void *) * (MAX_DEVICES - i - 1));              sizeof(void *) * (MAX_DEVICES - i - 1));
504          memmove(&mem->dev_dyntrans_write_low[i], &mem->dev_dyntrans_write_low          memmove(&mem->dev_dyntrans_write_low[i], &mem->dev_dyntrans_write_low
505              [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));              [i+1], sizeof(uint64_t) * (MAX_DEVICES - i - 1));
506          memmove(&mem->dev_dyntrans_write_high[i], &mem->dev_dyntrans_write_high          memmove(&mem->dev_dyntrans_write_high[i], &mem->dev_dyntrans_write_high
507              [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));              [i+1], sizeof(uint64_t) * (MAX_DEVICES - i - 1));
508  }  }
509    
510    
# Line 508  unsigned char *memory_paddr_to_hostaddr( Line 534  unsigned char *memory_paddr_to_hostaddr(
534          table = mem->pagetable;          table = mem->pagetable;
535          entry = (paddr >> shrcount) & mask;          entry = (paddr >> shrcount) & mask;
536    
537          /*  printf("memory_paddr_to_hostaddr(): p=%16llx w=%i => entry=0x%x\n",          /*  printf("memory_paddr_to_hostaddr(): p=%16"PRIx64
538              (long long)paddr, writeflag, entry);  */              " w=%i => entry=0x%x\n", (uint64_t) paddr, writeflag, entry);  */
539    
540          if (table[entry] == NULL) {          if (table[entry] == NULL) {
541                  size_t alloclen;                  size_t alloclen;
# Line 532  unsigned char *memory_paddr_to_hostaddr( Line 558  unsigned char *memory_paddr_to_hostaddr(
558                  /*  Anonymous mmap() should return zero-filled memory,                  /*  Anonymous mmap() should return zero-filled memory,
559                      try malloc + memset if mmap failed.  */                      try malloc + memset if mmap failed.  */
560                  table[entry] = (void *) mmap(NULL, alloclen,                  table[entry] = (void *) mmap(NULL, alloclen,
561                      PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,                      PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
                     -1, 0);  
562                  if (table[entry] == NULL) {                  if (table[entry] == NULL) {
563                          table[entry] = malloc(alloclen);                          table[entry] = malloc(alloclen);
564                          if (table[entry] == NULL) {                          if (table[entry] == NULL) {
# Line 547  unsigned char *memory_paddr_to_hostaddr( Line 572  unsigned char *memory_paddr_to_hostaddr(
572          return (unsigned char *) table[entry];          return (unsigned char *) table[entry];
573  }  }
574    
575    
576    #define UPDATE_CHECKSUM(value) {                                        \
577                    internal_state -= 0x118c7771c0c0a77fULL;                \
578                    internal_state = ((internal_state + (value)) << 7) ^    \
579                        (checksum >> 11) ^ ((checksum - (value)) << 3) ^    \
580                        (internal_state - checksum) ^ ((value) - internal_state); \
581                    checksum ^= internal_state;                             \
582            }
583    
584    
585    /*
586     *  memory_checksum():
587     *
588     *  Calculate a 64-bit checksum of everything in a struct memory. This is
589     *  useful for tracking down bugs; an old (presumably working) version of
590     *  the emulator can be compared to a newer (buggy) version.
591     */
592    uint64_t memory_checksum(struct memory *mem)
593    {
594            uint64_t internal_state = 0x80624185376feff2ULL;
595            uint64_t checksum = 0xcb9a87d5c010072cULL;
596            const int n_entries = (1 << BITS_PER_PAGETABLE) - 1;
597            const size_t len = (1 << BITS_PER_MEMBLOCK) / sizeof(uint64_t);
598            size_t entry, i;
599    
600            for (entry=0; entry<=n_entries; entry++) {
601                    uint64_t **table = mem->pagetable;
602                    uint64_t *memblock = table[entry];
603    
604                    if (memblock == NULL) {
605                            UPDATE_CHECKSUM(0x1198ab7c8174a76fULL);
606                            continue;
607                    }
608    
609                    for (i=0; i<len; i++)
610                            UPDATE_CHECKSUM(memblock[i]);
611            }
612    
613            return checksum;
614    }
615    

Legend:
Removed from v.14  
changed lines
  Added in v.24

  ViewVC Help
Powered by ViewVC 1.1.26