/[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 6 by dpavlin, Mon Oct 8 16:18:11 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 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.37 2005/06/02 12:31:39 debug Exp $   *  $Id: memory_rw.c,v 1.82 2005/12/31 15:48:32 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.
# Line 66  Line 66 
66   *  (MEMORY_ACCESS_FAILED is 0.)   *  (MEMORY_ACCESS_FAILED is 0.)
67   */   */
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 misc_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          no_exceptions = cache_flags & NO_EXCEPTIONS;          int dyntrans_device_danger = 0;
         cache = cache_flags & CACHE_FLAGS_MASK;  
87    
88  #ifdef MEM_PPC          no_exceptions = misc_flags & NO_EXCEPTIONS;
89          if (cpu->cd.ppc.bits == 32)          cache = misc_flags & CACHE_FLAGS_MASK;
                 vaddr &= 0xffffffff;  
 #endif  
   
 #ifdef MEM_ARM  
         vaddr &= 0x0fffffff;  
 #endif  
90    
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 && !(misc_flags & PHYSICAL)) {
94                  if ((vaddr & 0xffff) + len > 0x10000) {                  if ((vaddr & 0xffff) + len > 0x10000) {
95                          /*  Do one byte at a time:  */                          /*  Do one byte at a time:  */
96                          int res = 0, i;                          int res = 0;
97                            size_t i;
98                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
99                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
100                                      writeflag, cache_flags);                                      writeflag, misc_flags);
101                          return res;                          return res;
102                  }                  }
103          }          }
104    
105          /*  Crossing a page boundary? Then do one byte at a time:  */          /*  Crossing a page boundary? Then do one byte at a time:  */
106          if ((vaddr & 0xfff) + len > 0x1000 && !(cache_flags & PHYSICAL)          if ((vaddr & 0xfff) + len > 0x1000 && !(misc_flags & PHYSICAL)
107              && cpu->cd.x86.cr[0] & X86_CR0_PG) {              && cpu->cd.x86.cr[0] & X86_CR0_PG) {
108                  /*  For WRITES: Read ALL BYTES FIRST and write them back!!!                  /*  For WRITES: Read ALL BYTES FIRST and write them back!!!
109                      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
110                      than both pages around the boundary are writable so we don't                      than both pages around the boundary are writable so we don't
111                      do a partial write.  */                      do a partial write.  */
112                  int res = 0, i;                  int res = 0;
113                    size_t i;
114                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
115                          unsigned char tmp;                          unsigned char tmp;
116                          for (i=0; i<len; i++) {                          for (i=0; i<len; i++) {
117                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
118                                      MEM_READ, cache_flags);                                      MEM_READ, misc_flags);
119                                  if (!res)                                  if (!res)
120                                          return 0;                                          return 0;
121                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
122                                      MEM_WRITE, cache_flags);                                      MEM_WRITE, misc_flags);
123                                  if (!res)                                  if (!res)
124                                          return 0;                                          return 0;
125                          }                          }
126                          for (i=0; i<len; i++) {                          for (i=0; i<len; i++) {
127                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
128                                      MEM_WRITE, cache_flags);                                      MEM_WRITE, misc_flags);
129                                  if (!res)                                  if (!res)
130                                          return 0;                                          return 0;
131                          }                          }
# Line 133  int MEMORY_RW(struct cpu *cpu, struct me Line 133  int MEMORY_RW(struct cpu *cpu, struct me
133                          for (i=0; i<len; i++) {                          for (i=0; i<len; i++) {
134                                  /*  Do one byte at a time:  */                                  /*  Do one byte at a time:  */
135                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,                                  res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
136                                      writeflag, cache_flags);                                      writeflag, misc_flags);
137                                  if (!res) {                                  if (!res) {
138                                          if (cache == CACHE_INSTRUCTION) {                                          if (cache == CACHE_INSTRUCTION) {
139                                                  fatal("FAILED instruction "                                                  fatal("FAILED instruction "
# Line 150  int MEMORY_RW(struct cpu *cpu, struct me Line 150  int MEMORY_RW(struct cpu *cpu, struct me
150          }          }
151  #endif  /*  X86  */  #endif  /*  X86  */
152    
 #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  
   
153  #ifdef MEM_MIPS  #ifdef MEM_MIPS
 #ifdef BINTRANS  
154          if (bintrans_cached) {          if (bintrans_cached) {
155                  if (cache == CACHE_INSTRUCTION) {                  if (cache == CACHE_INSTRUCTION) {
156                          cpu->cd.mips.pc_bintrans_host_4kpage = NULL;                          cpu->cd.mips.pc_bintrans_host_4kpage = NULL;
157                          cpu->cd.mips.pc_bintrans_paddr_valid = 0;                          cpu->cd.mips.pc_bintrans_paddr_valid = 0;
158                  }                  }
159          }          }
 #endif  
160  #endif  /*  MEM_MIPS  */  #endif  /*  MEM_MIPS  */
161    
162  #ifdef MEM_USERLAND  #ifdef MEM_USERLAND
163    #ifdef MEM_ALPHA
164            paddr = vaddr;
165    #else
166          paddr = vaddr & 0x7fffffff;          paddr = vaddr & 0x7fffffff;
167    #endif
168          goto have_paddr;          goto have_paddr;
169  #endif  #endif
170    
# Line 193  int MEMORY_RW(struct cpu *cpu, struct me Line 186  int MEMORY_RW(struct cpu *cpu, struct me
186          }          }
187  #endif  /*  MEM_MIPS  */  #endif  /*  MEM_MIPS  */
188    
189          if (cache_flags & PHYSICAL || cpu->translate_address == NULL) {          if (misc_flags & PHYSICAL || cpu->translate_address == NULL) {
190                  paddr = vaddr;                  paddr = vaddr;
191    #ifdef MEM_ALPHA
192                    /*  paddr &= 0x1fffffff;  For testalpha  */
193                    paddr &= 0x000003ffffffffffULL;
194    #endif
195          } else {          } else {
196                  ok = cpu->translate_address(cpu, vaddr, &paddr,                  ok = cpu->translate_address(cpu, vaddr, &paddr,
197                      (writeflag? FLAG_WRITEFLAG : 0) +                      (writeflag? FLAG_WRITEFLAG : 0) +
198                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)
199  #ifdef MEM_X86  #ifdef MEM_X86
200                      + (cache_flags & NO_SEGMENTATION)                      + (misc_flags & NO_SEGMENTATION)
201    #endif
202    #ifdef MEM_ARM
203                        + (misc_flags & MEMORY_USER_ACCESS)
204  #endif  #endif
205                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));
206                  /*  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 213  int MEMORY_RW(struct cpu *cpu, struct me
213    
214  #ifdef MEM_X86  #ifdef MEM_X86
215          /*  DOS debugging :-)  */          /*  DOS debugging :-)  */
216          if (!quiet_mode && !(cache_flags & PHYSICAL)) {          if (!quiet_mode && !(misc_flags & PHYSICAL)) {
217                  if (paddr >= 0x400 && paddr <= 0x4ff)                  if (paddr >= 0x400 && paddr <= 0x4ff)
218                          debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==                          debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==
219                              MEM_WRITE? "writing to" : "reading from",                              MEM_WRITE? "writing to" : "reading from",
# Line 255  have_paddr: Line 255  have_paddr:
255    
256  #ifdef MEM_MIPS  #ifdef MEM_MIPS
257          /*  TODO: How about bintrans vs cache emulation?  */          /*  TODO: How about bintrans vs cache emulation?  */
 #ifdef BINTRANS  
258          if (bintrans_cached) {          if (bintrans_cached) {
259                  if (cache == CACHE_INSTRUCTION) {                  if (cache == CACHE_INSTRUCTION) {
260                          cpu->cd.mips.pc_bintrans_paddr_valid = 1;                          cpu->cd.mips.pc_bintrans_paddr_valid = 1;
261                          cpu->cd.mips.pc_bintrans_paddr = paddr;                          cpu->cd.mips.pc_bintrans_paddr = paddr;
262                  }                  }
263          }          }
 #endif  
264  #endif  /*  MEM_MIPS  */  #endif  /*  MEM_MIPS  */
265    
266    
# Line 271  have_paddr: Line 269  have_paddr:
269          /*          /*
270           *  Memory mapped device?           *  Memory mapped device?
271           *           *
272           *  TODO: this is utterly slow.           *  TODO: if paddr < base, but len enough, then the device should
273           *  TODO2: if paddr<base, but len enough, then we should write           *  still be written to!
          *  to a device to  
274           */           */
275          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {
 #ifdef BINTRANS  
276                  uint64_t orig_paddr = paddr;                  uint64_t orig_paddr = paddr;
277  #endif                  int i, start, end, res;
                 int i, start, res;  
278    
 #ifdef BINTRANS  
279                  /*                  /*
280                   *  Really really slow, but unfortunately necessary. This is                   *  Really really slow, but unfortunately necessary. This is
281                   *  to avoid the folowing scenario:                   *  to avoid the folowing scenario:
# Line 290  have_paddr: Line 284  have_paddr:
284                   *      b) offsets 0x124..0x777 are a device                   *      b) offsets 0x124..0x777 are a device
285                   *                   *
286                   *      1) a read is done from offset 0x100. the page is                   *      1) a read is done from offset 0x100. the page is
287                   *         added to the bintrans system as a "RAM" page                   *         added to the dyntrans system as a "RAM" page
288                   *      2) a bintranslated read is done from offset 0x200,                   *      2) a dyntranslated read is done from offset 0x200,
289                   *         which should access the device, but since the                   *         which should access the device, but since the
290                   *         entire page is added, it will access non-existant                   *         entire page is added, it will access non-existant
291                   *         RAM instead, without warning.                   *         RAM instead, without warning.
292                   *                   *
293                   *  Setting bintrans_device_danger = 1 on accesses which are                   *  Setting dyntrans_device_danger = 1 on accesses which are
294                   *  on _any_ offset on pages that are device mapped avoids                   *  on _any_ offset on pages that are device mapped avoids
295                   *  this problem, but it is probably not very fast.                   *  this problem, but it is probably not very fast.
296                     *
297                     *  TODO: Convert this into a quick (multi-level, 64-bit)
298                     *  address space lookup, to find dangerous pages.
299                   */                   */
300                  if (bintrans_cached) {  #if 1
301                          for (i=0; i<mem->n_mmapped_devices; i++)                  for (i=0; i<mem->n_mmapped_devices; i++)
302                                  if (paddr >= (mem->dev_baseaddr[i] & ~0xfff) &&                          if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) &&
303                                      paddr <= ((mem->dev_baseaddr[i] +                              paddr <= ((mem->dev_endaddr[i]-1) | offset_mask)) {
304                                      mem->dev_length[i] - 1) | 0xfff)) {                                  dyntrans_device_danger = 1;
305                                          bintrans_device_danger = 1;                                  break;
306                                          break;                          }
                                 }  
                 }  
307  #endif  #endif
308    
309                  i = start = mem->last_accessed_device;                  start = 0; end = mem->n_mmapped_devices - 1;
310                    i = mem->last_accessed_device;
311    
312                  /*  Scan through all devices:  */                  /*  Scan through all devices:  */
313                  do {                  do {
314                          if (paddr >= mem->dev_baseaddr[i] &&                          if (paddr >= mem->dev_baseaddr[i] &&
315                              paddr < mem->dev_baseaddr[i] + mem->dev_length[i]) {                              paddr < mem->dev_endaddr[i]) {
316                                  /*  Found a device, let's access it:  */                                  /*  Found a device, let's access it:  */
317                                  mem->last_accessed_device = i;                                  mem->last_accessed_device = i;
318    
# Line 324  have_paddr: Line 320  have_paddr:
320                                  if (paddr + len > mem->dev_length[i])                                  if (paddr + len > mem->dev_length[i])
321                                          len = mem->dev_length[i] - paddr;                                          len = mem->dev_length[i] - paddr;
322    
323  #ifdef BINTRANS                                  if (cpu->update_translation_table != NULL &&
324                                  if (bintrans_cached && mem->dev_flags[i] &                                      !(ok & MEMORY_NOT_FULL_PAGE) &&
325                                      MEM_BINTRANS_OK) {                                      mem->dev_flags[i] & DM_DYNTRANS_OK) {
326                                          int wf = writeflag == MEM_WRITE? 1 : 0;                                          int wf = writeflag == MEM_WRITE? 1 : 0;
327                                            unsigned char *host_addr;
328    
329                                          if (writeflag) {                                          if (!(mem->dev_flags[i] &
330                                                DM_DYNTRANS_WRITE_OK))
331                                                    wf = 0;
332    
333                                            if (writeflag && wf) {
334                                                  if (paddr < mem->                                                  if (paddr < mem->
335                                                      dev_bintrans_write_low[i])                                                      dev_dyntrans_write_low[i])
336                                                          mem->                                                          mem->
337                                                          dev_bintrans_write_low                                                          dev_dyntrans_write_low
338                                                              [i] =                                                              [i] = paddr &
339                                                              paddr & ~0xfff;                                                              ~offset_mask;
340                                                  if (paddr > mem->                                                  if (paddr >= mem->
341                                                      dev_bintrans_write_high[i])                                                      dev_dyntrans_write_high[i])
342                                                          mem->                                                          mem->
343                                                          dev_bintrans_write_high                                                          dev_dyntrans_write_high
344                                                              [i] = paddr | 0xfff;                                                              [i] = paddr |
345                                                                offset_mask;
346                                          }                                          }
347    
348                                          if (!(mem->dev_flags[i] &                                          if (mem->dev_flags[i] &
349                                              MEM_BINTRANS_WRITE_OK))                                              DM_EMULATED_RAM) {
350                                                  wf = 0;                                                  /*  MEM_WRITE to force the page
351                                                        to be allocated, if it
352                                          update_translation_table(cpu,                                                      wasn't already  */
353                                              vaddr & ~0xfff,                                                  uint64_t *pp = (uint64_t *)
354                                              mem->dev_bintrans_data[i] +                                                      mem->dev_dyntrans_data[i];
355                                              (paddr & ~0xfff),                                                  uint64_t p = orig_paddr - *pp;
356                                              wf, orig_paddr & ~0xfff);                                                  host_addr =
357                                                        memory_paddr_to_hostaddr(
358                                                        mem, p, MEM_WRITE)
359                                                        + (p & ~offset_mask
360                                                        & ((1 <<
361                                                        BITS_PER_MEMBLOCK) - 1));
362                                            } else {
363                                                    host_addr =
364                                                        mem->dev_dyntrans_data[i] +
365                                                        (paddr & ~offset_mask);
366                                            }
367                                            cpu->update_translation_table(cpu,
368                                                vaddr & ~offset_mask, host_addr,
369                                                wf, orig_paddr & ~offset_mask);
370                                  }                                  }
 #endif  
371    
372                                  res = 0;                                  res = 0;
373                                  if (!no_exceptions || (mem->dev_flags[i] &                                  if (!no_exceptions || (mem->dev_flags[i] &
374                                      MEM_READING_HAS_NO_SIDE_EFFECTS))                                      DM_READS_HAVE_NO_SIDE_EFFECTS))
375                                          res = mem->dev_f[i](cpu, mem, paddr,                                          res = mem->dev_f[i](cpu, mem, paddr,
376                                              data, len, writeflag,                                              data, len, writeflag,
377                                              mem->dev_extra[i]);                                              mem->dev_extra[i]);
# Line 366  have_paddr: Line 380  have_paddr:
380                                  if (res == 0)                                  if (res == 0)
381                                          res = -1;                                          res = -1;
382    
383    #ifdef MEM_MIPS
384                                  cpu->cd.mips.instruction_delay +=                                  cpu->cd.mips.instruction_delay +=
385                                      ( (abs(res) - 1) *                                      ( (abs(res) - 1) *
386                                       cpu->cd.mips.cpu_type.instrs_per_cycle );                                       cpu->cd.mips.cpu_type.instrs_per_cycle );
387  #endif  #endif
388    #endif
389    
390  #ifndef MEM_X86  #ifndef MEM_X86
391                                  /*                                  /*
# Line 391  have_paddr: Line 407  have_paddr:
407                                  goto do_return_ok;                                  goto do_return_ok;
408                          }                          }
409    
410                          i ++;                          if (paddr < mem->dev_baseaddr[i])
411                          if (i == mem->n_mmapped_devices)                                  end = i - 1;
412                                  i = 0;                          if (paddr >= mem->dev_endaddr[i])
413                  } while (i != start);                                  start = i + 1;
414                            i = (start + end) >> 1;
415                    } while (start <= end);
416          }          }
417    
418    
# Line 406  have_paddr: Line 424  have_paddr:
424          switch (cpu->cd.mips.cpu_type.mmu_model) {          switch (cpu->cd.mips.cpu_type.mmu_model) {
425          case MMU3K:          case MMU3K:
426                  /*  if not uncached addess  (TODO: generalize this)  */                  /*  if not uncached addess  (TODO: generalize this)  */
427                  if (!(cache_flags & PHYSICAL) && cache != CACHE_NONE &&                  if (!(misc_flags & PHYSICAL) && cache != CACHE_NONE &&
428                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&
429                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {
430                          if (memory_cache_R3000(cpu, cache, paddr,                          if (memory_cache_R3000(cpu, cache, paddr,
# Line 414  have_paddr: Line 432  have_paddr:
432                                  goto do_return_ok;                                  goto do_return_ok;
433                  }                  }
434                  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  
435          default:          default:
436                  /*  R4000 etc  */                  /*  R4000 etc  */
437                  /*  TODO  */                  /*  TODO  */
# Line 465  have_paddr: Line 456  have_paddr:
456                  {                  {
457                          if (paddr >= mem->physical_max) {                          if (paddr >= mem->physical_max) {
458                                  char *symbol;                                  char *symbol;
 #ifdef MEM_MIPS  
459                                  uint64_t offset;                                  uint64_t offset;
460    #ifdef MEM_MIPS
461                                    uint64_t old_pc = cpu->cd.mips.pc_last;
462    #else
463                                    uint64_t old_pc = cpu->pc;
464  #endif  #endif
465    
466                                  /*  This allows for example OS kernels to probe                                  /*  This allows for example OS kernels to probe
467                                      memory a few KBs past the end of memory,                                      memory a few KBs past the end of memory,
468                                      without giving too many warnings.  */                                      without giving too many warnings.  */
469                                  if (!quiet_mode && paddr >=                                  if (!quiet_mode && !no_exceptions && paddr >=
470                                      mem->physical_max + 0x40000) {                                      mem->physical_max + 0x40000) {
471                                          fatal("[ memory_rw(): writeflag=%i ",                                          fatal("[ memory_rw(): writeflag=%i ",
472                                              writeflag);                                              writeflag);
# Line 499  have_paddr: Line 494  have_paddr:
494                                                                      data[i]);                                                                      data[i]);
495                                                  debug("}");                                                  debug("}");
496                                          }                                          }
497  #ifdef MEM_MIPS  
498                                            fatal(" paddr=0x%llx >= physical_max"
499                                                "; pc=", (long long)paddr);
500                                            if (cpu->is_32bit)
501                                                    fatal("0x%08x",(int)old_pc);
502                                            else
503                                                    fatal("0x%016llx",
504                                                        (long long)old_pc);
505                                          symbol = get_symbol_name(                                          symbol = get_symbol_name(
506                                              &cpu->machine->symbol_context,                                              &cpu->machine->symbol_context,
507                                              cpu->cd.mips.pc_last, &offset);                                              old_pc, &offset);
508  #else                                          fatal(" <%s> ]\n",
509                                          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");  
510                                  }                                  }
511    
512                                  if (cpu->machine->single_step_on_bad_addr) {                                  if (cpu->machine->single_step_on_bad_addr) {
513                                          fatal("[ unimplemented access to "                                          fatal("[ unimplemented access to "
514                                              "0x%016llx, pc = 0x%016llx ]\n",                                              "0x%llx, pc=0x",(long long)paddr);
515                                              (long long)paddr,                                          if (cpu->is_32bit)
516                                              (long long)cpu->pc);                                                  fatal("%08x ]\n",
517                                                        (int)old_pc);
518                                            else
519                                                    fatal("%016llx ]\n",
520                                                        (long long)old_pc);
521                                          single_step = 1;                                          single_step = 1;
522                                  }                                  }
523                          }                          }
# Line 563  have_paddr: Line 560  have_paddr:
560    
561          /*          /*
562           *  Uncached access:           *  Uncached access:
563             *
564             *  1)  Translate the physical address to a host address.
565             *
566             *  2)  Insert this virtual->physical->host translation into the
567             *      fast translation arrays (using update_translation_table()).
568             *
569             *  3)  If this was a Write, then invalidate any code translations
570             *      in that page.
571           */           */
572          memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag);          memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag);
573          if (memblock == NULL) {          if (memblock == NULL) {
# Line 573  have_paddr: Line 578  have_paddr:
578    
579          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);
580    
581  #ifdef BINTRANS          if (cpu->update_translation_table != NULL && !dyntrans_device_danger
582          if (bintrans_cached && !bintrans_device_danger)  #ifndef MEM_MIPS
583                  update_translation_table(cpu, vaddr & ~0xfff,  /*          && !(misc_flags & MEMORY_USER_ACCESS)  */
584                      memblock + (offset & ~0xfff),  #ifndef MEM_USERLAND
585  #if 0              && !(ok & MEMORY_NOT_FULL_PAGE)
                     cache == CACHE_INSTRUCTION?  
                         (writeflag == MEM_WRITE? 1 : 0)  
                         : ok - 1,  
 #else  
                     writeflag == MEM_WRITE? 1 : 0,  
586  #endif  #endif
                     paddr & ~0xfff);  
587  #endif  #endif
588                && !no_exceptions)
589                    cpu->update_translation_table(cpu, vaddr & ~offset_mask,
590                        memblock + (offset & ~offset_mask),
591                        (misc_flags & MEMORY_USER_ACCESS) |
592    #ifndef MEM_MIPS
593                        (cache == CACHE_INSTRUCTION? TLB_CODE : 0) |
594    #endif
595    #if !defined(MEM_MIPS) && !defined(MEM_USERLAND)
596                        (cache == CACHE_INSTRUCTION?
597                            (writeflag == MEM_WRITE? 1 : 0) : ok - 1),
598    #else
599                        (writeflag == MEM_WRITE? 1 : 0),
600    #endif
601                        paddr & ~offset_mask);
602    
603            /*  Invalidate code translations for the page we are writing to.  */
604            if (writeflag == MEM_WRITE && cpu->invalidate_code_translation != NULL)
605                    cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR);
606    
607          if (writeflag == MEM_WRITE) {          if (writeflag == MEM_WRITE) {
608                  if (len == sizeof(uint32_t) && (offset & 3)==0)                  /*  Ugly optimization, but it works:  */
609                    if (len == sizeof(uint32_t) && (offset & 3)==0
610                        && ((size_t)data&3)==0)
611                          *(uint32_t *)(memblock + offset) = *(uint32_t *)data;                          *(uint32_t *)(memblock + offset) = *(uint32_t *)data;
612                  else if (len == sizeof(uint8_t))                  else if (len == sizeof(uint8_t))
613                          *(uint8_t *)(memblock + offset) = *(uint8_t *)data;                          *(uint8_t *)(memblock + offset) = *(uint8_t *)data;
614                  else                  else
615                          memcpy(memblock + offset, data, len);                          memcpy(memblock + offset, data, len);
616          } else {          } else {
617                  if (len == sizeof(uint32_t) && (offset & 3)==0)                  /*  Ugly optimization, but it works:  */
618                    if (len == sizeof(uint32_t) && (offset & 3)==0
619                        && ((size_t)data&3)==0)
620                          *(uint32_t *)data = *(uint32_t *)(memblock + offset);                          *(uint32_t *)data = *(uint32_t *)(memblock + offset);
621                  else if (len == sizeof(uint8_t))                  else if (len == sizeof(uint8_t))
622                          *(uint8_t *)data = *(uint8_t *)(memblock + offset);                          *(uint8_t *)data = *(uint8_t *)(memblock + offset);
# Line 605  have_paddr: Line 626  have_paddr:
626  #ifdef MEM_MIPS  #ifdef MEM_MIPS
627                  if (cache == CACHE_INSTRUCTION) {                  if (cache == CACHE_INSTRUCTION) {
628                          cpu->cd.mips.pc_last_host_4k_page = memblock                          cpu->cd.mips.pc_last_host_4k_page = memblock
629                              + (offset & ~0xfff);                              + (offset & ~offset_mask);
 #ifdef BINTRANS  
630                          if (bintrans_cached) {                          if (bintrans_cached) {
631                                  cpu->cd.mips.pc_bintrans_host_4kpage =                                  cpu->cd.mips.pc_bintrans_host_4kpage =
632                                      cpu->cd.mips.pc_last_host_4k_page;                                      cpu->cd.mips.pc_last_host_4k_page;
633                          }                          }
 #endif  
634                  }                  }
635  #endif  /*  MIPS  */  #endif  /*  MIPS  */
636          }          }

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

  ViewVC Help
Powered by ViewVC 1.1.26