/[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 22 by dpavlin, Mon Oct 8 16:19:37 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.2 2005/11/30 16:23:09 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.
31   */   */
# Line 35  Line 35 
35    
36    
37  /*  /*
  *  insert_into_tiny_cache():  
  *  
  *  If the tiny cache is enabled (USE_TINY_CACHE), then this routine inserts  
  *  a vaddr to paddr translation first in the instruction (or data) tiny  
  *  translation cache.  
  */  
 static void insert_into_tiny_cache(struct cpu *cpu, int instr, int writeflag,  
         uint64_t vaddr, uint64_t paddr)  
 {  
 #ifdef USE_TINY_CACHE  
         int wf = 1 + (writeflag == MEM_WRITE);  
   
         if (cpu->machine->bintrans_enable)  
                 return;  
   
         paddr &= ~0xfff;  
         vaddr >>= 12;  
   
         if (instr) {  
                 /*  Code:  */  
                 memmove(&cpu->cd.mips.translation_cache_instr[1],  
                     &cpu->cd.mips.translation_cache_instr[0],  
                     sizeof(struct translation_cache_entry) *  
                     (N_TRANSLATION_CACHE_INSTR - 1));  
   
                 cpu->cd.mips.translation_cache_instr[0].wf = wf;  
                 cpu->cd.mips.translation_cache_instr[0].vaddr_pfn = vaddr;  
                 cpu->cd.mips.translation_cache_instr[0].paddr = paddr;  
         } else {  
                 /*  Data:  */  
                 memmove(&cpu->cd.mips.translation_cache_data[1],  
                     &cpu->cd.mips.translation_cache_data[0],  
                     sizeof(struct translation_cache_entry) *  
                     (N_TRANSLATION_CACHE_DATA - 1));  
   
                 cpu->cd.mips.translation_cache_data[0].wf = wf;  
                 cpu->cd.mips.translation_cache_data[0].vaddr_pfn = vaddr;  
                 cpu->cd.mips.translation_cache_data[0].paddr = paddr;  
         }  
 #endif  
 }  
   
   
 /*  
38   *  memory_cache_R3000():   *  memory_cache_R3000():
39   *   *
40   *  R2000/R3000 specific cache handling.   *  R2000/R3000 specific cache handling.
# Line 89  static void insert_into_tiny_cache(struc Line 45  static void insert_into_tiny_cache(struc
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 105  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));  
   
 #ifdef ENABLE_INSTRUCTION_DELAYS  
         if (!hit)  
                 cpu->cd.mips.instruction_delay +=  
                     cpu->cd.mips.cpu_type.instrs_per_cycle  
                     * cpu->cd.mips.cache_miss_penalty[which_cache];  
 #endif  
   
         /*  
          *  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];  
                 }  
         }  
   
         /*  Run instructions from the right host page:  */  
         if (cache == CACHE_INSTRUCTION) {  
                 memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag);  
                 if (memblock != NULL) {  
                         cpu->cd.mips.pc_last_host_4k_page = memblock +  
                             (paddr & ((1 << BITS_PER_MEMBLOCK) - 1) & ~0xfff);  
                 }  
         }  
   
         /*  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 283  int memory_cache_R3000(struct cpu *cpu, Line 69  int memory_cache_R3000(struct cpu *cpu,
69                  & ~cpu->cd.mips.cache_mask[which_cache])                  & ~cpu->cd.mips.cache_mask[which_cache])
70              == (paddr & ~(cpu->cd.mips.cache_mask[which_cache]));              == (paddr & ~(cpu->cd.mips.cache_mask[which_cache]));
71    
 #ifdef ENABLE_INSTRUCTION_DELAYS  
         if (!hit)  
                 cpu->cd.mips.instruction_delay +=  
                     cpu->cd.mips.cpu_type.instrs_per_cycle  
                     * cpu->cd.mips.cache_miss_penalty[which_cache];  
 #endif  
   
72          /*          /*
73           *  The cache miss bit is only set on cache reads, and only to the           *  The cache miss bit is only set on cache reads, and only to the
74           *  data cache. (?)           *  data cache. (?)
# Line 314  int memory_cache_R3000(struct cpu *cpu, Line 93  int memory_cache_R3000(struct cpu *cpu,
93    
94          /*  Data cache isolated?  Then don't access main memory:  */          /*  Data cache isolated?  Then don't access main memory:  */
95          if (cache_isolated) {          if (cache_isolated) {
96                  /*  debug("ISOLATED write=%i cache=%i vaddr=%016llx "                  /*  debug("ISOLATED write=%i cache=%i vaddr=%016"PRIx64" "
97                      "paddr=%016llx => addr in cache = 0x%lx\n",                      "paddr=%016"PRIx64" => addr in cache = 0x%lx\n",
98                      writeflag, cache, (long long)vaddr,                      writeflag, cache, (uint64_t) vaddr,
99                      (long long)paddr, addr);  */                      (uint64_t) paddr, addr);  */
100    
101                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
102                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
# Line 335  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    
 #ifndef EXPERIMENTAL_NEWMIPS  
   
 #define MEMORY_RW       mips_memory_rw  
 #define MEM_MIPS  
 #include "../memory_rw.c"  
 #undef MEM_MIPS  
 #undef MEMORY_RW  
   
 #endif  

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

  ViewVC Help
Powered by ViewVC 1.1.26