/[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 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC revision 28 by dpavlin, Mon Oct 8 16:20:26 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.180 2005/10/25 15:51:02 debug Exp $   *  $Id: memory.c,v 1.192 2006/07/14 16:33:27 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 (cpu->byte_order == EMUL_LITTLE_ENDIAN)          if (len & MEM_PCI_LITTLE_ENDIAN) {
96                    len &= ~MEM_PCI_LITTLE_ENDIAN;
97                    byte_order = EMUL_LITTLE_ENDIAN;
98            }
99    
100            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 299  void memory_device_dyntrans_access(struc Line 306  void memory_device_dyntrans_access(struc
306                                              | INVALIDATE_PADDR);                                              | 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 326  void memory_device_dyntrans_access(struc Line 313  void memory_device_dyntrans_access(struc
313    
314    
315  /*  /*
316   *  memory_device_register_statefunction():   *  memory_device_update_data():
317   *   *
318   *  TODO: Hm. This is semi-ugly. Should probably be rewritten/redesigned   *  Update a device' dyntrans data pointer.
319   *  some day.   *
320     *  SUPER-IMPORTANT NOTE: Anyone who changes a dyntrans data pointer while
321     *  things are running also needs to invalidate all CPUs' address translation
322     *  caches!  Otherwise, these may contain old pointers to the old data.
323   */   */
324  void memory_device_register_statefunction(  void memory_device_update_data(struct memory *mem, void *extra,
325          struct memory *mem, void *extra,          unsigned char *data)
         int (*dev_f_state)(struct cpu *,  
             struct memory *, void *extra, int wf, int nr,  
             int *type, char **namep, void **data, size_t *len))  
326  {  {
327          int i;          int i;
328    
329          for (i=0; i<mem->n_mmapped_devices; i++)          for (i=0; i<mem->n_mmapped_devices; i++) {
330                  if (mem->dev_extra[i] == extra) {                  if (mem->dev_extra[i] != extra)
331                          mem->dev_f_state[i] = dev_f_state;                          continue;
                         return;  
                 }  
332    
333          printf("memory_device_register_statefunction(): "                  mem->dev_dyntrans_data[i] = data;
334              "couldn't find the device\n");                  mem->dev_dyntrans_write_low[i] = (uint64_t)-1;
335          exit(1);                  mem->dev_dyntrans_write_high[i] = 0;
336            }
337  }  }
338    
339    
# Line 363  void memory_device_register(struct memor Line 349  void memory_device_register(struct memor
349                  size_t,int,void *),                  size_t,int,void *),
350          void *extra, int flags, unsigned char *dyntrans_data)          void *extra, int flags, unsigned char *dyntrans_data)
351  {  {
352          int i;          int i, newi = 0;
353    
354          if (mem->n_mmapped_devices >= MAX_DEVICES) {          if (mem->n_mmapped_devices >= MAX_DEVICES) {
355                  fprintf(stderr, "memory_device_register(): too many "                  fprintf(stderr, "memory_device_register(): too many "
# Line 371  void memory_device_register(struct memor Line 357  void memory_device_register(struct memor
357                  exit(1);                  exit(1);
358          }          }
359    
360          /*  Check for collisions:  */          /*
361             *  Figure out at which index to insert this device, and simultaneously
362             *  check for collisions:
363             */
364            newi = -1;
365          for (i=0; i<mem->n_mmapped_devices; i++) {          for (i=0; i<mem->n_mmapped_devices; i++) {
366                    if (i == 0 && baseaddr + len <= mem->dev_baseaddr[i])
367                            newi = i;
368                    if (i > 0 && baseaddr + len <= mem->dev_baseaddr[i] &&
369                        baseaddr >= mem->dev_endaddr[i-1])
370                            newi = i;
371                    if (i == mem->n_mmapped_devices - 1 &&
372                        baseaddr >= mem->dev_endaddr[i])
373                            newi = i + 1;
374    
375                  /*  If we are not colliding with device i, then continue:  */                  /*  If we are not colliding with device i, then continue:  */
376                  if (baseaddr + len <= mem->dev_baseaddr[i])                  if (baseaddr + len <= mem->dev_baseaddr[i])
377                          continue;                          continue;
378                  if (baseaddr >= mem->dev_baseaddr[i] + mem->dev_length[i])                  if (baseaddr >= mem->dev_endaddr[i])
379                          continue;                          continue;
380    
381                  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",  
382                      device_name, i, mem->dev_name[i]);                      device_name, i, mem->dev_name[i]);
383                    exit(1);
384            }
385            if (mem->n_mmapped_devices == 0)
386                    newi = 0;
387            if (newi == -1) {
388                    fatal("INTERNAL ERROR\n");
389                    exit(1);
390            }
391    
392            if (verbose >= 2) {
393                    /*  (40 bits of physical address is displayed)  */
394                    debug("device at 0x%010"PRIx64": %s", (uint64_t) baseaddr,
395                        device_name);
396    
397                    if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
398                        && (baseaddr & mem->dev_dyntrans_alignment) != 0) {
399                            fatal("\nWARNING: Device dyntrans access, but unaligned"
400                                " baseaddr 0x%"PRIx64".\n", (uint64_t) baseaddr);
401                    }
402    
403                    if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
404                            debug(" (dyntrans %s)",
405                                (flags & DM_DYNTRANS_WRITE_OK)? "R/W" : "R");
406                    }
407                    debug("\n");
408          }          }
409    
410          /*  (40 bits of physical address is displayed)  */          for (i=0; i<mem->n_mmapped_devices; i++) {
411          debug("device %2i at 0x%010llx: %s",                  if (dyntrans_data == mem->dev_dyntrans_data[i] &&
412              mem->n_mmapped_devices, (long long)baseaddr, device_name);                      mem->dev_flags[i] & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
413                        && flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
414          if (flags & (MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK)                          fatal("ERROR: the data pointer used for dyntrans "
415              && (baseaddr & mem->dev_dyntrans_alignment) != 0) {                              "accesses must only be used once!\n");
416                  fatal("\nWARNING: Device dyntrans access, but unaligned"                          fatal("(%p cannot be used by '%s'; already in use by '"
417                      " baseaddr 0x%llx.\n", (long long)baseaddr);                              "%s')\n", dyntrans_data, device_name,
418          }                              mem->dev_name[i]);
419                            exit(1);
420          if (flags & (MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK)) {                  }
421                  debug(" (dyntrans %s)",          }
                     (flags & MEM_DYNTRANS_WRITE_OK)? "R/W" : "R");  
         }  
         debug("\n");  
   
         mem->dev_name[mem->n_mmapped_devices] = strdup(device_name);  
         mem->dev_baseaddr[mem->n_mmapped_devices] = baseaddr;  
         mem->dev_endaddr[mem->n_mmapped_devices] = baseaddr + len;  
         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;  
