diff -urN qemu-0.8.2/block.c qemu-new/block.c
--- qemu-0.8.2/block.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/block.c	2006-09-11 15:46:30.000000000 +0100
@@ -23,6 +23,7 @@
  */
 #include "vl.h"
 #include "block_int.h"
+#include "cpu-pretend.h"
 
 #ifdef _BSD
 #include <sys/types.h>
@@ -423,24 +424,27 @@
 
     while (nb_sectors > 0) {
         if (sector_num == 0 && bs->boot_sector_enabled) {
-            memcpy(buf, bs->boot_sector_data, 512);
+            cpu_memcpy(buf, bs->boot_sector_data, 512);
             n = 1;
         } else if (bs->backing_hd) {
             if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
                 ret = drv->bdrv_read(bs, sector_num, buf, n);
                 if (ret < 0)
                     return -1;
+                cpu_pretend_write(buf, n * 512);
             } else {
                 /* read from the base image */
                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
                 if (ret < 0)
                     return -1;
+                cpu_pretend_write(buf, n * 512);
             }
         } else {
             ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
             if (ret < 0)
                 return -1;
             /* no need to loop */
+            cpu_pretend_write(buf, nb_sectors * 512);
             break;
         }
         nb_sectors -= n;
@@ -459,8 +463,9 @@
     if (bs->read_only)
         return -1;
     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
-        memcpy(bs->boot_sector_data, buf, 512);   
+        cpu_memcpy(bs->boot_sector_data, buf, 512);   
     }
+    cpu_pretend_read(buf, nb_sectors * 512);
     return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
 }
 
diff -urN qemu-0.8.2/cpu-all.h qemu-new/cpu-all.h
--- qemu-0.8.2/cpu-all.h	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/cpu-all.h	2006-09-11 17:16:28.000000000 +0100
@@ -20,6 +20,8 @@
 #ifndef CPU_ALL_H
 #define CPU_ALL_H
 
+#include "cpu-pretend.h"
+
 #if defined(__arm__) || defined(__sparc__)
 #define WORDS_ALIGNED
 #endif
@@ -595,30 +597,30 @@
 #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE))
 #define h2g(x) ((target_ulong)(x - GUEST_BASE))
 
-#define saddr(x) g2h(x)
-#define laddr(x) g2h(x)
+#define saddr(x, l) g2h(x)
+#define laddr(x, l) g2h(x)
 
 #else /* !CONFIG_USER_ONLY */
 /* NOTE: we use double casts if pointers and target_ulong have
    different sizes */
-#define saddr(x) (uint8_t *)(long)(x)
-#define laddr(x) (uint8_t *)(long)(x)
+#define saddr(x, l) (cpu_pretend_write((void *)x, l), (uint8_t *)(long)(x))
+#define laddr(x, l) (cpu_pretend_read((void *)x, l), (uint8_t *)(long)(x))
 #endif
 
-#define ldub_raw(p) ldub_p(laddr((p)))
-#define ldsb_raw(p) ldsb_p(laddr((p)))
-#define lduw_raw(p) lduw_p(laddr((p)))
-#define ldsw_raw(p) ldsw_p(laddr((p)))
-#define ldl_raw(p) ldl_p(laddr((p)))
-#define ldq_raw(p) ldq_p(laddr((p)))
-#define ldfl_raw(p) ldfl_p(laddr((p)))
-#define ldfq_raw(p) ldfq_p(laddr((p)))
-#define stb_raw(p, v) stb_p(saddr((p)), v)
-#define stw_raw(p, v) stw_p(saddr((p)), v)
-#define stl_raw(p, v) stl_p(saddr((p)), v)
-#define stq_raw(p, v) stq_p(saddr((p)), v)
-#define stfl_raw(p, v) stfl_p(saddr((p)), v)
-#define stfq_raw(p, v) stfq_p(saddr((p)), v)
+#define ldub_raw(p) ldub_p(laddr((p), 1))
+#define ldsb_raw(p) ldsb_p(laddr((p), 1))
+#define lduw_raw(p) lduw_p(laddr((p), 2))
+#define ldsw_raw(p) ldsw_p(laddr((p), 2))
+#define ldl_raw(p) ldl_p(laddr((p), 4))
+#define ldq_raw(p) ldq_p(laddr((p), 8))
+#define ldfl_raw(p) ldfl_p(laddr((p), 4))
+#define ldfq_raw(p) ldfq_p(laddr((p), 8))
+#define stb_raw(p, v) stb_p(saddr((p), 1), v)
+#define stw_raw(p, v) stw_p(saddr((p), 2), v)
+#define stl_raw(p, v) stl_p(saddr((p), 4), v)
+#define stq_raw(p, v) stq_p(saddr((p), 8), v)
+#define stfl_raw(p, v) stfl_p(saddr((p), 4), v)
+#define stfq_raw(p, v) stfq_p(saddr((p), 8), v)
 
 
 #if defined(CONFIG_USER_ONLY) 
