/[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 10 by dpavlin, Mon Oct 8 16:18:27 2007 UTC
# 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.38 2005/06/27 07:03:39 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 76  int MEMORY_RW(struct cpu *cpu, struct me Line 76  int MEMORY_RW(struct cpu *cpu, struct me
76          unsigned char *memblock;          unsigned char *memblock;
77  #ifdef BINTRANS  #ifdef BINTRANS
78          int bintrans_cached = cpu->machine->bintrans_enable;          int bintrans_cached = cpu->machine->bintrans_enable;
79            int bintrans_device_danger = 0;
80  #endif  #endif
81          no_exceptions = cache_flags & NO_EXCEPTIONS;          no_exceptions = cache_flags & NO_EXCEPTIONS;
82          cache = cache_flags & CACHE_FLAGS_MASK;          cache = cache_flags & CACHE_FLAGS_MASK;
# Line 85  int MEMORY_RW(struct cpu *cpu, struct me Line 86  int MEMORY_RW(struct cpu *cpu, struct me
86                  vaddr &= 0xffffffff;                  vaddr &= 0xffffffff;
87  #endif  #endif
88    
89    #ifdef MEM_ARM
90            vaddr &= 0x3fffffff;
91    #endif
92    
93    #ifdef MEM_X86
94            /*  Real-mode wrap-around:  */
95            if (REAL_MODE && !(cache_flags & PHYSICAL)) {
96                    if ((vaddr & 0xffff) + len > 0x10000) {
97                            /*  Do one byte at a time:  */
98                            int res = 0, i;
99                            for (i=0; i<len; i++)
100                                    res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
101                                        writeflag, cache_flags);
102                            return res;
103                    }
104            }
105    
106            /*  Crossing a page boundary? Then do one byte at a time:  */
107            if ((vaddr & 0xfff) + len > 0x1000 && !(cache_flags & PHYSICAL)
108                && cpu->cd.x86.cr[0] & X86_CR0_PG) {
109                    /*  For WRITES: Read ALL BYTES FIRST and write them back!!!
110                        Then do a write of all the new bytes. This is to make sure
111                        than both pages around the boundary are writable so we don't
112                        do a partial write.  */
113                    int res = 0, i;
114                    if (writeflag == MEM_WRITE) {
115                            unsigned char tmp;
116                            for (i=0; i<len; i++) {
117                                    res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
118                                        MEM_READ, cache_flags);
119                                    if (!res)
120                                            return 0;
121                                    res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,
122                                        MEM_WRITE, cache_flags);
123                                    if (!res)
124                                            return 0;
125                            }
126                            for (i=0; i<len; i++) {
127                                    res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
128                                        MEM_WRITE, cache_flags);
129                                    if (!res)
130                                            return 0;
131                            }
132                    } else {
133                            for (i=0; i<len; i++) {
134                                    /*  Do one byte at a time:  */
135                                    res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,
136                                        writeflag, cache_flags);
137                                    if (!res) {
138                                            if (cache == CACHE_INSTRUCTION) {
139                                                    fatal("FAILED instruction "
140                                                        "fetch across page boundar"
141                                                        "y: todo. vaddr=0x%08x\n",
142                                                        (int)vaddr);
143                                                    cpu->running = 0;
144                                            }
145                                            return 0;
146                                    }
147                            }
148                    }
149                    return res;
150            }
151    #endif  /*  X86  */
152    
153  #ifdef MEM_URISC  #ifdef MEM_URISC
154          {          {
155                  uint64_t mask = (uint64_t) -1;                  uint64_t mask = (uint64_t) -1;
# Line 134  int MEMORY_RW(struct cpu *cpu, struct me Line 199  int MEMORY_RW(struct cpu *cpu, struct me
199                  ok = cpu->translate_address(cpu, vaddr, &paddr,                  ok = cpu->translate_address(cpu, vaddr, &paddr,
200                      (writeflag? FLAG_WRITEFLAG : 0) +                      (writeflag? FLAG_WRITEFLAG : 0) +
201                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)
202    #ifdef MEM_X86
203                        + (cache_flags & NO_SEGMENTATION)
204    #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
207                      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 211  int MEMORY_RW(struct cpu *cpu, struct me
211          }          }
212    
213    
214    #ifdef MEM_X86
215            /*  DOS debugging :-)  */
216            if (!quiet_mode && !(cache_flags & PHYSICAL)) {
217                    if (paddr >= 0x400 && paddr <= 0x4ff)
218                            debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==
219                                MEM_WRITE? "writing to" : "reading from",
220                                (int)paddr);
221    #if 0
222                    if (paddr >= 0xf0000 && paddr <= 0xfffff)
223                            debug("{ BIOS ACCESS: %s 0x%x }\n",
224                                writeflag == MEM_WRITE? "writing to" :
225                                "reading from", (int)paddr);
226    #endif
227            }
228    #endif
229    
230  #ifdef MEM_MIPS  #ifdef MEM_MIPS
231          /*          /*
232           *  If correct cache emulation is enabled, and we need to simluate           *  If correct cache emulation is enabled, and we need to simluate
# Line 164  int MEMORY_RW(struct cpu *cpu, struct me Line 248  int MEMORY_RW(struct cpu *cpu, struct me
248  #endif  /*  ifndef MEM_USERLAND  */  #endif  /*  ifndef MEM_USERLAND  */
249    
250    
251    #if defined(MEM_MIPS) || defined(MEM_USERLAND)
252  have_paddr:  have_paddr:
253    #endif
254    
255    
256  #ifdef MEM_MIPS  #ifdef MEM_MIPS
# Line 180  have_paddr: Line 266  have_paddr:
266  #endif  /*  MEM_MIPS  */  #endif  /*  MEM_MIPS  */
267    
268    
         if (!(cache_flags & PHYSICAL))  
                 if (no_exceptions)  
                         goto no_exception_access;  
   
269    
270  #ifndef MEM_USERLAND  #ifndef MEM_USERLAND
271          /*          /*
# Line 198  have_paddr: Line 280  have_paddr:
280                  uint64_t orig_paddr = paddr;                  uint64_t orig_paddr = paddr;
281  #endif  #endif
282                  int i, start, res;                  int i, start, res;
283    
284    #ifdef BINTRANS
285                    /*
286                     *  Really really slow, but unfortunately necessary. This is
287                     *  to avoid the folowing scenario:
288                     *
289                     *      a) offsets 0x000..0x123 are normal memory
290                     *      b) offsets 0x124..0x777 are a device
291                     *
292                     *      1) a read is done from offset 0x100. the page is
293                     *         added to the bintrans system as a "RAM" page
294                     *      2) a bintranslated read is done from offset 0x200,
295                     *         which should access the device, but since the
296                     *         entire page is added, it will access non-existant
297                     *         RAM instead, without warning.
298                     *
299                     *  Setting bintrans_device_danger = 1 on accesses which are
300                     *  on _any_ offset on pages that are device mapped avoids
301                     *  this problem, but it is probably not very fast.
302                     */
303                    if (bintrans_cached) {
304                            for (i=0; i<mem->n_mmapped_devices; i++)
305                                    if (paddr >= (mem->dev_baseaddr[i] & ~0xfff) &&
306                                        paddr <= ((mem->dev_baseaddr[i] +
307                                        mem->dev_length[i] - 1) | 0xfff)) {
308                                            bintrans_device_danger = 1;
309                                            break;
310                                    }
311                    }
312    #endif
313    
314                  i = start = mem->last_accessed_device;                  i = start = mem->last_accessed_device;
315    
316                  /*  Scan through all devices:  */                  /*  Scan through all devices:  */
# Line 242  have_paddr: Line 355  have_paddr:
355                                  }                                  }
356  #endif  #endif
357    
358                                  res = mem->dev_f[i](cpu, mem, paddr, data, len,                                  res = 0;
359                                      writeflag, mem->dev_extra[i]);                                  if (!no_exceptions || (mem->dev_flags[i] &
360                                        MEM_READING_HAS_NO_SIDE_EFFECTS))
361                                            res = mem->dev_f[i](cpu, mem, paddr,
362                                                data, len, writeflag,
363                                                mem->dev_extra[i]);
364    
365  #ifdef ENABLE_INSTRUCTION_DELAYS  #ifdef ENABLE_INSTRUCTION_DELAYS
366                                  if (res == 0)                                  if (res == 0)
# Line 253  have_paddr: Line 370  have_paddr:
370                                      ( (abs(res) - 1) *                                      ( (abs(res) - 1) *
371                                       cpu->cd.mips.cpu_type.instrs_per_cycle );                                       cpu->cd.mips.cpu_type.instrs_per_cycle );
372  #endif  #endif
373    
374    #ifndef MEM_X86
375                                  /*                                  /*
376                                   *  If accessing the memory mapped device                                   *  If accessing the memory mapped device
377                                   *  failed, then return with a DBE exception.                                   *  failed, then return with a DBE exception.
378                                   */                                   */
379                                  if (res <= 0) {                                  if (res <= 0 && !no_exceptions) {
380                                          debug("%s device '%s' addr %08lx "                                          debug("%s device '%s' addr %08lx "
381                                              "failed\n", writeflag?                                              "failed\n", writeflag?
382                                              "writing to" : "reading from",                                              "writing to" : "reading from",
# Line 268  have_paddr: Line 387  have_paddr:
387  #endif  #endif
388                                          return MEMORY_ACCESS_FAILED;                                          return MEMORY_ACCESS_FAILED;
389                                  }                                  }
390    #endif
391                                  goto do_return_ok;                                  goto do_return_ok;
392                          }                          }
393    
# Line 332  have_paddr: Line 451  have_paddr:
451    
452          /*  Outside of physical RAM?  */          /*  Outside of physical RAM?  */
453          if (paddr >= mem->physical_max) {          if (paddr >= mem->physical_max) {
454                  if ((paddr & 0xffff000000ULL) == 0x1f000000) {  #ifdef MEM_MIPS
455                    if ((paddr & 0xffffc00000ULL) == 0x1fc00000) {
456                          /*  Ok, this is PROM stuff  */                          /*  Ok, this is PROM stuff  */
457                  } else if ((paddr & 0xfffff00000ULL) == 0x1ff00000) {                  } else if ((paddr & 0xfffff00000ULL) == 0x1ff00000) {
458                          /*  Sprite reads from this area of memory...  */                          /*  Sprite reads from this area of memory...  */
# Line 340  have_paddr: Line 460  have_paddr:
460                          if (writeflag == MEM_READ)                          if (writeflag == MEM_READ)
461                                  memset(data, 0, len);                                  memset(data, 0, len);
462                          goto do_return_ok;                          goto do_return_ok;
463                  } else {                  } else
464                          if (paddr >= mem->physical_max + 0 * 1024) {  #endif /* MIPS */
465                    {
466                            if (paddr >= mem->physical_max) {
467                                  char *symbol;                                  char *symbol;
468  #ifdef MEM_MIPS  #ifdef MEM_MIPS
469                                  uint64_t offset;                                  uint64_t offset;
470  #endif  #endif
471                                  if (!quiet_mode) {                                  /*  This allows for example OS kernels to probe
472                                        memory a few KBs past the end of memory,
473                                        without giving too many warnings.  */
474                                    if (!quiet_mode && paddr >=
475                                        mem->physical_max + 0x40000) {
476                                          fatal("[ memory_rw(): writeflag=%i ",                                          fatal("[ memory_rw(): writeflag=%i ",
477                                              writeflag);                                              writeflag);
478                                          if (writeflag) {                                          if (writeflag) {
# Line 400  have_paddr: Line 526  have_paddr:
526                          }                          }
527    
528                          if (writeflag == MEM_READ) {                          if (writeflag == MEM_READ) {
529    #ifdef MEM_X86
530                                    /*  Reading non-existant memory on x86:  */
531                                    memset(data, 0xff, len);
532    #else
533                                  /*  Return all zeroes? (Or 0xff? TODO)  */                                  /*  Return all zeroes? (Or 0xff? TODO)  */
534                                  memset(data, 0, len);                                  memset(data, 0, len);
535    #endif
536    
537  #ifdef MEM_MIPS  #ifdef MEM_MIPS
538                                  /*                                  /*
# Line 409  have_paddr: Line 540  have_paddr:
540                                   *  an exceptions on an illegal read:                                   *  an exceptions on an illegal read:
541                                   */                                   */
542                                  if (cache != CACHE_NONE && cpu->machine->                                  if (cache != CACHE_NONE && cpu->machine->
543                                      dbe_on_nonexistant_memaccess) {                                      dbe_on_nonexistant_memaccess &&
544                                        !no_exceptions) {
545                                          if (paddr >= mem->physical_max &&                                          if (paddr >= mem->physical_max &&
546                                              paddr < mem->physical_max+1048576)                                              paddr < mem->physical_max+1048576)
547                                                  mips_cpu_exception(cpu,                                                  mips_cpu_exception(cpu,
# Line 429  have_paddr: Line 561  have_paddr:
561  #endif  /*  ifndef MEM_USERLAND  */  #endif  /*  ifndef MEM_USERLAND  */
562    
563    
 no_exception_access:  
   
564          /*          /*
565           *  Uncached access:           *  Uncached access:
566           */           */
# Line 444  no_exception_access: Line 574  no_exception_access:
574          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);
575    
576  #ifdef BINTRANS  #ifdef BINTRANS
577          if (bintrans_cached)          if (bintrans_cached && !bintrans_device_danger)
578                  update_translation_table(cpu, vaddr & ~0xfff,                  update_translation_table(cpu, vaddr & ~0xfff,
579                      memblock + (offset & ~0xfff),                      memblock + (offset & ~0xfff),
580  #if 0  #if 0
# Line 472  no_exception_access: Line 602  no_exception_access:
602                  else                  else
603                          memcpy(data, memblock + offset, len);                          memcpy(data, memblock + offset, len);
604    
605    #ifdef MEM_MIPS
606                  if (cache == CACHE_INSTRUCTION) {                  if (cache == CACHE_INSTRUCTION) {
607                          cpu->cd.mips.pc_last_host_4k_page = memblock                          cpu->cd.mips.pc_last_host_4k_page = memblock
608                              + (offset & ~0xfff);                              + (offset & ~0xfff);
# Line 482  no_exception_access: Line 613  no_exception_access:
613                          }                          }
614  #endif  #endif
615                  }                  }
616    #endif  /*  MIPS  */
617          }          }
618    
619    

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

  ViewVC Help
Powered by ViewVC 1.1.26