/[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 30 by dpavlin, Mon Oct 8 16:20:40 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_rw.c,v 1.38 2005/06/27 07:03:39 debug Exp $   *  $Id: memory_rw.c,v 1.95 2006/07/25 21:49:14 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 48  Line 48 
48   *                      a placeholder for data when reading from memory   *                      a placeholder for data when reading from memory
49   *      len             the length of the 'data' buffer   *      len             the length of the 'data' buffer
50   *      writeflag       set to MEM_READ or MEM_WRITE   *      writeflag       set to MEM_READ or MEM_WRITE
51   *      cache_flags     CACHE_{NONE,DATA,INSTRUCTION} | other flags   *      misc_flags      CACHE_{NONE,DATA,INSTRUCTION} | other flags
52   *   *
53   *  If the address indicates access to a memory mapped device, that device'   *  If the address indicates access to a memory mapped device, that device'
54   *  read/write access function is called.   *  read/write access function is called.
55   *   *
  *  If instruction latency/delay support is enabled, then  
  *  cpu->instruction_delay is increased by the number of instruction to  
  *  delay execution.  
  *  
56   *  This function should not be called with cpu == NULL.   *  This function should not be called with cpu == NULL.
57   *   *
58   *  Returns one of the following:   *  Returns one of the following:
# Line 66  Line 62 
62   *  (MEMORY_ACCESS_FAILED is 0.)   *  (MEMORY_ACCESS_FAILED is 0.)
63   */   */
64  int MEMORY_RW(struct cpu *cpu, struct memory *mem, uint64_t vaddr,  int MEMORY_RW(struct cpu *cpu, struct memory *mem, uint64_t vaddr,
65          unsigned char *data, size_t len, int writeflag, int cache_flags)          unsigned char *data, size_t len, int writeflag, int misc_flags)
66  {  {
67    #ifdef MEM_ALPHA
68            const int offset_mask = 0x1fff;
69    #else
70            const int offset_mask = 0xfff;
71    #endif
72    
73  #ifndef MEM_USERLAND  #ifndef MEM_USERLAND
74          int ok = 1;          int ok = 1;
75  #endif  #endif
76          uint64_t paddr;          uint64_t paddr;
77          int cache, no_exceptions, offset;          int cache, no_exceptions, offset;
78          unsigned char *memblock;          unsigned char *memblock;
79  #ifdef BINTRANS          int dyntrans_device_danger = 0;
         int bintrans_cached = cpu->machine->bintrans_enable;  
         int bintrans_device_danger = 0;  
 #endif  
         no_exceptions = cache_flags & NO_EXCEPTIONS;  
         cache = cache_flags & CACHE_FLAGS_MASK;  
   
 #ifdef MEM_PPC  
         if (cpu->cd.ppc.bits == 32)  
                 vaddr &= 0xffffffff;  
 #endif  
80    
81  #ifdef MEM_ARM          no_exceptions = misc_flags & NO_EXCEPTIONS;
82          vaddr &= 0x3fffffff;          cache = misc_flags & CACHE_FLAGS_MASK;
 #endif  
83    
84  #ifdef MEM_X86  #ifdef MEM_X86
85          /*  Real-mode wrap-around:  */          /*  Real-mode wrap-around:  */
86          if (REAL_MODE && !(cache_flags & PHYSICAL)) {          if (REAL_MODE && !(misc_flags & PHYSICAL)) {
87                  if ((vaddr & 0xffff) + len > 0x10000) {                  if ((vaddr & 0xffff) + len > 0x10000) {
88                          /*  Do one byte at a time:  */                          /*  Do one byte at a time:  */
89                          int res = 0, i;                          int res = 0;
90                            size_t i;
91                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
92                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
93                                      writeflag, cache_flags);                                      writeflag, misc_flags);
94                          return res;                          return res;
95                  }                  }
96          }          }
97    
98          /*  Crossing a page boundary? Then do one byte at a time:  */          /*  Crossing a page boundary? Then do one byte at a time:  */
99          if ((vaddr & 0xfff) + len > 0x1000 && !(cache_flags & PHYSICAL)          if ((vaddr & 0xfff) + len > 0x1000 && !(misc_flags & PHYSICAL)
100              && cpu->cd.x86.cr[0] & X86_CR0_PG) {              && cpu->cd.x86.cr[0] & X86_CR0_PG) {
101                  /*  For WRITES: Read ALL BYTES FIRST and write them back!!!                  /*  For WRITES: Read ALL BYTES FIRST and write them back!!!
102                      Then do a write of all the new bytes. This is to make sure                      Then do a write of all the new bytes. This is to make sure
103                      than both pages around the boundary are writable so we don't                      than both pages around the boundary are writable so we don't
104                      do a partial write.  */                      do a partial write.  */
105                  int res = 0, i;                  int res = 0;
106                    size_t i;
107                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
108                          unsigned char tmp;                          unsigned char tmp;
109                          for (i=0; i<len; i++) {                          for (i=0; i<len; i++) {
110                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
111                                      MEM_READ, cache_flags);                                      MEM_READ, misc_flags);
112                                  if (!res)                                  if (!res)
113                                          return 0;                                          return 0;
114                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
115                                      MEM_WRITE, cache_flags);                                      MEM_WRITE, misc_flags);
116                                  if (!res)                                  if (!res)
117                                          return 0;                                          return 0;
118                          }                          }
119                          for (i=0; i<len; i++) {                          for (i=0; i<len; i++) {
120                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
121                                      MEM_WRITE, cache_flags);                                      MEM_WRITE, misc_flags);
122                                  if (!res)                                  if (!res)
123                                          return 0;                                          return 0;
124                          }                          }
# Line 133  int MEMORY_RW(struct cpu *cpu, struct me Line 126  int MEMORY_RW(struct cpu *cpu, struct me
126                          for (i=0; i<len; i++) {                          for (i=0; i<len; i++) {
127                                  /*  Do one byte at a time:  */                                  /*  Do one byte at a time:  */
128                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
129                                      writeflag, cache_flags);                                      writeflag, misc_flags);
130                                  if (!res) {                                  if (!res) {
131                                          if (cache == CACHE_INSTRUCTION) {                                          if (cache == CACHE_INSTRUCTION) {
132                                                  fatal("FAILED instruction "                                                  fatal("FAILED instruction "
# Line 150  int MEMORY_RW(struct cpu *cpu, struct me Line 143  int MEMORY_RW(struct cpu *cpu, struct me
143          }          }
144  #endif  /*  X86  */  #endif  /*  X86  */
145    
 #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  
   
 #ifdef MEM_MIPS  
 #ifdef BINTRANS  
         if (bintrans_cached) {  
                 if (cache == CACHE_INSTRUCTION) {  
                         cpu->cd.mips.pc_bintrans_host_4kpage = NULL;  
                         cpu->cd.mips.pc_bintrans_paddr_valid = 0;  
                 }  
         }  
 #endif  
 #endif  /*  MEM_MIPS  */  
146    
147  #ifdef MEM_USERLAND  #ifdef MEM_USERLAND
148    #ifdef MEM_ALPHA
149            paddr = vaddr;
150    #else
151          paddr = vaddr & 0x7fffffff;          paddr = vaddr & 0x7fffffff;
         goto have_paddr;  
152  #endif  #endif
153    #else   /*  !MEM_USERLAND  */
154  #ifndef MEM_USERLAND          if (misc_flags & PHYSICAL || cpu->translate_v2p == NULL) {
 #ifdef MEM_MIPS  
         /*  
          *  For instruction fetch, are we on the same page as the last  
          *  instruction we fetched?  
          *  
          *  NOTE: There's no need to check this stuff here if this address  
          *  is known to be in host ram, as it's done at instruction fetch  
          *  time in cpu.c!  Only check if _host_4k_page == NULL.  
          */  
         if (cache == CACHE_INSTRUCTION &&  
             cpu->cd.mips.pc_last_host_4k_page == NULL &&  
             (vaddr & ~0xfff) == cpu->cd.mips.pc_last_virtual_page) {  
                 paddr = cpu->cd.mips.pc_last_physical_page | (vaddr & 0xfff);  
                 goto have_paddr;  
         }  
 #endif  /*  MEM_MIPS  */  
   
         if (cache_flags & PHYSICAL || cpu->translate_address == NULL) {  
155                  paddr = vaddr;                  paddr = vaddr;
156          } else {          } else {
157                  ok = cpu->translate_address(cpu, vaddr, &paddr,                  ok = cpu->translate_v2p(cpu, vaddr, &paddr,
158                      (writeflag? FLAG_WRITEFLAG : 0) +                      (writeflag? FLAG_WRITEFLAG : 0) +
159                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)
160  #ifdef MEM_X86  #ifdef MEM_X86
161                      + (cache_flags & NO_SEGMENTATION)                      + (misc_flags & NO_SEGMENTATION)
162    #endif
163    #ifdef MEM_ARM
164                        + (misc_flags & MEMORY_USER_ACCESS)
165  #endif  #endif
166                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));
167                  /*  If the translation caused an exception, or was invalid in                  /*  If the translation caused an exception, or was invalid in
# Line 213  int MEMORY_RW(struct cpu *cpu, struct me Line 174  int MEMORY_RW(struct cpu *cpu, struct me
174    
175  #ifdef MEM_X86  #ifdef MEM_X86
176          /*  DOS debugging :-)  */          /*  DOS debugging :-)  */
177          if (!quiet_mode && !(cache_flags & PHYSICAL)) {          if (!quiet_mode && !(misc_flags & PHYSICAL)) {
178                  if (paddr >= 0x400 && paddr <= 0x4ff)                  if (paddr >= 0x400 && paddr <= 0x4ff)
179                          debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==                          debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==
180                              MEM_WRITE? "writing to" : "reading from",                              MEM_WRITE? "writing to" : "reading from",
# Line 226  int MEMORY_RW(struct cpu *cpu, struct me Line 187  int MEMORY_RW(struct cpu *cpu, struct me
187  #endif  #endif
188          }          }
189  #endif  #endif
190    #endif  /*  !MEM_USERLAND  */
 #ifdef MEM_MIPS  
         /*  
          *  If correct cache emulation is enabled, and we need to simluate  
          *  cache misses even from the instruction cache, we can't run directly  
          *  from a host page. :-/  
          */  
 #if defined(ENABLE_CACHE_EMULATION) && defined(ENABLE_INSTRUCTION_DELAYS)  
 #else  
         if (cache == CACHE_INSTRUCTION) {  
                 cpu->cd.mips.pc_last_virtual_page = vaddr & ~0xfff;  
                 cpu->cd.mips.pc_last_physical_page = paddr & ~0xfff;  
                 cpu->cd.mips.pc_last_host_4k_page = NULL;  
   
                 /*  _last_host_4k_page will be set to 1 further down,  
                     if the page is actually in host ram  */  
         }  
 #endif  
 #endif  /*  MEM_MIPS  */  
 #endif  /*  ifndef MEM_USERLAND  */  
   
   
 #if defined(MEM_MIPS) || defined(MEM_USERLAND)  
 have_paddr:  
 #endif  
   
   
 #ifdef MEM_MIPS  
         /*  TODO: How about bintrans vs cache emulation?  */  
 #ifdef BINTRANS  
         if (bintrans_cached) {  
                 if (cache == CACHE_INSTRUCTION) {  
                         cpu->cd.mips.pc_bintrans_paddr_valid = 1;  
                         cpu->cd.mips.pc_bintrans_paddr = paddr;  
                 }  
         }  
 #endif  
 #endif  /*  MEM_MIPS  */  
   
191    
192    
193  #ifndef MEM_USERLAND  #ifndef MEM_USERLAND
194          /*          /*
195           *  Memory mapped device?           *  Memory mapped device?
196           *           *
197           *  TODO: this is utterly slow.           *  TODO: if paddr < base, but len enough, then the device should
198           *  TODO2: if paddr<base, but len enough, then we should write           *  still be written to!
          *  to a device to  
199           */           */
200          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {
 #ifdef BINTRANS  
201                  uint64_t orig_paddr = paddr;                  uint64_t orig_paddr = paddr;
202  #endif                  int i, start, end, res;
                 int i, start, res;  
203    
 #ifdef BINTRANS  
204                  /*                  /*
205                   *  Really really slow, but unfortunately necessary. This is                   *  Really really slow, but unfortunately necessary. This is
206                   *  to avoid the folowing scenario:                   *  to avoid the folowing scenario:
# Line 290  have_paddr: Line 209  have_paddr:
209                   *      b) offsets 0x124..0x777 are a device                   *      b) offsets 0x124..0x777 are a device
210                   *                   *
211                   *      1) a read is done from offset 0x100. the page is                   *      1) a read is done from offset 0x100. the page is
212                   *         added to the bintrans system as a "RAM" page                   *         added to the dyntrans system as a "RAM" page
213                   *      2) a bintranslated read is done from offset 0x200,                   *      2) a dyntranslated read is done from offset 0x200,
214                   *         which should access the device, but since the                   *         which should access the device, but since the
215                   *         entire page is added, it will access non-existant                   *         entire page is added, it will access non-existant
216                   *         RAM instead, without warning.                   *         RAM instead, without warning.
217                   *                   *
218                   *  Setting bintrans_device_danger = 1 on accesses which are                   *  Setting dyntrans_device_danger = 1 on accesses which are
219                   *  on _any_ offset on pages that are device mapped avoids                   *  on _any_ offset on pages that are device mapped avoids
220                   *  this problem, but it is probably not very fast.                   *  this problem, but it is probably not very fast.
221                     *
222                     *  TODO: Convert this into a quick (multi-level, 64-bit)
223                     *  address space lookup, to find dangerous pages.
224                   */                   */
225                  if (bintrans_cached) {  #if 1
226                          for (i=0; i<mem->n_mmapped_devices; i++)                  for (i=0; i<mem->n_mmapped_devices; i++)
227                                  if (paddr >= (mem->dev_baseaddr[i] & ~0xfff) &&                          if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) &&
228                                      paddr <= ((mem->dev_baseaddr[i] +                              paddr <= ((mem->dev_endaddr[i]-1) | offset_mask)) {
229                                      mem->dev_length[i] - 1) | 0xfff)) {                                  dyntrans_device_danger = 1;
230                                          bintrans_device_danger = 1;                                  break;
231                                          break;                          }
                                 }  
                 }  
232  #endif  #endif
233    
234                  i = start = mem->last_accessed_device;                  start = 0; end = mem->n_mmapped_devices - 1;
235                    i = mem->last_accessed_device;
236    
237                  /*  Scan through all devices:  */                  /*  Scan through all devices:  */
238                  do {                  do {
239                          if (paddr >= mem->dev_baseaddr[i] &&                          if (paddr >= mem->dev_baseaddr[i] &&
240                              paddr < mem->dev_baseaddr[i] + mem->dev_length[i]) {                              paddr < mem->dev_endaddr[i]) {
241                                  /*  Found a device, let's access it:  */                                  /*  Found a device, let's access it:  */
242                                  mem->last_accessed_device = i;                                  mem->last_accessed_device = i;
243    
# Line 324  have_paddr: Line 245  have_paddr:
245                                  if (paddr + len > mem->dev_length[i])                                  if (paddr + len > mem->dev_length[i])
246                                          len = mem->dev_length[i] - paddr;                                          len = mem->dev_length[i] - paddr;
247    
248  #ifdef BINTRANS                                  if (cpu->update_translation_table != NULL &&
249                                  if (bintrans_cached && mem->dev_flags[i] &                                      !(ok & MEMORY_NOT_FULL_PAGE) &&
250                                      MEM_BINTRANS_OK) {                                      mem->dev_flags[i] & DM_DYNTRANS_OK) {
251                                          int wf = writeflag == MEM_WRITE? 1 : 0;                                          int wf = writeflag == MEM_WRITE? 1 : 0;
252                                            unsigned char *host_addr;
253    
254                                          if (writeflag) {                                          if (!(mem->dev_flags[i] &
255                                                DM_DYNTRANS_WRITE_OK))
256                                                    wf = 0;
257    
258                                            if (writeflag && wf) {
259                                                  if (paddr < mem->                                                  if (paddr < mem->
260                                                      dev_bintrans_write_low[i])                                                      dev_dyntrans_write_low[i])
261                                                          mem->                                                          mem->
262                                                          dev_bintrans_write_low                                                          dev_dyntrans_write_low
263                                                              [i] =                                                              [i] = paddr &
264                                                              paddr & ~0xfff;                                                              ~offset_mask;
265                                                  if (paddr > mem->                                                  if (paddr >= mem->
266                                                      dev_bintrans_write_high[i])                                                      dev_dyntrans_write_high[i])
267                                                          mem->                                                          mem->
268                                                          dev_bintrans_write_high                                                          dev_dyntrans_write_high
269                                                              [i] = paddr | 0xfff;                                                              [i] = paddr |
270                                                                offset_mask;
271                                          }                                          }
272    
273                                          if (!(mem->dev_flags[i] &                                          if (mem->dev_flags[i] &
274                                              MEM_BINTRANS_WRITE_OK))                                              DM_EMULATED_RAM) {
275                                                  wf = 0;                                                  /*  MEM_WRITE to force the page
276                                                        to be allocated, if it
277                                                        wasn't already  */
278                                                    uint64_t *pp = (uint64_t *)
279                                                        mem->dev_dyntrans_data[i];
280                                                    uint64_t p = orig_paddr - *pp;
281                                                    host_addr =
282                                                        memory_paddr_to_hostaddr(
283                                                        mem, p & ~offset_mask,
284                                                        MEM_WRITE);
285                                            } else {
286                                                    host_addr =
287                                                        mem->dev_dyntrans_data[i] +
288                                                        (paddr & ~offset_mask);
289                                            }
290    
291                                          update_translation_table(cpu,                                          cpu->update_translation_table(cpu,
292                                              vaddr & ~0xfff,                                              vaddr & ~offset_mask, host_addr,
293                                              mem->dev_bintrans_data[i] +                                              wf, orig_paddr & ~offset_mask);
                                             (paddr & ~0xfff),  
                                             wf, orig_paddr & ~0xfff);  
294                                  }                                  }
 #endif  
295    
296                                  res = 0;                                  res = 0;
297                                  if (!no_exceptions || (mem->dev_flags[i] &                                  if (!no_exceptions || (mem->dev_flags[i] &
298                                      MEM_READING_HAS_NO_SIDE_EFFECTS))                                      DM_READS_HAVE_NO_SIDE_EFFECTS))
299                                          res = mem->dev_f[i](cpu, mem, paddr,                                          res = mem->dev_f[i](cpu, mem, paddr,
300                                              data, len, writeflag,                                              data, len, writeflag,
301                                              mem->dev_extra[i]);                                              mem->dev_extra[i]);
302    
 #ifdef ENABLE_INSTRUCTION_DELAYS  
303                                  if (res == 0)                                  if (res == 0)
304                                          res = -1;                                          res = -1;
305    
                                 cpu->cd.mips.instruction_delay +=  
                                     ( (abs(res) - 1) *  
                                      cpu->cd.mips.cpu_type.instrs_per_cycle );  
 #endif  
   
306  #ifndef MEM_X86  #ifndef MEM_X86
307                                  /*                                  /*
308                                   *  If accessing the memory mapped device                                   *  If accessing the memory mapped device
# Line 391  have_paddr: Line 323  have_paddr:
323                                  goto do_return_ok;                                  goto do_return_ok;
324                          }                          }
325    
326                          i ++;                          if (paddr < mem->dev_baseaddr[i])
327                          if (i == mem->n_mmapped_devices)                                  end = i - 1;
328                                  i = 0;                          if (paddr >= mem->dev_endaddr[i])
329                  } while (i != start);                                  start = i + 1;
330                            i = (start + end) >> 1;
331                    } while (start <= end);
332          }          }
333    
334    
# Line 406  have_paddr: Line 340  have_paddr:
340          switch (cpu->cd.mips.cpu_type.mmu_model) {          switch (cpu->cd.mips.cpu_type.mmu_model) {
341          case MMU3K:          case MMU3K:
342                  /*  if not uncached addess  (TODO: generalize this)  */                  /*  if not uncached addess  (TODO: generalize this)  */
343                  if (!(cache_flags & PHYSICAL) && cache != CACHE_NONE &&                  if (!(misc_flags & PHYSICAL) && cache != CACHE_NONE &&
344                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&
345                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {
346                          if (memory_cache_R3000(cpu, cache, paddr,                          if (memory_cache_R3000(cpu, cache, paddr,
# Line 414  have_paddr: Line 348  have_paddr:
348                                  goto do_return_ok;                                  goto do_return_ok;
349                  }                  }
350                  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  
351          default:          default:
352                  /*  R4000 etc  */                  /*  R4000 etc  */
353                  /*  TODO  */                  /*  TODO  */
# Line 464  have_paddr: Line 371  have_paddr:
371  #endif /* MIPS */  #endif /* MIPS */
372                  {                  {
373                          if (paddr >= mem->physical_max) {                          if (paddr >= mem->physical_max) {
374                                    uint64_t offset, old_pc = cpu->pc;
375                                  char *symbol;                                  char *symbol;
376  #ifdef MEM_MIPS  
                                 uint64_t offset;  
 #endif  
377                                  /*  This allows for example OS kernels to probe                                  /*  This allows for example OS kernels to probe
378                                      memory a few KBs past the end of memory,                                      memory a few KBs past the end of memory,
379                                      without giving too many warnings.  */                                      without giving too many warnings.  */
380                                  if (!quiet_mode && paddr >=                                  if (!quiet_mode && !no_exceptions && paddr >=
381                                      mem->physical_max + 0x40000) {                                      mem->physical_max + 0x40000) {
382                                          fatal("[ memory_rw(): writeflag=%i ",                                          fatal("[ memory_rw(): writeflag=%i ",
383                                              writeflag);                                              writeflag);
# Line 499  have_paddr: Line 405  have_paddr:
405                                                                      data[i]);                                                                      data[i]);
406                                                  debug("}");                                                  debug("}");
407                                          }                                          }
408  #ifdef MEM_MIPS  
409                                            fatal(" paddr=0x%llx >= physical_max"
410                                                "; pc=", (long long)paddr);
411                                            if (cpu->is_32bit)
412                                                    fatal("0x%08x",(int)old_pc);
413                                            else
414                                                    fatal("0x%016llx",
415                                                        (long long)old_pc);
416                                          symbol = get_symbol_name(                                          symbol = get_symbol_name(
417                                              &cpu->machine->symbol_context,                                              &cpu->machine->symbol_context,
418                                              cpu->cd.mips.pc_last, &offset);                                              old_pc, &offset);
419  #else                                          fatal(" <%s> ]\n",
420                                          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");  
                                 }  
   
                                 if (cpu->machine->single_step_on_bad_addr) {  
                                         fatal("[ unimplemented access to "  
                                             "0x%016llx, pc = 0x%016llx ]\n",  
                                             (long long)paddr,  
                                             (long long)cpu->pc);  
                                         single_step = 1;  
421                                  }                                  }
422                          }                          }
423    
# Line 563  have_paddr: Line 459  have_paddr:
459    
460          /*          /*
461           *  Uncached access:           *  Uncached access:
462             *
463             *  1)  Translate the physical address to a host address.
464             *
465             *  2)  Insert this virtual->physical->host translation into the
466             *      fast translation arrays (using update_translation_table()).
467             *
468             *  3)  If this was a Write, then invalidate any code translations
469             *      in that page.
470           */           */
471          memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag);          memblock = memory_paddr_to_hostaddr(mem, paddr & ~offset_mask,
472                writeflag);
473          if (memblock == NULL) {          if (memblock == NULL) {
474                  if (writeflag == MEM_READ)                  if (writeflag == MEM_READ)
475                          memset(data, 0, len);                          memset(data, 0, len);
476                  goto do_return_ok;                  goto do_return_ok;
477          }          }
478    
479          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);          offset = paddr & offset_mask;
480    
481  #ifdef BINTRANS          if (cpu->update_translation_table != NULL && !dyntrans_device_danger
482          if (bintrans_cached && !bintrans_device_danger)  #ifdef MEM_MIPS
483                  update_translation_table(cpu, vaddr & ~0xfff,              /*  Ugly hack for R2000/R3000 caches:  */
484                      memblock + (offset & ~0xfff),              && (cpu->cd.mips.cpu_type.mmu_model != MMU3K ||
485  #if 0              !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS1_ISOL_CACHES))
                     cache == CACHE_INSTRUCTION?  
                         (writeflag == MEM_WRITE? 1 : 0)  
                         : ok - 1,  
 #else  
                     writeflag == MEM_WRITE? 1 : 0,  
486  #endif  #endif
487                      paddr & ~0xfff);  #ifndef MEM_MIPS
488    /*          && !(misc_flags & MEMORY_USER_ACCESS)  */
489    #ifndef MEM_USERLAND
490                && !(ok & MEMORY_NOT_FULL_PAGE)
491    #endif
492    #endif
493                && !no_exceptions)
494                    cpu->update_translation_table(cpu, vaddr & ~offset_mask,
495                        memblock, (misc_flags & MEMORY_USER_ACCESS) |
496    #if !defined(MEM_MIPS) && !defined(MEM_USERLAND)
497                        (cache == CACHE_INSTRUCTION?
498                            (writeflag == MEM_WRITE? 1 : 0) : ok - 1),
499    #else
500                        (writeflag == MEM_WRITE? 1 : 0),
501  #endif  #endif
502                        paddr & ~offset_mask);
503    
504            /*  Invalidate code translations for the page we are writing to.  */
505            if (writeflag == MEM_WRITE && cpu->invalidate_code_translation != NULL)
506                    cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR);
507    
508            if ((paddr&((1<<BITS_PER_MEMBLOCK)-1)) + len > (1<<BITS_PER_MEMBLOCK)) {
509                    printf("Write over memblock boundary?\n");
510                    exit(1);
511            }
512    
513          if (writeflag == MEM_WRITE) {          if (writeflag == MEM_WRITE) {
514                  if (len == sizeof(uint32_t) && (offset & 3)==0)                  /*  Ugly optimization, but it works:  */
515                    if (len == sizeof(uint32_t) && (offset & 3)==0
516                        && ((size_t)data&3)==0)
517                          *(uint32_t *)(memblock + offset) = *(uint32_t *)data;                          *(uint32_t *)(memblock + offset) = *(uint32_t *)data;
518                  else if (len == sizeof(uint8_t))                  else if (len == sizeof(uint8_t))
519                          *(uint8_t *)(memblock + offset) = *(uint8_t *)data;                          *(uint8_t *)(memblock + offset) = *(uint8_t *)data;
520                  else                  else
521                          memcpy(memblock + offset, data, len);                          memcpy(memblock + offset, data, len);
522          } else {          } else {
523                  if (len == sizeof(uint32_t) && (offset & 3)==0)                  /*  Ugly optimization, but it works:  */
524                    if (len == sizeof(uint32_t) && (offset & 3)==0
525                        && ((size_t)data&3)==0)
526                          *(uint32_t *)data = *(uint32_t *)(memblock + offset);                          *(uint32_t *)data = *(uint32_t *)(memblock + offset);
527                  else if (len == sizeof(uint8_t))                  else if (len == sizeof(uint8_t))
528                          *(uint8_t *)data = *(uint8_t *)(memblock + offset);                          *(uint8_t *)data = *(uint8_t *)(memblock + offset);
529                  else                  else
530                          memcpy(data, memblock + offset, len);                          memcpy(data, memblock + offset, len);
   
 #ifdef MEM_MIPS  
                 if (cache == CACHE_INSTRUCTION) {  
                         cpu->cd.mips.pc_last_host_4k_page = memblock  
                             + (offset & ~0xfff);  
 #ifdef BINTRANS  
                         if (bintrans_cached) {  
                                 cpu->cd.mips.pc_bintrans_host_4kpage =  
                                     cpu->cd.mips.pc_last_host_4k_page;  
                         }  
 #endif  
                 }  
 #endif  /*  MIPS  */  
531          }          }
532    
533    

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

  ViewVC Help
Powered by ViewVC 1.1.26