diff --git a/extmod/machine_mem.c b/extmod/machine_mem.c
new file mode 100644
index 0000000000000000000000000000000000000000..634ef2f6b5440ff07d8ed4c7fc8b8ac767dd57d4
--- /dev/null
+++ b/extmod/machine_mem.c
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * 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 "extmod/machine_mem.h"
+
+#if MICROPY_PY_MACHINE
+
+STATIC void machine_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+    (void)kind;
+    machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_printf(print, "<%u-bit memory>", 8 * self->elem_size);
+}
+
+STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
+    // TODO support slice index to read/write multiple values at once
+    machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
+    if (value == MP_OBJ_NULL) {
+        // delete
+        return MP_OBJ_NULL; // op not supported
+    } else if (value == MP_OBJ_SENTINEL) {
+        // load
+        uintptr_t addr = machine_mem_get_read_addr(index, self->elem_size);
+        uint32_t val;
+        switch (self->elem_size) {
+            case 1: val = (*(uint8_t*)addr); break;
+            case 2: val = (*(uint16_t*)addr); break;
+            default: val = (*(uint32_t*)addr); break;
+        }
+        return mp_obj_new_int(val);
+    } else {
+        // store
+        uintptr_t addr = machine_mem_get_write_addr(index, self->elem_size);
+        uint32_t val = mp_obj_get_int(value);
+        switch (self->elem_size) {
+            case 1: (*(uint8_t*)addr) = val; break;
+            case 2: (*(uint16_t*)addr) = val; break;
+            default: (*(uint32_t*)addr) = val; break;
+        }
+        return mp_const_none;
+    }
+}
+
+const mp_obj_type_t machine_mem_type = {
+    { &mp_type_type },
+    .name = MP_QSTR_mem,
+    .print = machine_mem_print,
+    .subscr = machine_mem_subscr,
+};
+
+const machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1};
+const machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2};
+const machine_mem_obj_t machine_mem32_obj = {{&machine_mem_type}, 4};
+
+#endif // MICROPY_PY_MACHINE
diff --git a/extmod/machine_mem.h b/extmod/machine_mem.h
new file mode 100644
index 0000000000000000000000000000000000000000..aeac0c2a2527cfc7b7b0d63977527d036afe033e
--- /dev/null
+++ b/extmod/machine_mem.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Damien P. George
+ *
+ * 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.
+ */
+
+
+#ifndef MICROPY_EXTMOD_MACHINE_MEM
+#define MICROPY_EXTMOD_MACHINE_MEM
+
+#include "py/obj.h"
+
+typedef struct _machine_mem_obj_t {
+    mp_obj_base_t base;
+    unsigned elem_size; // in bytes
+} machine_mem_obj_t;
+
+extern const mp_obj_type_t machine_mem_type;
+
+extern const machine_mem_obj_t machine_mem8_obj;
+extern const machine_mem_obj_t machine_mem16_obj;
+extern const machine_mem_obj_t machine_mem32_obj;
+
+// It is expected that a port will provide the following 2 functions.
+// We define the prototypes here, but the modmachine.c file for a port should
+// provide the implementation
+uintptr_t machine_mem_get_read_addr(mp_obj_t addr_o, uint align);
+uintptr_t machine_mem_get_write_addr(mp_obj_t addr_o, uint align);
+
+#endif /*  MICROPY_EXTMOD_MACHINE_MEM */
diff --git a/py/objmodule.c b/py/objmodule.c
index 71b0b0a269d3d716bbd764b151d821e63743b774..32ded891962d37f154699c670c3fdbf69fe8e84d 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -184,9 +184,6 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
 #if MICROPY_PY_UBINASCII
     { MP_ROM_QSTR(MP_QSTR_ubinascii), MP_ROM_PTR(&mp_module_ubinascii) },
 #endif
-#if MICROPY_PY_MACHINE
-    { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) },
-#endif
 #if MICROPY_PY_USSL
     { MP_ROM_QSTR(MP_QSTR_ussl), MP_ROM_PTR(&mp_module_ussl) },
 #endif
diff --git a/py/py.mk b/py/py.mk
index 75e7f461e49b8c81462b9e39acc9a3494536538a..b2f62468da135fb9eee21cee020d9a88492be347 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -165,7 +165,7 @@ PY_O_BASENAME = \
 	../extmod/moduheapq.o \
 	../extmod/moduhashlib.o \
 	../extmod/modubinascii.o \
-	../extmod/modmachine.o \
+	../extmod/machine_mem.o \
 	../extmod/modussl.o \
 	../extmod/fsusermount.o \
 
diff --git a/unix/Makefile b/unix/Makefile
index 677c3b4fde2a4b3846dd6ac4812c8a7e4a68f8bc..b905b06834e3057e4f0717c07ecd7a5eff97ffdd 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -114,6 +114,7 @@ SRC_C = \
 	unix_mphal.c \
 	input.c \
 	file.c \
