<html>
<body>
  <div id="body" style="background-color:#ffffff;" >
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head" style="border-bottom-width:1px;border-bottom-style:solid;" ><td class="headtd" style="padding:0;padding-top:.2em;" colspan="4">Commit in <b><tt>lxdream/src/sh4</tt></b></td></tr>
<tr><td><tt><a href="#file1">mmu.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+240</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-2</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">defbd44429d8 -> 677b1d85f1b4</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file2">mmu.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+10</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">defbd44429d8 -> 677b1d85f1b4</td></tr>
<tr><td><tt><a href="#file3">sh4core.in</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+11</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-26</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">defbd44429d8 -> 677b1d85f1b4</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file4">shadow.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+109</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-206</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">defbd44429d8 -> 677b1d85f1b4</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+370</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-234</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >4 modified files</small><br />
<pre class="comment" style="white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd;" >
Fix MMU on non-translated platforms
  - reintroduce old VMA translation functions (slightly modified)
  - modify shadow processing to work on post-translated memory ops
</pre>
<hr /><a name="file1" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>mmu.c</b></big> <small id="info" style="color: #888888;" >defbd44429d8 -> 677b1d85f1b4</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/mmu.c
+++ lxdream/src/sh4/mmu.c
@@ -34,6 +34,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > mem_region_fn_t *sh4_address_space;
 mem_region_fn_t *sh4_user_address_space;
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/* External address space (usually the same as the global ext_address_space) */
+static mem_region_fn_t *sh4_ext_address_space;
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /* Accessed from the UTLB accessor methods */
 uint32_t mmu_urc;
 uint32_t mmu_urb;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -92,6 +95,19 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #define IS_STOREQUEUE_PROTECTED() (mmu_user_storequeue_regions == &mmu_default_regions[DEFAULT_STOREQUEUE_SQMD_REGIONS])
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#ifndef SH4_TRANSLATOR
+/* Dummy MMU vtable functions */
+void mmu_utlb_init_vtable( struct utlb_entry *ent, struct utlb_page_entry *page, gboolean writable )
+{
+}
+void mmu_utlb_init_storequeue_vtable( struct utlb_entry *ent, struct utlb_page_entry *page )
+{
+}
+void mmu_utlb_1k_init_vtable( struct utlb_1k_entry *entry )
+{
+}
+#endif
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /*********************** Module public functions ****************************/
 
 /**
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -101,6 +117,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >                            
 void MMU_init()
 {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    sh4_ext_address_space = ext_address_space;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     sh4_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
     sh4_user_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
     mmu_user_storequeue_regions = &mmu_default_regions[DEFAULT_STOREQUEUE_REGIONS];
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -343,6 +360,14 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /********************** Address space maintenance *************************/
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+mem_region_fn_t *mmu_set_ext_address_space( mem_region_fn_t *ext )
+{
+    mem_region_fn_t *old_ext = sh4_ext_address_space;
+    sh4_ext_address_space = ext;
+    mmu_set_tlb_enabled(IS_TLB_ENABLED());
+    return old_ext;
+}
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * MMU accessor functions just increment URC - fixup here if necessary
  */
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -415,10 +440,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         mmu_utlb_register_all();
     } else {
         for( i=0, ptr = sh4_address_space; i<7; i++, ptr += LXDREAM_PAGE_TABLE_ENTRIES ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            memcpy( ptr, ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            memcpy( ptr, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >sh4_</span>ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
         for( i=0, ptr = sh4_user_address_space; i<4; i++, ptr += LXDREAM_PAGE_TABLE_ENTRIES ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-            memcpy( ptr, ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+            memcpy( ptr, <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >sh4_</span>ext_address_space, sizeof(mem_region_fn_t) * LXDREAM_PAGE_TABLE_ENTRIES );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
 
         mmu_register_mem_region( 0xE0000000, 0xE4000000, &p4_region_storequeue );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -1190,6 +1215,219 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ * Translate a virtual to physical address for reading, raising exceptions as
+ * observed.
+ * @param addr Pointer to the virtual memory address. On successful return,
+ * will be updated to contain the physical address.
+ */
+mem_region_fn_t FASTCALL mmu_get_region_for_vma_read( sh4vma_t *paddr )
+{
+    sh4vma_t addr = *paddr;
+    uint32_t mmucr = MMIO_READ(MMU,MMUCR);
+    if( addr & 0x80000000 ) {
+        if( IS_SH4_PRIVMODE() ) {
+            if( addr >= 0xE0000000 ) {
+                return sh4_address_space[((uint32_t)addr)>>12]; /* P4 - passthrough */
+            } else if( addr < 0xC0000000 ) {
+                /* P1, P2 regions are pass-through (no translation) */
+                return sh4_ext_address_space[VMA_TO_EXT_ADDR(addr)>>12];
+            }
+        } else {
+            if( addr >= 0xE0000000 && addr < 0xE4000000 &&
+                    ((mmucr&MMUCR_SQMD) == 0) ) {
+                /* Conditional user-mode access to the store-queue (no translation) */
+                return &p4_region_storequeue;
+            }
+            sh4_raise_exception(EXC_DATA_ADDR_READ);
+            return NULL;
+        }
+    }
+
+    if( (mmucr & MMUCR_AT) == 0 ) {
+        return sh4_ext_address_space[VMA_TO_EXT_ADDR(addr)>>12];
+    }
+
+    /* If we get this far, translation is required */
+    int entryNo;
+    if( ((mmucr & MMUCR_SV) == 0) || !IS_SH4_PRIVMODE() ) {
+        entryNo = mmu_utlb_lookup_vpn_asid( addr );
+    } else {
+        entryNo = mmu_utlb_lookup_vpn( addr );
+    }
+
+    switch(entryNo) {
+    case -1:
+        RAISE_TLB_ERROR(EXC_TLB_MISS_READ,addr);
+        return NULL;
+    case -2:
+        RAISE_TLB_MULTIHIT_ERROR(addr);
+        return NULL;
+    default:
+        if( (mmu_utlb[entryNo].flags & TLB_USERMODE) == 0 &&
+                !IS_SH4_PRIVMODE() ) {
+            /* protection violation */
+            RAISE_MEM_ERROR(EXC_TLB_PROT_READ,addr);
+            return NULL;
+        }
+
+        /* finally generate the target address */
+        sh4addr_t pma = (mmu_utlb[entryNo].ppn & mmu_utlb[entryNo].mask) |
+                (addr & (~mmu_utlb[entryNo].mask));
+        if( pma > 0x1C000000 ) { // Remap 1Cxx .. 1Fxx region to P4
+            addr = pma | 0xE0000000;
+            *paddr = addr;
+            return sh4_address_space[addr>>12];
+        } else {
+            *paddr = pma;
+            return sh4_ext_address_space[pma>>12];
+        }
+    }
+}
+
+/**
+ * Translate a virtual to physical address for prefetch, which mostly
+ * does not raise exceptions.
+ * @param addr Pointer to the virtual memory address. On successful return,
+ * will be updated to contain the physical address.
+ */
+mem_region_fn_t FASTCALL mmu_get_region_for_vma_prefetch( sh4vma_t *paddr )
+{
+    sh4vma_t addr = *paddr;
+    uint32_t mmucr = MMIO_READ(MMU,MMUCR);
+    if( addr & 0x80000000 ) {
+        if( IS_SH4_PRIVMODE() ) {
+            if( addr >= 0xE0000000 ) {
+                return sh4_address_space[((uint32_t)addr)>>12]; /* P4 - passthrough */
+            } else if( addr < 0xC0000000 ) {
+                /* P1, P2 regions are pass-through (no translation) */
+                return sh4_ext_address_space[VMA_TO_EXT_ADDR(addr)>>12];
+            }
+        } else {
+            if( addr >= 0xE0000000 && addr < 0xE4000000 &&
+                    ((mmucr&MMUCR_SQMD) == 0) ) {
+                /* Conditional user-mode access to the store-queue (no translation) */
+                return &p4_region_storequeue;
+            }
+            sh4_raise_exception(EXC_DATA_ADDR_READ);
+            return NULL;
+        }
+    }
+
+    if( (mmucr & MMUCR_AT) == 0 ) {
+        return sh4_ext_address_space[VMA_TO_EXT_ADDR(addr)>>12];
+    }
+
+    /* If we get this far, translation is required */
+    int entryNo;
+    if( ((mmucr & MMUCR_SV) == 0) || !IS_SH4_PRIVMODE() ) {
+        entryNo = mmu_utlb_lookup_vpn_asid( addr );
+    } else {
+        entryNo = mmu_utlb_lookup_vpn( addr );
+    }
+
+    switch(entryNo) {
+    case -1:
+        return &mem_region_unmapped;
+    case -2:
+        RAISE_TLB_MULTIHIT_ERROR(addr);
+        return NULL;
+    default:
+        if( (mmu_utlb[entryNo].flags & TLB_USERMODE) == 0 &&
+                !IS_SH4_PRIVMODE() ) {
+            /* protection violation */
+            return &mem_region_unmapped;
+        }
+
+        /* finally generate the target address */
+        sh4addr_t pma = (mmu_utlb[entryNo].ppn & mmu_utlb[entryNo].mask) |
+                (addr & (~mmu_utlb[entryNo].mask));
+        if( pma > 0x1C000000 ) { // Remap 1Cxx .. 1Fxx region to P4
+            addr = pma | 0xE0000000;
+            *paddr = addr;
+            return sh4_address_space[addr>>12];
+        } else {
+            *paddr = pma;
+            return sh4_ext_address_space[pma>>12];
+        }
+    }
+}
+
+/**
+ * Translate a virtual to physical address for writing, raising exceptions as
+ * observed.
+ */
+mem_region_fn_t FASTCALL mmu_get_region_for_vma_write( sh4vma_t *paddr )
+{
+    sh4vma_t addr = *paddr;
+    uint32_t mmucr = MMIO_READ(MMU,MMUCR);
+    if( addr & 0x80000000 ) {
+        if( IS_SH4_PRIVMODE() ) {
+            if( addr >= 0xE0000000 ) {
+                return sh4_address_space[((uint32_t)addr)>>12]; /* P4 - passthrough */
+            } else if( addr < 0xC0000000 ) {
+                /* P1, P2 regions are pass-through (no translation) */
+                return sh4_ext_address_space[VMA_TO_EXT_ADDR(addr)>>12];
+            }
+        } else {
+            if( addr >= 0xE0000000 && addr < 0xE4000000 &&
+                    ((mmucr&MMUCR_SQMD) == 0) ) {
+                /* Conditional user-mode access to the store-queue (no translation) */
+                return &p4_region_storequeue;
+            }
+            sh4_raise_exception(EXC_DATA_ADDR_WRITE);
+            return NULL;
+        }
+    }
+
+    if( (mmucr & MMUCR_AT) == 0 ) {
+        return sh4_ext_address_space[VMA_TO_EXT_ADDR(addr)>>12];
+    }
+
+    /* If we get this far, translation is required */
+    int entryNo;
+    if( ((mmucr & MMUCR_SV) == 0) || !IS_SH4_PRIVMODE() ) {
+        entryNo = mmu_utlb_lookup_vpn_asid( addr );
+    } else {
+        entryNo = mmu_utlb_lookup_vpn( addr );
+    }
+
+    switch(entryNo) {
+    case -1:
+        RAISE_TLB_ERROR(EXC_TLB_MISS_WRITE,addr);
+        return NULL;
+    case -2:
+        RAISE_TLB_MULTIHIT_ERROR(addr);
+        return NULL;
+    default:
+        if( IS_SH4_PRIVMODE() ? ((mmu_utlb[entryNo].flags & TLB_WRITABLE) == 0)
+                : ((mmu_utlb[entryNo].flags & TLB_USERWRITABLE) != TLB_USERWRITABLE) ) {
+            /* protection violation */
+            RAISE_MEM_ERROR(EXC_TLB_PROT_WRITE,addr);
+            return NULL;
+        }
+
+        if( (mmu_utlb[entryNo].flags & TLB_DIRTY) == 0 ) {
+            RAISE_MEM_ERROR(EXC_INIT_PAGE_WRITE, addr);
+            return NULL;
+        }
+
+        /* finally generate the target address */
+        sh4addr_t pma = (mmu_utlb[entryNo].ppn & mmu_utlb[entryNo].mask) |
+                (addr & (~mmu_utlb[entryNo].mask));
+        if( pma > 0x1C000000 ) { // Remap 1Cxx .. 1Fxx region to P4
+            addr = pma | 0xE0000000;
+            *paddr = addr;
+            return sh4_address_space[addr>>12];
+        } else {
+            *paddr = pma;
+            return sh4_ext_address_space[pma>>12];
+        }
+    }
+}
+
+
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /********************** TLB Direct-Access Regions ***************************/
 #define ITLB_ENTRY(addr) ((addr>>7)&0x03)
 
</pre></div>
<hr /><a name="file2" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>mmu.h</b></big> <small id="info" style="color: #888888;" >defbd44429d8 -> 677b1d85f1b4</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/mmu.h
+++ lxdream/src/sh4/mmu.h
@@ -106,8 +106,18 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     mem_region_fn_t tlb_multihit;
 };
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/** Set the MMU's target external address space
+ * @return the previous address space.
+ */
+mem_region_fn_t *mmu_set_ext_address_space( mem_region_fn_t *space );
+
+/* Address translation functions */
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > sh4addr_t FASTCALL mmu_vma_to_phys_disasm( sh4vma_t vma );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+mem_region_fn_t FASTCALL mmu_get_region_for_vma_read( sh4vma_t *addr );
+mem_region_fn_t FASTCALL mmu_get_region_for_vma_write( sh4vma_t *addr );
+mem_region_fn_t FASTCALL mmu_get_region_for_vma_prefetch( sh4vma_t *addr );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/* Translator provided helpers */
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void mmu_utlb_init_vtable( struct utlb_entry *ent, struct utlb_page_entry *page, gboolean writable ); 
 void mmu_utlb_1k_init_vtable( struct utlb_1k_entry *ent ); 
 void mmu_utlb_init_storequeue_vtable( struct utlb_entry *ent, struct utlb_page_entry *page );
</pre></div>
<hr /><a name="file3" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>sh4core.in</b></big> <small id="info" style="color: #888888;" >defbd44429d8 -> 677b1d85f1b4</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/sh4core.in
+++ lxdream/src/sh4/sh4core.in
@@ -162,28 +162,14 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define ADDRSPACE (IS_SH4_PRIVMODE() ? sh4_address_space : sh4_user_address_space)
 #define SQADDRSPACE (IS_SH4_PRIVMODE() ? storequeue_address_space : storequeue_user_address_space)
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#ifdef HAVE_FRAME_ADDRESS
-static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
-#define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
-#define MEM_READ_BYTE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte)((addr), &&except)
-#define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte_for_write)((addr), &&except)
-#define MEM_READ_WORD( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_word)((addr), &&except)
-#define MEM_READ_LONG( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_long)((addr), &&except)
-#define MEM_WRITE_BYTE( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_byte)((addr), (val), &&except)
-#define MEM_WRITE_WORD( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_word)((addr), (val), &&except)
-#define MEM_WRITE_LONG( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_long)((addr), (val), &&except)
-#define MEM_PREFETCH( addr ) ((mem_prefetch_exc_fn_t)ADDRSPACE[(addr)>>12]->prefetch)((addr), &&except)
-#else
-#define INIT_EXCEPTIONS(label)
-#define MEM_READ_BYTE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte(addr)
-#define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte_for_write(addr)
-#define MEM_READ_WORD( addr, val ) val = ADDRSPACE[(addr)>>12]->read_word(addr)
-#define MEM_READ_LONG( addr, val ) val = ADDRSPACE[(addr)>>12]->read_long(addr)
-#define MEM_WRITE_BYTE( addr, val ) ADDRSPACE[(addr)>>12]->write_byte(addr, val)
-#define MEM_WRITE_WORD( addr, val ) ADDRSPACE[(addr)>>12]->write_word(addr, val)
-#define MEM_WRITE_LONG( addr, val ) ADDRSPACE[(addr)>>12]->write_long(addr, val)
-#define MEM_PREFETCH( addr ) ADDRSPACE[(addr)>>12]->prefetch(addr)
-#endif
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define MEM_READ_BYTE( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_read(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_byte(addrtmp); }
+#define MEM_READ_BYTE_FOR_WRITE( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_byte_for_write(addrtmp); }
+#define MEM_READ_WORD( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_read(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_word(addrtmp); }
+#define MEM_READ_LONG( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_read(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_long(addrtmp); }
+#define MEM_WRITE_BYTE( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->write_byte(addrtmp,val); }
+#define MEM_WRITE_WORD( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->write_word(addrtmp,val); }
+#define MEM_WRITE_LONG( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->write_long(addrtmp,val); }
+#define MEM_PREFETCH( addr )  addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_prefetch(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->prefetch(addrtmp); }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -346,10 +332,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     uint32_t tmp;
     float ftmp;
     double dtmp;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    int64_t memtmp; // temporary holder for memory reads
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    sh4addr_t addrtmp; // temporary holder for memory addresses
+    mem_region_fn_t fntmp;
+    
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    INIT_EXCEPTIONS(except)
-    
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #define R0 sh4r.r[0]
     pc = sh4r.pc;
     if( pc > 0xFFFFFF00 ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -1306,7 +1292,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     sh4r.pc = sh4r.new_pc;
     sh4r.new_pc += 2;
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-except:
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     sh4r.in_delay_slot = 0;
     return TRUE;
 }
</pre></div>
<hr /><a name="file4" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/sh4</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>shadow.c</b></big> <small id="info" style="color: #888888;" >defbd44429d8 -> 677b1d85f1b4</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/sh4/shadow.c
+++ lxdream/src/sh4/shadow.c
@@ -23,18 +23,12 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #include "clock.h"
 #include "mem.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "mmio.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "sh4/sh4.h"
 #include "sh4/sh4core.h"
 #include "sh4/sh4trans.h"
 #include "sh4/mmu.h"
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#ifdef HAVE_FRAME_ADDRESS
-static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
-#define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
-#else
-#define INIT_EXCEPTIONS(label)
-#endif
-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > typedef enum {
     READ_LONG,
     WRITE_LONG,
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -53,13 +47,17 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     MemOp op;
     sh4addr_t addr;
     uint32_t value;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    sh4addr_t exception_pc;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > };
 
 static struct sh4_registers shadow_sh4r;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static struct mem_region_fn **log_address_space;
-static struct mem_region_fn **check_address_space;
-static struct mem_region_fn **real_address_space;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static struct mem_region_fn **shadow_address_space;
+static struct mem_region_fn **p4_address_space;
+
+typedef enum {
+    SHADOW_LOG,
+    SHADOW_CHECK
+} shadow_mode_t;
+static shadow_mode_t shadow_address_mode = SHADOW_LOG;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #define MEM_LOG_SIZE 4096
 static struct mem_log_entry *mem_log;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -68,7 +66,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #define IS_STORE_QUEUE(X) (((X)&0xFC000000) == 0xE0000000)
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static void log_mem_op( MemOp op, sh4addr_t addr, uint32_t value<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >, int exception</span> )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static void log_mem_op( MemOp op, sh4addr_t addr, uint32_t value )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     if( mem_log_posn == mem_log_size ) {
         struct mem_log_entry *tmp = realloc(mem_log, mem_log_size * sizeof(struct mem_log_entry) * 2);
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -79,11 +77,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     mem_log[mem_log_posn].op = op;
     mem_log[mem_log_posn].addr = addr;
     mem_log[mem_log_posn].value = value;
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( exception ) {
-        mem_log[mem_log_posn].exception_pc = sh4r.pc;
-    } else {
-        mem_log[mem_log_posn].exception_pc = -1;
-    }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     mem_log_posn++;
 }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -103,7 +96,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static int32_t check_mem_op( MemOp op, sh4addr_t addr, uint32_t value<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >, int *exception</span> )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static int32_t check_mem_op( MemOp op, sh4addr_t addr, uint32_t value )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
     if( mem_check_posn >= mem_log_posn ) {
         fprintf( stderr, "Unexpected interpreter memory operation: " );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -121,14 +114,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         print_mem_op(stderr, op, addr, value );
         abort();
     }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
-    if( mem_log[mem_check_posn].exception_pc != -1 ) {
-        sh4_reraise_exception(mem_log[mem_check_posn].exception_pc);
-        *exception = 1;
-    } else {
-        *exception = 0;
-    }
-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return mem_log[mem_check_posn++].value;
 }
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -201,202 +186,117 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return isgood;
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static FASTCALL int32_t log_read_long( sh4addr_t addr, void *exc )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static mem_region_fn_t real_region( sh4addr_t addr )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    INIT_EXCEPTIONS(except);
-    int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_long)(addr, &&except);
-    log_mem_op( READ_LONG, addr, rv, 0 );
-    return rv;
-except:
-    log_mem_op( READ_LONG, addr, rv, 1 );
-    SH4_EXCEPTION_EXIT();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( addr >= 0xE0000000 )
+        return p4_address_space[VMA_TO_EXT_ADDR(addr)>>12];
+    else
+        return ext_address_space[VMA_TO_EXT_ADDR(addr)>>12];
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static FASTCALL int32_t log_read_word( sh4addr_t addr, void *exc )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static FASTCALL int32_t shadow_read_long( sh4addr_t addr )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    INIT_EXCEPTIONS(except);
-    int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_word)(addr, &&except);
-    log_mem_op( READ_WORD, addr, rv, 0 );
-    return rv;
-except:
-    log_mem_op( READ_WORD, addr, rv, 1 );
-    SH4_EXCEPTION_EXIT();
-}
-
-static FASTCALL int32_t log_read_byte( sh4addr_t addr, void *exc )
-{
-    INIT_EXCEPTIONS(except);
-    int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_byte)(addr, &&except);
-    log_mem_op( READ_BYTE, addr, rv, 0 );
-    return rv;
-except:
-    log_mem_op( READ_BYTE, addr, rv, 1 );
-    SH4_EXCEPTION_EXIT();
-}
-
-static FASTCALL int32_t log_read_byte_for_write( sh4addr_t addr, void *exc )
-{
-    INIT_EXCEPTIONS(except);
-    int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_byte_for_write)(addr, &&except);
-    log_mem_op( READ_BYTE_FOR_WRITE, addr, rv, 0 );
-    return rv;
-except:
-    log_mem_op( READ_BYTE_FOR_WRITE, addr, rv, 1 );
-    SH4_EXCEPTION_EXIT();
-}
-
-static FASTCALL void log_write_long( sh4addr_t addr, uint32_t val, void *exc )
-{
-    INIT_EXCEPTIONS(except);
-    ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_long)(addr, val, &&except);
-    if( !IS_STORE_QUEUE(addr) )
-        log_mem_op( WRITE_LONG, addr, val, 0 );
-    return;
-except:
-    if( !IS_STORE_QUEUE(addr) )
-        log_mem_op( WRITE_LONG, addr, val, 1 );
-    SH4_EXCEPTION_EXIT();
-}
-
-static FASTCALL void log_write_word( sh4addr_t addr, uint32_t val, void *exc )
-{
-    INIT_EXCEPTIONS(except);
-    ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_word)(addr, val, &&except);
-    if( !IS_STORE_QUEUE(addr) )
-        log_mem_op( WRITE_WORD, addr, val, 0 );
-    return;
-except:
-    if( !IS_STORE_QUEUE(addr) )
-        log_mem_op( WRITE_WORD, addr, val, 1 );
-    SH4_EXCEPTION_EXIT();
-}
-
-static FASTCALL void log_write_byte( sh4addr_t addr, uint32_t val, void *exc )
-{
-    INIT_EXCEPTIONS(except);
-    ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_byte)(addr, val, &&except);
-    if( !IS_STORE_QUEUE(addr) )
-        log_mem_op( WRITE_BYTE, addr, val, 0 );
-    return;
-except:
-    if( !IS_STORE_QUEUE(addr) )
-        log_mem_op( WRITE_BYTE, addr, val, 1 );
-    SH4_EXCEPTION_EXIT();
-}
-
-static FASTCALL void log_prefetch( sh4addr_t addr, void *exc )
-{
-    INIT_EXCEPTIONS(except);
-    ((mem_prefetch_exc_fn_t)real_address_space[addr>>12]->prefetch)(addr, &&except);
-    log_mem_op( PREFETCH, addr, 0, 0 );
-    return;
-except:
-    log_mem_op( PREFETCH, addr, 0, 1 );
-    SH4_EXCEPTION_EXIT();
-}
-
-static FASTCALL int32_t check_read_long( sh4addr_t addr, void *exc )
-{
-    int except;
-    int32_t value = check_mem_op( READ_LONG, addr, 0, &except );
-    if( except ) {
-        SH4_EXCEPTION_EXIT();
-    }
-    return value;
-}
-
-static FASTCALL int32_t check_read_word( sh4addr_t addr, void *exc )
-{
-    int except;
-    int32_t value = check_mem_op( READ_WORD, addr, 0, &except );
-    if( except ) {
-        SH4_EXCEPTION_EXIT();
-    }
-    return value;
-}
-
-static FASTCALL int32_t check_read_byte( sh4addr_t addr, void *exc )
-{
-    int except;
-    int32_t value = check_mem_op( READ_BYTE, addr, 0, &except );
-    if( except ) {
-        SH4_EXCEPTION_EXIT();
-    }
-    return value;
-}
-
-static FASTCALL int32_t check_read_byte_for_write( sh4addr_t addr, void *exc )
-{
-    int except;
-    int32_t value = check_mem_op( READ_BYTE_FOR_WRITE, addr, 0, &except );
-    if( except ) {
-        SH4_EXCEPTION_EXIT();
-    }
-    return value;
-}
-
-static FASTCALL void check_write_long( sh4addr_t addr, uint32_t value, void *exc )
-{
-    if( !IS_STORE_QUEUE(addr) ) {
-        int except;
-        check_mem_op( WRITE_LONG, addr, value, &except );
-        if( except ) {
-            SH4_EXCEPTION_EXIT();
-        }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( shadow_address_mode == SHADOW_LOG ) {
+        int32_t rv = real_region(addr)->read_long(addr);
+        log_mem_op( READ_LONG, addr, rv );
+        return rv;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        real_address_space[addr>>12]->write_long(addr, value);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        return check_mem_op( READ_LONG, addr, 0 );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static FASTCALL void check_write_word( sh4addr_t addr, uint32_t value, void *exc )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static FASTCALL int32_t shadow_read_word( sh4addr_t addr )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( !IS_STORE_QUEUE(addr) ) {
-        int except;
-        check_mem_op( WRITE_WORD, addr, value, &except );
-        if( except ) {
-            SH4_EXCEPTION_EXIT();
-        }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( shadow_address_mode == SHADOW_LOG ) {
+        int32_t rv = real_region(addr)->read_word(addr);
+        log_mem_op( READ_WORD, addr, rv );
+        return rv;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        real_address_space[addr>>12]->write_word(addr, value);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        return check_mem_op( READ_WORD, addr, 0 );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static FASTCALL void check_write_byte( sh4addr_t addr, uint32_t value, void *exc )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static FASTCALL int32_t shadow_read_byte( sh4addr_t addr )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( !IS_STORE_QUEUE(addr) ){
-        int except;
-        check_mem_op( WRITE_BYTE, addr, value, &except );
-        if( except ) {
-            SH4_EXCEPTION_EXIT();
-        }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( shadow_address_mode == SHADOW_LOG ) {
+        int32_t rv = real_region(addr)->read_byte(addr);
+        log_mem_op( READ_BYTE, addr, rv );
+        return rv;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        real_address_space[addr>>12]->write_byte(addr, value);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        return check_mem_op( READ_BYTE, addr, 0 );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static FASTCALL void check_prefetch( sh4addr_t addr, void *exc )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static FASTCALL int32_t shadow_read_byte_for_write( sh4addr_t addr )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    int except;
-    check_mem_op( PREFETCH, addr, 0, &except );
-    if( except ) {
-        SH4_EXCEPTION_EXIT();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( shadow_address_mode == SHADOW_LOG ) {
+        int32_t rv = real_region(addr)->read_byte_for_write(addr);
+        log_mem_op( READ_BYTE_FOR_WRITE, addr, rv );
+        return rv;
+    } else {
+        return check_mem_op( READ_BYTE_FOR_WRITE, addr, 0 );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-struct mem_region_fn log_fns = {
-        (mem_read_fn_t)log_read_long, (mem_write_fn_t)log_write_long,
-        (mem_read_fn_t)log_read_word, (mem_write_fn_t)log_write_word,
-        (mem_read_fn_t)log_read_byte, (mem_write_fn_t)log_write_byte,
-        NULL, NULL, (mem_prefetch_fn_t)log_prefetch, (mem_read_fn_t)log_read_byte_for_write };
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static FASTCALL void shadow_write_long( sh4addr_t addr, uint32_t val )
+{
+    if( shadow_address_mode == SHADOW_LOG ) {
+        real_region(addr)->write_long(addr, val);
+        if( !IS_STORE_QUEUE(addr) )
+            log_mem_op( WRITE_LONG, addr, val );
+    } else {
+        if( !IS_STORE_QUEUE(addr) ) {
+            check_mem_op( WRITE_LONG, addr, val );
+        } else {
+            real_region(addr)->write_long(addr, val);
+        }
+    }
+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-struct mem_region_fn check_fns = {
-        (mem_read_fn_t)check_read_long, (mem_write_fn_t)check_write_long,
-        (mem_read_fn_t)check_read_word, (mem_write_fn_t)check_write_word,
-        (mem_read_fn_t)check_read_byte, (mem_write_fn_t)check_write_byte,
-        NULL, NULL, (mem_prefetch_fn_t)check_prefetch, (mem_read_fn_t)check_read_byte_for_write };
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static FASTCALL void shadow_write_word( sh4addr_t addr, uint32_t val )
+{
+    if( shadow_address_mode == SHADOW_LOG ) {
+        real_region(addr)->write_word(addr, val);
+        if( !IS_STORE_QUEUE(addr) )
+            log_mem_op( WRITE_WORD, addr, val );
+    } else {
+        if( !IS_STORE_QUEUE(addr) ) {
+            check_mem_op( WRITE_WORD, addr, val );
+        } else {
+            real_region(addr)->write_word(addr, val);
+        }
+    }
+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static FASTCALL void shadow_write_byte( sh4addr_t addr, uint32_t val )
+{
+    if( shadow_address_mode == SHADOW_LOG ) {
+        real_region(addr)->write_byte(addr, val);
+        if( !IS_STORE_QUEUE(addr) )
+            log_mem_op( WRITE_BYTE, addr, val );
+    } else {
+        if( !IS_STORE_QUEUE(addr) ) {
+            check_mem_op( WRITE_BYTE, addr, val );
+        } else {
+            real_region(addr)->write_byte(addr, val);
+        }
+    }
+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static FASTCALL void shadow_prefetch( sh4addr_t addr )
+{
+    if( shadow_address_mode == SHADOW_LOG ) {
+        real_region(addr)->prefetch(addr);
+        log_mem_op( PREFETCH, addr, 0 );
+    } else {
+        check_mem_op( PREFETCH, addr, 0 );
+    }
+}
+struct mem_region_fn shadow_fns = {
+        shadow_read_long, shadow_write_long,
+        shadow_read_word, shadow_write_word,
+        shadow_read_byte, shadow_write_byte,
+        NULL, NULL, shadow_prefetch, shadow_read_byte_for_write };
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 void sh4_shadow_block_begin()
 {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -412,7 +312,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     memcpy( &temp_sh4r, &sh4r, sizeof(struct sh4_registers) );
     memcpy( &sh4r, &shadow_sh4r, sizeof(struct sh4_registers) );
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    sh4_address_space = check_address_space;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    shadow_address_mode = SHADOW_CHECK;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     mem_check_posn = 0;
     sh4r.new_pc = sh4r.pc + 2;
     while( sh4r.slice_cycle < temp_sh4r.slice_cycle ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -434,18 +334,17 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
         abort();
     }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    sh4_address_space = real_address_space;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    shadow_address_mode = SHADOW_LOG;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 
 void sh4_shadow_init()
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    real_address_space = sh4_address_space;
-    log_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
-    check_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
-    for( unsigned i=0; i < (256 * 4096); i++ ) {
-        log_address_space[i] = &log_fns;
-        check_address_space[i] = &check_fns;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    shadow_address_mode = SHADOW_LOG;
+    p4_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 32 );
+    shadow_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 32 );
+    for( unsigned i=0; i < (32 * 4096); i++ ) {
+        shadow_address_space[i] = &shadow_fns;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
     mem_log_size = MEM_LOG_SIZE;
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -454,6 +353,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     sh4_translate_set_callbacks( sh4_shadow_block_begin, sh4_shadow_block_end );
     sh4_translate_set_fastmem( FALSE );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    sh4_translate_set_address_space( log_address_space, log_address_space );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    memcpy( p4_address_space, sh4_address_space + (0xE0000000>>LXDREAM_PAGE_BITS),
+            sizeof(mem_region_fn_t) * (0x20000000>>LXDREAM_PAGE_BITS) );
+    memcpy( sh4_address_space + (0xE0000000>>LXDREAM_PAGE_BITS), shadow_address_space,
+            sizeof(mem_region_fn_t) * (0x20000000>>LXDREAM_PAGE_BITS) );
+    mmu_set_ext_address_space(shadow_address_space);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>