/[gxemul]/trunk/src/cpus/memory_mips.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/cpus/memory_mips.c

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

revision 31 by dpavlin, Mon Oct 8 16:20:26 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 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_mips.c,v 1.9 2006/07/14 16:33:28 debug Exp $   *  $Id: memory_mips.c,v 1.10 2006/09/01 16:52:58 debug Exp $
29   *   *
30   *  MIPS-specific memory routines. Included from cpu_mips.c.   *  MIPS-specific memory routines. Included from cpu_mips.c.
  *  
  *  NOTE: The cache emulation code (ifdef ENABLE_CACHE_EMULATION) is old  
  *        and doesn't work with dyntrans. TODO: rewrite this.  
31   */   */
32    
33  #include <sys/types.h>  #include <sys/types.h>
# Line 48  Line 45 
45  int memory_cache_R3000(struct cpu *cpu, int cache, uint64_t paddr,  int memory_cache_R3000(struct cpu *cpu, int cache, uint64_t paddr,
46          int writeflag, size_t len, unsigned char *data)          int writeflag, size_t len, unsigned char *data)
47  {  {
 #ifdef ENABLE_CACHE_EMULATION  
         struct r3000_cache_line *rp;  
         int cache_line;  
         uint32_t tag_mask;  
         unsigned char *memblock;  
         struct memory *mem = cpu->mem;  
 #endif  
48          unsigned int i;          unsigned int i;
49          int cache_isolated = 0, addr, hit, which_cache = cache;          int cache_isolated = 0, addr, hit, which_cache = cache;
50    
# Line 63  int memory_cache_R3000(struct cpu *cpu, Line 53  int memory_cache_R3000(struct cpu *cpu,
53                  return 0;                  return 0;
54    
55    
 #ifdef ENABLE_CACHE_EMULATION  
         if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS1_SWAP_CACHES)  
                 which_cache ^= 1;  
   
         tag_mask = 0xffffffff & ~cpu->cd.mips.cache_mask[which_cache];  
         cache_line = (paddr & cpu->cd.mips.cache_mask[which_cache])  
             / cpu->cd.mips.cache_linesize[which_cache];  
         rp = (struct r3000_cache_line *) cpu->cd.mips.cache_tags[which_cache];  
   
         /*  Is this a cache hit or miss?  */  
         hit = (rp[cache_line].tag_valid & R3000_TAG_VALID) &&  
             (rp[cache_line].tag_paddr == (paddr & tag_mask));  
   
         /*  
          *  The cache miss bit is only set on cache reads, and only to the  
          *  data cache. (?)  
          *  
          *  (TODO: is this correct? I don't remember where I got this from.)  
          */  
         if (cache == CACHE_DATA && writeflag==MEM_READ) {  
                 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~MIPS1_CACHE_MISS;  
                 if (!hit)  
                         cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |=  
                             MIPS1_CACHE_MISS;  
         }  
   
         /*  
          *  Is the Data cache isolated?  Then don't access main memory:  
          */  
         if (cache == CACHE_DATA &&  
             cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS1_ISOL_CACHES)  
                 cache_isolated = 1;  
   
         addr = paddr & cpu->cd.mips.cache_mask[which_cache];  
   
         /*  
          *  If there was a miss and the cache is not isolated, then flush  
          *  the old cacheline back to main memory, and read in the new  
          *  cacheline.  
          *  
          *  Then access the cache.  
          */  
 /*  
         fatal("L1 CACHE isolated=%i hit=%i write=%i cache=%i cacheline=%i"  
             " paddr=%08x => addr in"  
             " cache = 0x%lx\n", cache_isolated, hit, writeflag,  
             which_cache, cache_line, (int)paddr,  
             addr);  
 */  
         if (!hit && !cache_isolated) {  
                 unsigned char *dst, *src;  
                 uint64_t old_cached_paddr = rp[cache_line].tag_paddr  
                     + cache_line * cpu->cd.mips.cache_linesize[which_cache];  
   
                 /*  Flush the old cacheline to main memory:  */  
                 if ((rp[cache_line].tag_valid & R3000_TAG_VALID) &&  
                     (rp[cache_line].tag_valid & R3000_TAG_DIRTY)) {  
 /*                      fatal("  FLUSHING old tag=0%08x "  
                             "old_cached_paddr=0x%08x\n",  
                             rp[cache_line].tag_paddr,  
                             old_cached_paddr);  
 */  
                         memblock = memory_paddr_to_hostaddr(  
                             mem, old_cached_paddr & ~cpu->cd.mips.  
                             cache_mask[which_cache], MEM_WRITE);  
   
                         src = cpu->cd.mips.cache[which_cache];  
                         dst = memblock;  
   
                         src += cache_line *  
                             cpu->cd.mips.cache_linesize[which_cache];  
                         dst += cache_line *  
                             cpu->cd.mips.cache_linesize[which_cache];  
   
                         if (memblock == NULL) {  
                                 fatal("BUG in memory.c! Hm.\n");  
                         } else {  
                                 memcpy(dst, src,  
                                     cpu->cd.mips.cache_linesize[which_cache]);  
                         }  
                 }  
   
                 /*  Copy from main memory into the cache:  */  
                 memblock = memory_paddr_to_hostaddr(mem, paddr  
                     & ~cpu->cd.mips.cache_mask[which_cache], writeflag);  
   
 /*              fatal("  FETCHING new paddr=0%08x\n", paddr);  
 */  
                 dst = cpu->cd.mips.cache[which_cache];  
   
                 if (memblock == NULL) {  
                         if (writeflag == MEM_READ)  
                         memset(dst, 0,  
                             cpu->cd.mips.cache_linesize[which_cache]);  
                 } else {  
                         src = memblock;  
   
                         src += cache_line *  
                             cpu->cd.mips.cache_linesize[which_cache];  
                         dst += cache_line *  
                             cpu->cd.mips.cache_linesize[which_cache];  
                         memcpy(dst, src,  
                             cpu->cd.mips.cache_linesize[which_cache]);  
                 }  
   
                 rp[cache_line].tag_paddr = paddr & tag_mask;  
                 rp[cache_line].tag_valid = R3000_TAG_VALID;  
         }  
   
         if (cache_isolated && writeflag == MEM_WRITE) {  
                 rp[cache_line].tag_valid = 0;  
         }  
   
         if (writeflag==MEM_READ) {  
                 for (i=0; i<len; i++)  
                         data[i] = cpu->cd.mips.cache[which_cache][(addr+i) &  
                             cpu->cd.mips.cache_mask[which_cache]];  
         } else {  
                 for (i=0; i<len; i++) {  
                         if (cpu->cd.mips.cache[which_cache][(addr+i) &  
                             cpu->cd.mips.cache_mask[which_cache]] != data[i]) {  
                                 rp[cache_line].tag_valid |= R3000_TAG_DIRTY;  
                         }  
                         cpu->cd.mips.cache[which_cache][(addr+i) &  
                             cpu->cd.mips.cache_mask[which_cache]] = data[i];  
                 }  
         }  
   
         /*  Write-through! (Write to main memory as well.)  */  
         if (writeflag == MEM_READ || cache_isolated)  
                 return 1;  
   
 #else  
   
56          /*          /*
57           *  R2000/R3000 without correct cache emulation:           *  R2000/R3000 without correct cache emulation:
58           *           *
# Line 258  int memory_cache_R3000(struct cpu *cpu, Line 114  int memory_cache_R3000(struct cpu *cpu,
114                  /*  No!  Not when not emulating caches fully. (TODO?)  */                  /*  No!  Not when not emulating caches fully. (TODO?)  */
115                  cpu->cd.mips.cache_last_paddr[cache] = paddr;                  cpu->cd.mips.cache_last_paddr[cache] = paddr;
116          }          }
 #endif  
117    
118          return 0;          return 0;
119  }  }

Legend:
Removed from v.31  
changed lines
  Added in v.32

  ViewVC Help
Powered by ViewVC 1.1.26