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

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

revision 10 by dpavlin, Mon Oct 8 16:18:27 2007 UTC revision 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: memory_rw.c,v 1.38 2005/06/27 07:03:39 debug Exp $   *  $Id: memory_rw.c,v 1.64 2005/09/22 09:06:59 debug Exp $
29   *   *
30   *  Generic memory_rw(), with special hacks for specific CPU families.   *  Generic memory_rw(), with special hacks for specific CPU families.
31   *   *
# Line 68  Line 68 
68  int MEMORY_RW(struct cpu *cpu, struct memory *mem, uint64_t vaddr,  int MEMORY_RW(struct cpu *cpu, struct memory *mem, uint64_t vaddr,
69          unsigned char *data, size_t len, int writeflag, int cache_flags)          unsigned char *data, size_t len, int writeflag, int cache_flags)
70  {  {
71    #ifdef MEM_ALPHA
72            const int offset_mask = 0x1fff;
73    #else
74            const int offset_mask = 0xfff;
75    #endif
76    
77  #ifndef MEM_USERLAND  #ifndef MEM_USERLAND
78          int ok = 1;          int ok = 1;
79  #endif  #endif
80          uint64_t paddr;          uint64_t paddr;
81          int cache, no_exceptions, offset;          int cache, no_exceptions, offset;
82          unsigned char *memblock;          unsigned char *memblock;
83  #ifdef BINTRANS  #ifdef MEM_MIPS
84          int bintrans_cached = cpu->machine->bintrans_enable;          int bintrans_cached = cpu->machine->bintrans_enable;
         int bintrans_device_danger = 0;  
85  #endif  #endif
86            int bintrans_device_danger = 0;
87    
88          no_exceptions = cache_flags & NO_EXCEPTIONS;          no_exceptions = cache_flags & NO_EXCEPTIONS;
89          cache = cache_flags & CACHE_FLAGS_MASK;          cache = cache_flags & CACHE_FLAGS_MASK;
90    
 #ifdef MEM_PPC  
         if (cpu->cd.ppc.bits == 32)  
                 vaddr &= 0xffffffff;  
 #endif  
   
 #ifdef MEM_ARM  
         vaddr &= 0x3fffffff;  
 #endif  
   
91  #ifdef MEM_X86  #ifdef MEM_X86
92          /*  Real-mode wrap-around:  */          /*  Real-mode wrap-around:  */
93          if (REAL_MODE && !(cache_flags & PHYSICAL)) {          if (REAL_MODE && !(cache_flags & PHYSICAL)) {
# Line 150  int MEMORY_RW(struct cpu *cpu, struct me Line 148  int MEMORY_RW(struct cpu *cpu, struct me
148          }          }
149  #endif  /*  X86  */  #endif  /*  X86  */
150    
 #ifdef MEM_URISC  
         {  
                 uint64_t mask = (uint64_t) -1;  
                 if (cpu->cd.urisc.wordlen < 64)  
                         mask = ((int64_t)1 << cpu->cd.urisc.wordlen) - 1;  
                 vaddr &= mask;  
         }  
 #endif  
   
151  #ifdef MEM_MIPS  #ifdef MEM_MIPS
 #ifdef BINTRANS  
152          if (bintrans_cached) {          if (bintrans_cached) {
153                  if (cache == CACHE_INSTRUCTION) {                  if (cache == CACHE_INSTRUCTION) {
154                          cpu->cd.mips.pc_bintrans_host_4kpage = NULL;                          cpu->cd.mips.pc_bintrans_host_4kpage = NULL;
155                          cpu->cd.mips.pc_bintrans_paddr_valid = 0;                          cpu->cd.mips.pc_bintrans_paddr_valid = 0;
156                  }                  }
157          }          }
 #endif  
158  #endif  /*  MEM_MIPS  */  #endif  /*  MEM_MIPS  */
159    
160  #ifdef MEM_USERLAND  #ifdef MEM_USERLAND
161    #ifdef MEM_ALPHA
162            paddr = vaddr;
163    #else
164          paddr = vaddr & 0x7fffffff;          paddr = vaddr & 0x7fffffff;
165    #endif
166          goto have_paddr;          goto have_paddr;
167  #endif  #endif
168    
# Line 195  int MEMORY_RW(struct cpu *cpu, struct me Line 186  int MEMORY_RW(struct cpu *cpu, struct me
186    
187          if (cache_flags & PHYSICAL || cpu->translate_address == NULL) {          if (cache_flags & PHYSICAL || cpu->translate_address == NULL) {
188                  paddr = vaddr;                  paddr = vaddr;
189    
190    #ifdef MEM_ALPHA
191                    /*  paddr &= 0x1fffffff;  For testalpha  */
192                    paddr &= 0x000003ffffffffffULL;
193    #endif
194    
195    #ifdef MEM_IA64
196                    /*  For testia64  */
197                    paddr &= 0x3fffffff;
198    #endif
199    
200    #ifdef MEM_PPC
201                    if (cpu->cd.ppc.bits == 32)
202                            paddr &= 0xffffffff;
203    #endif
204    
205    #ifdef MEM_SH
206                    paddr &= 0xffffffff;
207    #endif
208          } else {          } else {
209                  ok = cpu->translate_address(cpu, vaddr, &paddr,                  ok = cpu->translate_address(cpu, vaddr, &paddr,
210                      (writeflag? FLAG_WRITEFLAG : 0) +                      (writeflag? FLAG_WRITEFLAG : 0) +
# Line 202  int MEMORY_RW(struct cpu *cpu, struct me Line 212  int MEMORY_RW(struct cpu *cpu, struct me
212  #ifdef MEM_X86  #ifdef MEM_X86
213                      + (cache_flags & NO_SEGMENTATION)                      + (cache_flags & NO_SEGMENTATION)
214  #endif  #endif
215    #ifdef MEM_ARM
216                        + (cache_flags & MEMORY_USER_ACCESS)
217    #endif
218                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));
219                  /*  If the translation caused an exception, or was invalid in                  /*  If the translation caused an exception, or was invalid in
220                      some way, we simply return without doing the memory                      some way, we simply return without doing the memory
# Line 255  have_paddr: Line 268  have_paddr:
268    
269  #ifdef MEM_MIPS  #ifdef MEM_MIPS
270          /*  TODO: How about bintrans vs cache emulation?  */          /*  TODO: How about bintrans vs cache emulation?  */
 #ifdef BINTRANS  
271          if (bintrans_cached) {          if (bintrans_cached) {
272                  if (cache == CACHE_INSTRUCTION) {                  if (cache == CACHE_INSTRUCTION) {
273                          cpu->cd.mips.pc_bintrans_paddr_valid = 1;                          cpu->cd.mips.pc_bintrans_paddr_valid = 1;
274                          cpu->cd.mips.pc_bintrans_paddr = paddr;                          cpu->cd.mips.pc_bintrans_paddr = paddr;
275                  }                  }
276          }          }
 #endif  
277  #endif  /*  MEM_MIPS  */  #endif  /*  MEM_MIPS  */
278    
279    
# Line 276  have_paddr: Line 287  have_paddr:
287           *  to a device to           *  to a device to
288           */           */
289          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {
 #ifdef BINTRANS  
290                  uint64_t orig_paddr = paddr;                  uint64_t orig_paddr = paddr;
 #endif  
291                  int i, start, res;                  int i, start, res;
292    
 #ifdef BINTRANS  
293                  /*                  /*
294                   *  Really really slow, but unfortunately necessary. This is                   *  Really really slow, but unfortunately necessary. This is
295                   *  to avoid the folowing scenario:                   *  to avoid the folowing scenario:
# Line 300  have_paddr: Line 308  have_paddr:
308                   *  on _any_ offset on pages that are device mapped avoids                   *  on _any_ offset on pages that are device mapped avoids
309                   *  this problem, but it is probably not very fast.                   *  this problem, but it is probably not very fast.
310                   */                   */
311                  if (bintrans_cached) {                  for (i=0; i<mem->n_mmapped_devices; i++)
312                          for (i=0; i<mem->n_mmapped_devices; i++)                          if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) &&
313                                  if (paddr >= (mem->dev_baseaddr[i] & ~0xfff) &&                              paddr <= ((mem->dev_baseaddr[i] +
314                                      paddr <= ((mem->dev_baseaddr[i] +                              mem->dev_length[i] - 1) | offset_mask)) {
315                                      mem->dev_length[i] - 1) | 0xfff)) {                                  bintrans_device_danger = 1;
316                                          bintrans_device_danger = 1;                                  break;
317                                          break;                          }
                                 }  
                 }  
 #endif  
318    
319                  i = start = mem->last_accessed_device;                  i = start = mem->last_accessed_device;
320    
# Line 324  have_paddr: Line 329  have_paddr:
329                                  if (paddr + len > mem->dev_length[i])                                  if (paddr + len > mem->dev_length[i])
330                                          len = mem->dev_length[i] - paddr;                                          len = mem->dev_length[i] - paddr;
331    
332  #ifdef BINTRANS                                  if (cpu->update_translation_table != NULL &&
333                                  if (bintrans_cached && mem->dev_flags[i] &                                      mem->dev_flags[i] & MEM_DYNTRANS_OK) {
                                     MEM_BINTRANS_OK) {  
334                                          int wf = writeflag == MEM_WRITE? 1 : 0;                                          int wf = writeflag == MEM_WRITE? 1 : 0;
335    
336                                          if (writeflag) {                                          if (writeflag) {
337                                                  if (paddr < mem->                                                  if (paddr < mem->
338                                                      dev_bintrans_write_low[i])                                                      dev_dyntrans_write_low[i])
339                                                          mem->                                                          mem->
340                                                          dev_bintrans_write_low                                                          dev_dyntrans_write_low
341                                                              [i] =                                                              [i] = paddr &
342                                                              paddr & ~0xfff;                                                              ~offset_mask;
343                                                  if (paddr > mem->                                                  if (paddr >= mem->
344                                                      dev_bintrans_write_high[i])                                                      dev_dyntrans_write_high[i])
345                                                          mem->                                                          mem->
346                                                          dev_bintrans_write_high                                                          dev_dyntrans_write_high
347                                                              [i] = paddr | 0xfff;                                                              [i] = paddr |
348                                                                offset_mask;
349                                          }                                          }
350    
351                                          if (!(mem->dev_flags[i] &                                          if (!(mem->dev_flags[i] &
352                                              MEM_BINTRANS_WRITE_OK))                                              MEM_DYNTRANS_WRITE_OK))
353                                                  wf = 0;                                                  wf = 0;
354    
355                                          update_translation_table(cpu,                                          cpu->update_translation_table(cpu,
356                                              vaddr & ~0xfff,                                              vaddr & ~offset_mask,
357                                              mem->dev_bintrans_data[i] +                                              mem->dev_dyntrans_data[i] +
358                                              (paddr & ~0xfff),                                              (paddr & ~offset_mask),
359                                              wf, orig_paddr & ~0xfff);                                              wf, orig_paddr & ~offset_mask);
360                                  }                                  }
 #endif  
361    
362                                  res = 0;                                  res = 0;
363                                  if (!no_exceptions || (mem->dev_flags[i] &                                  if (!no_exceptions || (mem->dev_flags[i] &
# Line 414  have_paddr: Line 418  have_paddr:
418                                  goto do_return_ok;                                  goto do_return_ok;
419                  }                  }
420                  break;                  break;
 #if 0  
 /*  Remove this, it doesn't work anyway  */  
         case MMU10K:  
                 /*  other cpus:  */  
                 /*  
                  *  SUPER-UGLY HACK for SGI-IP32 PROM, R10000:  
                  *  K0 bits == 0x3 means uncached...  
                  *  
                  *  It seems that during bootup, the SGI-IP32 prom  
                  *  stores a return pointers a 0x80000f10, then tests  
                  *  memory by writing bit patterns to 0xa0000xxx, and  
                  *  then when it's done, reads back the return pointer  
                  *  from 0x80000f10.  
                  *  
                  *  I need to find the correct way to disconnect the  
                  *  cache from the main memory for R10000.  (TODO !!!)  
                  */  
 /*              if ((cpu->cd.mips.coproc[0]->reg[COP0_CONFIG] & 7) == 3) {  */  
 /*  
                 if (cache == CACHE_DATA &&  
                     cpu->r10k_cache_disable_TODO) {  
                         paddr &= ((512*1024)-1);  
                         paddr += 512*1024;  
                 }  
 */  
                 break;  
 #endif  
421          default:          default:
422                  /*  R4000 etc  */                  /*  R4000 etc  */
423                  /*  TODO  */                  /*  TODO  */
# Line 465  have_paddr: Line 442  have_paddr:
442                  {                  {
443                          if (paddr >= mem->physical_max) {                          if (paddr >= mem->physical_max) {
444                                  char *symbol;                                  char *symbol;
445  #ifdef MEM_MIPS                                  uint64_t old_pc;
446                                  uint64_t offset;                                  uint64_t offset;
447    
448    #ifdef MEM_MIPS
449                                    old_pc = cpu->cd.mips.pc_last;
450    #else
451                                    /*  Default instruction size on most
452                                        RISC archs is 32 bits:  */
453                                    old_pc = cpu->pc - sizeof(uint32_t);
454  #endif  #endif
455    
456                                  /*  This allows for example OS kernels to probe                                  /*  This allows for example OS kernels to probe
457                                      memory a few KBs past the end of memory,                                      memory a few KBs past the end of memory,
458                                      without giving too many warnings.  */                                      without giving too many warnings.  */
459                                  if (!quiet_mode && paddr >=                                  if (!quiet_mode && !no_exceptions && paddr >=
460                                      mem->physical_max + 0x40000) {                                      mem->physical_max + 0x40000) {
461                                          fatal("[ memory_rw(): writeflag=%i ",                                          fatal("[ memory_rw(): writeflag=%i ",
462                                              writeflag);                                              writeflag);
# Line 499  have_paddr: Line 484  have_paddr:
484                                                                      data[i]);                                                                      data[i]);
485                                                  debug("}");                                                  debug("}");
486                                          }                                          }
487  #ifdef MEM_MIPS  
488                                            fatal(" paddr=0x%llx >= physical_max"
489                                                "; pc=", (long long)paddr);
490                                            if (cpu->is_32bit)
491                                                    fatal("0x%08x",(int)old_pc);
492                                            else
493                                                    fatal("0x%016llx",
494                                                        (long long)old_pc);
495                                          symbol = get_symbol_name(                                          symbol = get_symbol_name(
496                                              &cpu->machine->symbol_context,                                              &cpu->machine->symbol_context,
497                                              cpu->cd.mips.pc_last, &offset);                                              old_pc, &offset);
498  #else                                          fatal(" <%s> ]\n",
499                                          symbol = "(unimpl for non-MIPS)";                                              symbol? symbol : " no symbol ");
 #endif  
   
 /*  TODO: fix! not mips.pc_last for for example ppc  */  
   
                                         fatal(" paddr=%llx >= physical_max pc="  
                                             "0x%08llx <%s> ]\n",  
                                             (long long)paddr,  
                                             (long long)cpu->cd.mips.pc_last,  
                                             symbol? symbol : "no symbol");  
500                                  }                                  }
501    
502                                  if (cpu->machine->single_step_on_bad_addr) {                                  if (cpu->machine->single_step_on_bad_addr) {
503                                          fatal("[ unimplemented access to "                                          fatal("[ unimplemented access to "
504                                              "0x%016llx, pc = 0x%016llx ]\n",                                              "0x%llx, pc=0x",(long long)paddr);
505                                              (long long)paddr,                                          if (cpu->is_32bit)
506                                              (long long)cpu->pc);                                                  fatal("%08x ]\n",
507                                                        (int)old_pc);
508                                            else
509                                                    fatal("%016llx ]\n",
510                                                        (long long)old_pc);
511                                          single_step = 1;                                          single_step = 1;
512                                  }                                  }
513                          }                          }
# Line 573  have_paddr: Line 560  have_paddr:
560    
561          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);
562    
563  #ifdef BINTRANS          if (cpu->update_translation_table != NULL && !bintrans_device_danger)
564          if (bintrans_cached && !bintrans_device_danger)                  cpu->update_translation_table(cpu, vaddr & ~offset_mask,
565                  update_translation_table(cpu, vaddr & ~0xfff,                      memblock + (offset & ~offset_mask),
                     memblock + (offset & ~0xfff),  
566  #if 0  #if 0
567                      cache == CACHE_INSTRUCTION?                      cache == CACHE_INSTRUCTION?
568                          (writeflag == MEM_WRITE? 1 : 0)                          (writeflag == MEM_WRITE? 1 : 0)
# Line 584  have_paddr: Line 570  have_paddr:
570  #else  #else
571                      writeflag == MEM_WRITE? 1 : 0,                      writeflag == MEM_WRITE? 1 : 0,
572  #endif  #endif
573                      paddr & ~0xfff);                      paddr & ~offset_mask);
574  #endif  
575            if (writeflag == MEM_WRITE &&
576                cpu->invalidate_code_translation != NULL)
577                    cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR);
578    
579          if (writeflag == MEM_WRITE) {          if (writeflag == MEM_WRITE) {
580                  if (len == sizeof(uint32_t) && (offset & 3)==0)                  /*  Ugly optimization, but it works:  */
581                    if (len == sizeof(uint32_t) && (offset & 3)==0
582                        && ((size_t)data&3)==0)
583                          *(uint32_t *)(memblock + offset) = *(uint32_t *)data;                          *(uint32_t *)(memblock + offset) = *(uint32_t *)data;
584                  else if (len == sizeof(uint8_t))                  else if (len == sizeof(uint8_t))
585                          *(uint8_t *)(memblock + offset) = *(uint8_t *)data;                          *(uint8_t *)(memblock + offset) = *(uint8_t *)data;
586                  else                  else
587                          memcpy(memblock + offset, data, len);                          memcpy(memblock + offset, data, len);
588          } else {          } else {
589                  if (len == sizeof(uint32_t) && (offset & 3)==0)                  /*  Ugly optimization, but it works:  */
590                    if (len == sizeof(uint32_t) && (offset & 3)==0
591                        && ((size_t)data&3)==0)
592                          *(uint32_t *)data = *(uint32_t *)(memblock + offset);                          *(uint32_t *)data = *(uint32_t *)(memblock + offset);
593                  else if (len == sizeof(uint8_t))                  else if (len == sizeof(uint8_t))
594                          *(uint8_t *)data = *(uint8_t *)(memblock + offset);                          *(uint8_t *)data = *(uint8_t *)(memblock + offset);
# Line 605  have_paddr: Line 598  have_paddr:
598  #ifdef MEM_MIPS  #ifdef MEM_MIPS
599                  if (cache == CACHE_INSTRUCTION) {                  if (cache == CACHE_INSTRUCTION) {
600                          cpu->cd.mips.pc_last_host_4k_page = memblock                          cpu->cd.mips.pc_last_host_4k_page = memblock
601                              + (offset & ~0xfff);                              + (offset & ~offset_mask);
 #ifdef BINTRANS  
602                          if (bintrans_cached) {                          if (bintrans_cached) {
603                                  cpu->cd.mips.pc_bintrans_host_4kpage =                                  cpu->cd.mips.pc_bintrans_host_4kpage =
604                                      cpu->cd.mips.pc_last_host_4k_page;                                      cpu->cd.mips.pc_last_host_4k_page;
605                          }                          }
 #endif  
606                  }                  }
607  #endif  /*  MIPS  */  #endif  /*  MIPS  */
608          }          }

Legend:
Removed from v.10  
changed lines
  Added in v.14

  ViewVC Help
Powered by ViewVC 1.1.26