/[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 2 by dpavlin, Mon Oct 8 16:17:48 2007 UTC revision 24 by dpavlin, Mon Oct 8 16:19:56 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.10 2005/03/01 08:23:55 debug Exp $   *  $Id: memory_rw.c,v 1.87 2006/06/22 11:43:03 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;
80          int bintrans_cached = cpu->machine->bintrans_enable;  
81  #endif          no_exceptions = misc_flags & NO_EXCEPTIONS;
82          no_exceptions = cache_flags & NO_EXCEPTIONS;          cache = misc_flags & CACHE_FLAGS_MASK;
         cache = cache_flags & CACHE_FLAGS_MASK;  
83    
84  #ifdef MEM_PPC  #ifdef MEM_X86
85          if (cpu->cd.ppc.bits == 32)          /*  Real-mode wrap-around:  */
86                  vaddr &= 0xffffffff;          if (REAL_MODE && !(misc_flags & PHYSICAL)) {
87  #endif                  if ((vaddr & 0xffff) + len > 0x10000) {
88                            /*  Do one byte at a time:  */
89  #ifdef MEM_URISC                          int res = 0;
90          {                          size_t i;
91                  uint64_t mask = (uint64_t) -1;                          for (i=0; i<len; i++)
92                  if (cpu->cd.urisc.wordlen < 64)                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
93                          mask = ((int64_t)1 << cpu->cd.urisc.wordlen) - 1;                                      writeflag, misc_flags);
94                  vaddr &= mask;                          return res;
95                    }
96          }          }
 #endif  
97    
98  #ifdef MEM_MIPS          /*  Crossing a page boundary? Then do one byte at a time:  */
99  #ifdef BINTRANS          if ((vaddr & 0xfff) + len > 0x1000 && !(misc_flags & PHYSICAL)
100          if (bintrans_cached) {              && cpu->cd.x86.cr[0] & X86_CR0_PG) {
101                  if (cache == CACHE_INSTRUCTION) {                  /*  For WRITES: Read ALL BYTES FIRST and write them back!!!
102                          cpu->cd.mips.pc_bintrans_host_4kpage = NULL;                      Then do a write of all the new bytes. This is to make sure
103                          cpu->cd.mips.pc_bintrans_paddr_valid = 0;                      than both pages around the boundary are writable so we don't
104                        do a partial write.  */
105                    int res = 0;
106                    size_t i;
107                    if (writeflag == MEM_WRITE) {
108                            unsigned char tmp;
109                            for (i=0; i<len; i++) {
110                                    res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
111                                        MEM_READ, misc_flags);
112                                    if (!res)
113                                            return 0;
114                                    res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
115                                        MEM_WRITE, misc_flags);
116                                    if (!res)
117                                            return 0;
118                            }
119                            for (i=0; i<len; i++) {
120                                    res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
121                                        MEM_WRITE, misc_flags);
122                                    if (!res)
123                                            return 0;
124                            }
125                    } else {
126                            for (i=0; i<len; i++) {
127                                    /*  Do one byte at a time:  */
128                                    res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
129                                        writeflag, misc_flags);
130                                    if (!res) {
131                                            if (cache == CACHE_INSTRUCTION) {
132                                                    fatal("FAILED instruction "
133                                                        "fetch across page boundar"
134                                                        "y: todo. vaddr=0x%08x\n",
135                                                        (int)vaddr);
136                                                    cpu->running = 0;
137                                            }
138                                            return 0;
139                                    }
140                            }
141                  }                  }
142                    return res;
143          }          }
144  #endif  #endif  /*  X86  */
145  #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_address == 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_address(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
161                        + (misc_flags & NO_SEGMENTATION)
162    #endif
163    #ifdef MEM_ARM
164                        + (misc_flags & MEMORY_USER_ACCESS)
165    #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
168                      some way, we simply return without doing the memory                      some way, we simply return without doing the memory
# Line 143  int MEMORY_RW(struct cpu *cpu, struct me Line 172  int MEMORY_RW(struct cpu *cpu, struct me
172          }          }
173    
174    
175  #ifdef MEM_MIPS  #ifdef MEM_X86
176          /*          /*  DOS debugging :-)  */
177           *  If correct cache emulation is enabled, and we need to simluate          if (!quiet_mode && !(misc_flags & PHYSICAL)) {
178           *  cache misses even from the instruction cache, we can't run directly                  if (paddr >= 0x400 && paddr <= 0x4ff)
179           *  from a host page. :-/                          debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==
180           */                              MEM_WRITE? "writing to" : "reading from",
181  #if defined(ENABLE_CACHE_EMULATION) && defined(ENABLE_INSTRUCTION_DELAYS)                              (int)paddr);
182  #else  #if 0
183          if (cache == CACHE_INSTRUCTION) {                  if (paddr >= 0xf0000 && paddr <= 0xfffff)
184                  cpu->cd.mips.pc_last_virtual_page = vaddr & ~0xfff;                          debug("{ BIOS ACCESS: %s 0x%x }\n",
185                  cpu->cd.mips.pc_last_physical_page = paddr & ~0xfff;                              writeflag == MEM_WRITE? "writing to" :
186                  cpu->cd.mips.pc_last_host_4k_page = NULL;                              "reading from", (int)paddr);
   
                 /*  _last_host_4k_page will be set to 1 further down,  
                     if the page is actually in host ram  */  
         }  
187  #endif  #endif
 #endif  /*  MEM_MIPS  */  
 #endif  /*  ifndef MEM_USERLAND  */  
   
   
 have_paddr:  
   
   
 #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;  
                 }  
