Add cache flush in py/asmarm.c and add new MP_PLAT_ALLOC_EXEC and MP_PLAT_FREE_EXEC macros

Fixes issue #840
diff --git a/py/asmarm.c b/py/asmarm.c
index 8ba22fa..fff95fd 100644
--- a/py/asmarm.c
+++ b/py/asmarm.c
@@ -40,8 +40,8 @@
 
 struct _asm_arm_t {
     uint pass;
-    uint code_offset;
-    uint code_size;
+    mp_uint_t code_offset;
+    mp_uint_t code_size;
     byte *code_base;
     byte dummy_data[4];
 
@@ -64,7 +64,7 @@
 
 void asm_arm_free(asm_arm_t *as, bool free_code) {
     if (free_code) {
-        m_del(byte, as->code_base, as->code_size);
+        MP_PLAT_FREE_EXEC(as->code_base, as->code_size);
     }
 
     m_del_obj(asm_arm_t, as);
@@ -80,9 +80,22 @@
 
 void asm_arm_end_pass(asm_arm_t *as) {
     if (as->pass == ASM_ARM_PASS_COMPUTE) {
-        // calculate size of code in bytes
-        as->code_size = as->code_offset;
-        as->code_base = m_new(byte, as->code_size);
+        MP_PLAT_ALLOC_EXEC(as->code_offset, (void**) &as->code_base, &as->code_size);
+        if(as->code_base == NULL) {
+            assert(0);
+        }
+    }
+    else if(as->pass == ASM_ARM_PASS_EMIT) {
+#ifdef __arm__
+        // flush I- and D-cache
+	asm volatile(
+                "0:"
+                "mrc p15, 0, r15, c7, c10, 3\n"
+                "bne 0b\n"
+                "mov r0, #0\n"
+	        "mcr p15, 0, r0, c7, c7, 0\n"
+                : : : "r0", "cc");
+#endif
     }
 }
 
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 1102bb7..95f8778 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -67,7 +67,7 @@
 
 void asm_thumb_free(asm_thumb_t *as, bool free_code) {
     if (free_code) {
-        m_del(byte, as->code_base, as->code_size);
+        MP_PLAT_FREE_EXEC(as->code_base, as->code_size);
     }
     /*
     if (as->label != NULL) {
@@ -94,9 +94,10 @@
 
 void asm_thumb_end_pass(asm_thumb_t *as) {
     if (as->pass == ASM_THUMB_PASS_COMPUTE) {
-        // calculate size of code in bytes
-        as->code_size = as->code_offset;
-        as->code_base = m_new(byte, as->code_size);
+        MP_PLAT_ALLOC_EXEC(as->code_offset, (void**) &as->code_base, &as->code_size);
+        if(as->code_base == NULL) {
+            assert(0);
+        }
         //printf("code_size: %u\n", as->code_size);
     }
 
diff --git a/py/asmx64.c b/py/asmx64.c
index 4695bdc..cf9d8b0 100644
--- a/py/asmx64.c
+++ b/py/asmx64.c
@@ -113,8 +113,8 @@
 
 struct _asm_x64_t {
     uint pass;
-    uint code_offset;
-    uint code_size;
+    mp_uint_t code_offset;
+    mp_uint_t code_size;
     byte *code_base;
     byte dummy_data[8];
 
@@ -123,18 +123,6 @@
     int num_locals;
 };
 
-// for allocating memory, see src/v8/src/platform-linux.cc
-void *alloc_mem(uint req_size, uint *alloc_size, bool is_exec) {
-    req_size = (req_size + 0xfff) & (~0xfff);
-    int prot = PROT_READ | PROT_WRITE | (is_exec ? PROT_EXEC : 0);
-    void *ptr = mmap(NULL, req_size, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-    if (ptr == MAP_FAILED) {
-        assert(0);
-    }
-    *alloc_size = req_size;
-    return ptr;
-}
-
 asm_x64_t *asm_x64_new(uint max_num_labels) {
     asm_x64_t *as;
 
@@ -147,8 +135,7 @@
 
 void asm_x64_free(asm_x64_t *as, bool free_code) {
     if (free_code) {
-        // need to un-mmap
-        //m_free(as->code_base);
+        MP_PLAT_FREE_EXEC(as->code_base, as->code_size);
     }
     /*
     if (as->label != NULL) {
@@ -176,11 +163,10 @@
 
 void asm_x64_end_pass(asm_x64_t *as) {
     if (as->pass == ASM_X64_PASS_COMPUTE) {
-        // calculate size of code in bytes
-        as->code_size = as->code_offset;
-        //as->code_base = m_new(byte, as->code_size); need to allocale executable memory
-        uint actual_alloc;
-        as->code_base = alloc_mem(as->code_size, &actual_alloc, true);
+        MP_PLAT_ALLOC_EXEC(as->code_offset, (void**) &as->code_base, &as->code_size);
+	if(as->code_base == NULL) {
+            assert(0);
+        }
         //printf("code_size: %u\n", as->code_size);
     }
 
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 2b89fab..78c288d 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -440,6 +440,14 @@
 #define MICROPY_MAKE_POINTER_CALLABLE(p) (p)
 #endif
 
+#ifndef MP_PLAT_ALLOC_EXEC
+#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) do { *ptr = m_new(byte, min_size); *size = min_size; } while(0)
+#endif
+
+#ifndef MP_PLAT_FREE_EXEC
+#define MP_PLAT_FREE_EXEC(ptr, size) m_del(byte, ptr, size)
+#endif
+
 // printf format spec to use for mp_int_t and friends
 #ifndef INT_FMT
 #ifdef __LP64__
diff --git a/unix/Makefile b/unix/Makefile
index ed79121..04a2dbd 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -75,6 +75,7 @@
 	file.c \
 	modsocket.c \
 	modos.c \
+        alloc.c \
 	$(SRC_MOD)
 
 ifeq ($(UNAME_S),Darwin)
diff --git a/unix/alloc.c b/unix/alloc.c
new file mode 100644
index 0000000..2c09f18
--- /dev/null
+++ b/unix/alloc.c
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Fabian Vogt
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#include "mpconfigport.h"
+
+void mp_unix_alloc_exec(mp_uint_t min_size, void** ptr, mp_uint_t *size)
+{
+    // size needs to be a multiple of the page size
+    *size = (min_size + 0xfff) & (~0xfff);
+    *ptr = mmap(NULL, *size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    if (*ptr == MAP_FAILED) {
+        *ptr = NULL;
+    }
+}
+
+void mp_unix_free_exec(void *ptr, mp_uint_t size)
+{
+    munmap(ptr, size);
+}
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 900bca7..7056f3a 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -114,6 +114,11 @@
 typedef void *machine_ptr_t; // must be of pointer size
 typedef const void *machine_const_ptr_t; // must be of pointer size
 
+void mp_unix_alloc_exec(mp_uint_t min_size, void** ptr, mp_uint_t *size);
+void mp_unix_free_exec(void *ptr, mp_uint_t size);
+#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) mp_unix_alloc_exec(min_size, ptr, size)
+#define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size)
+
 extern const struct _mp_obj_fun_builtin_t mp_builtin_input_obj;
 extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
 #define MICROPY_PORT_BUILTINS \