--- trunk/src/memory_rw.c 2007/10/08 16:18:00 4 +++ trunk/src/memory_rw.c 2007/10/08 16:18:11 6 @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * - * $Id: memory_rw.c,v 1.16 2005/04/19 01:24:35 debug Exp $ + * $Id: memory_rw.c,v 1.37 2005/06/02 12:31:39 debug Exp $ * * Generic memory_rw(), with special hacks for specific CPU families. * @@ -86,29 +86,69 @@ vaddr &= 0xffffffff; #endif +#ifdef MEM_ARM + vaddr &= 0x0fffffff; +#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; + /* Real-mode wrap-around: */ + if (REAL_MODE && !(cache_flags & PHYSICAL)) { + if ((vaddr & 0xffff) + len > 0x10000) { + /* Do one byte at a time: */ + int res = 0, i; + for (i=0; i 0x1000 && !(cache_flags & PHYSICAL) + && cpu->cd.x86.cr[0] & X86_CR0_PG) { + /* For WRITES: Read ALL BYTES FIRST and write them back!!! + Then do a write of all the new bytes. This is to make sure + than both pages around the boundary are writable so we don't + do a partial write. */ + int res = 0, i; + if (writeflag == MEM_WRITE) { + unsigned char tmp; + for (i=0; irunning = 0; + } return 0; } } } + return res; } -#endif +#endif /* X86 */ #ifdef MEM_URISC { @@ -159,6 +199,9 @@ ok = cpu->translate_address(cpu, vaddr, &paddr, (writeflag? FLAG_WRITEFLAG : 0) + (no_exceptions? FLAG_NOEXCEPTIONS : 0) +#ifdef MEM_X86 + + (cache_flags & NO_SEGMENTATION) +#endif + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0)); /* If the translation caused an exception, or was invalid in some way, we simply return without doing the memory @@ -168,6 +211,22 @@ } +#ifdef MEM_X86 + /* DOS debugging :-) */ + if (!quiet_mode && !(cache_flags & PHYSICAL)) { + if (paddr >= 0x400 && paddr <= 0x4ff) + debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag == + MEM_WRITE? "writing to" : "reading from", + (int)paddr); +#if 0 + if (paddr >= 0xf0000 && paddr <= 0xfffff) + debug("{ BIOS ACCESS: %s 0x%x }\n", + writeflag == MEM_WRITE? "writing to" : + "reading from", (int)paddr); +#endif + } +#endif + #ifdef MEM_MIPS /* * If correct cache emulation is enabled, and we need to simluate @@ -207,10 +266,6 @@ #endif /* MEM_MIPS */ - if (!(cache_flags & PHYSICAL)) - if (no_exceptions) - goto no_exception_access; - #ifndef MEM_USERLAND /* @@ -300,8 +355,12 @@ } #endif - res = mem->dev_f[i](cpu, mem, paddr, data, len, - writeflag, mem->dev_extra[i]); + res = 0; + if (!no_exceptions || (mem->dev_flags[i] & + MEM_READING_HAS_NO_SIDE_EFFECTS)) + res = mem->dev_f[i](cpu, mem, paddr, + data, len, writeflag, + mem->dev_extra[i]); #ifdef ENABLE_INSTRUCTION_DELAYS if (res == 0) @@ -311,11 +370,13 @@ ( (abs(res) - 1) * cpu->cd.mips.cpu_type.instrs_per_cycle ); #endif + +#ifndef MEM_X86 /* * If accessing the memory mapped device * failed, then return with a DBE exception. */ - if (res <= 0) { + if (res <= 0 && !no_exceptions) { debug("%s device '%s' addr %08lx " "failed\n", writeflag? "writing to" : "reading from", @@ -326,7 +387,7 @@ #endif return MEMORY_ACCESS_FAILED; } - +#endif goto do_return_ok; } @@ -390,7 +451,8 @@ /* Outside of physical RAM? */ if (paddr >= mem->physical_max) { - if ((paddr & 0xffff000000ULL) == 0x1f000000) { +#ifdef MEM_MIPS + if ((paddr & 0xffffc00000ULL) == 0x1fc00000) { /* Ok, this is PROM stuff */ } else if ((paddr & 0xfffff00000ULL) == 0x1ff00000) { /* Sprite reads from this area of memory... */ @@ -398,13 +460,19 @@ if (writeflag == MEM_READ) memset(data, 0, len); goto do_return_ok; - } else { - if (paddr >= mem->physical_max + 0 * 1024) { + } else +#endif /* MIPS */ + { + if (paddr >= mem->physical_max) { char *symbol; #ifdef MEM_MIPS uint64_t offset; #endif - if (!quiet_mode) { + /* This allows for example OS kernels to probe + memory a few KBs past the end of memory, + without giving too many warnings. */ + if (!quiet_mode && paddr >= + mem->physical_max + 0x40000) { fatal("[ memory_rw(): writeflag=%i ", writeflag); if (writeflag) { @@ -458,8 +526,13 @@ } if (writeflag == MEM_READ) { +#ifdef MEM_X86 + /* Reading non-existant memory on x86: */ + memset(data, 0xff, len); +#else /* Return all zeroes? (Or 0xff? TODO) */ memset(data, 0, len); +#endif #ifdef MEM_MIPS /* @@ -467,7 +540,8 @@ * an exceptions on an illegal read: */ if (cache != CACHE_NONE && cpu->machine-> - dbe_on_nonexistant_memaccess) { + dbe_on_nonexistant_memaccess && + !no_exceptions) { if (paddr >= mem->physical_max && paddr < mem->physical_max+1048576) mips_cpu_exception(cpu, @@ -487,8 +561,6 @@ #endif /* ifndef MEM_USERLAND */ -no_exception_access: - /* * Uncached access: */ @@ -530,6 +602,7 @@ else memcpy(data, memblock + offset, len); +#ifdef MEM_MIPS if (cache == CACHE_INSTRUCTION) { cpu->cd.mips.pc_last_host_4k_page = memblock + (offset & ~0xfff); @@ -540,6 +613,7 @@ } #endif } +#endif /* MIPS */ }