+	modmachine.c \
 	modos.c \
 	moduselect.c \
 	alloc.c \
diff --git a/extmod/modmachine.c b/unix/modmachine.c
similarity index 62%
rename from extmod/modmachine.c
rename to unix/modmachine.c
index 675a32086355c6f4369f8578fe3b858bd20053b0..cada0e0b691a7e0a516b6f3d4f0f5f1bbab6d695 100644
--- a/extmod/modmachine.c
+++ b/unix/modmachine.c
@@ -29,6 +29,9 @@
 
 #include "py/nlr.h"
 #include "py/obj.h"
+
+#include "extmod/machine_mem.h"
+
 #if MICROPY_PLAT_DEV_MEM
 #include <errno.h>
 #include <fcntl.h>
@@ -39,8 +42,7 @@
 
 #if MICROPY_PY_MACHINE
 
-
-STATIC uintptr_t get_addr(mp_obj_t addr_o, uint align) {
+uintptr_t machine_mem_get_read_addr(mp_obj_t addr_o, uint align) {
     uintptr_t addr = mp_obj_int_get_truncated(addr_o);
     if ((addr & (align - 1)) != 0) {
         nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align));
@@ -70,57 +72,10 @@ STATIC uintptr_t get_addr(mp_obj_t addr_o, uint align) {
     return addr;
 }
 
-typedef struct _machine_mem_obj_t {
-    mp_obj_base_t base;
-    unsigned elem_size; // in bytes
-} machine_mem_obj_t;
-
-STATIC void machine_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
-    (void)kind;
-    machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
-    mp_printf(print, "<%u-bit memory>", 8 * self->elem_size);
-}
-
-STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
-    // TODO support slice index to read/write multiple values at once
-    machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
-    if (value == MP_OBJ_NULL) {
-        // delete
-        return MP_OBJ_NULL; // op not supported
-    } else if (value == MP_OBJ_SENTINEL) {
-        // load
-        uintptr_t addr = get_addr(index, self->elem_size);
-        uint32_t val;
-        switch (self->elem_size) {
-            case 1: val = (*(uint8_t*)addr); break;
-            case 2: val = (*(uint16_t*)addr); break;
-            default: val = (*(uint32_t*)addr); break;
-        }
-        return mp_obj_new_int(val);
-    } else {
-        // store
-        uintptr_t addr = get_addr(index, self->elem_size);
-        uint32_t val = mp_obj_get_int(value);
-        switch (self->elem_size) {
-            case 1: (*(uint8_t*)addr) = val; break;
-            case 2: (*(uint16_t*)addr) = val; break;
-            default: (*(uint32_t*)addr) = val; break;
-        }
-        return mp_const_none;
-    }
+uintptr_t machine_mem_get_write_addr(mp_obj_t addr_o, uint align) {
+    return machine_mem_get_read_addr(addr_o, align);
 }
 
-STATIC const mp_obj_type_t machine_mem_type = {
-    { &mp_type_type },
-    .name = MP_QSTR_mem,
-    .print = machine_mem_print,
-    .subscr = machine_mem_subscr,
-};
-
-STATIC const machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1};
-STATIC const machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2};
-STATIC const machine_mem_obj_t machine_mem32_obj = {{&machine_mem_type}, 4};
-
 STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
     { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) },
 
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index d85b98b8dc567e80e1fecdba068767035f54f7f1..5161066c00fea5b96bceb0fdcf8aaaac89f0e423 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -124,6 +124,7 @@
 #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF   (1)
 #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE  (256)
 
+extern const struct _mp_obj_module_t mp_module_machine;
 extern const struct _mp_obj_module_t mp_module_os;
 extern const struct _mp_obj_module_t mp_module_uselect;
 extern const struct _mp_obj_module_t mp_module_time;
@@ -163,6 +164,7 @@ extern const struct _mp_obj_module_t mp_module_jni;
     MICROPY_PY_JNI_DEF \
     MICROPY_PY_TIME_DEF \
     MICROPY_PY_SOCKET_DEF \
+    { MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \
     { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \
     { MP_ROM_QSTR(MP_QSTR_uselect), MP_ROM_PTR(&mp_module_uselect) }, \
     MICROPY_PY_TERMIOS_DEF \
diff --git a/windows/Makefile b/windows/Makefile
index 10c5f2ba7f6f729ec57376e394589ed9ef6a0651..ba89fccae3ae0593d2006a3745aedd41dbf94f79 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -32,6 +32,7 @@ SRC_C = \
 	unix/file.c \
 	unix/input.c \
 	unix/modos.c \
+	unix/modmachine.c \
 	unix/modtime.c \
 	unix/gccollect.c \
 	windows_mphal.c \