/[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 24 by dpavlin, Mon Oct 8 16:19:56 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.7 2006/06/22 11:43:03 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;  
         int offset;  
 #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 64  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, MEM_WRITE);  
                         offset = old_cached_paddr  
                             & ((1 << BITS_PER_MEMBLOCK) - 1)  
                             & ~cpu->cd.mips.cache_mask[which_cache];  
   
                         src = cpu->cd.mips.cache[which_cache];  
                         dst = memblock + (offset &  
                             ~cpu->cd.mips.cache_mask[which_cache]);  
   
                         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]);  
                         }  
                         /*  offset is the offset within  
                          *  the memblock:  
                          *  printf("read: offset = 0x%x\n", offset);  
                          */  
                 }  
   
                 /*  Copy from main memory into the cache:  */  
                 memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag);  
                 offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1)  
                     & ~cpu->cd.mips.cache_mask[which_cache];  
                 /*  offset is offset within the memblock:  
                  *  printf("write: offset = 0x%x\n", offset);  
                  */  
   
 /*              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 + (offset &  
                             ~cpu->cd.mips.cache_mask[which_cache]);  
   
                         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 271  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  }  }
120    
121    
122  #define TRANSLATE_ADDRESS       translate_address_mmu3k  #define TRANSLATE_ADDRESS       translate_v2p_mmu3k
123  #define V2P_MMU3K  #define V2P_MMU3K
124  #include "memory_mips_v2p.c"  #include "memory_mips_v2p.c"
125  #undef TRANSLATE_ADDRESS  #undef TRANSLATE_ADDRESS
126  #undef V2P_MMU3K  #undef V2P_MMU3K
127    
128  #define TRANSLATE_ADDRESS       translate_address_mmu8k  #define TRANSLATE_ADDRESS       translate_v2p_mmu8k
129  #define V2P_MMU8K  #define V2P_MMU8K
130  #include "memory_mips_v2p.c"  #include "memory_mips_v2p.c"
131  #undef TRANSLATE_ADDRESS  #undef TRANSLATE_ADDRESS
132  #undef V2P_MMU8K  #undef V2P_MMU8K
133    
134  #define TRANSLATE_ADDRESS       translate_address_mmu10k  #define TRANSLATE_ADDRESS       translate_v2p_mmu10k
135  #define V2P_MMU10K  #define V2P_MMU10K
136  #include "memory_mips_v2p.c"  #include "memory_mips_v2p.c"
137  #undef TRANSLATE_ADDRESS  #undef TRANSLATE_ADDRESS
138  #undef V2P_MMU10K  #undef V2P_MMU10K
139    
140  /*  Almost generic  :-)  */  /*  Almost generic  :-)  */
141  #define TRANSLATE_ADDRESS       translate_address_mmu4100  #define TRANSLATE_ADDRESS       translate_v2p_mmu4100
142  #define V2P_MMU4100  #define V2P_MMU4100
143  #include "memory_mips_v2p.c"  #include "memory_mips_v2p.c"
144  #undef TRANSLATE_ADDRESS  #undef TRANSLATE_ADDRESS
145  #undef V2P_MMU4100  #undef V2P_MMU4100
146    
147  #define TRANSLATE_ADDRESS       translate_address_generic  #define TRANSLATE_ADDRESS       translate_v2p_generic
148  #include "memory_mips_v2p.c"  #include "memory_mips_v2p.c"
149    
150    

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

  ViewVC Help
Powered by ViewVC 1.1.26