@@ -818,6 +820,7 @@
 extern int phys_ram_fd;
 extern uint8_t *phys_ram_base;
 extern uint8_t *phys_ram_dirty;
+extern uint8_t *phys_ram_valid;
 
 /* physical memory access */
 #define TLB_INVALID_MASK   (1 << 3)
diff -urN qemu-0.8.2/cpu-pretend.h qemu-new/cpu-pretend.h
--- qemu-0.8.2/cpu-pretend.h	1970-01-01 01:00:00.000000000 +0100
+++ qemu-new/cpu-pretend.h	2006-09-11 17:47:30.000000000 +0100
@@ -0,0 +1,23 @@
+#ifndef CPU_PRETEND_H
+#define CPU_PRETEND_H
+
+#include <string.h>
+#include <sys/types.h>
+
+void cpu_pretend_read(const void * p, size_t size);
+void cpu_pretend_write(const void * p, size_t size);
+static inline void * cpu_memcpy(void * dest, const void * src, size_t n)
+{
+	cpu_pretend_read(src, n);
+	cpu_pretend_write(dest, n);
+	return memcpy(dest, src, n);
+}
+static inline char * cpu_strcpy(char * dest, const char * src)
+{
+	size_t len_src = strlen(src) + 1;
+	cpu_pretend_read(src, len_src);
+	cpu_pretend_write(dest, len_src);
+	return strcpy(dest, src);
+}
+
+#endif
diff -urN qemu-0.8.2/exec.c qemu-new/exec.c
--- qemu-0.8.2/exec.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/exec.c	2006-09-12 03:55:44.000000000 +0100
@@ -81,6 +81,7 @@
 int phys_ram_fd;
 uint8_t *phys_ram_base;
 uint8_t *phys_ram_dirty;
+uint8_t *phys_ram_valid;
 
 CPUState *first_cpu;
 /* current CPU in the current thread. It is only valid inside
@@ -2049,6 +2050,7 @@
                 addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
                 /* RAM case */
                 ptr = phys_ram_base + addr1;
+                cpu_pretend_write(ptr, l);
                 memcpy(ptr, buf, l);
                 if (!cpu_physical_memory_is_dirty(addr1)) {
                     /* invalidate code */
@@ -2083,7 +2085,7 @@
                 /* RAM case */
                 ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
                     (addr & ~TARGET_PAGE_MASK);
-                memcpy(buf, ptr, l);
+                cpu_memcpy(buf, ptr, l);
             }
         }
         len -= l;
@@ -2123,6 +2125,7 @@
             addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
             /* ROM/RAM case */
             ptr = phys_ram_base + addr1;
+            cpu_pretend_write(ptr, l);
             memcpy(ptr, buf, l);
         }
         len -= l;
@@ -2157,6 +2160,7 @@
         /* RAM case */
         ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
             (addr & ~TARGET_PAGE_MASK);
+        cpu_pretend_read(ptr, 4);
         val = ldl_p(ptr);
     }
     return val;
@@ -2193,6 +2197,7 @@
         /* RAM case */
         ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + 
             (addr & ~TARGET_PAGE_MASK);
+        cpu_pretend_read(ptr, 8);
         val = ldq_p(ptr);
     }
     return val;