188          }          }
189  #endif  #endif
190  #endif  /*  MEM_MIPS  */  #endif  /*  !MEM_USERLAND  */
   
   
         if (!(cache_flags & PHYSICAL))  
                 if (no_exceptions)  
                         goto no_exception_access;  
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                    int i, start, end, res;
203    
204                    /*
205                     *  Really really slow, but unfortunately necessary. This is
206                     *  to avoid the folowing scenario:
207                     *
208                     *      a) offsets 0x000..0x123 are normal memory
209                     *      b) offsets 0x124..0x777 are a device
210                     *
211                     *      1) a read is done from offset 0x100. the page is
212                     *         added to the dyntrans system as a "RAM" page
213                     *      2) a dyntranslated read is done from offset 0x200,
214                     *         which should access the device, but since the
215                     *         entire page is added, it will access non-existant
216                     *         RAM instead, without warning.
217                     *
218                     *  Setting dyntrans_device_danger = 1 on accesses which are
219                     *  on _any_ offset on pages that are device mapped avoids
220                     *  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 1
226                    for (i=0; i<mem->n_mmapped_devices; i++)
227                            if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) &&
228                                paddr <= ((mem->dev_endaddr[i]-1) | offset_mask)) {
229                                    dyntrans_device_danger = 1;
230                                    break;
231                            }
232  #endif  #endif
233                  int i, start, res;  
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 211  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                                          update_translation_table(cpu,                                                      wasn't already  */
278                                              vaddr & ~0xfff,                                                  uint64_t *pp = (uint64_t *)
279                                              mem->dev_bintrans_data[i] +                                                      mem->dev_dyntrans_data[i];
280                                              (paddr & ~0xfff),                                                  uint64_t p = orig_paddr - *pp;
281                                              wf, orig_paddr & ~0xfff);                                                  host_addr =
282                                                        memory_paddr_to_hostaddr(
283                                                        mem, p, MEM_WRITE)
284                                                        + (p & ~offset_mask
285                                                        & ((1 <<
286                                                        BITS_PER_MEMBLOCK) - 1));
287                                            } else {
288                                                    host_addr =
289                                                        mem->dev_dyntrans_data[i] +
290                                                        (paddr & ~offset_mask);
291                                            }
292                                            cpu->update_translation_table(cpu,
293                                                vaddr & ~offset_mask, host_addr,
294                                                wf, orig_paddr & ~offset_mask);
295                                  }                                  }
 #endif  
