/[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 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 28 by dpavlin, Mon Oct 8 16:20:26 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: memory.c,v 1.187 2006/01/14 12:51:59 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 270  char *memory_conv_to_string(struct cpu * Line 270  char *memory_conv_to_string(struct cpu *
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 307  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 334  void memory_device_dyntrans_access(struc Line 313  void memory_device_dyntrans_access(struc
313    
314    
315  /*  /*
316     *  memory_device_update_data():
317     *
318     *  Update a device' dyntrans data pointer.
319     *
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_update_data(struct memory *mem, void *extra,
325            unsigned char *data)
326    {
327            int i;
328    
329            for (i=0; i<mem->n_mmapped_devices; i++) {
330                    if (mem->dev_extra[i] != extra)
331                            continue;
332    
333                    mem->dev_dyntrans_data[i] = data;
334                    mem->dev_dyntrans_write_low[i] = (uint64_t)-1;
335                    mem->dev_dyntrans_write_high[i] = 0;
336            }
337    }
338    
339    
340    /*
341   *  memory_device_register():   *  memory_device_register():
342   *   *
343   *  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 387  void memory_device_register(struct memor Line 391  void memory_device_register(struct memor
391    
392          if (verbose >= 2) {          if (verbose >= 2) {
393                  /*  (40 bits of physical address is displayed)  */                  /*  (40 bits of physical address is displayed)  */
394                  debug("device at 0x%010llx: %s", (long long)baseaddr,                  debug("device at 0x%010"PRIx64": %s", (uint64_t) baseaddr,
395                      device_name);                      device_name);
396    
397                  if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)                  if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
398                      && (baseaddr & mem->dev_dyntrans_alignment) != 0) {                      && (baseaddr & mem->dev_dyntrans_alignment) != 0) {
399                          fatal("\nWARNING: Device dyntrans access, but unaligned"                          fatal("\nWARNING: Device dyntrans access, but unaligned"
400                              " baseaddr 0x%llx.\n", (long long)baseaddr);                              " baseaddr 0x%"PRIx64".\n", (uint64_t) baseaddr);
401                  }                  }
402    
403                  if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {                  if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
# Line 539  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 551  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 590  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.22  
changed lines
  Added in v.28

  ViewVC Help
Powered by ViewVC 1.1.26