@@ -2323,6 +2328,31 @@
     return 0;
 }
 
+void cpu_pretend_write(const void * p, size_t size)
+{
+	unsigned long from = (unsigned long)p - (unsigned long)phys_ram_base;
+	unsigned long i;
+	for (i = from; i < from + size && i < phys_ram_size; i++)
+		phys_ram_valid[i] = 0xff;
+}
+
+void cpu_pretend_read(const void * p, size_t size)
+{
+	unsigned long from = (unsigned long)p - (unsigned long)phys_ram_base;
+	unsigned long i;
+	for (i = from; i < from + size && i < phys_ram_size; i++)
+		if (phys_ram_valid[i] != 0xff) {
+			fprintf(stderr,
+				"Uninitialised read of address %lx, size %x",
+				from, size);
+			if (cpu_single_env)
+				fprintf(stderr, " with PC approximately %lx", GET_PC(cpu_single_env));
+			fprintf(stderr, "\n");
+			cpu_pretend_write(p, size);
+			return;
+		}
+}
+
 void dump_exec_info(FILE *f,
                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
 {
diff -urN qemu-0.8.2/hw/acpi.c qemu-new/hw/acpi.c
--- qemu-0.8.2/hw/acpi.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/acpi.c	2006-09-11 14:33:29.000000000 +0100
@@ -539,6 +539,7 @@
 
     cpu_register_physical_memory(base_addr, acpi_tables_size, 
                                  base_addr | IO_MEM_ROM);
+    cpu_pretend_write(phys_ram_base + base_addr, acpi_tables_size);
     
     /* RSDP */
     memset(rsdp, 0, sizeof(*rsdp));
diff -urN qemu-0.8.2/hw/arm_boot.c qemu-new/hw/arm_boot.c
--- qemu-0.8.2/hw/arm_boot.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/arm_boot.c	2006-09-11 14:20:20.000000000 +0100
@@ -53,7 +53,7 @@
         int cmdline_size;
 
         cmdline_size = strlen(kernel_cmdline);
-        memcpy (p + 2, kernel_cmdline, cmdline_size + 1);
+        cpu_memcpy (p + 2, kernel_cmdline, cmdline_size + 1);
         cmdline_size = (cmdline_size >> 2) + 1;
         stl_raw(p++, cmdline_size + 2);
         stl_raw(p++, 0x54410009);
diff -urN qemu-0.8.2/hw/mips_r4k.c qemu-new/hw/mips_r4k.c
--- qemu-0.8.2/hw/mips_r4k.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/mips_r4k.c	2006-09-11 14:24:47.000000000 +0100
@@ -252,10 +252,11 @@
         }
 
 	/* Store command line.  */
-        strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
+        cpu_strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
         /* FIXME: little endian support */
         *(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
         *(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
+        cpu_pretend_write(phys_ram_base + (16 << 20) - 264, 8);
     }
 
     /* Init internal devices */
diff -urN qemu-0.8.2/hw/pc.c qemu-new/hw/pc.c
--- qemu-0.8.2/hw/pc.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/pc.c	2006-09-11 15:20:40.000000000 +0100
@@ -386,6 +386,8 @@
     if (size < 0)
         goto fail;
     close(fd);
+    cpu_pretend_write(real_addr, (setup_sects + 1) * 512);
+    cpu_pretend_write(addr, size);
     return size;
  fail:
     close(fd);
@@ -739,6 +741,7 @@
         }
         pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
                 kernel_cmdline);
+        cpu_pretend_write(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096);
         stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x20, 0xA33F);
         stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x22,
                 KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
diff -urN qemu-0.8.2/hw/ppc.c qemu-new/hw/ppc.c
--- qemu-0.8.2/hw/ppc.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/ppc.c	2006-09-11 14:36:18.000000000 +0100
@@ -407,7 +407,7 @@
     NVRAM_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
         /* XXX: put the cmdline in NVRAM too ? */