422    
423          if (mem->dev_name[mem->n_mmapped_devices] == NULL) {          mem->n_mmapped_devices++;
424    
425            /*
426             *  YUCK! This is ugly. TODO: fix
427             */
428            /*  Make space for the new entry:  */
429            memmove(&mem->dev_name[newi+1], &mem->dev_name[newi], sizeof(char *) *
430                (MAX_DEVICES - newi - 1));
431            memmove(&mem->dev_baseaddr[newi+1], &mem->dev_baseaddr[newi],
432                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
433            memmove(&mem->dev_endaddr[newi+1], &mem->dev_endaddr[newi],
434                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
435            memmove(&mem->dev_length[newi+1], &mem->dev_length[newi],
436                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
437            memmove(&mem->dev_flags[newi+1], &mem->dev_flags[newi], sizeof(int) *
438                (MAX_DEVICES - newi - 1));
439            memmove(&mem->dev_extra[newi+1], &mem->dev_extra[newi], sizeof(void *) *
440                (MAX_DEVICES - newi - 1));
441            memmove(&mem->dev_f[newi+1], &mem->dev_f[newi], sizeof(void *) *
442                (MAX_DEVICES - newi - 1));
443            memmove(&mem->dev_dyntrans_data[newi+1], &mem->dev_dyntrans_data[newi],
444                sizeof(void *) * (MAX_DEVICES - newi - 1));
445            memmove(&mem->dev_dyntrans_write_low[newi+1],
446                &mem->dev_dyntrans_write_low[newi],
447                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
448            memmove(&mem->dev_dyntrans_write_high[newi+1],
449                &mem->dev_dyntrans_write_high[newi],
450                sizeof(uint64_t) * (MAX_DEVICES - newi - 1));
451    
452    
453            mem->dev_name[newi] = strdup(device_name);
454            mem->dev_baseaddr[newi] = baseaddr;
455            mem->dev_endaddr[newi] = baseaddr + len;
456            mem->dev_length[newi] = len;
457            mem->dev_flags[newi] = flags;
458            mem->dev_dyntrans_data[newi] = dyntrans_data;
459    
460            if (mem->dev_name[newi] == NULL) {
461                  fprintf(stderr, "out of memory\n");                  fprintf(stderr, "out of memory\n");
462                  exit(1);                  exit(1);
463          }          }
464    
465          if (flags & (MEM_DYNTRANS_OK | MEM_DYNTRANS_WRITE_OK)          if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
466              && !(flags & MEM_EMULATED_RAM) && dyntrans_data == NULL) {              && !(flags & DM_EMULATED_RAM) && dyntrans_data == NULL) {
467                  fatal("\nERROR: Device dyntrans access, but dyntrans_data"                  fatal("\nERROR: Device dyntrans access, but dyntrans_data"
468                      " = NULL!\n");                      " = NULL!\n");
469                  exit(1);                  exit(1);
# Line 426  void memory_device_register(struct memor Line 476  void memory_device_register(struct memor
476                  exit(1);                  exit(1);
477          }          }
478    
479          mem->dev_dyntrans_write_low[mem->n_mmapped_devices] = (uint64_t)-1;          mem->dev_dyntrans_write_low[newi] = (uint64_t)-1;
480          mem->dev_dyntrans_write_high[mem->n_mmapped_devices] = 0;          mem->dev_dyntrans_write_high[newi] = 0;
481          mem->dev_f[mem->n_mmapped_devices] = f;          mem->dev_f[newi] = f;
482          mem->dev_extra[mem->n_mmapped_devices] = extra;          mem->dev_extra[newi] = extra;
         mem->n_mmapped_devices++;  
483    
484          if (baseaddr < mem->mmap_dev_minaddr)          if (baseaddr < mem->mmap_dev_minaddr)
485                  mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;                  mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;
# Line 465  void memory_device_remove(struct memory Line 514  void memory_device_remove(struct memory
514              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
515          memmove(&mem->dev_baseaddr[i], &mem->dev_baseaddr[i+1],          memmove(&mem->dev_baseaddr[i], &mem->dev_baseaddr[i+1],
516              sizeof(uint64_t) * (MAX_DEVICES - i - 1));              sizeof(uint64_t) * (MAX_DEVICES - i - 1));
517            memmove(&mem->dev_endaddr[i], &mem->dev_endaddr[i+1],
518                sizeof(uint64_t) * (MAX_DEVICES - i - 1));
519          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) *
520              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
521          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 473  void memory_device_remove(struct memory Line 524  void memory_device_remove(struct memory
524              (MAX_DEVICES - i - 1));              (MAX_DEVICES - i - 1));
525          memmove(&mem->dev_f[i], &mem->dev_f[i+1], sizeof(void *) *          memmove(&mem->dev_f[i], &mem->dev_f[i+1], sizeof(void *) *
526              (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));  
527          memmove(&mem->dev_dyntrans_data[i], &mem->dev_dyntrans_data[i+1],          memmove(&mem->dev_dyntrans_data[i], &mem->dev_dyntrans_data[i+1],
528              sizeof(void *) * (MAX_DEVICES - i - 1));              sizeof(void *) * (MAX_DEVICES - i - 1));
529          memmove(&mem->dev_dyntrans_write_low[i], &mem->dev_dyntrans_write_low          memmove(&mem->dev_dyntrans_write_low[i], &mem->dev_dyntrans_write_low
530              [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));              [i+1], sizeof(uint64_t) * (MAX_DEVICES - i - 1));
531          memmove(&mem->dev_dyntrans_write_high[i], &mem->dev_dyntrans_write_high          memmove(&mem->dev_dyntrans_write_high[i], &mem->dev_dyntrans_write_high
532              [i+1], sizeof(void *) * (MAX_DEVICES - i - 1));              [i+1], sizeof(uint64_t) * (MAX_DEVICES - i - 1));
533  }  }
534    
535    
# Line 494  void memory_device_remove(struct memory Line 543  void memory_device_remove(struct memory
543  /*  /*
544   *  memory_paddr_to_hostaddr():   *  memory_paddr_to_hostaddr():
545   *   *
546   *  Translate a physical address into a host address.   *  Translate a physical address into a host address. The usual way to call
547     *  this function is to make sure that paddr is page aligned, which will result
548     *  in the host _page_ corresponding to that address.
549   *   *
550   *  Return value is a pointer to a host memblock, or NULL on failure.   *  Return value is a pointer to the address in the host, or NULL on failure.
551   *  On reads, a NULL return value should be interpreted as reading all zeroes.   *  On reads, a NULL return value should be interpreted as reading all zeroes.
552   */   */
553  unsigned char *memory_paddr_to_hostaddr(struct memory *mem,  unsigned char *memory_paddr_to_hostaddr(struct memory *mem,
# Line 506  unsigned char *memory_paddr_to_hostaddr( Line 557  unsigned char *memory_paddr_to_hostaddr(
557          int entry;          int entry;
558          const int mask = (1 << BITS_PER_PAGETABLE) - 1;          const int mask = (1 << BITS_PER_PAGETABLE) - 1;
559          const int shrcount = MAX_BITS - BITS_PER_PAGETABLE;          const int shrcount = MAX_BITS - BITS_PER_PAGETABLE;
560            unsigned char *hostptr;
561    
562          table = mem->pagetable;          table = mem->pagetable;
563          entry = (paddr >> shrcount) & mask;          entry = (paddr >> shrcount) & mask;
564    
565          /*  printf("memory_paddr_to_hostaddr(): p=%16llx w=%i => entry=0x%x\n",          /*  printf("memory_paddr_to_hostaddr(): p=%16"PRIx64
566              (long long)paddr, writeflag, entry);  */              " w=%i => entry=0x%x\n", (uint64_t) paddr, writeflag, entry);  */
567    
568          if (table[entry] == NULL) {          if (table[entry] == NULL) {
569                  size_t alloclen;                  size_t alloclen;
# Line 534  unsigned char *memory_paddr_to_hostaddr( Line 586  unsigned char *memory_paddr_to_hostaddr(
586                  /*  Anonymous mmap() should return zero-filled memory,                  /*  Anonymous mmap() should return zero-filled memory,
587                      try malloc + memset if mmap failed.  */                      try malloc + memset if mmap failed.  */
588                  table[entry] = (void *) mmap(NULL, alloclen,                  table[entry] = (void *) mmap(NULL, alloclen,
589                      PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,                      PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
                     -1, 0);  
590                  if (table[entry] == NULL) {                  if (table[entry] == NULL) {
591                          table[entry] = malloc(alloclen);                          table[entry] = malloc(alloclen);
592                          if (table[entry] == NULL) {                          if (table[entry] == NULL) {
# Line 546  unsigned char *memory_paddr_to_hostaddr( Line 597  unsigned char *memory_paddr_to_hostaddr(
597                  }                  }
598          }          }
599    
600          return (unsigned char *) table[entry];          hostptr = (unsigned char *) table[entry];
601    
602            if (hostptr != NULL)
603                    hostptr += (paddr & ((1 << BITS_PER_MEMBLOCK) - 1));
604    
605            return hostptr;
606    }
607    
608    
609    #define UPDATE_CHECKSUM(value) {                                        \
610                    internal_state -= 0x118c7771c0c0a77fULL;                \
611                    internal_state = ((internal_state + (value)) << 7) ^    \
612                        (checksum >> 11) ^ ((checksum - (value)) << 3) ^    \
613                        (internal_state - checksum) ^ ((value) - internal_state); \
614                    checksum ^= internal_state;                             \
615            }
616    
617    
618    /*
619     *  memory_checksum():
620     *
621     *  Calculate a 64-bit checksum of everything in a struct memory. This is
622     *  useful for tracking down bugs; an old (presumably working) version of
623     *  the emulator can be compared to a newer (buggy) version.
624     */
625    uint64_t memory_checksum(struct memory *mem)
626    {
627            uint64_t internal_state = 0x80624185376feff2ULL;
628            uint64_t checksum = 0xcb9a87d5c010072cULL;
629            const int n_entries = (1 << BITS_PER_PAGETABLE) - 1;
630            const size_t len = (1 << BITS_PER_MEMBLOCK) / sizeof(uint64_t);
631            size_t entry, i;
632    
633            for (entry=0; entry<=n_entries; entry++) {
634                    uint64_t **table = mem->pagetable;
635                    uint64_t *memblock = table[entry];
636    
637                    if (memblock == NULL) {
638                            UPDATE_CHECKSUM(0x1198ab7c8174a76fULL);
639                            continue;
640                    }
641    
642                    for (i=0; i<len; i++)
643                            UPDATE_CHECKSUM(memblock[i]);
644            }
645    
646            return checksum;
647  }  }
648    

Legend:
Removed from v.18  
changed lines
  Added in v.28

  ViewVC Help
Powered by ViewVC 1.1.26