296    
297                                  res = mem->dev_f[i](cpu, mem, paddr, data, len,                                  res = 0;
298                                      writeflag, mem->dev_extra[i]);                                  if (!no_exceptions || (mem->dev_flags[i] &
299                                        DM_READS_HAVE_NO_SIDE_EFFECTS))
300                                            res = mem->dev_f[i](cpu, mem, paddr,
301                                                data, len, writeflag,
302                                                mem->dev_extra[i]);
303    
 #ifdef ENABLE_INSTRUCTION_DELAYS  
304                                  if (res == 0)                                  if (res == 0)
305                                          res = -1;                                          res = -1;
306    
307                                  cpu->cd.mips.instruction_delay +=  #ifndef MEM_X86
                                     ( (abs(res) - 1) *  
                                      cpu->cd.mips.cpu_type.instrs_per_cycle );  
 #endif  
308                                  /*                                  /*
309                                   *  If accessing the memory mapped device                                   *  If accessing the memory mapped device
310                                   *  failed, then return with a DBE exception.                                   *  failed, then return with a DBE exception.
311                                   */                                   */
312                                  if (res <= 0) {                                  if (res <= 0 && !no_exceptions) {
313                                          debug("%s device '%s' addr %08lx "                                          debug("%s device '%s' addr %08lx "
314                                              "failed\n", writeflag?                                              "failed\n", writeflag?
315                                              "writing to" : "reading from",                                              "writing to" : "reading from",
# Line 268  have_paddr: Line 320  have_paddr:
320  #endif  #endif
321                                          return MEMORY_ACCESS_FAILED;                                          return MEMORY_ACCESS_FAILED;
322                                  }                                  }
323    #endif
324                                  goto do_return_ok;                                  goto do_return_ok;
325                          }                          }
326    
327                          i ++;                          if (paddr < mem->dev_baseaddr[i])
328                          if (i == mem->n_mmapped_devices)                                  end = i - 1;
329                                  i = 0;                          if (paddr >= mem->dev_endaddr[i])
330                  } while (i != start);                                  start = i + 1;
331                            i = (start + end) >> 1;
332                    } while (start <= end);
333          }          }
334    
335    
# Line 287  have_paddr: Line 341  have_paddr:
341          switch (cpu->cd.mips.cpu_type.mmu_model) {          switch (cpu->cd.mips.cpu_type.mmu_model) {
342          case MMU3K:          case MMU3K:
343                  /*  if not uncached addess  (TODO: generalize this)  */                  /*  if not uncached addess  (TODO: generalize this)  */
344                  if (!(cache_flags & PHYSICAL) && cache != CACHE_NONE &&                  if (!(misc_flags & PHYSICAL) && cache != CACHE_NONE &&
345                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&
346                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {
347                          if (memory_cache_R3000(cpu, cache, paddr,                          if (memory_cache_R3000(cpu, cache, paddr,
# Line 295  have_paddr: Line 349  have_paddr:
349                                  goto do_return_ok;                                  goto do_return_ok;
350                  }                  }
351                  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  
352          default:          default:
353                  /*  R4000 etc  */                  /*  R4000 etc  */
354                  /*  TODO  */                  /*  TODO  */
# Line 332  have_paddr: Line 359  have_paddr:
359    
360          /*  Outside of physical RAM?  */          /*  Outside of physical RAM?  */
361          if (paddr >= mem->physical_max) {          if (paddr >= mem->physical_max) {
362                  if ((paddr & 0xffff000000ULL) == 0x1f000000) {  #ifdef MEM_MIPS
363                    if ((paddr & 0xffffc00000ULL) == 0x1fc00000) {
364                          /*  Ok, this is PROM stuff  */                          /*  Ok, this is PROM stuff  */
365                  } else if ((paddr & 0xfffff00000ULL) == 0x1ff00000) {                  } else if ((paddr & 0xfffff00000ULL) == 0x1ff00000) {
366                          /*  Sprite reads from this area of memory...  */                          /*  Sprite reads from this area of memory...  */
# Line 340  have_paddr: Line 368  have_paddr:
368                          if (writeflag == MEM_READ)                          if (writeflag == MEM_READ)
369                                  memset(data, 0, len);                                  memset(data, 0, len);
370                          goto do_return_ok;                          goto do_return_ok;
371                  } else {                  } else
372                          if (paddr >= mem->physical_max + 0 * 1024) {  #endif /* MIPS */
373                    {
374                            if (paddr >= mem->physical_max) {
375                                    uint64_t offset, old_pc = cpu->pc;
376                                  char *symbol;                                  char *symbol;
377  #ifdef MEM_MIPS  
378                                  uint64_t offset;                                  /*  This allows for example OS kernels to probe
379  #endif                                      memory a few KBs past the end of memory,
380                                  if (!quiet_mode) {                                      without giving too many warnings.  */
381                                    if (!quiet_mode && !no_exceptions && paddr >=
382                                        mem->physical_max + 0x40000) {
383                                          fatal("[ memory_rw(): writeflag=%i ",                                          fatal("[ memory_rw(): writeflag=%i ",
384                                              writeflag);                                              writeflag);
385                                          if (writeflag) {                                          if (writeflag) {
# Line 373  have_paddr: Line 406  have_paddr:
406                                                                      data[i]);                                                                      data[i]);
407                                                  debug("}");                                                  debug("}");
408                                          }                                          }
409  #ifdef MEM_MIPS  
410                                            fatal(" paddr=0x%llx >= physical_max"
411                                                "; pc=", (long long)paddr);
412                                            if (cpu->is_32bit)
413                                                    fatal("0x%08x",(int)old_pc);
414                                            else
415                                                    fatal("0x%016llx",
416                                                        (long long)old_pc);
417                                          symbol = get_symbol_name(                                          symbol = get_symbol_name(
418                                              &cpu->machine->symbol_context,                                              &cpu->machine->symbol_context,
419                                              cpu->cd.mips.pc_last, &offset);                                              old_pc, &offset);
420  #else                                          fatal(" <%s> ]\n",
421                                          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;  
422                                  }                                  }
423                          }                          }
424    
425                          if (writeflag == MEM_READ) {                          if (writeflag == MEM_READ) {
426    #ifdef MEM_X86
427                                    /*  Reading non-existant memory on x86:  */
428                                    memset(data, 0xff, len);
429    #else
430                                  /*  Return all zeroes? (Or 0xff? TODO)  */                                  /*  Return all zeroes? (Or 0xff? TODO)  */
431                                  memset(data, 0, len);                                  memset(data, 0, len);
432    #endif
433    
434  #ifdef MEM_MIPS  #ifdef MEM_MIPS
435                                  /*                                  /*
# Line 409  have_paddr: Line 437  have_paddr:
437                                   *  an exceptions on an illegal read:                                   *  an exceptions on an illegal read:
438                                   */                                   */
439                                  if (cache != CACHE_NONE && cpu->machine->                                  if (cache != CACHE_NONE && cpu->machine->
440                                      dbe_on_nonexistant_memaccess) {                                      dbe_on_nonexistant_memaccess &&
441                                        !no_exceptions) {
442                                          if (paddr >= mem->physical_max &&                                          if (paddr >= mem->physical_max &&
443                                              paddr < mem->physical_max+1048576)                                              paddr < mem->physical_max+1048576)
444                                                  mips_cpu_exception(cpu,                                                  mips_cpu_exception(cpu,
# Line 429  have_paddr: Line 458  have_paddr:
458  #endif  /*  ifndef MEM_USERLAND  */  #endif  /*  ifndef MEM_USERLAND  */
459    
460    
 no_exception_access:  
   
461          /*          /*
462           *  Uncached access:           *  Uncached access:
463             *
464             *  1)  Translate the physical address to a host address.
465             *
466             *  2)  Insert this virtual->physical->host translation into the
467             *      fast translation arrays (using update_translation_table()).
468             *
469             *  3)  If this was a Write, then invalidate any code translations
470             *      in that page.
471           */           */
472          memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag);          memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag);
473          if (memblock == NULL) {          if (memblock == NULL) {
# Line 443  no_exception_access: Line 478  no_exception_access:
478    
479          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);
480    
481  #ifdef BINTRANS          if (cpu->update_translation_table != NULL && !dyntrans_device_danger
482          if (bintrans_cached)  #ifndef MEM_MIPS
483                  update_translation_table(cpu, vaddr & ~0xfff,  /*          && !(misc_flags & MEMORY_USER_ACCESS)  */
484                      memblock + (offset & ~0xfff),  #ifndef MEM_USERLAND
485  #if 0              && !(ok & MEMORY_NOT_FULL_PAGE)
                     cache == CACHE_INSTRUCTION?  
                         (writeflag == MEM_WRITE? 1 : 0)  
                         : ok - 1,  
 #else  
                     writeflag == MEM_WRITE? 1 : 0,  
486  #endif  #endif
                     paddr & ~0xfff);  
487  #endif  #endif
488                && !no_exceptions)
489                    cpu->update_translation_table(cpu, vaddr & ~offset_mask,
490                        memblock + (offset & ~offset_mask),
491                        (misc_flags & MEMORY_USER_ACCESS) |
492    #ifndef MEM_MIPS
493                        (cache == CACHE_INSTRUCTION? TLB_CODE : 0) |
494    #endif
495    #if !defined(MEM_MIPS) && !defined(MEM_USERLAND)
496                        (cache == CACHE_INSTRUCTION?
497                            (writeflag == MEM_WRITE? 1 : 0) : ok - 1),
498    #else
499                        (writeflag == MEM_WRITE? 1 : 0),
500    #endif
501                        paddr & ~offset_mask);
502    
503            /*  Invalidate code translations for the page we are writing to.  */
504            if (writeflag == MEM_WRITE && cpu->invalidate_code_translation != NULL)
505                    cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR);
506    
507          if (writeflag == MEM_WRITE) {          if (writeflag == MEM_WRITE) {
508                  if (len == sizeof(uint32_t) && (offset & 3)==0)                  /*  Ugly optimization, but it works:  */
509                    if (len == sizeof(uint32_t) && (offset & 3)==0
510                        && ((size_t)data&3)==0)
511                          *(uint32_t *)(memblock + offset) = *(uint32_t *)data;                          *(uint32_t *)(memblock + offset) = *(uint32_t *)data;
512                  else if (len == sizeof(uint8_t))                  else if (len == sizeof(uint8_t))
513                          *(uint8_t *)(memblock + offset) = *(uint8_t *)data;                          *(uint8_t *)(memblock + offset) = *(uint8_t *)data;
514                  else                  else
515                          memcpy(memblock + offset, data, len);                          memcpy(memblock + offset, data, len);
516          } else {          } else {
517                  if (len == sizeof(uint32_t) && (offset & 3)==0)                  /*  Ugly optimization, but it works:  */
518                    if (len == sizeof(uint32_t) && (offset & 3)==0
519                        && ((size_t)data&3)==0)
520                          *(uint32_t *)data = *(uint32_t *)(memblock + offset);                          *(uint32_t *)data = *(uint32_t *)(memblock + offset);
521                  else if (len == sizeof(uint8_t))                  else if (len == sizeof(uint8_t))
522                          *(uint8_t *)data = *(uint8_t *)(memblock + offset);                          *(uint8_t *)data = *(uint8_t *)(memblock + offset);
523                  else                  else
524                          memcpy(data, memblock + offset, len);                          memcpy(data, memblock + offset, len);
   
                 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  
                 }  
525          }          }
526    
527    

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

  ViewVC Help
Powered by ViewVC 1.1.26