-        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
+        cpu_strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
         NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
         NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
     } else {
diff -urN qemu-0.8.2/hw/ppc_chrp.c qemu-new/hw/ppc_chrp.c
--- qemu-0.8.2/hw/ppc_chrp.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/ppc_chrp.c	2006-09-11 14:23:48.000000000 +0100
@@ -378,6 +378,7 @@
         phys_ram_base[vga_bios_offset + 3] = 'V';
         cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4), 
                      vga_bios_size);
+        cpu_pretend_write(phys_ram_base + vga_bios_offset, vga_bios_size + 4);
         vga_bios_size += 8;
     }
     vga_bios_size = (vga_bios_size + 0xfff) & ~0xfff;
diff -urN qemu-0.8.2/hw/sun4m.c qemu-new/hw/sun4m.c
--- qemu-0.8.2/hw/sun4m.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/sun4m.c	2006-09-11 14:25:06.000000000 +0100
@@ -137,7 +137,7 @@
     nvram_set_lword(nvram,  0x38, KERNEL_LOAD_ADDR);
     nvram_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
-	strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
+	cpu_strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
 	nvram_set_lword(nvram,  0x40, CMDLINE_ADDR);
         nvram_set_lword(nvram,  0x44, strlen(cmdline));
     }
diff -urN qemu-0.8.2/hw/sun4u.c qemu-new/hw/sun4u.c
--- qemu-0.8.2/hw/sun4u.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/sun4u.c	2006-09-11 14:26:31.000000000 +0100
@@ -195,7 +195,7 @@
     NVRAM_set_lword(nvram,  0x3C, kernel_size);
     if (cmdline) {
         /* XXX: put the cmdline in NVRAM too ? */
-        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
+        cpu_strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
         NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
         NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
     } else {
diff -urN qemu-0.8.2/hw/tcx.c qemu-new/hw/tcx.c
--- qemu-0.8.2/hw/tcx.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/tcx.c	2006-09-11 15:02:32.000000000 +0100
@@ -276,6 +276,8 @@
 {
     TCXState *s;
     int io_memory;
+    
+    cpu_pretend_write(vram_base, vram_size);
 
     s = qemu_mallocz(sizeof(TCXState));
     if (!s)
diff -urN qemu-0.8.2/hw/vga.c qemu-new/hw/vga.c
--- qemu-0.8.2/hw/vga.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/hw/vga.c	2006-09-11 15:44:47.000000000 +0100
@@ -1727,6 +1727,8 @@
 {
     int i, j, v, b;
 
+    cpu_pretend_write(vga_ram_base, vga_ram_size);
+
     for(i = 0;i < 256; i++) {
         v = 0;
         for(j = 0; j < 8; j++) {
diff -urN qemu-0.8.2/loader.c qemu-new/loader.c
--- qemu-0.8.2/loader.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/loader.c	2006-09-11 14:59:12.000000000 +0100
@@ -50,6 +50,7 @@
         return -1;
     }
     close(fd);
+    cpu_pretend_write(addr, size);
     return size;
 }
 
diff -urN qemu-0.8.2/qemu-img.c qemu-new/qemu-img.c
--- qemu-0.8.2/qemu-img.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/qemu-img.c	2006-09-11 15:29:13.000000000 +0100
@@ -129,6 +129,9 @@
     printf(" %s", name);
 }
 
+void cpu_pretend_read(const void * p, size_t size) { }
+void cpu_pretend_write(const void * p, size_t size) { }
+
 void help(void)
 {
     printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2005 Fabrice Bellard\n"
diff -urN qemu-0.8.2/target-arm/cpu.h qemu-new/target-arm/cpu.h
--- qemu-0.8.2/target-arm/cpu.h	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/target-arm/cpu.h	2006-09-12 03:54:00.000000000 +0100
@@ -22,6 +22,8 @@
 
 #define TARGET_LONG_BITS 32
 
+#define GET_PC(env) env->regs[15]
+
 #include "cpu-defs.h"
 
 #include "softfloat.h"
diff -urN qemu-0.8.2/target-i386/cpu.h qemu-new/target-i386/cpu.h
--- qemu-0.8.2/target-i386/cpu.h	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/target-i386/cpu.h	2006-09-12 03:53:47.000000000 +0100
@@ -20,6 +20,8 @@
 #ifndef CPU_I386_H
 #define CPU_I386_H
 
+#define GET_PC(env) env->eip
+
 #include "config.h"
 
 #ifdef TARGET_X86_64
diff -urN qemu-0.8.2/target-i386/helper.c qemu-new/target-i386/helper.c
--- qemu-0.8.2/target-i386/helper.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/target-i386/helper.c	2006-09-11 20:37:52.000000000 +0100
@@ -3538,3 +3538,5 @@
     }
     env = saved_env;
 }
+
+unsigned long get_pc(void) { return cpu_single_env->eip; }
diff -urN qemu-0.8.2/target-i386/op.c qemu-new/target-i386/op.c
--- qemu-0.8.2/target-i386/op.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/target-i386/op.c	2006-09-11 17:27:49.000000000 +0100
@@ -18,7 +18,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#define ASM_SOFTMMU
 #include "exec.h"
 
 /* n must be a constant to be efficient */
diff -urN qemu-0.8.2/target-mips/cpu.h qemu-new/target-mips/cpu.h
--- qemu-0.8.2/target-mips/cpu.h	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/target-mips/cpu.h	2006-09-12 03:54:53.000000000 +0100
@@ -3,6 +3,8 @@
 
 #define TARGET_HAS_ICE 1
 
+#define GET_PC(env) env->PC
+
 #include "config.h"
 #include "mips-defs.h"
 #include "cpu-defs.h"
diff -urN qemu-0.8.2/target-ppc/cpu.h qemu-new/target-ppc/cpu.h
--- qemu-0.8.2/target-ppc/cpu.h	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/target-ppc/cpu.h	2006-09-12 03:54:20.000000000 +0100
@@ -22,6 +22,8 @@
 
 #include "config.h"
 
+#define GET_PC(env) env->nip
+
 #define TARGET_LONG_BITS 32
 
 #include "cpu-defs.h"
diff -urN qemu-0.8.2/target-sh4/cpu.h qemu-new/target-sh4/cpu.h
--- qemu-0.8.2/target-sh4/cpu.h	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/target-sh4/cpu.h	2006-09-12 03:54:36.000000000 +0100
@@ -22,6 +22,8 @@
 
 #include "config.h"
 
+#define GET_PC(env) env->pc
+
 #define TARGET_LONG_BITS 32
 #define TARGET_HAS_ICE 1
 
diff -urN qemu-0.8.2/target-sparc/cpu.h qemu-new/target-sparc/cpu.h
--- qemu-0.8.2/target-sparc/cpu.h	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/target-sparc/cpu.h	2006-09-12 03:55:05.000000000 +0100
@@ -3,6 +3,8 @@
 
 #include "config.h"
 
+#define GET_PC(env) env->pc
+
 #if !defined(TARGET_SPARC64)
 #define TARGET_LONG_BITS 32
 #define TARGET_FPREGS 32
diff -urN qemu-0.8.2/vl.c qemu-new/vl.c
--- qemu-0.8.2/vl.c	2006-07-22 18:23:34.000000000 +0100
+++ qemu-new/vl.c	2006-09-11 15:23:20.000000000 +0100
@@ -4768,6 +4768,8 @@
         if (ret)
             return ret;
     }
+    /* Forget about phys_ram_valid. */
+    memset(phys_ram_valid, 0xff, phys_ram_size);
     return 0;
 }
 
@@ -6073,10 +6075,12 @@
     phys_ram_size = ram_size + vga_ram_size + bios_size;
 
     phys_ram_base = qemu_vmalloc(phys_ram_size);
-    if (!phys_ram_base) {
+    phys_ram_valid = qemu_vmalloc(phys_ram_size);
+    if (!phys_ram_base || !phys_ram_valid) {
         fprintf(stderr, "Could not allocate physical memory\n");
         exit(1);
     }
+    memset(phys_ram_valid, 0, phys_ram_size);
 
     /* we always create the cdrom drive, even if no disk is there */
     bdrv_init();
