$OpenBSD: patch-source_mupen64plus-core_src_r4300_recomp_c,v 1.1.1.1 2011/12/26 13:38:27 stsp Exp $
--- src/r4300/recomp.c.orig	Sun Dec 18 23:13:44 2011
+++ src/r4300/recomp.c	Sun Dec 18 20:04:55 2011
@@ -2159,6 +2159,17 @@ static void (*recomp_ops[64])(void) =
    RSC     , RSWC1  , RSV  , RSV   , RSCD , RSDC1, RSV   , RSD
 };
 
+static int get_block_length(const precomp_block *block)
+{
+  return (block->end-block->start)/4;
+}
+
+static size_t get_block_memsize(const precomp_block *block)
+{
+  int length = get_block_length(block);
+  return ((length+1)+(length>>2)) * sizeof(precomp_instr);
+}
+
 /**********************************************************************
  ******************** initialize an empty block ***********************
  **********************************************************************/
@@ -2171,12 +2182,26 @@ void init_block(int *source, precomp_block *block)
   DebugMessage(M64MSG_INFO, "init block %x - %x", (int) block->start, (int) block->end);
 #endif
 
-  length = (block->end-block->start)/4;
+  length = get_block_length(block);
    
   if (!block->block)
   {
-    long memsize = ((length+1)+(length>>2)) * sizeof(precomp_instr);
-    block->block = (precomp_instr *) malloc_exec(memsize);
+    size_t memsize = get_block_memsize(block);
+    if (r4300emu == CORE_DYNAREC) {
+        block->block = (precomp_instr *) malloc_exec(memsize);
+        if (!block->block) {
+            DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate executable memory for dynamic recompiler. Try to use an interpreter mode.");
+            return;
+        }
+    }
+    else {
+        block->block = (precomp_instr *) malloc(memsize);
+        if (!block->block) {
+            DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate memory for cached interpreter.");
+            return;
+        }
+    }
+
     memset(block->block, 0, memsize);
     already_exist = 0;
   }
@@ -2338,6 +2363,22 @@ void init_block(int *source, precomp_block *block)
   end_section(COMPILER_SECTION);
 }
 
+void free_block(precomp_block *block)
+{
+    size_t memsize = get_block_memsize(block);
+
+    if (block->block) {
+        if (r4300emu == CORE_DYNAREC)
+            free_exec(block->block, memsize);
+        else
+            free(block->block);
+        block->block = NULL;
+    }
+    if (block->code) { free_exec(block->code, block->max_code_length); block->code = NULL; }
+    if (block->jumps_table) { free(block->jumps_table); block->jumps_table = NULL; }
+    if (block->riprel_table) { free(block->riprel_table); block->riprel_table = NULL; }
+}
+
 /**********************************************************************
  ********************* recompile a block of code **********************
  **********************************************************************/
@@ -2594,17 +2635,16 @@ void *malloc_exec(size_t size)
 #if defined(WIN32)
 	return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
 #elif defined(__GNUC__)
-   int pagesize = sysconf(_SC_PAGE_SIZE);
-   if (pagesize == -1)
-       { DebugMessage(M64MSG_ERROR, "Memory error: couldn't determine system memory page size."); return NULL; }
 
-   /* Allocate a buffer aligned on a page boundary; initial protection is PROT_READ | PROT_WRITE */
-   void *block = valloc(size);
-   if (block == NULL)
-       { DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate %i byte block of %i-byte aligned memory.", (int) size, pagesize); return NULL; }
+   #ifndef  MAP_ANONYMOUS
+      #ifdef MAP_ANON
+         #define MAP_ANONYMOUS MAP_ANON
+      #endif
+   #endif
 
-   if (mprotect(block, size, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
-       { DebugMessage(M64MSG_ERROR, "Memory error: couldn't set RWX permissions on %i byte block of memory.", (int) size); return NULL; }
+   void *block = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+   if (block == MAP_FAILED)
+       { DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate %zi byte block of aligned RWX memory.", size); return NULL; }
 
    return block;
 #else
@@ -2615,30 +2655,30 @@ void *malloc_exec(size_t size)
 /**********************************************************************
  ************* reallocate memory with executable bit set **************
  **********************************************************************/
-void *realloc_exec(void *ptr, size_t size, size_t newsize)
+void *realloc_exec(void *ptr, size_t oldsize, size_t newsize)
 {
    void* block = malloc_exec(newsize);
    if (block != NULL)
    {
       size_t copysize;
-      if (size < newsize)
-         copysize = size;
+      if (oldsize < newsize)
+         copysize = oldsize;
       else
          copysize = newsize;
       memcpy(block, ptr, copysize);
    }
-   free_exec(ptr);
+   free_exec(ptr, oldsize);
    return block;
 }
 
 /**********************************************************************
  **************** frees memory with executable bit set ****************
  **********************************************************************/
-void free_exec(void *ptr)
+void free_exec(void *ptr, size_t length)
 {
 #if defined(WIN32)
 	VirtualFree(ptr, 0, MEM_RELEASE);
-#else
-	free(ptr);
+#else
+	munmap(ptr, length);
 #endif
 }
