--- trunk/src/memory_rw.c 2007/10/08 16:17:48 2 +++ trunk/src/memory_rw.c 2007/10/08 16:18:00 4 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: memory_rw.c,v 1.10 2005/03/01 08:23:55 debug Exp $ + * $Id: memory_rw.c,v 1.16 2005/04/19 01:24:35 debug Exp $ * * Generic memory_rw(), with special hacks for specific CPU families. * @@ -76,6 +76,7 @@ unsigned char *memblock; #ifdef BINTRANS int bintrans_cached = cpu->machine->bintrans_enable; + int bintrans_device_danger = 0; #endif no_exceptions = cache_flags & NO_EXCEPTIONS; cache = cache_flags & CACHE_FLAGS_MASK; @@ -85,6 +86,30 @@ vaddr &= 0xffffffff; #endif +#ifdef MEM_X86 + if (cpu->cd.x86.bits == 32) { + if ((vaddr >> 32) == 0xffffffff) + vaddr &= 0xffffffff; + + /* TODO: Actual address translation */ + if ((vaddr >> 32) == 0) { + vaddr &= 0x0fffffff; + + if (cpu->cd.x86.mode == 16) { + vaddr = (cpu->cd.x86.cursegment<<4) + + (vaddr & 0xffff); + /* TODO: A20 stuff */ + if ((vaddr & 0xffff) + len > 0x10000) { + fatal("x86 memory access crossing" + " segment boundary: TODO\n"); + cpu->running = 0; + return 0; + } + } + } + } +#endif + #ifdef MEM_URISC { uint64_t mask = (uint64_t) -1; @@ -164,7 +189,9 @@ #endif /* ifndef MEM_USERLAND */ +#if defined(MEM_MIPS) || defined(MEM_USERLAND) have_paddr: +#endif #ifdef MEM_MIPS @@ -198,6 +225,37 @@ uint64_t orig_paddr = paddr; #endif int i, start, res; + +#ifdef BINTRANS + /* + * Really really slow, but unfortunately necessary. This is + * to avoid the folowing scenario: + * + * a) offsets 0x000..0x123 are normal memory + * b) offsets 0x124..0x777 are a device + * + * 1) a read is done from offset 0x100. the page is + * added to the bintrans system as a "RAM" page + * 2) a bintranslated read is done from offset 0x200, + * which should access the device, but since the + * entire page is added, it will access non-existant + * RAM instead, without warning. + * + * Setting bintrans_device_danger = 1 on accesses which are + * on _any_ offset on pages that are device mapped avoids + * this problem, but it is probably not very fast. + */ + if (bintrans_cached) { + for (i=0; in_mmapped_devices; i++) + if (paddr >= (mem->dev_baseaddr[i] & ~0xfff) && + paddr <= ((mem->dev_baseaddr[i] + + mem->dev_length[i] - 1) | 0xfff)) { + bintrans_device_danger = 1; + break; + } + } +#endif + i = start = mem->last_accessed_device; /* Scan through all devices: */ @@ -444,7 +502,7 @@ offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1); #ifdef BINTRANS - if (bintrans_cached) + if (bintrans_cached && !bintrans_device_danger) update_translation_table(cpu, vaddr & ~0xfff, memblock + (offset & ~0xfff), #if 0